@prolibu-suite/cobalt-core 0.10.4 → 0.11.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 (736) hide show
  1. package/custom-elements.json +4362 -388
  2. package/dist/cjs/co-accordion.cjs.entry.js +3 -3
  3. package/dist/cjs/co-action-bar.cjs.entry.js +3 -3
  4. package/dist/cjs/co-app-shell.cjs.entry.js +3 -3
  5. package/dist/cjs/co-audio-player.cjs.entry.js +4 -4
  6. package/dist/cjs/co-autocomplete.cjs.entry.js +2 -2
  7. package/dist/cjs/co-avatar-group.cjs.entry.js +1 -1
  8. package/dist/cjs/co-avatar.cjs.entry.js +7 -4
  9. package/dist/cjs/co-badge.cjs.entry.js +2 -2
  10. package/dist/cjs/co-bottom-sheet.cjs.entry.js +5 -5
  11. package/dist/cjs/co-breadcrumb-item.cjs.entry.js +3 -3
  12. package/dist/cjs/co-breadcrumb.cjs.entry.js +2 -2
  13. package/dist/cjs/co-button-group.cjs.entry.js +3 -3
  14. package/dist/cjs/co-button.cjs.entry.js +9 -7
  15. package/dist/cjs/co-calendar-month_2.cjs.entry.js +4 -4
  16. package/dist/cjs/co-calendar_3.cjs.entry.js +72 -27
  17. package/dist/cjs/co-card.cjs.entry.js +3 -3
  18. package/dist/cjs/co-carousel-item.cjs.entry.js +2 -2
  19. package/dist/cjs/co-carousel.cjs.entry.js +3 -3
  20. package/dist/cjs/co-checkbox-group.cjs.entry.js +1 -1
  21. package/dist/cjs/co-checkbox.cjs.entry.js +13 -5
  22. package/dist/cjs/co-chip_2.cjs.entry.js +9 -6
  23. package/dist/cjs/co-color-area.cjs.entry.js +169 -0
  24. package/dist/cjs/co-color-picker.cjs.entry.js +5 -5
  25. package/dist/cjs/co-color-slider.cjs.entry.js +189 -0
  26. package/dist/cjs/co-column-picker.cjs.entry.js +3 -3
  27. package/dist/cjs/co-combobox.cjs.entry.js +5 -5
  28. package/dist/cjs/co-command-search.cjs.entry.js +5 -5
  29. package/dist/cjs/co-data-table-pagination.cjs.entry.js +5 -5
  30. package/dist/cjs/co-data-table.cjs.entry.js +3 -3
  31. package/dist/cjs/co-date-picker.cjs.entry.js +2 -2
  32. package/dist/cjs/co-date-range-picker.cjs.entry.js +2 -2
  33. package/dist/cjs/co-date-range.cjs.entry.js +2 -2
  34. package/dist/cjs/co-date-time-picker.cjs.entry.js +4 -4
  35. package/dist/cjs/co-document-editor.cjs.entry.js +1161 -0
  36. package/dist/cjs/co-drive-card.cjs.entry.js +2 -2
  37. package/dist/cjs/co-drop-zone.cjs.entry.js +2 -2
  38. package/dist/cjs/co-emoji-picker.cjs.entry.js +3 -3
  39. package/dist/cjs/co-empty-state.cjs.entry.js +3 -3
  40. package/dist/cjs/co-event-calendar.cjs.entry.js +3 -3
  41. package/dist/cjs/co-event-popover.cjs.entry.js +3 -3
  42. package/dist/cjs/co-fab.cjs.entry.js +3 -3
  43. package/dist/cjs/co-file-field.cjs.entry.js +8 -8
  44. package/dist/cjs/co-file-type-tile.cjs.entry.js +3 -3
  45. package/dist/cjs/co-gradient-bar.cjs.entry.js +220 -0
  46. package/dist/cjs/co-helper-text.cjs.entry.js +3 -3
  47. package/dist/cjs/co-icon-button.cjs.entry.js +49 -9
  48. package/dist/cjs/co-icon.cjs.entry.js +3 -3
  49. package/dist/cjs/co-input.cjs.entry.js +14 -8
  50. package/dist/cjs/co-json-field.cjs.entry.js +5 -5
  51. package/dist/cjs/{co-tooltip.cjs.entry.js → co-kbd_2.cjs.entry.js} +194 -6
  52. package/dist/cjs/co-lightbox.cjs.entry.js +5 -5
  53. package/dist/cjs/co-list-footer.cjs.entry.js +2 -2
  54. package/dist/cjs/co-list-item.cjs.entry.js +5 -5
  55. package/dist/cjs/co-loader.cjs.entry.js +1 -1
  56. package/dist/cjs/co-media-thumb.cjs.entry.js +3 -3
  57. package/dist/cjs/co-menu-divider.cjs.entry.js +3 -3
  58. package/dist/cjs/co-menu-item.cjs.entry.js +41 -43
  59. package/dist/cjs/co-menu.cjs.entry.js +81 -5
  60. package/dist/cjs/co-modal.cjs.entry.js +350 -7
  61. package/dist/cjs/co-navbar.cjs.entry.js +3 -3
  62. package/dist/cjs/co-number-field.cjs.entry.js +5 -5
  63. package/dist/cjs/co-overlay.cjs.entry.js +8 -4
  64. package/dist/cjs/co-page-header.cjs.entry.js +2 -2
  65. package/dist/cjs/co-phone-field.cjs.entry.js +3 -3
  66. package/dist/cjs/co-popover.cjs.entry.js +67 -6
  67. package/dist/cjs/co-progress-bar.cjs.entry.js +3 -3
  68. package/dist/cjs/co-progress-circle.cjs.entry.js +3 -3
  69. package/dist/cjs/co-provider-logo_2.cjs.entry.js +2 -2
  70. package/dist/cjs/co-radio-group.cjs.entry.js +4 -4
  71. package/dist/cjs/co-radio.cjs.entry.js +4 -4
  72. package/dist/cjs/co-rating.cjs.entry.js +4 -4
  73. package/dist/cjs/co-ref-field.cjs.entry.js +5 -5
  74. package/dist/cjs/co-rich-text-editor.cjs.entry.js +26 -92
  75. package/dist/cjs/co-rich-text-toolbar.cjs.entry.js +79 -20
  76. package/dist/cjs/co-rich-text-viewer.cjs.entry.js +9 -2
  77. package/dist/cjs/co-row.cjs.entry.js +3 -3
  78. package/dist/cjs/co-segmented-bar.cjs.entry.js +3 -3
  79. package/dist/cjs/co-select.cjs.entry.js +158 -29
  80. package/dist/cjs/co-separator.cjs.entry.js +2 -2
  81. package/dist/cjs/co-sidebar-nav.cjs.entry.js +20 -5
  82. package/dist/cjs/co-sidebar.cjs.entry.js +3 -3
  83. package/dist/cjs/co-slider.cjs.entry.js +203 -23
  84. package/dist/cjs/co-swatch-grid.cjs.entry.js +121 -0
  85. package/dist/cjs/co-switch.cjs.entry.js +5 -5
  86. package/dist/cjs/co-tab-group.cjs.entry.js +113 -4
  87. package/dist/cjs/co-tab.cjs.entry.js +15 -5
  88. package/dist/cjs/co-tags-field.cjs.entry.js +8 -8
  89. package/dist/cjs/co-textarea.cjs.entry.js +6 -6
  90. package/dist/cjs/co-tile.cjs.entry.js +61 -0
  91. package/dist/cjs/co-time-field.cjs.entry.js +2 -2
  92. package/dist/cjs/co-toast.cjs.entry.js +3 -3
  93. package/dist/cjs/co-toggle-button-group.cjs.entry.js +26 -5
  94. package/dist/cjs/co-toggle-button.cjs.entry.js +67 -6
  95. package/dist/cjs/co-transfer-list.cjs.entry.js +3 -3
  96. package/dist/cjs/co-tree-item.cjs.entry.js +110 -0
  97. package/dist/cjs/co-video.cjs.entry.js +3 -3
  98. package/dist/cjs/cobalt.cjs.js +2 -2
  99. package/dist/cjs/{color-CML2Cfdh.js → color-DQVrQGi0.js} +10 -5
  100. package/dist/cjs/{fieldChip-B6YIGU1V.js → fieldChip-C7MxxBVO.js} +1 -1
  101. package/dist/cjs/gradientStops-CMpH4fB_.js +153 -0
  102. package/dist/cjs/hsv-DpfSF3M2.js +95 -0
  103. package/dist/cjs/{index-MDAnKsze.js → index-bHoidDwv.js} +67 -27
  104. package/dist/cjs/index-oMHzCXm6.js +144 -0
  105. package/dist/cjs/loader.cjs.js +2 -2
  106. package/dist/cjs/{index-2kMmd5-a.js → pagination-DV43TRj9.js} +1780 -297
  107. package/dist/cjs/{positioning-CyatXeT_.js → positioning-CILo5esi.js} +45 -18
  108. package/dist/cjs/{requiredMark-D-t-IPN0.js → requiredMark-21yHvvZS.js} +1 -1
  109. package/dist/cjs/rich-text-host-ueFSfW-6.js +119 -0
  110. package/dist/cjs/{richTextI18n-B28uAhh4.js → richTextI18n-DXGIv5w1.js} +45 -0
  111. package/dist/cjs/submenu-RlaX6irw.js +65 -0
  112. package/dist/cjs/{toolbar-config-CYACt9hh.js → toolbar-config-DczL6C4W.js} +32 -0
  113. package/dist/cobalt/cobalt.css +1 -1
  114. package/dist/cobalt/cobalt.esm.js +1 -1
  115. package/dist/cobalt/{p-ee149fd2.entry.js → p-05000ef3.entry.js} +1 -1
  116. package/dist/cobalt/p-06689166.entry.js +1 -0
  117. package/dist/cobalt/{p-1dc55e43.entry.js → p-0a5cfed0.entry.js} +1 -1
  118. package/dist/cobalt/p-1289131f.entry.js +1 -0
  119. package/dist/cobalt/{p-c7d7d7f7.entry.js → p-136beb2c.entry.js} +1 -1
  120. package/dist/cobalt/{p-b437eff6.entry.js → p-1693b614.entry.js} +1 -1
  121. package/dist/cobalt/p-1bfb69ae.entry.js +1 -0
  122. package/dist/cobalt/{p-2c9dba2f.entry.js → p-1f3d5313.entry.js} +1 -1
  123. package/dist/cobalt/{p-b821d9de.entry.js → p-22233b31.entry.js} +1 -1
  124. package/dist/cobalt/{p-c30b4cb5.entry.js → p-26fa36f8.entry.js} +1 -1
  125. package/dist/cobalt/p-2794c500.entry.js +1 -0
  126. package/dist/cobalt/p-297b55cd.entry.js +1 -0
  127. package/dist/cobalt/{p-17244412.entry.js → p-2a2b0c7a.entry.js} +1 -1
  128. package/dist/cobalt/{p-2636b7eb.entry.js → p-2e5702a0.entry.js} +1 -1
  129. package/dist/cobalt/p-3011c84f.entry.js +1 -0
  130. package/dist/cobalt/{p-4d65e713.entry.js → p-30760f77.entry.js} +1 -1
  131. package/dist/cobalt/{p-6dd220e0.entry.js → p-3b9a8e86.entry.js} +1 -1
  132. package/dist/cobalt/p-4111fefa.entry.js +1 -0
  133. package/dist/cobalt/{p-a32b20eb.entry.js → p-44edde81.entry.js} +1 -1
  134. package/dist/cobalt/{p-292b0389.entry.js → p-45007758.entry.js} +1 -1
  135. package/dist/cobalt/p-48c23310.entry.js +1 -0
  136. package/dist/cobalt/p-4b327483.entry.js +1 -0
  137. package/dist/cobalt/p-4c6caa41.entry.js +1 -0
  138. package/dist/cobalt/{p-000a15b8.entry.js → p-5534a64f.entry.js} +1 -1
  139. package/dist/cobalt/p-5573985a.entry.js +1 -0
  140. package/dist/cobalt/p-57d250ad.entry.js +1 -0
  141. package/dist/cobalt/{p-826ee074.entry.js → p-59d3e8fc.entry.js} +1 -1
  142. package/dist/cobalt/{p-4592ca00.entry.js → p-5a32b9a2.entry.js} +1 -1
  143. package/dist/cobalt/p-5b2aa70e.entry.js +1 -0
  144. package/dist/cobalt/{p-d29bb0fa.entry.js → p-5d6e02dd.entry.js} +1 -1
  145. package/dist/cobalt/{p-623cc195.entry.js → p-608d251d.entry.js} +1 -1
  146. package/dist/cobalt/{p-011dc80b.entry.js → p-66fc1528.entry.js} +1 -1
  147. package/dist/cobalt/{p-11c5ce78.entry.js → p-67ad9544.entry.js} +1 -1
  148. package/dist/cobalt/{p-290066ef.entry.js → p-6c157ea2.entry.js} +1 -1
  149. package/dist/cobalt/{p-a2462d7a.entry.js → p-6d541199.entry.js} +1 -1
  150. package/dist/cobalt/{p-58d9b650.entry.js → p-7376f4ed.entry.js} +1 -1
  151. package/dist/cobalt/{p-39a50e7f.entry.js → p-7569375a.entry.js} +1 -1
  152. package/dist/cobalt/{p-7b5c555c.entry.js → p-763698b3.entry.js} +1 -1
  153. package/dist/cobalt/{p-f57dffca.entry.js → p-7675cebe.entry.js} +1 -1
  154. package/dist/cobalt/p-78a20284.entry.js +1 -0
  155. package/dist/cobalt/{p-aa9400bf.entry.js → p-7f3523ce.entry.js} +1 -1
  156. package/dist/cobalt/{p-24196410.entry.js → p-86b6fd81.entry.js} +1 -1
  157. package/dist/cobalt/{p-996f4e38.entry.js → p-889563d5.entry.js} +1 -1
  158. package/dist/cobalt/{p-eadfd661.entry.js → p-8ab5b396.entry.js} +1 -1
  159. package/dist/cobalt/{p-c91d4fc6.entry.js → p-8b2e4579.entry.js} +1 -1
  160. package/dist/cobalt/p-8cd3acaa.entry.js +1 -0
  161. package/dist/cobalt/{p-23ab0cc5.entry.js → p-8f701eac.entry.js} +1 -1
  162. package/dist/cobalt/p-90fad0f9.entry.js +1 -0
  163. package/dist/cobalt/{p-76249983.entry.js → p-97a4fbba.entry.js} +1 -1
  164. package/dist/cobalt/p-9b46a8fe.entry.js +1 -0
  165. package/dist/cobalt/{p-ee2023da.entry.js → p-9bee9dc8.entry.js} +1 -1
  166. package/dist/cobalt/{p-2f9cbbd5.entry.js → p-9cf10331.entry.js} +1 -1
  167. package/dist/cobalt/p-9dc01092.entry.js +1 -0
  168. package/dist/cobalt/p-9e406172.entry.js +1 -0
  169. package/dist/cobalt/p-B1JT7us1.js +1 -0
  170. package/dist/cobalt/{p-BRbgGqLw.js → p-BVGGRfNG.js} +1 -1
  171. package/dist/cobalt/p-BmdKHBZP.js +1 -0
  172. package/dist/cobalt/p-BtliEQAT.js +1 -0
  173. package/dist/cobalt/p-COJdaKBU.js +1 -0
  174. package/dist/cobalt/{p-BAYo-RBt.js → p-CRxTFT_z.js} +1 -1
  175. package/dist/cobalt/p-CYN5B3IQ.js +1 -0
  176. package/dist/cobalt/p-DJkaRtbb.js +2 -0
  177. package/dist/cobalt/p-DU-KOQ8L.js +1 -0
  178. package/dist/cobalt/p-DXLeDZvr.js +1 -0
  179. package/dist/cobalt/{p-D_zA1Pv4.js → p-DgJovDdy.js} +1 -1
  180. package/dist/cobalt/p-RVQJEYxa.js +1 -0
  181. package/dist/cobalt/{p-1861fe41.entry.js → p-a07dedd1.entry.js} +1 -1
  182. package/dist/cobalt/{p-08e42e00.entry.js → p-a336178b.entry.js} +1 -1
  183. package/dist/cobalt/{p-f9a7b7c6.entry.js → p-a52ed6ff.entry.js} +1 -1
  184. package/dist/cobalt/{p-aaca6dab.entry.js → p-a930cdd7.entry.js} +1 -1
  185. package/dist/cobalt/{p-eb82358d.entry.js → p-b1994bb4.entry.js} +1 -1
  186. package/dist/cobalt/p-b2b13da8.entry.js +1 -0
  187. package/dist/cobalt/{p-c2ebf0ec.entry.js → p-b5ec4286.entry.js} +1 -1
  188. package/dist/cobalt/p-b9401dd7.entry.js +1 -0
  189. package/dist/cobalt/p-b9dfb333.entry.js +1 -0
  190. package/dist/cobalt/p-bc3ba0cd.entry.js +1 -0
  191. package/dist/cobalt/{p-d375014b.entry.js → p-bc4fbfa6.entry.js} +1 -1
  192. package/dist/cobalt/{p-d0b2c418.entry.js → p-c109a1e1.entry.js} +1 -1
  193. package/dist/cobalt/{p-ee9a623d.entry.js → p-c1caa112.entry.js} +1 -1
  194. package/dist/cobalt/p-c9990662.entry.js +1 -0
  195. package/dist/cobalt/p-cc4b51fa.entry.js +1 -0
  196. package/dist/cobalt/p-cc5989e9.entry.js +1 -0
  197. package/dist/cobalt/{p-e4264532.entry.js → p-ce2b2048.entry.js} +1 -1
  198. package/dist/cobalt/p-d1c378ff.entry.js +1 -0
  199. package/dist/cobalt/p-d1e83525.entry.js +1 -0
  200. package/dist/cobalt/{p-59963937.entry.js → p-d1f47915.entry.js} +1 -1
  201. package/dist/cobalt/{p-28764b8e.entry.js → p-d4979025.entry.js} +1 -1
  202. package/dist/cobalt/p-d6e7c258.entry.js +1 -0
  203. package/dist/cobalt/p-d75d2f3d.entry.js +1 -0
  204. package/dist/cobalt/p-db42c4ab.entry.js +1 -0
  205. package/dist/cobalt/{p-44c4e4a3.entry.js → p-e4ff2fcb.entry.js} +1 -1
  206. package/dist/cobalt/p-e6116149.entry.js +1 -0
  207. package/dist/cobalt/{p-0c004735.entry.js → p-e99ddf9c.entry.js} +1 -1
  208. package/dist/cobalt/{p-1cc818ca.entry.js → p-ea24eea8.entry.js} +1 -1
  209. package/dist/cobalt/{p-07416e31.entry.js → p-ea564148.entry.js} +1 -1
  210. package/dist/cobalt/{p-8471abe2.entry.js → p-ec7a6bf2.entry.js} +1 -1
  211. package/dist/cobalt/{p-fb2d1144.entry.js → p-ee42dca6.entry.js} +1 -1
  212. package/dist/cobalt/{p-49834b8e.entry.js → p-ee88ec40.entry.js} +1 -1
  213. package/dist/cobalt/p-eeb114da.entry.js +1 -0
  214. package/dist/cobalt/{p-f6691108.entry.js → p-f0898e21.entry.js} +1 -1
  215. package/dist/cobalt/p-f246946a.entry.js +1 -0
  216. package/dist/cobalt/{p-b90d41e4.entry.js → p-f5934cd9.entry.js} +1 -1
  217. package/dist/cobalt/p-f5e1873d.entry.js +1 -0
  218. package/dist/cobalt/p-f60bd4d6.entry.js +1 -0
  219. package/dist/cobalt/p-f813569c.entry.js +1 -0
  220. package/dist/cobalt/{p-f7eb1a40.entry.js → p-f8c7941f.entry.js} +1 -1
  221. package/dist/cobalt/{p-44ea675f.entry.js → p-f8d3c71e.entry.js} +1 -1
  222. package/dist/cobalt/{p-91e73a92.entry.js → p-ffbe955a.entry.js} +1 -1
  223. package/dist/cobalt/p-xnrKkNWQ.js +1 -0
  224. package/dist/collection/collection-manifest.json +8 -0
  225. package/dist/collection/components/co-accordion/co-accordion.js +2 -2
  226. package/dist/collection/components/co-action-bar/co-action-bar.js +2 -2
  227. package/dist/collection/components/co-app-shell/co-app-shell.js +2 -2
  228. package/dist/collection/components/co-audio-player/co-audio-player.js +3 -3
  229. package/dist/collection/components/co-autocomplete/co-autocomplete.js +1 -1
  230. package/dist/collection/components/co-avatar/co-avatar.css +11 -2
  231. package/dist/collection/components/co-avatar/co-avatar.js +7 -4
  232. package/dist/collection/components/co-avatar-group/co-avatar-group.js +1 -1
  233. package/dist/collection/components/co-badge/co-badge.js +1 -1
  234. package/dist/collection/components/co-bottom-sheet/co-bottom-sheet.js +4 -4
  235. package/dist/collection/components/co-breadcrumb/co-breadcrumb.js +1 -1
  236. package/dist/collection/components/co-breadcrumb-item/co-breadcrumb-item.js +2 -2
  237. package/dist/collection/components/co-button/co-button.css +73 -6
  238. package/dist/collection/components/co-button/co-button.js +33 -11
  239. package/dist/collection/components/co-button-group/co-button-group.js +2 -2
  240. package/dist/collection/components/co-calendar/calendarMarks.js +40 -0
  241. package/dist/collection/components/co-calendar/co-calendar.css +11 -1
  242. package/dist/collection/components/co-calendar/co-calendar.js +82 -20
  243. package/dist/collection/components/co-calendar-month/co-calendar-month.js +1 -1
  244. package/dist/collection/components/co-calendar-timegrid/co-calendar-timegrid.js +2 -2
  245. package/dist/collection/components/co-card/co-card.js +2 -2
  246. package/dist/collection/components/co-carousel/co-carousel.js +2 -2
  247. package/dist/collection/components/co-carousel-item/co-carousel-item.js +1 -1
  248. package/dist/collection/components/co-checkbox/co-checkbox.css +43 -1
  249. package/dist/collection/components/co-checkbox/co-checkbox.js +31 -3
  250. package/dist/collection/components/co-checkbox-group/co-checkbox-group.js +1 -1
  251. package/dist/collection/components/co-chip/co-chip.js +2 -2
  252. package/dist/collection/components/co-color-area/co-color-area.css +83 -0
  253. package/dist/collection/components/co-color-area/co-color-area.js +341 -0
  254. package/dist/collection/components/co-color-picker/co-color-picker.js +2 -2
  255. package/dist/collection/components/co-color-slider/co-color-slider.css +115 -0
  256. package/dist/collection/components/co-color-slider/co-color-slider.js +353 -0
  257. package/dist/collection/components/co-column-picker/co-column-picker.js +2 -2
  258. package/dist/collection/components/co-combobox/co-combobox.js +4 -4
  259. package/dist/collection/components/co-command-search/co-command-search.js +5 -5
  260. package/dist/collection/components/co-data-table/co-data-table.js +3 -3
  261. package/dist/collection/components/co-data-table-pagination/co-data-table-pagination.js +4 -4
  262. package/dist/collection/components/co-date-field/co-date-field.js +4 -4
  263. package/dist/collection/components/co-date-range/co-date-range.js +1 -1
  264. package/dist/collection/components/co-date-range-picker/co-date-range-picker.js +2 -2
  265. package/dist/collection/components/co-date-time-picker/co-date-time-picker.js +3 -3
  266. package/dist/collection/components/co-document-editor/change-throttle.js +30 -0
  267. package/dist/collection/components/co-document-editor/co-document-editor.css +438 -0
  268. package/dist/collection/components/co-document-editor/co-document-editor.js +1542 -0
  269. package/dist/collection/components/co-document-editor/document-props.js +40 -0
  270. package/dist/collection/components/co-document-editor/header-tools.js +11 -0
  271. package/dist/collection/components/co-document-editor/image-bar.js +66 -0
  272. package/dist/collection/components/co-document-editor/page-styles.js +90 -0
  273. package/dist/collection/components/co-document-editor/zoom.js +45 -0
  274. package/dist/collection/components/co-drive-card/co-drive-card.js +1 -1
  275. package/dist/collection/components/co-drop-zone/co-drop-zone.js +1 -1
  276. package/dist/collection/components/co-emoji-picker/co-emoji-picker.js +2 -2
  277. package/dist/collection/components/co-empty-state/co-empty-state.js +2 -2
  278. package/dist/collection/components/co-event-calendar/co-event-calendar.js +2 -2
  279. package/dist/collection/components/co-event-popover/co-event-popover.js +1 -1
  280. package/dist/collection/components/co-fab/co-fab.js +2 -2
  281. package/dist/collection/components/co-file-field/co-file-field.js +6 -6
  282. package/dist/collection/components/co-file-type-tile/co-file-type-tile.js +2 -2
  283. package/dist/collection/components/co-gradient-bar/co-gradient-bar.css +138 -0
  284. package/dist/collection/components/co-gradient-bar/co-gradient-bar.js +407 -0
  285. package/dist/collection/components/co-helper-text/co-helper-text.js +2 -2
  286. package/dist/collection/components/co-icon/co-icon.js +2 -2
  287. package/dist/collection/components/co-icon-button/co-icon-button.css +95 -19
  288. package/dist/collection/components/co-icon-button/co-icon-button.js +120 -10
  289. package/dist/collection/components/co-input/co-input.css +122 -0
  290. package/dist/collection/components/co-input/co-input.js +37 -11
  291. package/dist/collection/components/co-json-field/co-json-field.js +3 -3
  292. package/dist/collection/components/co-kbd/co-kbd.css +99 -0
  293. package/dist/collection/components/co-kbd/co-kbd.js +291 -0
  294. package/dist/collection/components/co-lightbox/co-lightbox.js +4 -4
  295. package/dist/collection/components/co-list-footer/co-list-footer.js +1 -1
  296. package/dist/collection/components/co-list-item/co-list-item.js +4 -4
  297. package/dist/collection/components/co-media-thumb/co-media-thumb.js +2 -2
  298. package/dist/collection/components/co-menu/co-menu.css +60 -0
  299. package/dist/collection/components/co-menu/co-menu.js +143 -3
  300. package/dist/collection/components/co-menu-divider/co-menu-divider.css +17 -0
  301. package/dist/collection/components/co-menu-divider/co-menu-divider.js +1 -1
  302. package/dist/collection/components/co-menu-item/co-menu-item.css +42 -6
  303. package/dist/collection/components/co-menu-item/co-menu-item.js +58 -4
  304. package/dist/collection/components/co-modal/co-modal.css +212 -1
  305. package/dist/collection/components/co-modal/co-modal.js +339 -9
  306. package/dist/collection/components/co-navbar/co-navbar.js +2 -2
  307. package/dist/collection/components/co-number-field/co-number-field.js +3 -3
  308. package/dist/collection/components/co-option-list/co-option-list.css +64 -21
  309. package/dist/collection/components/co-option-list/co-option-list.js +6 -2
  310. package/dist/collection/components/co-overlay/co-overlay.js +7 -3
  311. package/dist/collection/components/co-page-header/co-page-header.js +1 -1
  312. package/dist/collection/components/co-phone-field/co-phone-field.js +1 -1
  313. package/dist/collection/components/co-popover/co-popover.css +15 -2
  314. package/dist/collection/components/co-popover/co-popover.js +130 -5
  315. package/dist/collection/components/co-progress-bar/co-progress-bar.js +2 -2
  316. package/dist/collection/components/co-progress-circle/co-progress-circle.js +2 -2
  317. package/dist/collection/components/co-radio/co-radio.js +3 -3
  318. package/dist/collection/components/co-radio-group/co-radio-group.js +4 -4
  319. package/dist/collection/components/co-rating/co-rating.js +3 -3
  320. package/dist/collection/components/co-ref-field/co-ref-field.js +5 -5
  321. package/dist/collection/components/co-rich-text-editor/co-rich-text-editor.js +23 -90
  322. package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.css +12 -0
  323. package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.js +123 -18
  324. package/dist/collection/components/co-rich-text-viewer/co-rich-text-viewer.js +8 -1
  325. package/dist/collection/components/co-row/co-row.js +2 -2
  326. package/dist/collection/components/co-segmented-bar/co-segmented-bar.js +3 -3
  327. package/dist/collection/components/co-select/co-select.css +194 -10
  328. package/dist/collection/components/co-select/co-select.js +163 -32
  329. package/dist/collection/components/co-select/virtualRows.js +57 -0
  330. package/dist/collection/components/co-separator/co-separator.js +1 -1
  331. package/dist/collection/components/co-sidebar/co-sidebar.js +2 -2
  332. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.css +10 -0
  333. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +19 -4
  334. package/dist/collection/components/co-skeleton/co-skeleton.js +1 -1
  335. package/dist/collection/components/co-slider/co-slider.css +148 -5
  336. package/dist/collection/components/co-slider/co-slider.js +240 -21
  337. package/dist/collection/components/co-swatch-grid/co-swatch-grid.css +56 -0
  338. package/dist/collection/components/co-swatch-grid/co-swatch-grid.js +292 -0
  339. package/dist/collection/components/co-switch/co-switch.js +3 -3
  340. package/dist/collection/components/co-tab/co-tab.css +60 -0
  341. package/dist/collection/components/co-tab/co-tab.js +36 -6
  342. package/dist/collection/components/co-tab-group/co-tab-group.css +24 -0
  343. package/dist/collection/components/co-tab-group/co-tab-group.js +124 -2
  344. package/dist/collection/components/co-tab-group/revealTab.js +26 -0
  345. package/dist/collection/components/co-tags-field/co-tags-field.js +5 -5
  346. package/dist/collection/components/co-textarea/co-textarea.js +4 -4
  347. package/dist/collection/components/co-tile/co-tile.css +63 -0
  348. package/dist/collection/components/co-tile/co-tile.js +162 -0
  349. package/dist/collection/components/co-time-field/co-time-field.js +1 -1
  350. package/dist/collection/components/co-toast/co-toast.js +4 -4
  351. package/dist/collection/components/co-toggle-button/co-toggle-button.css +101 -0
  352. package/dist/collection/components/co-toggle-button/co-toggle-button.js +80 -8
  353. package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.css +21 -0
  354. package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.js +28 -7
  355. package/dist/collection/components/co-tooltip/co-tooltip.css +36 -0
  356. package/dist/collection/components/co-tooltip/co-tooltip.js +51 -3
  357. package/dist/collection/components/co-transfer-list/co-transfer-list.js +3 -3
  358. package/dist/collection/components/co-tree-item/co-tree-item.css +226 -0
  359. package/dist/collection/components/co-tree-item/co-tree-item.js +353 -0
  360. package/dist/collection/components/co-tree-item/treeItemI18n.js +16 -0
  361. package/dist/collection/components/co-video/co-video.js +2 -2
  362. package/dist/collection/utils/color.js +9 -5
  363. package/dist/collection/utils/dragMove.js +95 -0
  364. package/dist/collection/utils/gradientBarI18n.js +24 -0
  365. package/dist/collection/utils/gradientStops.js +142 -0
  366. package/dist/collection/utils/hsv.js +114 -0
  367. package/dist/collection/utils/kbdI18n.js +29 -0
  368. package/dist/collection/utils/positioning.js +44 -18
  369. package/dist/collection/utils/rich-text-host.js +109 -0
  370. package/dist/collection/utils/richTextI18n.js +45 -0
  371. package/dist/collection/utils/submenu.js +23 -3
  372. package/dist/collection/utils/swatchGridI18n.js +14 -0
  373. package/dist/collection/utils/test/fake-block-layout.js +41 -0
  374. package/dist/collection/utils/test/prosemirror-dom-shim.js +17 -0
  375. package/dist/collection/utils/test/shared-contract-css.js +9 -0
  376. package/dist/components/co-accordion.js +1 -1
  377. package/dist/components/co-action-bar.js +1 -1
  378. package/dist/components/co-app-shell.js +1 -1
  379. package/dist/components/co-audio-player.js +1 -1
  380. package/dist/components/co-autocomplete.js +1 -1
  381. package/dist/components/co-avatar-group.js +1 -1
  382. package/dist/components/co-avatar.js +1 -1
  383. package/dist/components/co-badge.js +1 -1
  384. package/dist/components/co-bottom-sheet.js +1 -1
  385. package/dist/components/co-breadcrumb-item.js +1 -1
  386. package/dist/components/co-breadcrumb.js +1 -1
  387. package/dist/components/co-button-group.js +1 -1
  388. package/dist/components/co-button.js +1 -1
  389. package/dist/components/co-calendar-month.js +1 -1
  390. package/dist/components/co-calendar-timegrid.js +1 -1
  391. package/dist/components/co-calendar.js +1 -1
  392. package/dist/components/co-card.js +1 -1
  393. package/dist/components/co-carousel-item.js +1 -1
  394. package/dist/components/co-carousel.js +1 -1
  395. package/dist/components/co-checkbox-group.js +1 -1
  396. package/dist/components/co-checkbox.js +1 -1
  397. package/dist/components/co-chip.js +1 -1
  398. package/dist/components/co-color-area.d.ts +11 -0
  399. package/dist/components/co-color-area.js +1 -0
  400. package/dist/components/co-color-picker.js +1 -1
  401. package/dist/components/co-color-slider.d.ts +11 -0
  402. package/dist/components/co-color-slider.js +1 -0
  403. package/dist/components/co-column-picker.js +1 -1
  404. package/dist/components/co-combobox.js +1 -1
  405. package/dist/components/co-command-search.js +1 -1
  406. package/dist/components/co-data-table-pagination.js +1 -1
  407. package/dist/components/co-data-table.js +1 -1
  408. package/dist/components/co-date-field.js +1 -1
  409. package/dist/components/co-date-picker.js +1 -1
  410. package/dist/components/co-date-range-picker.js +1 -1
  411. package/dist/components/co-date-range.js +1 -1
  412. package/dist/components/co-date-time-picker.js +1 -1
  413. package/dist/components/co-document-editor.d.ts +11 -0
  414. package/dist/components/co-document-editor.js +1 -0
  415. package/dist/components/co-drawer.js +1 -1
  416. package/dist/components/co-drive-card.js +1 -1
  417. package/dist/components/co-drop-zone.js +1 -1
  418. package/dist/components/co-emoji-picker.js +1 -1
  419. package/dist/components/co-empty-state.js +1 -1
  420. package/dist/components/co-event-calendar.js +1 -1
  421. package/dist/components/co-event-popover.js +1 -1
  422. package/dist/components/co-fab.js +1 -1
  423. package/dist/components/co-file-field.js +1 -1
  424. package/dist/components/co-file-type-tile.js +1 -1
  425. package/dist/components/co-gradient-bar.d.ts +11 -0
  426. package/dist/components/co-gradient-bar.js +1 -0
  427. package/dist/components/co-helper-text.js +1 -1
  428. package/dist/components/co-icon-button.js +1 -1
  429. package/dist/components/co-icon.js +1 -1
  430. package/dist/components/co-input.js +1 -1
  431. package/dist/components/co-json-field.js +1 -1
  432. package/dist/components/co-kbd.d.ts +11 -0
  433. package/dist/components/co-kbd.js +1 -0
  434. package/dist/components/co-lightbox.js +1 -1
  435. package/dist/components/co-list-footer.js +1 -1
  436. package/dist/components/co-list-item.js +1 -1
  437. package/dist/components/co-media-thumb.js +1 -1
  438. package/dist/components/co-menu-divider.js +1 -1
  439. package/dist/components/co-menu-item.js +1 -1
  440. package/dist/components/co-menu.js +1 -1
  441. package/dist/components/co-modal.js +1 -1
  442. package/dist/components/co-navbar.js +1 -1
  443. package/dist/components/co-number-field.js +1 -1
  444. package/dist/components/co-option-list.js +1 -1
  445. package/dist/components/co-overlay.js +1 -1
  446. package/dist/components/co-page-header.js +1 -1
  447. package/dist/components/co-phone-field.js +1 -1
  448. package/dist/components/co-popover.js +1 -1
  449. package/dist/components/co-progress-bar.js +1 -1
  450. package/dist/components/co-progress-circle.js +1 -1
  451. package/dist/components/co-radio-group.js +1 -1
  452. package/dist/components/co-radio.js +1 -1
  453. package/dist/components/co-rating.js +1 -1
  454. package/dist/components/co-ref-field.js +1 -1
  455. package/dist/components/co-rich-text-editor.js +1 -1
  456. package/dist/components/co-rich-text-toolbar.js +1 -1
  457. package/dist/components/co-rich-text-viewer.js +1 -1
  458. package/dist/components/co-row.js +1 -1
  459. package/dist/components/co-segmented-bar.js +1 -1
  460. package/dist/components/co-select.js +1 -1
  461. package/dist/components/co-separator.js +1 -1
  462. package/dist/components/co-sidebar-nav.js +1 -1
  463. package/dist/components/co-sidebar.js +1 -1
  464. package/dist/components/co-skeleton.js +1 -1
  465. package/dist/components/co-slider.js +1 -1
  466. package/dist/components/co-swatch-grid.d.ts +11 -0
  467. package/dist/components/co-swatch-grid.js +1 -0
  468. package/dist/components/co-switch.js +1 -1
  469. package/dist/components/co-tab-group.js +1 -1
  470. package/dist/components/co-tab.js +1 -1
  471. package/dist/components/co-tags-field.js +1 -1
  472. package/dist/components/co-textarea.js +1 -1
  473. package/dist/components/co-tile.d.ts +11 -0
  474. package/dist/components/co-tile.js +1 -0
  475. package/dist/components/co-time-field.js +1 -1
  476. package/dist/components/co-toast.js +1 -1
  477. package/dist/components/co-toggle-button-group.js +1 -1
  478. package/dist/components/co-toggle-button.js +1 -1
  479. package/dist/components/co-tooltip.js +1 -1
  480. package/dist/components/co-transfer-list.js +1 -1
  481. package/dist/components/co-tree-item.d.ts +11 -0
  482. package/dist/components/co-tree-item.js +1 -0
  483. package/dist/components/co-video.js +1 -1
  484. package/dist/components/index.js +1 -1
  485. package/dist/components/p-B1JT7us1.js +1 -0
  486. package/dist/components/{p-Nt4JJxbL.js → p-B20o5exO.js} +1 -1
  487. package/dist/components/{p-DNJAIVfI.js → p-B3kKOgsA.js} +1 -1
  488. package/dist/components/{p-P4HlMBlL.js → p-BIDSDP05.js} +1 -1
  489. package/dist/components/p-BOqtnWTJ.js +1 -0
  490. package/dist/components/p-BQltjDw5.js +1 -0
  491. package/dist/components/p-BR0LYW9v.js +1 -0
  492. package/dist/components/{p-BRbgGqLw.js → p-BVGGRfNG.js} +1 -1
  493. package/dist/components/p-BZDl9aFl.js +1 -0
  494. package/dist/components/p-BcXdId8y.js +1 -0
  495. package/dist/components/p-BmdKHBZP.js +1 -0
  496. package/dist/components/{p-NNxjElcX.js → p-BraiMwgs.js} +1 -1
  497. package/dist/components/p-BtliEQAT.js +1 -0
  498. package/dist/components/p-Bymi-A7C.js +1 -0
  499. package/dist/components/p-C-f8wTqe.js +1 -0
  500. package/dist/components/{p-BhCVadcA.js → p-C1jZYtUS.js} +1 -1
  501. package/dist/components/{p-CT2enQ6h.js → p-C3G8oPgU.js} +1 -1
  502. package/dist/components/{p-B56LX2SH.js → p-CGH3E8uK.js} +1 -1
  503. package/dist/components/p-COJdaKBU.js +1 -0
  504. package/dist/components/{p-BAYo-RBt.js → p-CRxTFT_z.js} +1 -1
  505. package/dist/components/{p-Du_CgT5E.js → p-CfJgypOl.js} +1 -1
  506. package/dist/components/{p-uxdXViMV.js → p-ChwSnCFf.js} +1 -1
  507. package/dist/components/{p-Dc_Kbari.js → p-CpGEV0iM.js} +1 -1
  508. package/dist/components/{p-DvR45CLa.js → p-D9or2g4j.js} +1 -1
  509. package/dist/components/{p-e5KibEs8.js → p-DJ468fPu.js} +1 -1
  510. package/dist/components/{p-DFlJMEJ-.js → p-DKXCr-hE.js} +1 -1
  511. package/dist/components/p-DU-KOQ8L.js +1 -0
  512. package/dist/components/p-DXLeDZvr.js +1 -0
  513. package/dist/components/{p-BGDqldEg.js → p-DfcPGitr.js} +1 -1
  514. package/dist/components/p-Dg-Ti_Bf.js +1 -0
  515. package/dist/components/p-Dh_eRYKu.js +1 -0
  516. package/dist/components/p-Dp650Gpp.js +1 -0
  517. package/dist/components/p-FA1kBmZ-.js +1 -0
  518. package/dist/components/p-RVQJEYxa.js +1 -0
  519. package/dist/components/p-d4rf3H8p.js +1 -0
  520. package/dist/components/{p-Dxa7c4Ap.js → p-dnaee7fS.js} +1 -1
  521. package/dist/components/p-f2xwcrXa.js +1 -0
  522. package/dist/esm/co-accordion.entry.js +3 -3
  523. package/dist/esm/co-action-bar.entry.js +3 -3
  524. package/dist/esm/co-app-shell.entry.js +3 -3
  525. package/dist/esm/co-audio-player.entry.js +4 -4
  526. package/dist/esm/co-autocomplete.entry.js +2 -2
  527. package/dist/esm/co-avatar-group.entry.js +1 -1
  528. package/dist/esm/co-avatar.entry.js +7 -4
  529. package/dist/esm/co-badge.entry.js +2 -2
  530. package/dist/esm/co-bottom-sheet.entry.js +5 -5
  531. package/dist/esm/co-breadcrumb-item.entry.js +3 -3
  532. package/dist/esm/co-breadcrumb.entry.js +2 -2
  533. package/dist/esm/co-button-group.entry.js +3 -3
  534. package/dist/esm/co-button.entry.js +9 -7
  535. package/dist/esm/co-calendar-month_2.entry.js +4 -4
  536. package/dist/esm/co-calendar_3.entry.js +72 -27
  537. package/dist/esm/co-card.entry.js +3 -3
  538. package/dist/esm/co-carousel-item.entry.js +2 -2
  539. package/dist/esm/co-carousel.entry.js +3 -3
  540. package/dist/esm/co-checkbox-group.entry.js +1 -1
  541. package/dist/esm/co-checkbox.entry.js +13 -5
  542. package/dist/esm/co-chip_2.entry.js +9 -6
  543. package/dist/esm/co-color-area.entry.js +167 -0
  544. package/dist/esm/co-color-picker.entry.js +5 -5
  545. package/dist/esm/co-color-slider.entry.js +187 -0
  546. package/dist/esm/co-column-picker.entry.js +3 -3
  547. package/dist/esm/co-combobox.entry.js +5 -5
  548. package/dist/esm/co-command-search.entry.js +5 -5
  549. package/dist/esm/co-data-table-pagination.entry.js +5 -5
  550. package/dist/esm/co-data-table.entry.js +3 -3
  551. package/dist/esm/co-date-picker.entry.js +2 -2
  552. package/dist/esm/co-date-range-picker.entry.js +2 -2
  553. package/dist/esm/co-date-range.entry.js +2 -2
  554. package/dist/esm/co-date-time-picker.entry.js +4 -4
  555. package/dist/esm/co-document-editor.entry.js +1159 -0
  556. package/dist/esm/co-drive-card.entry.js +2 -2
  557. package/dist/esm/co-drop-zone.entry.js +2 -2
  558. package/dist/esm/co-emoji-picker.entry.js +3 -3
  559. package/dist/esm/co-empty-state.entry.js +3 -3
  560. package/dist/esm/co-event-calendar.entry.js +3 -3
  561. package/dist/esm/co-event-popover.entry.js +3 -3
  562. package/dist/esm/co-fab.entry.js +3 -3
  563. package/dist/esm/co-file-field.entry.js +8 -8
  564. package/dist/esm/co-file-type-tile.entry.js +3 -3
  565. package/dist/esm/co-gradient-bar.entry.js +218 -0
  566. package/dist/esm/co-helper-text.entry.js +3 -3
  567. package/dist/esm/co-icon-button.entry.js +49 -9
  568. package/dist/esm/co-icon.entry.js +3 -3
  569. package/dist/esm/co-input.entry.js +14 -8
  570. package/dist/esm/co-json-field.entry.js +5 -5
  571. package/dist/esm/{co-tooltip.entry.js → co-kbd_2.entry.js} +194 -7
  572. package/dist/esm/co-lightbox.entry.js +5 -5
  573. package/dist/esm/co-list-footer.entry.js +2 -2
  574. package/dist/esm/co-list-item.entry.js +5 -5
  575. package/dist/esm/co-loader.entry.js +1 -1
  576. package/dist/esm/co-media-thumb.entry.js +3 -3
  577. package/dist/esm/co-menu-divider.entry.js +3 -3
  578. package/dist/esm/co-menu-item.entry.js +39 -41
  579. package/dist/esm/co-menu.entry.js +81 -5
  580. package/dist/esm/co-modal.entry.js +350 -7
  581. package/dist/esm/co-navbar.entry.js +3 -3
  582. package/dist/esm/co-number-field.entry.js +5 -5
  583. package/dist/esm/co-overlay.entry.js +8 -4
  584. package/dist/esm/co-page-header.entry.js +2 -2
  585. package/dist/esm/co-phone-field.entry.js +3 -3
  586. package/dist/esm/co-popover.entry.js +67 -6
  587. package/dist/esm/co-progress-bar.entry.js +3 -3
  588. package/dist/esm/co-progress-circle.entry.js +3 -3
  589. package/dist/esm/co-provider-logo_2.entry.js +2 -2
  590. package/dist/esm/co-radio-group.entry.js +4 -4
  591. package/dist/esm/co-radio.entry.js +4 -4
  592. package/dist/esm/co-rating.entry.js +4 -4
  593. package/dist/esm/co-ref-field.entry.js +5 -5
  594. package/dist/esm/co-rich-text-editor.entry.js +26 -92
  595. package/dist/esm/co-rich-text-toolbar.entry.js +79 -20
  596. package/dist/esm/co-rich-text-viewer.entry.js +9 -2
  597. package/dist/esm/co-row.entry.js +3 -3
  598. package/dist/esm/co-segmented-bar.entry.js +3 -3
  599. package/dist/esm/co-select.entry.js +158 -29
  600. package/dist/esm/co-separator.entry.js +2 -2
  601. package/dist/esm/co-sidebar-nav.entry.js +20 -5
  602. package/dist/esm/co-sidebar.entry.js +3 -3
  603. package/dist/esm/co-slider.entry.js +203 -23
  604. package/dist/esm/co-swatch-grid.entry.js +119 -0
  605. package/dist/esm/co-switch.entry.js +5 -5
  606. package/dist/esm/co-tab-group.entry.js +113 -4
  607. package/dist/esm/co-tab.entry.js +15 -5
  608. package/dist/esm/co-tags-field.entry.js +8 -8
  609. package/dist/esm/co-textarea.entry.js +6 -6
  610. package/dist/esm/co-tile.entry.js +59 -0
  611. package/dist/esm/co-time-field.entry.js +2 -2
  612. package/dist/esm/co-toast.entry.js +3 -3
  613. package/dist/esm/co-toggle-button-group.entry.js +26 -5
  614. package/dist/esm/co-toggle-button.entry.js +67 -6
  615. package/dist/esm/co-transfer-list.entry.js +3 -3
  616. package/dist/esm/co-tree-item.entry.js +108 -0
  617. package/dist/esm/co-video.entry.js +3 -3
  618. package/dist/esm/cobalt.js +3 -3
  619. package/dist/esm/{color-BRbgGqLw.js → color-BVGGRfNG.js} +10 -6
  620. package/dist/esm/{fieldChip-uyggU8VV.js → fieldChip-B2ctp2m6.js} +1 -1
  621. package/dist/esm/gradientStops-DDK0y8ra.js +145 -0
  622. package/dist/esm/hsv-COJdaKBU.js +90 -0
  623. package/dist/esm/index-Cpo8HTwr.js +142 -0
  624. package/dist/esm/{index-DH5lfRNj.js → index-DJkaRtbb.js} +67 -28
  625. package/dist/esm/loader.js +3 -3
  626. package/dist/esm/{index-BBIYyvq-.js → pagination-D9OfZUnY.js} +1728 -297
  627. package/dist/esm/{positioning-DFHRS9cJ.js → positioning-BtliEQAT.js} +45 -19
  628. package/dist/esm/{requiredMark-BCJUuZvC.js → requiredMark-D5C5NzOE.js} +1 -1
  629. package/dist/esm/rich-text-host-BmdKHBZP.js +111 -0
  630. package/dist/esm/{richTextI18n-BYKAgwq3.js → richTextI18n-xnrKkNWQ.js} +45 -0
  631. package/dist/esm/submenu-DU-KOQ8L.js +57 -0
  632. package/dist/esm/{toolbar-config-BAYo-RBt.js → toolbar-config-CRxTFT_z.js} +32 -0
  633. package/dist/types/components/co-avatar/co-avatar.d.ts +4 -2
  634. package/dist/types/components/co-button/co-button.d.ts +6 -4
  635. package/dist/types/components/co-calendar/calendarMarks.d.ts +15 -0
  636. package/dist/types/components/co-calendar/co-calendar.d.ts +16 -0
  637. package/dist/types/components/co-checkbox/co-checkbox.d.ts +7 -0
  638. package/dist/types/components/co-color-area/co-color-area.d.ts +64 -0
  639. package/dist/types/components/co-color-slider/co-color-slider.d.ts +61 -0
  640. package/dist/types/components/co-date-time-picker/co-date-time-picker.d.ts +1 -1
  641. package/dist/types/components/co-document-editor/change-throttle.d.ts +9 -0
  642. package/dist/types/components/co-document-editor/co-document-editor.d.ts +276 -0
  643. package/dist/types/components/co-document-editor/document-props.d.ts +6 -0
  644. package/dist/types/components/co-document-editor/header-tools.d.ts +11 -0
  645. package/dist/types/components/co-document-editor/image-bar.d.ts +50 -0
  646. package/dist/types/components/co-document-editor/page-styles.d.ts +1 -0
  647. package/dist/types/components/co-document-editor/zoom.d.ts +26 -0
  648. package/dist/types/components/co-gradient-bar/co-gradient-bar.d.ts +72 -0
  649. package/dist/types/components/co-icon-button/co-icon-button.d.ts +34 -2
  650. package/dist/types/components/co-input/co-input.d.ts +14 -5
  651. package/dist/types/components/co-kbd/co-kbd.d.ts +43 -0
  652. package/dist/types/components/co-menu/co-menu.d.ts +40 -1
  653. package/dist/types/components/co-menu-item/co-menu-item.d.ts +17 -0
  654. package/dist/types/components/co-modal/co-modal.d.ts +111 -2
  655. package/dist/types/components/co-option-list/co-option-list.d.ts +1 -0
  656. package/dist/types/components/co-option-list/optionListLogic.d.ts +3 -0
  657. package/dist/types/components/co-popover/co-popover.d.ts +36 -0
  658. package/dist/types/components/co-rich-text-editor/co-rich-text-editor.d.ts +2 -5
  659. package/dist/types/components/co-rich-text-toolbar/co-rich-text-toolbar.d.ts +17 -2
  660. package/dist/types/components/co-select/co-select.d.ts +47 -5
  661. package/dist/types/components/co-select/virtualRows.d.ts +44 -0
  662. package/dist/types/components/co-slider/co-slider.d.ts +143 -1
  663. package/dist/types/components/co-swatch-grid/co-swatch-grid.d.ts +37 -0
  664. package/dist/types/components/co-tab/co-tab.d.ts +12 -2
  665. package/dist/types/components/co-tab-group/co-tab-group.d.ts +37 -0
  666. package/dist/types/components/co-tab-group/revealTab.d.ts +29 -0
  667. package/dist/types/components/co-tile/co-tile.d.ts +40 -0
  668. package/dist/types/components/co-toggle-button/co-toggle-button.d.ts +37 -2
  669. package/dist/types/components/co-toggle-button-group/co-toggle-button-group.d.ts +20 -2
  670. package/dist/types/components/co-tooltip/co-tooltip.d.ts +12 -0
  671. package/dist/types/components/co-tree-item/co-tree-item.d.ts +73 -0
  672. package/dist/types/components/co-tree-item/treeItemI18n.d.ts +6 -0
  673. package/dist/types/components.d.ts +1744 -88
  674. package/dist/types/utils/color.d.ts +9 -1
  675. package/dist/types/utils/dragMove.d.ts +63 -0
  676. package/dist/types/utils/gradientBarI18n.d.ts +8 -0
  677. package/dist/types/utils/gradientStops.d.ts +63 -0
  678. package/dist/types/utils/hsv.d.ts +44 -0
  679. package/dist/types/utils/kbdI18n.d.ts +25 -0
  680. package/dist/types/utils/positioning.d.ts +24 -0
  681. package/dist/types/utils/rich-text-host.d.ts +41 -0
  682. package/dist/types/utils/richTextI18n.d.ts +15 -0
  683. package/dist/types/utils/submenu.d.ts +16 -2
  684. package/dist/types/utils/swatchGridI18n.d.ts +6 -0
  685. package/dist/types/utils/test/fake-block-layout.d.ts +7 -0
  686. package/dist/types/utils/test/prosemirror-dom-shim.d.ts +1 -0
  687. package/dist/types/utils/test/shared-contract-css.d.ts +9 -0
  688. package/package.json +5 -5
  689. package/dist/cobalt/p-0678c797.entry.js +0 -1
  690. package/dist/cobalt/p-1d3a79af.entry.js +0 -1
  691. package/dist/cobalt/p-216a63ee.entry.js +0 -1
  692. package/dist/cobalt/p-3d31c575.entry.js +0 -1
  693. package/dist/cobalt/p-416795f5.entry.js +0 -1
  694. package/dist/cobalt/p-56551580.entry.js +0 -1
  695. package/dist/cobalt/p-58137c9e.entry.js +0 -1
  696. package/dist/cobalt/p-5a3e4c81.entry.js +0 -1
  697. package/dist/cobalt/p-5c756787.entry.js +0 -1
  698. package/dist/cobalt/p-67f3b9d6.entry.js +0 -1
  699. package/dist/cobalt/p-6a4f3179.entry.js +0 -1
  700. package/dist/cobalt/p-71cbc53c.entry.js +0 -1
  701. package/dist/cobalt/p-72e52af7.entry.js +0 -1
  702. package/dist/cobalt/p-8530ad16.entry.js +0 -1
  703. package/dist/cobalt/p-8a74bf7d.entry.js +0 -1
  704. package/dist/cobalt/p-8e05b979.entry.js +0 -1
  705. package/dist/cobalt/p-8ebc0c12.entry.js +0 -1
  706. package/dist/cobalt/p-8f2199ff.entry.js +0 -1
  707. package/dist/cobalt/p-9246e09c.entry.js +0 -1
  708. package/dist/cobalt/p-99a655f6.entry.js +0 -1
  709. package/dist/cobalt/p-BYKAgwq3.js +0 -1
  710. package/dist/cobalt/p-CJW9H3Gi.js +0 -1
  711. package/dist/cobalt/p-DFHRS9cJ.js +0 -1
  712. package/dist/cobalt/p-DH5lfRNj.js +0 -2
  713. package/dist/cobalt/p-a1b422ca.entry.js +0 -1
  714. package/dist/cobalt/p-ade07307.entry.js +0 -1
  715. package/dist/cobalt/p-b0762fd8.entry.js +0 -1
  716. package/dist/cobalt/p-b698188c.entry.js +0 -1
  717. package/dist/cobalt/p-bde32f8b.entry.js +0 -1
  718. package/dist/cobalt/p-db805569.entry.js +0 -1
  719. package/dist/cobalt/p-e3aae282.entry.js +0 -1
  720. package/dist/cobalt/p-e49a564c.entry.js +0 -1
  721. package/dist/cobalt/p-ef301976.entry.js +0 -1
  722. package/dist/cobalt/p-f4e1c3c3.entry.js +0 -1
  723. package/dist/cobalt/p-fMqVDypp.js +0 -1
  724. package/dist/components/p-2EOI1nrz.js +0 -1
  725. package/dist/components/p-7TncUlLN.js +0 -1
  726. package/dist/components/p-B4NCaKrR.js +0 -1
  727. package/dist/components/p-BJh68Jqe.js +0 -1
  728. package/dist/components/p-BrAFTkAn.js +0 -1
  729. package/dist/components/p-Bsh0JMGf.js +0 -1
  730. package/dist/components/p-CJW9H3Gi.js +0 -1
  731. package/dist/components/p-CWCYYQrF.js +0 -1
  732. package/dist/components/p-D9T7zKeL.js +0 -1
  733. package/dist/components/p-DFHRS9cJ.js +0 -1
  734. package/dist/components/p-DTPYZwaZ.js +0 -1
  735. package/dist/components/p-Dcg4krSX.js +0 -1
  736. package/dist/components/p-Dh8ffSjK.js +0 -1
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  var purify_es = require('./purify.es-DX41ZWS2.js');
4
- var toolbarConfig = require('./toolbar-config-CYACt9hh.js');
5
4
 
6
5
  // ::- Persistent data structure representing an ordered mapping from
7
6
  // strings to values, with some convenient update methods.
@@ -2657,7 +2656,7 @@ A DOM parser represents a strategy for parsing DOM content into a
2657
2656
  ProseMirror document conforming to a given schema. Its behavior is
2658
2657
  defined by an array of [rules](https://prosemirror.net/docs/ref/#model.ParseRule).
2659
2658
  */
2660
- class DOMParser {
2659
+ let DOMParser$1 = class DOMParser {
2661
2660
  /**
2662
2661
  Create a parser that targets the given schema, using the given
2663
2662
  parsing rules.
@@ -2808,7 +2807,7 @@ class DOMParser {
2808
2807
  return schema.cached.domParser ||
2809
2808
  (schema.cached.domParser = new DOMParser(schema, DOMParser.schemaRules(schema)));
2810
2809
  }
2811
- }
2810
+ };
2812
2811
  const blockTags = {
2813
2812
  address: true, article: true, aside: true, blockquote: true, canvas: true,
2814
2813
  dd: true, div: true, dl: true, fieldset: true, figcaption: true, figure: true,
@@ -10007,7 +10006,7 @@ function skipIgnoredNodesBefore(view) {
10007
10006
  break;
10008
10007
  }
10009
10008
  }
10010
- else if (isBlockNode(node)) {
10009
+ else if (isBlockNode$1(node)) {
10011
10010
  break;
10012
10011
  }
10013
10012
  else {
@@ -10055,7 +10054,7 @@ function skipIgnoredNodesAfter(view) {
10055
10054
  else
10056
10055
  break;
10057
10056
  }
10058
- else if (isBlockNode(node)) {
10057
+ else if (isBlockNode$1(node)) {
10059
10058
  break;
10060
10059
  }
10061
10060
  else {
@@ -10081,7 +10080,7 @@ function skipIgnoredNodesAfter(view) {
10081
10080
  if (moveNode)
10082
10081
  setSelFocus(view, moveNode, moveOffset);
10083
10082
  }
10084
- function isBlockNode(dom) {
10083
+ function isBlockNode$1(dom) {
10085
10084
  let desc = dom.pmViewDesc;
10086
10085
  return desc && desc.node && desc.node.isBlock;
10087
10086
  }
@@ -10361,7 +10360,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
10361
10360
  dom = child;
10362
10361
  }
10363
10362
  if (!slice) {
10364
- let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
10363
+ let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
10365
10364
  slice = parser.parseSlice(dom, {
10366
10365
  preserveWhitespace: !!(asText || sliceData),
10367
10366
  context: $context,
@@ -12462,7 +12461,7 @@ function parseBetween(view, from_, to_) {
12462
12461
  }
12463
12462
  }
12464
12463
  let startDoc = view.state.doc;
12465
- let parser = view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
12464
+ let parser = view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
12466
12465
  let $from = startDoc.resolve(from);
12467
12466
  let sel = null, doc = parser.parse(parent, {
12468
12467
  topNode: $from.parent,
@@ -14324,12 +14323,12 @@ function createNodeFromContent(content, schema, options) {
14324
14323
  })
14325
14324
  });
14326
14325
  if (options.slice) {
14327
- DOMParser.fromSchema(contentCheckSchema).parseSlice(
14326
+ DOMParser$1.fromSchema(contentCheckSchema).parseSlice(
14328
14327
  elementFromString(content),
14329
14328
  options.parseOptions
14330
14329
  );
14331
14330
  } else {
14332
- DOMParser.fromSchema(contentCheckSchema).parse(
14331
+ DOMParser$1.fromSchema(contentCheckSchema).parse(
14333
14332
  elementFromString(content),
14334
14333
  options.parseOptions
14335
14334
  );
@@ -14340,7 +14339,7 @@ function createNodeFromContent(content, schema, options) {
14340
14339
  });
14341
14340
  }
14342
14341
  }
14343
- const parser = DOMParser.fromSchema(schema);
14342
+ const parser = DOMParser$1.fromSchema(schema);
14344
14343
  if (options.slice) {
14345
14344
  return parser.parseSlice(elementFromString(content), options.parseOptions).content;
14346
14345
  }
@@ -34996,6 +34995,799 @@ var Subscript = Mark.create({
34996
34995
  }
34997
34996
  });
34998
34997
 
34998
+ function sanitizeFieldName(raw) {
34999
+ return String(raw ?? '')
35000
+ .trim()
35001
+ .replace(/\s+/g, '_')
35002
+ .replace(/[^\p{L}\p{N}_.]/gu, '_');
35003
+ }
35004
+ /** Admite un grupo `[…]` al final del contenido (enum en JSON). Nueva instancia por llamada (flag g). */
35005
+ function fieldTokenRegex() {
35006
+ return /\[\[\s*([^[\]]+?(?:\[[^[\]]*\])?)\s*\]\]/g;
35007
+ }
35008
+ function parseFieldToken(inner) {
35009
+ const parts = String(inner ?? '').split('|').map((p) => p.trim());
35010
+ let raw = parts[0] ?? '';
35011
+ const required = raw.endsWith('*');
35012
+ if (required)
35013
+ raw = raw.slice(0, -1);
35014
+ const name = sanitizeFieldName(raw);
35015
+ if (!name)
35016
+ return null;
35017
+ const type = parts[1] || 'string';
35018
+ let values = null;
35019
+ if (parts[2]?.startsWith('enum:')) {
35020
+ const rawEnum = parts[2].slice(5).trim();
35021
+ try {
35022
+ const parsed = JSON.parse(rawEnum);
35023
+ values = Array.isArray(parsed) ? parsed.map(String) : null;
35024
+ }
35025
+ catch {
35026
+ values = rawEnum.split(',').map((v) => v.trim()).filter(Boolean);
35027
+ }
35028
+ }
35029
+ return { name, required, type, enum: values };
35030
+ }
35031
+
35032
+ /** Meta de las transacciones que escribe el HOST (valores): no son edición del usuario. */
35033
+ const FIELD_SYNC_META = 'coFieldSync';
35034
+ function parseEnumAttr(raw) {
35035
+ if (!raw)
35036
+ return null;
35037
+ try {
35038
+ const v = JSON.parse(raw);
35039
+ return Array.isArray(v) ? v.map(String) : null;
35040
+ }
35041
+ catch {
35042
+ return null;
35043
+ }
35044
+ }
35045
+ /** Lista de campos en orden de primera aparición (sin repetidos). Acepta un doc de ProseMirror o su JSON. */
35046
+ function collectFields(doc, into = []) {
35047
+ const index = new Map(into.map((f, i) => [f.name, i]));
35048
+ const visit = (attrs) => {
35049
+ const name = attrs?.name;
35050
+ if (!name)
35051
+ return;
35052
+ const at = index.get(name);
35053
+ if (at === undefined) {
35054
+ index.set(name, into.length);
35055
+ into.push({ name, required: !!attrs.required, type: attrs.type || 'string', enum: attrs.enum ?? null });
35056
+ }
35057
+ else if (attrs.required) {
35058
+ into[at].required = true;
35059
+ }
35060
+ };
35061
+ if (typeof doc.descendants === 'function') {
35062
+ doc.descendants((node) => {
35063
+ if (node.type.name === 'mergeField') {
35064
+ visit(node.attrs);
35065
+ return false;
35066
+ }
35067
+ return true;
35068
+ });
35069
+ }
35070
+ else {
35071
+ const walk = (node) => {
35072
+ if (!node)
35073
+ return;
35074
+ if (node.type === 'mergeField')
35075
+ visit(node.attrs ?? {});
35076
+ node.content?.forEach(walk);
35077
+ };
35078
+ walk(doc);
35079
+ }
35080
+ return into;
35081
+ }
35082
+ /** Textblocks tocados por las transacciones (para no recorrer todo el doc por tecla). */
35083
+ function touchedTextblocks(transactions, state) {
35084
+ let ranges = [];
35085
+ transactions.forEach((tr) => {
35086
+ // Lo tocado por transacciones anteriores se lleva a las posiciones de ésta.
35087
+ ranges = ranges.map(([a, b]) => [tr.mapping.map(a, -1), tr.mapping.map(b, 1)]);
35088
+ if (!tr.docChanged)
35089
+ return;
35090
+ tr.mapping.maps.forEach((map, i) => {
35091
+ map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
35092
+ const rest = tr.mapping.slice(i + 1);
35093
+ ranges.push([rest.map(newStart, -1), rest.map(newEnd, 1)]);
35094
+ });
35095
+ });
35096
+ });
35097
+ const out = new Set();
35098
+ const size = state.doc.content.size;
35099
+ ranges.forEach(([from, to]) => {
35100
+ state.doc.nodesBetween(Math.max(0, from), Math.min(size, to), (node, pos) => {
35101
+ if (node.isTextblock) {
35102
+ out.add(pos);
35103
+ return false;
35104
+ }
35105
+ return true;
35106
+ });
35107
+ });
35108
+ return Array.from(out);
35109
+ }
35110
+ const MergeField = Node3.create({
35111
+ name: 'mergeField',
35112
+ group: 'inline',
35113
+ inline: true,
35114
+ atom: true,
35115
+ selectable: true,
35116
+ addOptions() {
35117
+ return { renameLabel: 'Field name' };
35118
+ },
35119
+ addAttributes() {
35120
+ return {
35121
+ name: { default: '', parseHTML: (el) => el.getAttribute('data-variable') || '', rendered: false },
35122
+ value: { default: '', parseHTML: (el) => el.getAttribute('data-value') ?? '', rendered: false },
35123
+ required: { default: false, parseHTML: (el) => el.getAttribute('data-required') === 'true', rendered: false },
35124
+ type: { default: 'string', parseHTML: (el) => el.getAttribute('data-type') || 'string', rendered: false },
35125
+ enum: { default: null, parseHTML: (el) => parseEnumAttr(el.getAttribute('data-enum')), rendered: false },
35126
+ };
35127
+ },
35128
+ // Prioridad 100: gana a las marcas `span[style]` (color/tamaño), como en V1.
35129
+ parseHTML() {
35130
+ return [{ tag: 'span[data-variable]', priority: 100 }];
35131
+ },
35132
+ // Forma canónica (spec §3.4): SIN estilos (D9), atributos en orden fijo.
35133
+ renderHTML({ node }) {
35134
+ const { name, value, type, required } = node.attrs;
35135
+ const attrs = {
35136
+ class: 'variable-node',
35137
+ 'data-variable': name,
35138
+ 'data-value': value ?? '',
35139
+ 'data-type': type || 'string',
35140
+ 'data-required': required ? 'true' : 'false',
35141
+ };
35142
+ if (node.attrs.enum)
35143
+ attrs['data-enum'] = JSON.stringify(node.attrs.enum);
35144
+ attrs.contenteditable = 'false';
35145
+ return ['span', attrs, value || `[[${name}]]`];
35146
+ },
35147
+ renderText({ node }) {
35148
+ return node.attrs.value || `[[${node.attrs.name}]]`;
35149
+ },
35150
+ addNodeView() {
35151
+ const renameLabel = this.options.renameLabel;
35152
+ return ({ node, getPos, editor }) => {
35153
+ const dom = document.createElement('span');
35154
+ dom.className = 'co-doc-field';
35155
+ dom.contentEditable = 'false';
35156
+ let current = node;
35157
+ let editing = false;
35158
+ const paint = (n) => {
35159
+ dom.textContent = n.attrs.value || `[[${n.attrs.name}]]`;
35160
+ dom.classList.toggle('co-doc-field--empty', !n.attrs.value);
35161
+ dom.classList.toggle('co-doc-field--required', !!n.attrs.required);
35162
+ dom.setAttribute('data-variable', n.attrs.name);
35163
+ };
35164
+ const startRename = () => {
35165
+ if (editing || !editor.isEditable)
35166
+ return;
35167
+ editing = true;
35168
+ const input = document.createElement('input');
35169
+ input.className = 'co-doc-field__input';
35170
+ input.value = current.attrs.name;
35171
+ input.setAttribute('aria-label', renameLabel);
35172
+ dom.textContent = '';
35173
+ dom.appendChild(input);
35174
+ input.focus();
35175
+ input.select();
35176
+ let done = false;
35177
+ const finish = (commit) => {
35178
+ if (done)
35179
+ return;
35180
+ done = true;
35181
+ editing = false;
35182
+ const next = sanitizeFieldName(input.value);
35183
+ const pos = typeof getPos === 'function' ? getPos() : undefined;
35184
+ if (commit && next && next !== current.attrs.name && typeof pos === 'number') {
35185
+ // Como V1: el campo renombrado arranca vacío (solo ESTE nodo).
35186
+ editor.view.dispatch(editor.state.tr.setNodeMarkup(pos, undefined, { ...current.attrs, name: next, value: '' }));
35187
+ }
35188
+ else {
35189
+ paint(current);
35190
+ }
35191
+ };
35192
+ input.addEventListener('keydown', (ev) => {
35193
+ ev.stopPropagation(); // Esc no debe cerrar el overlay del host
35194
+ if (ev.key === 'Enter') {
35195
+ ev.preventDefault();
35196
+ finish(true);
35197
+ }
35198
+ else if (ev.key === 'Escape') {
35199
+ ev.preventDefault();
35200
+ finish(false);
35201
+ }
35202
+ });
35203
+ input.addEventListener('blur', () => finish(false));
35204
+ };
35205
+ dom.addEventListener('dblclick', (ev) => {
35206
+ ev.preventDefault();
35207
+ startRename();
35208
+ });
35209
+ paint(node);
35210
+ return {
35211
+ dom,
35212
+ update(next) {
35213
+ if (next.type.name !== 'mergeField')
35214
+ return false;
35215
+ current = next;
35216
+ if (!editing)
35217
+ paint(next);
35218
+ return true;
35219
+ },
35220
+ stopEvent: (ev) => ev.target instanceof HTMLInputElement,
35221
+ ignoreMutation: () => true,
35222
+ };
35223
+ };
35224
+ },
35225
+ addCommands() {
35226
+ return {
35227
+ insertField: (name, opts = {}) => ({ commands }) => {
35228
+ const clean = sanitizeFieldName(name);
35229
+ if (!clean)
35230
+ return false;
35231
+ return commands.insertContent({
35232
+ type: this.name,
35233
+ attrs: {
35234
+ name: clean,
35235
+ value: opts.value ?? '',
35236
+ required: !!opts.required,
35237
+ type: opts.type || 'string',
35238
+ enum: opts.enum ?? null,
35239
+ },
35240
+ });
35241
+ },
35242
+ setFieldValues: (values) => ({ tr, state, dispatch }) => {
35243
+ let changed = false;
35244
+ state.doc.descendants((node, pos) => {
35245
+ if (node.type.name !== this.name)
35246
+ return true;
35247
+ if (!Object.prototype.hasOwnProperty.call(values, node.attrs.name))
35248
+ return false;
35249
+ const next = String(values[node.attrs.name] ?? '');
35250
+ if (next !== node.attrs.value) {
35251
+ changed = true;
35252
+ if (dispatch)
35253
+ tr.setNodeMarkup(pos, undefined, { ...node.attrs, value: next });
35254
+ }
35255
+ return false;
35256
+ });
35257
+ if (!changed)
35258
+ return false;
35259
+ if (dispatch) {
35260
+ tr.setMeta(FIELD_SYNC_META, true);
35261
+ tr.setMeta('addToHistory', false);
35262
+ }
35263
+ return true;
35264
+ },
35265
+ renameField: (from, to) => ({ tr, state, dispatch }) => {
35266
+ const clean = sanitizeFieldName(to);
35267
+ if (!clean || clean === from)
35268
+ return false; // renombrar a sí mismo borraría los valores
35269
+ let changed = false;
35270
+ state.doc.descendants((node, pos) => {
35271
+ if (node.type.name !== this.name)
35272
+ return true;
35273
+ if (node.attrs.name === from) {
35274
+ changed = true;
35275
+ if (dispatch)
35276
+ tr.setNodeMarkup(pos, undefined, { ...node.attrs, name: clean, value: '' });
35277
+ }
35278
+ return false;
35279
+ });
35280
+ return changed;
35281
+ },
35282
+ };
35283
+ },
35284
+ addProseMirrorPlugins() {
35285
+ const type = this.type;
35286
+ return [
35287
+ new Plugin({
35288
+ key: new PluginKey('coMergeFieldTokens'),
35289
+ // Convierte `[[…]]` escritos o pegados en campos, solo en los textblocks tocados.
35290
+ appendTransaction: (transactions, _old, state) => {
35291
+ if (!transactions.some((t) => t.docChanged && !t.getMeta(FIELD_SYNC_META)))
35292
+ return null;
35293
+ const blocks = touchedTextblocks(transactions, state);
35294
+ if (!blocks.length)
35295
+ return null;
35296
+ const hits = [];
35297
+ blocks.forEach((blockPos) => {
35298
+ const block = state.doc.nodeAt(blockPos);
35299
+ if (!block || block.type.spec.code)
35300
+ return;
35301
+ block.forEach((child, offset) => {
35302
+ if (!child.isText || !child.text || !child.text.includes('[['))
35303
+ return;
35304
+ const re = fieldTokenRegex();
35305
+ let m;
35306
+ while ((m = re.exec(child.text)) !== null) {
35307
+ const def = parseFieldToken(m[1]);
35308
+ if (!def)
35309
+ continue;
35310
+ const from = blockPos + 1 + offset + m.index;
35311
+ hits.push({ from, to: from + m[0].length, def });
35312
+ }
35313
+ });
35314
+ });
35315
+ if (!hits.length)
35316
+ return null;
35317
+ const tr = state.tr;
35318
+ hits
35319
+ .sort((a, b) => b.from - a.from)
35320
+ .forEach(({ from, to, def }) => {
35321
+ tr.replaceWith(from, to, type.create({ ...def, value: '' }));
35322
+ });
35323
+ return tr;
35324
+ },
35325
+ }),
35326
+ ];
35327
+ },
35328
+ });
35329
+
35330
+ /**
35331
+ * Marcador de firma `⟦sig:N⟧`. La forma canónica es la de V1
35332
+ * (tiptap-editor-html/utils/normalizeSignatureSlots.js) byte a byte: pdf.js lee
35333
+ * el token transparente de la capa de texto del PDF y deriva la posición.
35334
+ * Con font-size:1px Chromium colapsaba glifos: el token va a 8px y transparente.
35335
+ *
35336
+ * ⚠️ `editor.getHTML()` NO es la forma canónica: el DOMSerializer de ProseMirror
35337
+ * escribe `style` por CSSOM (`top:0` → `top: 0px;`). La forma exacta sale de
35338
+ * `signatureSlotHtml()` o de un serializador que escriba `style` con `setAttribute`
35339
+ * (`serializePrintHtml`).
35340
+ */
35341
+ const signatureToken = (n) => `⟦sig:${n}⟧`;
35342
+ const SIGNATURE_TOKEN_STYLE = 'position:absolute;top:0;left:0;color:transparent;font-size:8px;line-height:1;white-space:nowrap;pointer-events:none;user-select:none';
35343
+ const signatureBoxStyle = (w, h) => `display:inline-block;position:relative;width:${w}px;height:${h}px;vertical-align:top`;
35344
+ const SIGNATURE_DEFAULT_W = 150;
35345
+ const SIGNATURE_DEFAULT_H = 50;
35346
+ function nextFreeSlot(used = []) {
35347
+ const taken = new Set(used);
35348
+ let n = 1;
35349
+ while (taken.has(n))
35350
+ n += 1;
35351
+ return n;
35352
+ }
35353
+ /** Spec de la forma canónica (orden de atributos = el de V1). Lo usa `renderHTML`. */
35354
+ function signatureSlotSpec({ slot, w, h }) {
35355
+ return [
35356
+ 'span',
35357
+ {
35358
+ 'data-sig-slot': String(slot),
35359
+ 'data-w': String(w),
35360
+ 'data-h': String(h),
35361
+ contenteditable: 'false',
35362
+ style: signatureBoxStyle(w, h),
35363
+ },
35364
+ ['span', { style: SIGNATURE_TOKEN_STYLE }, signatureToken(slot)],
35365
+ ];
35366
+ }
35367
+ /**
35368
+ * La forma canónica como string, armada del MISMO spec que `renderHTML` y sin pasar
35369
+ * por CSSOM. Los valores son números y constantes propias: no hay nada que escapar.
35370
+ */
35371
+ function signatureSlotHtml(attrs) {
35372
+ const [tag, boxAttrs, [innerTag, innerAttrs, text]] = signatureSlotSpec(attrs);
35373
+ const attrsOf = (a) => Object.entries(a)
35374
+ .map(([k, v]) => ` ${k}="${v}"`)
35375
+ .join('');
35376
+ return `<${tag}${attrsOf(boxAttrs)}><${innerTag}${attrsOf(innerAttrs)}>${text}</${innerTag}></${tag}>`;
35377
+ }
35378
+ const toInt = (v, fallback) => {
35379
+ const n = parseInt(v ?? '', 10);
35380
+ return Number.isFinite(n) && n > 0 ? n : fallback;
35381
+ };
35382
+ const SignatureSlot = Node3.create({
35383
+ name: 'signatureSlot',
35384
+ group: 'inline',
35385
+ inline: true,
35386
+ atom: true,
35387
+ selectable: true,
35388
+ addOptions() {
35389
+ return { label: (slot) => `Signature ${slot}` };
35390
+ },
35391
+ addAttributes() {
35392
+ return {
35393
+ slot: { default: 1, parseHTML: (el) => toInt(el.getAttribute('data-sig-slot'), 1), rendered: false },
35394
+ w: { default: SIGNATURE_DEFAULT_W, parseHTML: (el) => toInt(el.getAttribute('data-w'), SIGNATURE_DEFAULT_W), rendered: false },
35395
+ h: { default: SIGNATURE_DEFAULT_H, parseHTML: (el) => toInt(el.getAttribute('data-h'), SIGNATURE_DEFAULT_H), rendered: false },
35396
+ };
35397
+ },
35398
+ parseHTML() {
35399
+ return [{ tag: 'span[data-sig-slot]', priority: 100 }];
35400
+ },
35401
+ renderHTML({ node }) {
35402
+ return signatureSlotSpec(node.attrs);
35403
+ },
35404
+ renderText({ node }) {
35405
+ return signatureToken(node.attrs.slot);
35406
+ },
35407
+ addNodeView() {
35408
+ const label = this.options.label;
35409
+ return ({ node }) => {
35410
+ const dom = document.createElement('span');
35411
+ dom.className = 'co-doc-signature';
35412
+ dom.contentEditable = 'false';
35413
+ const paint = (n) => {
35414
+ dom.style.width = `${n.attrs.w}px`;
35415
+ dom.style.height = `${n.attrs.h}px`;
35416
+ dom.textContent = label(n.attrs.slot);
35417
+ dom.setAttribute('data-sig-slot', String(n.attrs.slot));
35418
+ };
35419
+ paint(node);
35420
+ return {
35421
+ dom,
35422
+ update(next) {
35423
+ if (next.type.name !== 'signatureSlot')
35424
+ return false;
35425
+ paint(next);
35426
+ return true;
35427
+ },
35428
+ ignoreMutation: () => true,
35429
+ };
35430
+ };
35431
+ },
35432
+ addCommands() {
35433
+ return {
35434
+ insertSignatureSlot: (size = {}) => ({ state, commands }) => {
35435
+ const used = [];
35436
+ state.doc.descendants((n) => {
35437
+ if (n.type.name === this.name)
35438
+ used.push(n.attrs.slot);
35439
+ });
35440
+ return commands.insertContent({
35441
+ type: this.name,
35442
+ attrs: { slot: nextFreeSlot(used), w: size.w ?? SIGNATURE_DEFAULT_W, h: size.h ?? SIGNATURE_DEFAULT_H },
35443
+ });
35444
+ },
35445
+ };
35446
+ },
35447
+ });
35448
+
35449
+ /** Tamaño base del cuerpo de impresión (SharedContractUtils: 14px/1.5). */
35450
+ const BASE_FONT_PX = 14;
35451
+ /** Valor crudo de una propiedad del atributo style (conserva `#hex`; `el.style.color` lo pasaría a rgb). */
35452
+ function rawStyleValue(el, prop) {
35453
+ const style = el.getAttribute('style') || '';
35454
+ for (const decl of style.split(';')) {
35455
+ const i = decl.indexOf(':');
35456
+ if (i <= 0)
35457
+ continue;
35458
+ if (decl.slice(0, i).trim().toLowerCase() === prop) {
35459
+ const v = decl.slice(i + 1).trim();
35460
+ return v || null;
35461
+ }
35462
+ }
35463
+ return null;
35464
+ }
35465
+ /** V1 pasaba mal las unidades (12pt → 12px, 1.5em → 1px). Acá se convierten a px de verdad. */
35466
+ function normalizeFontSizePx(v) {
35467
+ if (v == null)
35468
+ return null;
35469
+ const m = /^\s*(\d+(?:\.\d+)?)\s*(px|pt|em|rem|%)?\s*$/i.exec(String(v));
35470
+ if (!m)
35471
+ return null;
35472
+ const n = parseFloat(m[1]);
35473
+ const unit = (m[2] || 'px').toLowerCase();
35474
+ const px = unit === 'px' ? n : unit === 'pt' ? (n * 4) / 3 : unit === '%' ? (n / 100) * BASE_FONT_PX : n * BASE_FONT_PX;
35475
+ const r = Math.round(px);
35476
+ return r >= 1 && r <= 400 ? `${r}px` : null;
35477
+ }
35478
+ /**
35479
+ * Color de texto en la forma de V1: `<span class="editor-text-style" style="color: X">`,
35480
+ * SIEMPRE por fuera del tamaño (un span con color + tamaño pierde el color en V1).
35481
+ * Se llama `textStyle` para que la barra lea `getAttributes('textStyle').color`.
35482
+ * Prioridad alta = marca más externa (link 1003 > color 1002 > tamaño 1001 > resto 100).
35483
+ *
35484
+ * La regla de parse queda con la prioridad por defecto (50): la firma
35485
+ * (`span[data-sig-slot]`) y el campo (`span[data-variable]`) van a 100 y le ganan
35486
+ * aunque lleven `style` inline.
35487
+ */
35488
+ const PrintTextColor = Mark.create({
35489
+ name: 'textStyle',
35490
+ priority: 1002,
35491
+ addAttributes() {
35492
+ return {
35493
+ color: { default: null, parseHTML: (el) => rawStyleValue(el, 'color'), rendered: false },
35494
+ };
35495
+ },
35496
+ parseHTML() {
35497
+ return [{ tag: 'span', consuming: false, getAttrs: (el) => (rawStyleValue(el, 'color') ? {} : false) }];
35498
+ },
35499
+ renderHTML({ mark }) {
35500
+ return ['span', { class: 'editor-text-style', style: `color: ${mark.attrs.color}` }, 0];
35501
+ },
35502
+ addCommands() {
35503
+ return {
35504
+ setColor: (color) => ({ commands }) => commands.setMark(this.name, { color }),
35505
+ unsetColor: () => ({ commands }) => commands.unsetMark(this.name),
35506
+ };
35507
+ },
35508
+ });
35509
+ /** Tamaño en px como marca APARTE, anidada dentro del color: `<span style="font-size: Npx">`. */
35510
+ const PrintFontSize = Mark.create({
35511
+ name: 'printFontSize',
35512
+ priority: 1001,
35513
+ addAttributes() {
35514
+ return {
35515
+ size: { default: null, parseHTML: (el) => normalizeFontSizePx(rawStyleValue(el, 'font-size')), rendered: false },
35516
+ };
35517
+ },
35518
+ parseHTML() {
35519
+ return [{ tag: 'span', consuming: false, getAttrs: (el) => (normalizeFontSizePx(rawStyleValue(el, 'font-size')) ? {} : false) }];
35520
+ },
35521
+ renderHTML({ mark }) {
35522
+ return ['span', { style: `font-size: ${mark.attrs.size}` }, 0];
35523
+ },
35524
+ addCommands() {
35525
+ return {
35526
+ setFontSize: (size) => ({ commands }) => {
35527
+ const px = normalizeFontSizePx(size);
35528
+ return px ? commands.setMark(this.name, { size: px }) : false;
35529
+ },
35530
+ unsetFontSize: () => ({ commands }) => commands.unsetMark(this.name),
35531
+ };
35532
+ },
35533
+ });
35534
+
35535
+ const IMAGE_LAYOUT_MODES = ['inline', 'wrap-left', 'wrap-right', 'break'];
35536
+ const MODE_PROPS = new Set(['float', 'clear', 'display', 'padding-left', 'padding-right']);
35537
+ const MODE_STYLES = {
35538
+ inline: { wrapper: ['display: inline-block'], container: ['display: inline-block'] },
35539
+ 'wrap-left': { wrapper: ['display: inline-block', 'float: left'], container: ['display: inline-block', 'float: left', 'padding-right: 8px'] },
35540
+ 'wrap-right': { wrapper: ['display: inline-block', 'float: right'], container: ['display: inline-block', 'float: right', 'padding-left: 8px'] },
35541
+ break: { wrapper: ['display: block'], container: ['display: block'] },
35542
+ };
35543
+ /** Una imagen nueva nace en línea (ruling del ledger); al leer una de V1 manda su wrapperstyle. */
35544
+ const DEFAULT_WRAPPER_STYLE = 'display: inline-block;';
35545
+ const DEFAULT_CONTAINER_STYLE = 'height: auto; cursor: pointer; display: inline-block;';
35546
+ function stripModeProps(style) {
35547
+ return String(style || '')
35548
+ .split(';')
35549
+ .map((d) => d.trim())
35550
+ .filter((d) => d.includes(':'))
35551
+ .filter((d) => !MODE_PROPS.has(d.slice(0, d.indexOf(':')).trim().toLowerCase()));
35552
+ }
35553
+ function applyImageLayoutMode(mode, { wrapperStyle = '', containerStyle = '' } = {}) {
35554
+ const preset = MODE_STYLES[mode];
35555
+ if (!preset)
35556
+ return { wrapperStyle: wrapperStyle || '', containerStyle: containerStyle || '' };
35557
+ const join = (mods, rest) => [...mods, ...rest].join('; ').replace(/;?\s*$/, ';');
35558
+ return {
35559
+ wrapperStyle: join(preset.wrapper, stripModeProps(wrapperStyle || '')),
35560
+ containerStyle: join(preset.container, stripModeProps(containerStyle || '')),
35561
+ };
35562
+ }
35563
+ function getImageLayoutMode({ wrapperStyle = '', containerStyle = '' } = {}) {
35564
+ const style = `${containerStyle || ''};${wrapperStyle || ''}`.toLowerCase();
35565
+ if (/float:\s*left/.test(style))
35566
+ return 'wrap-left';
35567
+ if (/float:\s*right/.test(style))
35568
+ return 'wrap-right';
35569
+ if (/display:\s*block\b/.test(style))
35570
+ return 'break';
35571
+ return 'inline';
35572
+ }
35573
+ const HEADER_IMG_MAX = { w: 400, h: 40 };
35574
+ /** Ancho que entra en la banda del encabezado (port de headerContainerStyle de V1). */
35575
+ function headerImageWidth(dims, max = HEADER_IMG_MAX) {
35576
+ if (!dims || !dims.w || !dims.h)
35577
+ return null;
35578
+ const scale = Math.min(1, max.h / dims.h, max.w / dims.w);
35579
+ return Math.max(1, Math.round(dims.w * scale));
35580
+ }
35581
+ /**
35582
+ * `width:` anclado a inicio de declaración: sin el ancla, `min-width`/`max-width` también
35583
+ * matchean y se leía (y se pisaba) el ancho equivocado de un `containerstyle` de V1.
35584
+ */
35585
+ const WIDTH_DECL = /(^|;)(\s*)width:\s*([0-9.]+)px/i;
35586
+ function withWidth(style, width) {
35587
+ if (!width)
35588
+ return style;
35589
+ const decl = `width: ${width}px`;
35590
+ return WIDTH_DECL.test(style)
35591
+ ? style.replace(WIDTH_DECL, (_m, sep, ws) => `${sep}${ws}${decl}`)
35592
+ : `${decl}; ${style}`.trim();
35593
+ }
35594
+ function parseWidth(el) {
35595
+ const attr = parseInt(el.getAttribute('width') || '', 10);
35596
+ if (attr > 0)
35597
+ return attr;
35598
+ const m = WIDTH_DECL.exec(el.getAttribute('containerstyle') || el.getAttribute('style') || '');
35599
+ return m ? Math.round(parseFloat(m[3])) : null;
35600
+ }
35601
+ /**
35602
+ * H10: el node view de resize de Tiptap solo copia los atributos RENDERIZADOS, y
35603
+ * `wrapperStyle`/`containerStyle` no lo son → en el editor toda imagen se veía en línea.
35604
+ * Se lleva el modo al contenedor (`[data-resize-container]`) para que la hoja pagine
35605
+ * como el PDF. `inline-flex`/`flex` (no `inline-block`/`block`): el contenedor de
35606
+ * resize los necesita para ubicar las manijas.
35607
+ */
35608
+ function syncImageModeToContainer(container, node) {
35609
+ const mode = getImageLayoutMode(node.attrs);
35610
+ container.dataset.imageLayout = mode;
35611
+ container.style.float = mode === 'wrap-left' ? 'left' : mode === 'wrap-right' ? 'right' : '';
35612
+ container.style.paddingLeft = mode === 'wrap-right' ? '8px' : '';
35613
+ container.style.paddingRight = mode === 'wrap-left' ? '8px' : '';
35614
+ container.style.display = mode === 'break' ? 'flex' : 'inline-flex';
35615
+ }
35616
+ const PrintImage = Image.extend({
35617
+ name: 'image',
35618
+ addOptions() {
35619
+ return { ...this.parent?.(), header: false };
35620
+ },
35621
+ addAttributes() {
35622
+ return {
35623
+ ...this.parent?.(),
35624
+ width: { default: null, parseHTML: (el) => parseWidth(el), rendered: false },
35625
+ dataFileId: { default: null, parseHTML: (el) => el.getAttribute('data-file-id'), rendered: false },
35626
+ containerStyle: { default: null, parseHTML: (el) => el.getAttribute('containerstyle'), rendered: false },
35627
+ wrapperStyle: { default: null, parseHTML: (el) => el.getAttribute('wrapperstyle'), rendered: false },
35628
+ };
35629
+ },
35630
+ parseHTML() {
35631
+ return [{ tag: this.options.allowBase64 ? 'img[src]' : 'img[src]:not([src^="data:"])', priority: 100 }];
35632
+ },
35633
+ renderHTML({ node }) {
35634
+ const a = node.attrs;
35635
+ const width = a.width ? Math.round(Number(a.width)) : null;
35636
+ const wrapper = a.wrapperStyle || DEFAULT_WRAPPER_STYLE;
35637
+ const container = withWidth(a.containerStyle || DEFAULT_CONTAINER_STYLE, width);
35638
+ const img = { src: a.src };
35639
+ if (a.alt)
35640
+ img.alt = a.alt;
35641
+ if (a.title)
35642
+ img.title = a.title;
35643
+ if (a.dataFileId)
35644
+ img['data-file-id'] = String(a.dataFileId);
35645
+ if (width) {
35646
+ img.width = String(width);
35647
+ img.style = this.options.header ? `width: ${width}px; height: auto;` : `width: ${width}px;`;
35648
+ }
35649
+ img.containerstyle = container;
35650
+ img.wrapperstyle = wrapper;
35651
+ return ['span', { style: wrapper }, ['img', img]];
35652
+ },
35653
+ addNodeView() {
35654
+ const parent = this.parent?.();
35655
+ if (!parent)
35656
+ return null;
35657
+ return (props) => {
35658
+ const view = parent(props);
35659
+ const container = view.dom;
35660
+ syncImageModeToContainer(container, props.node);
35661
+ const update = view.update?.bind(view);
35662
+ view.update = (node, decorations, inner) => {
35663
+ const ok = update ? update(node, decorations, inner) : node.type === props.node.type;
35664
+ if (ok)
35665
+ syncImageModeToContainer(container, node);
35666
+ return ok;
35667
+ };
35668
+ return view;
35669
+ };
35670
+ },
35671
+ addCommands() {
35672
+ return {
35673
+ ...this.parent?.(),
35674
+ setImageLayoutMode: (mode) => ({ state, tr, dispatch }) => {
35675
+ const sel = state.selection;
35676
+ if (!(sel instanceof NodeSelection) || sel.node.type.name !== this.name)
35677
+ return false;
35678
+ if (dispatch) {
35679
+ const next = applyImageLayoutMode(mode, {
35680
+ wrapperStyle: sel.node.attrs.wrapperStyle || DEFAULT_WRAPPER_STYLE,
35681
+ containerStyle: withWidth(sel.node.attrs.containerStyle || DEFAULT_CONTAINER_STYLE, sel.node.attrs.width),
35682
+ });
35683
+ tr.setNodeMarkup(sel.from, undefined, { ...sel.node.attrs, ...next });
35684
+ // H7: la NodeSelection no sobrevive al reemplazo de la hoja; sin esto la barra de imagen se cierra.
35685
+ tr.setSelection(NodeSelection.create(tr.doc, sel.from));
35686
+ }
35687
+ return true;
35688
+ },
35689
+ };
35690
+ },
35691
+ });
35692
+
35693
+ /** Validación de V1 (tiptap-editor-html/extensions/index.js): exige un `.`, rechaza `/` y `./`. */
35694
+ const printLinkAllowed = (url, ctx) => ctx.defaultValidate(url) && !url.startsWith('./') && !url.startsWith('/') && url.includes('.');
35695
+ /** Autolink APAGADO: generaba `<a>` dentro de `{{ }}` y rompía Handlebars. Prioridad 1003 = marca más externa. */
35696
+ const PrintLink = Link.extend({ inclusive: () => false, priority: 1003 }).configure({
35697
+ autolink: false,
35698
+ openOnClick: false,
35699
+ defaultProtocol: 'https',
35700
+ protocols: ['mailto', { scheme: 'tel', optionalSlashes: true }],
35701
+ HTMLAttributes: { target: '_blank', rel: 'noopener noreferrer', class: 'editor-link' },
35702
+ isAllowedUri: printLinkAllowed,
35703
+ });
35704
+
35705
+ /** Resalta `{{ … }}` con una DECORACIÓN: no toca el documento ni se serializa. */
35706
+ const HB_RE = /\{\{[^}]*\}\}/g;
35707
+ function build(doc) {
35708
+ const decos = [];
35709
+ doc.descendants((node, pos) => {
35710
+ if (!node.isText || !node.text)
35711
+ return true;
35712
+ HB_RE.lastIndex = 0;
35713
+ let m;
35714
+ while ((m = HB_RE.exec(node.text)) !== null) {
35715
+ decos.push(Decoration.inline(pos + m.index, pos + m.index + m[0].length, { class: 'co-doc-hb' }));
35716
+ }
35717
+ return true;
35718
+ });
35719
+ return DecorationSet.create(doc, decos);
35720
+ }
35721
+ const HandlebarsHighlight = Extension.create({
35722
+ name: 'handlebarsHighlight',
35723
+ addProseMirrorPlugins() {
35724
+ const key = new PluginKey('coHandlebarsHighlight');
35725
+ return [
35726
+ new Plugin({
35727
+ key,
35728
+ state: {
35729
+ init: (_config, { doc }) => build(doc),
35730
+ apply: (tr, old) => (tr.docChanged ? build(tr.doc) : old),
35731
+ },
35732
+ props: {
35733
+ decorations(state) {
35734
+ return key.getState(state);
35735
+ },
35736
+ },
35737
+ }),
35738
+ ];
35739
+ },
35740
+ });
35741
+
35742
+ /**
35743
+ * Presets `print` (cuerpo) y `print-header` (banda). Paridad ESTRICTA de
35744
+ * funciones de V1 (spec §3.5/§3.6, D7): sin subrayado, familia, peso,
35745
+ * interlineado, espaciado ni sangría; autolink apagado; sin nodo `variable`
35746
+ * (comparte selector `span[data-variable]` con el campo). `trailingNode` apagado:
35747
+ * V1 no lo tenía y una tabla al final sumaría una línea vacía al PDF.
35748
+ * Las etiquetas (`labels`) las localiza el host; sin ellas quedan en inglés.
35749
+ */
35750
+ function getPrintExtensions(preset, opts = {}) {
35751
+ const header = preset === 'print-header';
35752
+ const { features = {}, labels = {} } = opts;
35753
+ const starter = { underline: false, link: false, trailingNode: false };
35754
+ if (header) {
35755
+ Object.assign(starter, {
35756
+ heading: false, bulletList: false, orderedList: false, listItem: false, listKeymap: false,
35757
+ blockquote: false, codeBlock: false, horizontalRule: false,
35758
+ });
35759
+ }
35760
+ else {
35761
+ starter.heading = { levels: [1, 2, 3, 4] };
35762
+ }
35763
+ const exts = [
35764
+ StarterKit.configure(starter),
35765
+ PrintTextColor,
35766
+ PrintFontSize,
35767
+ Highlight.configure({ multicolor: true }),
35768
+ TextAlign.configure({ types: header ? ['paragraph'] : ['heading', 'paragraph'] }),
35769
+ HandlebarsHighlight,
35770
+ ];
35771
+ if (!header) {
35772
+ exts.push(PrintLink, Table.configure({ resizable: true, renderWrapper: true }), TableRow, TableHeader, TableCell);
35773
+ }
35774
+ exts.push(PrintImage.configure({
35775
+ inline: true,
35776
+ allowBase64: true,
35777
+ header,
35778
+ resize: header
35779
+ ? false
35780
+ : { enabled: true, directions: ['left', 'right', 'bottom-left', 'bottom-right'], minWidth: 50, minHeight: 20, alwaysPreserveAspectRatio: true },
35781
+ }));
35782
+ if (features.fields !== false) {
35783
+ exts.push(MergeField.configure({ renameLabel: labels.fieldName ?? 'Field name' }));
35784
+ }
35785
+ if (!header && features.signatureSlots !== false) {
35786
+ exts.push(labels.signature ? SignatureSlot.configure({ label: labels.signature }) : SignatureSlot);
35787
+ }
35788
+ return exts;
35789
+ }
35790
+
34999
35791
  /** Shared link configuration — never auto-opens inside the editor, safe rel. */
35000
35792
  const LINK_CONFIG = {
35001
35793
  openOnClick: false,
@@ -35074,6 +35866,8 @@ const PRESET_TOOLBAR = {
35074
35866
  email: 'full',
35075
35867
  document: 'full',
35076
35868
  'block-email': 'basic',
35869
+ print: 'document',
35870
+ 'print-header': 'document',
35077
35871
  };
35078
35872
  /** Suggested max length per preset (null = no limit). */
35079
35873
  const PRESET_MAXLENGTH = {
@@ -35083,10 +35877,22 @@ const PRESET_MAXLENGTH = {
35083
35877
  email: null,
35084
35878
  document: null,
35085
35879
  'block-email': null,
35880
+ print: null,
35881
+ 'print-header': null,
35086
35882
  };
35087
35883
  /** Build the ordered extension array for a preset. */
35088
35884
  function getExtensions(preset = 'task', options = {}) {
35089
- const { placeholder, maxLength, features = {}, includeUiExtensions = true } = options;
35885
+ const { placeholder, maxLength, features = {}, includeUiExtensions = true, labels } = options;
35886
+ // Presets de impresión: schema propio (spec contracts-v2-contract-editor §3.5/§3.6).
35887
+ if (preset === 'print' || preset === 'print-header') {
35888
+ const exts = getPrintExtensions(preset, {
35889
+ features: { fields: features.fields, signatureSlots: features.signatureSlots },
35890
+ labels,
35891
+ });
35892
+ if (includeUiExtensions && placeholder)
35893
+ exts.push(Placeholder.configure({ placeholder }));
35894
+ return exts;
35895
+ }
35090
35896
  const config = STARTERKIT_CONFIG[preset] ?? STARTERKIT_CONFIG.task;
35091
35897
  const exts = [StarterKit.configure(config), CobaltLink];
35092
35898
  // Color requires TextStyle to be registered first. Only presets that keep
@@ -35184,7 +35990,573 @@ function defaultToolbarForPreset(preset = 'task') {
35184
35990
  function maxLengthForPreset(preset = 'task') {
35185
35991
  return PRESET_MAXLENGTH[preset] ?? null;
35186
35992
  }
35187
- const PRESETS = ['comment', 'task', 'notes', 'email', 'document', 'block-email'];
35993
+ const PRESETS = ['comment', 'task', 'notes', 'email', 'document', 'block-email', 'print', 'print-header'];
35994
+
35995
+ // src/generateHTML.ts
35996
+ function getHTMLFromFragment(doc, schema, options) {
35997
+ if (typeof window === "undefined") {
35998
+ throw new Error(
35999
+ "getHTMLFromFragment can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
36000
+ );
36001
+ }
36002
+ const wrap = window.document.createElement("div");
36003
+ DOMSerializer.fromSchema(schema).serializeFragment(
36004
+ doc.content,
36005
+ {
36006
+ document: window.document
36007
+ },
36008
+ wrap
36009
+ );
36010
+ return wrap.innerHTML;
36011
+ }
36012
+
36013
+ // src/generateHTML.ts
36014
+ function generateHTML(doc, extensions) {
36015
+ if (typeof window === "undefined") {
36016
+ throw new Error(
36017
+ "generateHTML can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
36018
+ );
36019
+ }
36020
+ const schema = getSchema(extensions);
36021
+ const contentNode = Node$1.fromJSON(schema, doc);
36022
+ return getHTMLFromFragment(contentNode, schema);
36023
+ }
36024
+ function generateJSON(html, extensions, options) {
36025
+ if (typeof window === "undefined") {
36026
+ throw new Error(
36027
+ "generateJSON can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
36028
+ );
36029
+ }
36030
+ const schema = getSchema(extensions);
36031
+ const doc = new window.DOMParser().parseFromString(html, "text/html");
36032
+ if (!doc) {
36033
+ throw new Error("Failed to parse HTML string");
36034
+ }
36035
+ return DOMParser$1.fromSchema(schema).parse(doc.body, options).toJSON();
36036
+ }
36037
+
36038
+ const BASE_INLINE = ['p', 'br', 'strong', 'em', 'a', 'span'];
36039
+ const BASE_ATTR = ['href', 'target', 'rel', 'data-mention-id', 'data-mention-label'];
36040
+ const SANITIZE_CONFIGS = {
36041
+ // Más ancho que su schema A PROPÓSITO (única excepción al lock-step): el
36042
+ // editor `comment` no puede autorar listas ni headings (STARTERKIT_CONFIG los
36043
+ // apaga y ProseMirror descarta esos nodos al parsear el paste), pero el
36044
+ // VIEWER tiene que pintarlos cuando el HTML entra por API — una nota de
36045
+ // enriquecimiento (Apollo.io) trae <ul>/<li>/<h4> y con KEEP_CONTENT el
36046
+ // texto se hoisteaba al padre: lista corrida, heading fundido en el cuerpo.
36047
+ // Espejo inline en core/co-rich-text-viewer.tsx (ALLOWED_TAGS.comment).
36048
+ comment: {
36049
+ ALLOWED_TAGS: [...BASE_INLINE, 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4'],
36050
+ ALLOWED_ATTR: [...BASE_ATTR],
36051
+ ALLOW_DATA_ATTR: false,
36052
+ },
36053
+ task: {
36054
+ ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'input', 'label'],
36055
+ ALLOWED_ATTR: [...BASE_ATTR, 'type', 'checked', 'disabled', 'data-type', 'data-checked', 'data-variant'],
36056
+ ALLOW_DATA_ATTR: false,
36057
+ },
36058
+ // Lock-step con getExtensions('notes'): task sin checklists + TextStyle/Color
36059
+ // (`style` capado a STYLE_ALLOWED_PROPS) + Highlight multicolor (`mark` con
36060
+ // `data-color`).
36061
+ notes: {
36062
+ ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'mark'],
36063
+ ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-color'],
36064
+ ALLOW_DATA_ATTR: false,
36065
+ },
36066
+ email: {
36067
+ ALLOWED_TAGS: [
36068
+ ...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
36069
+ 'h2', 'h3', 'div', 'img',
36070
+ ],
36071
+ ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout'],
36072
+ ALLOW_DATA_ATTR: false,
36073
+ },
36074
+ document: {
36075
+ ALLOWED_TAGS: [
36076
+ ...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
36077
+ 'h1', 'h2', 'h3', 'h4', 'hr', 'div', 'mark', 'img',
36078
+ 'table', 'thead', 'tbody', 'tr', 'th', 'td',
36079
+ 'input', 'label', 'iframe',
36080
+ ],
36081
+ ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'colspan', 'rowspan', 'src', 'alt', 'width', 'height', 'type', 'checked', 'disabled', 'allowfullscreen', 'frameborder', 'allow', 'loading'],
36082
+ ALLOW_DATA_ATTR: true,
36083
+ },
36084
+ 'block-email': {
36085
+ ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'h2', 'h3', 'div', 'img'],
36086
+ ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout', 'data-type', 'data-label', 'data-href', 'data-bg', 'data-color', 'data-height'],
36087
+ ALLOW_DATA_ATTR: false,
36088
+ },
36089
+ // Espejo de getPrintExtensions('print'): cuerpo del documento de impresión.
36090
+ // `class` y data-* son parte de la forma que V1 re-parsea (editor-text-style,
36091
+ // variable-node, editor-link, tableWrapper, trailingBreak, data-variable…).
36092
+ print: {
36093
+ ALLOWED_TAGS: [
36094
+ 'p', 'br', 'strong', 'em', 's', 'code', 'a', 'span', 'mark',
36095
+ 'h1', 'h2', 'h3', 'h4', 'ul', 'ol', 'li', 'blockquote', 'pre', 'hr', 'img', 'div',
36096
+ 'table', 'colgroup', 'col', 'thead', 'tbody', 'tr', 'th', 'td',
36097
+ ],
36098
+ ALLOWED_ATTR: [
36099
+ 'href', 'target', 'rel', 'class', 'style', 'src', 'alt', 'title', 'width', 'height',
36100
+ 'colspan', 'rowspan', 'colwidth', 'start', 'contenteditable', 'containerstyle', 'wrapperstyle',
36101
+ ],
36102
+ ALLOW_DATA_ATTR: true,
36103
+ ADD_URI_SAFE_ATTR: ['containerstyle', 'wrapperstyle'],
36104
+ },
36105
+ // Espejo de getPrintExtensions('print-header'): la banda del encabezado.
36106
+ 'print-header': {
36107
+ ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 's', 'code', 'span', 'mark', 'img'],
36108
+ ALLOWED_ATTR: ['class', 'style', 'src', 'alt', 'title', 'width', 'height', 'contenteditable', 'containerstyle', 'wrapperstyle'],
36109
+ ALLOW_DATA_ATTR: true,
36110
+ ADD_URI_SAFE_ATTR: ['containerstyle', 'wrapperstyle'],
36111
+ },
36112
+ };
36113
+ /**
36114
+ * `<iframe>`s are permitted only with an `https:` source (blocks javascript:,
36115
+ * data:, and plain http: embeds). This is what makes allowing iframes safe-ish
36116
+ * for a trusted-author document; YouTube embeds satisfy it too.
36117
+ */
36118
+ const SAFE_IFRAME_SRC_RE = /^https:\/\/[^\s"'<>]+$/i;
36119
+ /** Tags forbidden in every preset, regardless of the allow-list. */
36120
+ const FORBID_TAGS = ['script', 'object', 'embed', 'form', 'textarea', 'style'];
36121
+ /** Attributes forbidden in every preset (event handlers handled by DOMPurify itself). */
36122
+ const FORBID_ATTR = ['onerror', 'onload', 'onclick'];
36123
+ /**
36124
+ * Resolve the effective config for a preset + feature overrides. Features can
36125
+ * only ADD capabilities (mirroring `getExtensions`, where they register extra
36126
+ * nodes); they never narrow a preset's base whitelist.
36127
+ */
36128
+ function configFor(preset, features) {
36129
+ const cfg = SANITIZE_CONFIGS[preset] ?? SANITIZE_CONFIGS.task;
36130
+ if (!features)
36131
+ return cfg;
36132
+ const tags = new Set(cfg.ALLOWED_TAGS);
36133
+ const attr = new Set(cfg.ALLOWED_ATTR);
36134
+ if (features.image) {
36135
+ tags.add('img');
36136
+ ['src', 'alt', 'width', 'height'].forEach((a) => attr.add(a));
36137
+ }
36138
+ if (features.variables)
36139
+ attr.add('data-variable');
36140
+ if (features.mentions) {
36141
+ // data-mention-id/label ya están en BASE_ATTR. Los attrs del markup V1
36142
+ // (quill-mention) se suman porque el BACKEND los parsea para notificar —
36143
+ // re-editar una nota no debe destruirlos.
36144
+ // Espejo inline en core/co-rich-text-viewer.tsx (el viewer no importa este módulo para no cargar el engine) — si cambias esta lista, cambia la del viewer.
36145
+ ['data-id', 'data-value', 'data-denotation-char', 'data-index'].forEach((a) => attr.add(a));
36146
+ }
36147
+ return { ...cfg, ALLOWED_TAGS: [...tags], ALLOWED_ATTR: [...attr] };
36148
+ }
36149
+ /**
36150
+ * `style` is only allowed in notes/email/document, and even there we cap it to
36151
+ * the properties our extensions actually emit (TextStyle/Color/TextAlign,
36152
+ * ListStyleExtension's `list-style-type`). Everything else — position,
36153
+ * background-image url(), etc. — is UI-redressing/tracking surface.
36154
+ */
36155
+ const STYLE_ALLOWED_PROPS = new Set(['color', 'background-color', 'text-align', 'list-style-type']);
36156
+ const UNSAFE_STYLE_VALUE = /url\s*\(|expression\s*\(/i;
36157
+ const DEFAULT_STYLE_POLICY = {
36158
+ attrs: new Set(['style']),
36159
+ allows: (prop) => STYLE_ALLOWED_PROPS.has(prop),
36160
+ keepOriginalWhenClean: false,
36161
+ };
36162
+ const COLOR_VALUE = /^(#[0-9a-f]{3,8}|rgba?\([\d.\s,%]+\)|hsla?\([\d.\s,%deg]+\)|[a-z]+)$/i;
36163
+ const LENGTH_TOKEN = /^(-?\d+(\.\d+)?(px|pt|em|rem|%|mm|cm|in)?|auto)$/i;
36164
+ const lengths = (v) => v.split(/\s+/).every((t) => LENGTH_TOKEN.test(t));
36165
+ const oneOf = (re) => (v) => re.test(v);
36166
+ /** Lo que emiten las extensiones del preset print y la firma canónica (spec §3.4, §4.1). */
36167
+ const PRINT_STYLE_RULES = {
36168
+ color: oneOf(COLOR_VALUE),
36169
+ 'background-color': oneOf(COLOR_VALUE),
36170
+ 'text-align': oneOf(/^(left|center|right|justify)$/i),
36171
+ 'font-size': oneOf(/^\d+(\.\d+)?(px|pt|em|rem|%)$/i),
36172
+ width: lengths,
36173
+ height: lengths,
36174
+ 'min-width': lengths,
36175
+ 'max-width': lengths,
36176
+ display: oneOf(/^(inline-block|inline|block|flex|inline-flex)$/i),
36177
+ float: oneOf(/^(left|right|none)$/i),
36178
+ margin: lengths,
36179
+ 'margin-top': lengths,
36180
+ 'margin-right': lengths,
36181
+ 'margin-bottom': lengths,
36182
+ 'margin-left': lengths,
36183
+ padding: lengths,
36184
+ 'padding-top': lengths,
36185
+ 'padding-right': lengths,
36186
+ 'padding-bottom': lengths,
36187
+ 'padding-left': lengths,
36188
+ 'vertical-align': oneOf(/^(top|middle|bottom|baseline|text-top|text-bottom)$/i),
36189
+ position: oneOf(/^(relative|absolute)$/i),
36190
+ top: lengths,
36191
+ left: lengths,
36192
+ 'line-height': oneOf(/^\d+(\.\d+)?(px)?$/i),
36193
+ 'white-space': oneOf(/^(nowrap|normal|pre-wrap)$/i),
36194
+ 'pointer-events': oneOf(/^none$/i),
36195
+ 'user-select': oneOf(/^none$/i),
36196
+ cursor: oneOf(/^(pointer|default)$/i),
36197
+ };
36198
+ const PRINT_STYLE_POLICY = {
36199
+ // containerstyle/wrapperstyle son CSS que V1 aplica inline a la imagen (H2).
36200
+ attrs: new Set(['style', 'containerstyle', 'wrapperstyle']),
36201
+ allows: (prop, value) => Object.prototype.hasOwnProperty.call(PRINT_STYLE_RULES, prop) && PRINT_STYLE_RULES[prop](value),
36202
+ keepOriginalWhenClean: true,
36203
+ };
36204
+ const STYLE_POLICIES = {
36205
+ print: PRINT_STYLE_POLICY,
36206
+ 'print-header': PRINT_STYLE_POLICY,
36207
+ };
36208
+ /**
36209
+ * Sanitize an HTML string for the given preset (+ feature overrides — pass the
36210
+ * same `features` you gave `getExtensions`/`createEditor` so the whitelist
36211
+ * stays in lock-step with the schema). Always strips script/object/embed/style/
36212
+ * form/event-handlers and `javascript:` URLs (DOMPurify default). `<iframe>` is
36213
+ * allowed ONLY for the document preset and ONLY with an `https:` source
36214
+ * (YouTube, Vimeo, Loom, Slides, … survive save/render; unsafe embeds are
36215
+ * dropped). `style` is capped to color/background-color/text-align.
36216
+ */
36217
+ function sanitize(html, preset = 'task', features) {
36218
+ if (!html)
36219
+ return '';
36220
+ const cfg = configFor(preset, features);
36221
+ purify_es.purify.addHook('uponSanitizeElement', (node, data) => {
36222
+ // Only allow <input type="checkbox"> (task list checkboxes); strip others.
36223
+ if (data.tagName === 'input' && node.type !== 'checkbox') {
36224
+ node.parentNode?.removeChild(node);
36225
+ }
36226
+ // Allow only https iframes (YouTube and other embeds); drop anything else.
36227
+ if (data.tagName === 'iframe') {
36228
+ const src = node.getAttribute('src') || '';
36229
+ if (!SAFE_IFRAME_SRC_RE.test(src))
36230
+ node.parentNode?.removeChild(node);
36231
+ }
36232
+ });
36233
+ // Cap `style` (and, in print, the image's containerstyle/wrapperstyle) to
36234
+ // the properties the preset's extensions actually emit; strip the rest
36235
+ // (position:fixed, background-image url(), expression(), …). Drop the attr
36236
+ // entirely when nothing survives. The default policy is the pre-print rule
36237
+ // verbatim (guarded by sanitizer.presets.snapshot.test.ts).
36238
+ const policy = STYLE_POLICIES[preset] ?? DEFAULT_STYLE_POLICY;
36239
+ purify_es.purify.addHook('uponSanitizeAttribute', (_node, data) => {
36240
+ if (!policy.attrs.has(data.attrName))
36241
+ return;
36242
+ const decls = data.attrValue.split(';').map((d) => d.trim()).filter(Boolean);
36243
+ const safe = decls.filter((d) => {
36244
+ const colon = d.indexOf(':');
36245
+ if (colon <= 0)
36246
+ return false;
36247
+ const prop = d.slice(0, colon).trim().toLowerCase();
36248
+ const value = d.slice(colon + 1).trim();
36249
+ return !UNSAFE_STYLE_VALUE.test(d) && policy.allows(prop, value);
36250
+ });
36251
+ if (policy.keepOriginalWhenClean && safe.length === decls.length && safe.length > 0)
36252
+ return;
36253
+ data.attrValue = safe.join('; ');
36254
+ if (!data.attrValue)
36255
+ data.keepAttr = false;
36256
+ });
36257
+ try {
36258
+ const clean = purify_es.purify.sanitize(html, {
36259
+ ALLOWED_TAGS: cfg.ALLOWED_TAGS,
36260
+ ALLOWED_ATTR: cfg.ALLOWED_ATTR,
36261
+ ALLOW_DATA_ATTR: cfg.ALLOW_DATA_ATTR ?? false,
36262
+ FORBID_TAGS,
36263
+ FORBID_ATTR,
36264
+ ADD_ATTR: ['target', 'allowfullscreen', 'frameborder', 'allow'],
36265
+ ...(cfg.ADD_URI_SAFE_ATTR ? { ADD_URI_SAFE_ATTR: cfg.ADD_URI_SAFE_ATTR } : {}),
36266
+ });
36267
+ return clean;
36268
+ }
36269
+ finally {
36270
+ purify_es.purify.removeHook('uponSanitizeElement');
36271
+ purify_es.purify.removeHook('uponSanitizeAttribute');
36272
+ }
36273
+ }
36274
+
36275
+ /**
36276
+ * Lector tolerante del HTML de impresión (spec contracts-v2-contract-editor §3.3).
36277
+ * Entrada: lo que guardó V1 (documento completo con CSS, fragmento que dejó
36278
+ * cheerio en el backend, cuerpo compilado de generateFromDeal) o lo que escribe
36279
+ * el serializador canónico. Salida: SOLO el cuerpo, sin restos de edición.
36280
+ * No usa schema: el parse lo hace readPrintHtml (print/io.ts).
36281
+ */
36282
+ const EDITING_CLASSES = ['ProseMirror-selectednode', 'variable-node--editing', 'selectedCell'];
36283
+ const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'UL', 'OL', 'LI', 'TABLE', 'BLOCKQUOTE', 'PRE', 'HR']);
36284
+ const INLINE_CONTENT_TAGS = new Set(['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6']);
36285
+ const HEAD_ONLY = 'style, script, meta, title, link, base';
36286
+ function normalizePrintHtml(html) {
36287
+ if (!html || !html.trim())
36288
+ return '';
36289
+ const doc = new DOMParser().parseFromString(html, 'text/html');
36290
+ const root = doc.querySelector('.tiptap.ProseMirror, .ProseMirror') ?? doc.body;
36291
+ root.querySelectorAll('#document-metadata').forEach((el) => el.remove());
36292
+ root.querySelectorAll(HEAD_ONLY).forEach((el) => el.remove());
36293
+ // prosemirror-model convierte estos br en saltos REALES al re-parsear: fuera todos.
36294
+ root.querySelectorAll('br.ProseMirror-trailingBreak, img.ProseMirror-separator').forEach((el) => el.remove());
36295
+ // V1 serializa por error la decoración de {{ }}.
36296
+ root.querySelectorAll('span.hb-token').forEach(unwrap);
36297
+ Array.from(root.querySelectorAll('*')).forEach(cleanEditingResidue);
36298
+ cleanCellStyles(root);
36299
+ rebuildSplitImages(root);
36300
+ // Tras desenvolver hb-token y quitar breaks quedan textos adyacentes: un token repartido entre ellos no matchearía.
36301
+ root.normalize();
36302
+ tokensToFieldSpans(root);
36303
+ return root.innerHTML;
36304
+ }
36305
+ function unwrap(el) {
36306
+ el.replaceWith(...Array.from(el.childNodes));
36307
+ }
36308
+ function cleanEditingResidue(el) {
36309
+ Array.from(el.attributes).forEach((a) => {
36310
+ if (a.name.startsWith('data-v-') || a.name === 'data-node-view-wrapper')
36311
+ el.removeAttribute(a.name);
36312
+ });
36313
+ EDITING_CLASSES.forEach((c) => el.classList.remove(c));
36314
+ if (el.getAttribute('class') === '')
36315
+ el.removeAttribute('class');
36316
+ }
36317
+ function cleanCellStyles(root) {
36318
+ root.querySelectorAll('td[style], th[style]').forEach((cell) => {
36319
+ const kept = (cell.getAttribute('style') || '')
36320
+ .split(';')
36321
+ .map((d) => d.trim())
36322
+ .filter((d) => {
36323
+ const i = d.indexOf(':');
36324
+ if (i <= 0)
36325
+ return false;
36326
+ const v = d.slice(i + 1).trim().toLowerCase();
36327
+ return v !== '' && v !== 'null' && v !== 'undefined';
36328
+ });
36329
+ if (kept.length)
36330
+ cell.setAttribute('style', kept.join('; '));
36331
+ else
36332
+ cell.removeAttribute('style');
36333
+ });
36334
+ }
36335
+ const isBlockNode = (n) => n.nodeType === 1 && BLOCK_TAGS.has(n.tagName);
36336
+ const isBlankText = (n) => n.nodeType === 3 && !(n.textContent ?? '').trim();
36337
+ /**
36338
+ * V1 guarda la imagen como `<div wrapper><div container><img></div></div>`
36339
+ * DENTRO del `<p>`; el parser HTML5 parte el párrafo en `<p>antes</p><div>…</div>después<p></p>`.
36340
+ * Se vuelve a juntar en un solo párrafo, con los estilos del wrapper y del
36341
+ * container copiados al `<img>` (así los lee el nodo image del preset print).
36342
+ */
36343
+ function rebuildSplitImages(root) {
36344
+ const doc = root.ownerDocument;
36345
+ Array.from(root.querySelectorAll('img')).forEach((img) => {
36346
+ const container = img.parentElement;
36347
+ // `container !== root`: un <img> suelto al tope del cuerpo no es una imagen partida.
36348
+ if (!container || container === root || container.tagName !== 'DIV' || container.firstElementChild !== img)
36349
+ return;
36350
+ const parent = container.parentElement;
36351
+ const wrapper = parent && parent.tagName === 'DIV' && parent.firstElementChild === container && parent !== root ? parent : null;
36352
+ const containerCss = container.getAttribute('style');
36353
+ if (containerCss && !img.hasAttribute('containerstyle'))
36354
+ img.setAttribute('containerstyle', containerCss);
36355
+ const wrapperCss = wrapper?.getAttribute('style');
36356
+ if (wrapperCss && !img.hasAttribute('wrapperstyle'))
36357
+ img.setAttribute('wrapperstyle', wrapperCss);
36358
+ const outer = wrapper ?? container;
36359
+ // El parser HTML5 solo parte <p>: dentro de un título (o de un <p> que no se
36360
+ // partió) la imagen queda en su lugar, sin recomponer hermanos ni crear <p>.
36361
+ if (outer.parentElement && INLINE_CONTENT_TAGS.has(outer.parentElement.tagName)) {
36362
+ outer.replaceWith(img);
36363
+ return;
36364
+ }
36365
+ const before = [];
36366
+ let prev = outer.previousSibling;
36367
+ while (prev && !isBlockNode(prev)) {
36368
+ before.unshift(prev);
36369
+ prev = prev.previousSibling;
36370
+ }
36371
+ const after = [];
36372
+ let next = outer.nextSibling;
36373
+ while (next && !isBlockNode(next)) {
36374
+ after.push(next);
36375
+ next = next.nextSibling;
36376
+ }
36377
+ // El `</p>` original quedó huérfano: el parser lo convierte en un <p></p> vacío.
36378
+ if (next && next.nodeName === 'P' && !next.hasChildNodes())
36379
+ next.remove();
36380
+ let target;
36381
+ if (before.every(isBlankText) && prev && prev.nodeName === 'P') {
36382
+ before.forEach((n) => n.parentNode?.removeChild(n));
36383
+ target = prev;
36384
+ }
36385
+ else {
36386
+ target = doc.createElement('p');
36387
+ outer.before(target);
36388
+ before.forEach((n) => target.appendChild(n));
36389
+ }
36390
+ target.appendChild(img);
36391
+ after.forEach((n) => target.appendChild(n));
36392
+ outer.remove();
36393
+ });
36394
+ }
36395
+ function tokensToFieldSpans(root) {
36396
+ const doc = root.ownerDocument;
36397
+ const walker = doc.createTreeWalker(root, NodeFilter.SHOW_TEXT);
36398
+ const targets = [];
36399
+ let n;
36400
+ while ((n = walker.nextNode())) {
36401
+ const t = n;
36402
+ if (!t.data.includes('[['))
36403
+ continue;
36404
+ if (t.parentElement?.closest('[data-variable], [data-sig-slot], pre, code'))
36405
+ continue;
36406
+ targets.push(t);
36407
+ }
36408
+ targets.forEach((t) => {
36409
+ const text = t.data;
36410
+ const re = fieldTokenRegex();
36411
+ const frag = doc.createDocumentFragment();
36412
+ let last = 0;
36413
+ let any = false;
36414
+ let m;
36415
+ while ((m = re.exec(text)) !== null) {
36416
+ const def = parseFieldToken(m[1]);
36417
+ if (!def)
36418
+ continue;
36419
+ any = true;
36420
+ if (m.index > last)
36421
+ frag.appendChild(doc.createTextNode(text.slice(last, m.index)));
36422
+ const span = doc.createElement('span');
36423
+ span.setAttribute('data-variable', def.name);
36424
+ span.setAttribute('data-value', '');
36425
+ span.setAttribute('data-type', def.type);
36426
+ span.setAttribute('data-required', def.required ? 'true' : 'false');
36427
+ if (def.enum)
36428
+ span.setAttribute('data-enum', JSON.stringify(def.enum));
36429
+ span.textContent = `[[${def.name}]]`;
36430
+ frag.appendChild(span);
36431
+ last = m.index + m[0].length;
36432
+ }
36433
+ if (!any)
36434
+ return;
36435
+ if (last < text.length)
36436
+ frag.appendChild(doc.createTextNode(text.slice(last)));
36437
+ t.replaceWith(frag);
36438
+ });
36439
+ }
36440
+
36441
+ /**
36442
+ * Serializador canónico del preset print (spec contracts-v2-contract-editor §3.4).
36443
+ * Escribe desde el DOCUMENTO (renderHTML del schema), nunca desde el DOM de
36444
+ * pantalla: así no se cuelan NodeViews, decoraciones ni los hacks de
36445
+ * prosemirror-view que V1 guardaba con innerHTML.
36446
+ *
36447
+ * H1: `DOMSerializer` escribe `style` por CSSOM (`dom.style.cssText = …`), que
36448
+ * normaliza el string (`#ff0000` → `rgb(255, 0, 0)`, `top:0` → `top: 0px;`) y
36449
+ * rompe la forma byte a byte de V1 (firma, color, tamaño, imagen). Por eso se
36450
+ * serializa con un `document` sustituto cuyos elementos no exponen `style`:
36451
+ * ProseMirror cae a `setAttribute` y conserva el string crudo. `editor.getHTML()`
36452
+ * NO es la forma canónica.
36453
+ */
36454
+ const TRAILING_BREAK_CLASS = 'ProseMirror-trailingBreak';
36455
+ const TRAILING_MARKER = 'data-co-trailing-break';
36456
+ /**
36457
+ * Como prosemirror-view, el trailingBreak se decide por el NODO: textblock vacío o
36458
+ * cuyo último hijo es un hardBreak (aunque el <br> quede dentro de un mark).
36459
+ */
36460
+ function needsTrailingBreak(node) {
36461
+ if (!node.isTextblock)
36462
+ return false;
36463
+ return node.childCount === 0 || node.lastChild.type.name === 'hardBreak';
36464
+ }
36465
+ /**
36466
+ * Marca el elemento de bloque (spec `[tag, attrs?, 0]`, hueco directo en el
36467
+ * elemento: p/h*) para que el <br> vaya como su ÚLTIMO hijo, fuera de los marks.
36468
+ */
36469
+ function withTrailingMarker(spec) {
36470
+ if (!Array.isArray(spec) || spec[spec.length - 1] !== 0)
36471
+ return spec;
36472
+ const attrs = spec[1];
36473
+ if (attrs && typeof attrs === 'object' && !Array.isArray(attrs) && !('nodeType' in attrs)) {
36474
+ return [spec[0], { ...attrs, [TRAILING_MARKER]: '' }, ...spec.slice(2)];
36475
+ }
36476
+ return [spec[0], { [TRAILING_MARKER]: '' }, ...spec.slice(1)];
36477
+ }
36478
+ function rawStyleDocument(real) {
36479
+ return {
36480
+ createElement: (tag) => {
36481
+ const el = real.createElement(tag);
36482
+ Object.defineProperty(el, 'style', { value: null });
36483
+ return el;
36484
+ },
36485
+ createElementNS: (ns, tag) => {
36486
+ const el = real.createElementNS(ns, tag);
36487
+ Object.defineProperty(el, 'style', { value: null });
36488
+ return el;
36489
+ },
36490
+ createTextNode: real.createTextNode.bind(real),
36491
+ createDocumentFragment: real.createDocumentFragment.bind(real),
36492
+ };
36493
+ }
36494
+ function printSerializer(schema) {
36495
+ const base = DOMSerializer.fromSchema(schema);
36496
+ const nodes = {};
36497
+ Object.entries(base.nodes).forEach(([name, render]) => {
36498
+ nodes[name] = (node) => {
36499
+ const spec = render(node);
36500
+ return needsTrailingBreak(node) ? withTrailingMarker(spec) : spec;
36501
+ };
36502
+ });
36503
+ return new DOMSerializer(nodes, base.marks);
36504
+ }
36505
+ function serializePrintHtml(doc) {
36506
+ const container = document.createElement('div');
36507
+ const fragment = printSerializer(doc.type.schema).serializeFragment(doc.content, {
36508
+ document: rawStyleDocument(document),
36509
+ });
36510
+ container.appendChild(fragment);
36511
+ // Sin el trailingBreak la línea vacía o final no ocupa alto en el PDF
36512
+ // (.tiptap p{margin:0}). El lector lo quita al volver.
36513
+ container.querySelectorAll(`[${TRAILING_MARKER}]`).forEach((el) => {
36514
+ el.removeAttribute(TRAILING_MARKER);
36515
+ const br = document.createElement('br');
36516
+ br.className = TRAILING_BREAK_CLASS;
36517
+ el.appendChild(br);
36518
+ });
36519
+ return container.innerHTML;
36520
+ }
36521
+
36522
+ function isPrintPreset(p) {
36523
+ return p === 'print' || p === 'print-header';
36524
+ }
36525
+ function schemaExtensions(preset, features) {
36526
+ return getExtensions(preset, { includeUiExtensions: false, features });
36527
+ }
36528
+ /** HTML de impresión (el de V1 incluido) → JSON: lector tolerante → limpieza del preset → parse. */
36529
+ function readPrintHtml(html, preset = 'print', features) {
36530
+ const clean = sanitize(normalizePrintHtml(html ?? ''), preset, features);
36531
+ return generateJSON(clean, schemaExtensions(preset, features));
36532
+ }
36533
+ /**
36534
+ * Documento → forma canónica (spec §3.4), pasada por la limpieza del preset.
36535
+ * Es la ÚNICA forma canónica: `editor.getHTML()` de Tiptap normaliza los `style`
36536
+ * (H1) y no sirve para guardar.
36537
+ */
36538
+ function writePrintHtml(doc, preset = 'print', features) {
36539
+ if (!doc)
36540
+ return '';
36541
+ const node = doc instanceof Node$1
36542
+ ? doc
36543
+ : Node$1.fromJSON(getSchema(schemaExtensions(preset, features)), doc);
36544
+ return sanitize(serializePrintHtml(node), preset, features);
36545
+ }
36546
+ /** Aplica valores a los campos de un HTML sin montar un editor (encabezado fuera de edición). */
36547
+ function setFieldValuesInHtml(html, values, preset = 'print-header', features) {
36548
+ if (!html)
36549
+ return '';
36550
+ const json = readPrintHtml(html, preset, features);
36551
+ const apply = (n) => {
36552
+ if (n.type === 'mergeField' && n.attrs && Object.prototype.hasOwnProperty.call(values, n.attrs.name)) {
36553
+ n.attrs = { ...n.attrs, value: String(values[n.attrs.name] ?? '') };
36554
+ }
36555
+ n.content?.forEach(apply);
36556
+ };
36557
+ apply(json);
36558
+ return writePrintHtml(json, preset, features);
36559
+ }
35188
36560
 
35189
36561
  /**
35190
36562
  * ProseMirror editorProps that insert pasted/dropped images optimistically
@@ -35310,6 +36682,11 @@ function autolinkTrailing(editor) {
35310
36682
  editor.view.dispatch(tr);
35311
36683
  return changed;
35312
36684
  }
36685
+ /** El autolink al perder foco solo corre si el link del schema lo tiene activo (print lo apaga). */
36686
+ function autolinkEnabled(editor) {
36687
+ const link = editor.extensionManager.extensions.find((ext) => ext.name === 'link');
36688
+ return !!(link && link.options.autolink);
36689
+ }
35313
36690
  /**
35314
36691
  * Create a configured Tiptap v3 editor for a Cobalt preset.
35315
36692
  *
@@ -35318,9 +36695,9 @@ function autolinkTrailing(editor) {
35318
36695
  * always false — Cobalt owns every style.
35319
36696
  */
35320
36697
  function createEditor(options = {}) {
35321
- const { preset = 'task', element = null, content = null, editable = true, placeholder, maxLength, features, customExtensions = [], bubbleMenuElement, imageUpload, onUpdate, onSelectionUpdate, onFocus, onBlur, onCreate, onDestroy, onContentError, } = options;
36698
+ const { preset = 'task', element = null, content = null, editable = true, placeholder, maxLength, features, labels, customExtensions = [], bubbleMenuElement, imageUpload, onUpdate, onSelectionUpdate, onFocus, onBlur, onCreate, onDestroy, onContentError, } = options;
35322
36699
  const extensions = [
35323
- ...getExtensions(preset, { placeholder, maxLength, features }),
36700
+ ...getExtensions(preset, { placeholder, maxLength, features, labels }),
35324
36701
  ...customExtensions,
35325
36702
  ];
35326
36703
  let editor;
@@ -35377,11 +36754,13 @@ function createEditor(options = {}) {
35377
36754
  },
35378
36755
  }));
35379
36756
  }
36757
+ // En print, un string es HTML de impresión (quizá de V1): pasa por el lector tolerante.
36758
+ const initialContent = isPrintPreset(preset) && typeof content === 'string' ? readPrintHtml(content, preset, features) : content;
35380
36759
  editor = new Editor({
35381
36760
  ...(element ? { element } : {}),
35382
36761
  ...(imageUpload ? { editorProps: imageDropPaste(imageUpload) } : {}),
35383
36762
  extensions,
35384
- content: content ?? '',
36763
+ content: initialContent ?? '',
35385
36764
  editable,
35386
36765
  injectCSS: false,
35387
36766
  // `enableContentCheck: true` makes tiptap THROW on invalid content from
@@ -35396,304 +36775,408 @@ function createEditor(options = {}) {
35396
36775
  onUpdate: ({ editor: e }) => onUpdate?.(e),
35397
36776
  onSelectionUpdate: ({ editor: e }) => onSelectionUpdate?.(e),
35398
36777
  onFocus: ({ editor: e }) => onFocus?.(e),
35399
- onBlur: ({ editor: e }) => { autolinkTrailing(e); onBlur?.(e); },
36778
+ onBlur: ({ editor: e }) => { if (autolinkEnabled(e))
36779
+ autolinkTrailing(e); onBlur?.(e); },
35400
36780
  onDestroy: () => onDestroy?.(),
35401
36781
  });
35402
36782
  return editor;
35403
36783
  }
35404
36784
 
35405
- // src/generateHTML.ts
35406
- function getHTMLFromFragment(doc, schema, options) {
35407
- if (typeof window === "undefined") {
35408
- throw new Error(
35409
- "getHTMLFromFragment can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
35410
- );
35411
- }
35412
- const wrap = window.document.createElement("div");
35413
- DOMSerializer.fromSchema(schema).serializeFragment(
35414
- doc.content,
35415
- {
35416
- document: window.document
35417
- },
35418
- wrap
35419
- );
35420
- return wrap.innerHTML;
35421
- }
35422
-
35423
- // src/generateHTML.ts
35424
- function generateHTML(doc, extensions) {
35425
- if (typeof window === "undefined") {
35426
- throw new Error(
35427
- "generateHTML can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
35428
- );
35429
- }
35430
- const schema = getSchema(extensions);
35431
- const contentNode = Node$1.fromJSON(schema, doc);
35432
- return getHTMLFromFragment(contentNode, schema);
35433
- }
35434
- function generateJSON(html, extensions, options) {
35435
- if (typeof window === "undefined") {
35436
- throw new Error(
35437
- "generateJSON can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
35438
- );
35439
- }
35440
- const schema = getSchema(extensions);
35441
- const doc = new window.DOMParser().parseFromString(html, "text/html");
35442
- if (!doc) {
35443
- throw new Error("Failed to parse HTML string");
35444
- }
35445
- return DOMParser.fromSchema(schema).parse(doc.body, options).toJSON();
35446
- }
35447
-
35448
- const BASE_INLINE = ['p', 'br', 'strong', 'em', 'a', 'span'];
35449
- const BASE_ATTR = ['href', 'target', 'rel', 'data-mention-id', 'data-mention-label'];
35450
- const SANITIZE_CONFIGS = {
35451
- // Más ancho que su schema A PROPÓSITO (única excepción al lock-step): el
35452
- // editor `comment` no puede autorar listas ni headings (STARTERKIT_CONFIG los
35453
- // apaga y ProseMirror descarta esos nodos al parsear el paste), pero el
35454
- // VIEWER tiene que pintarlos cuando el HTML entra por API — una nota de
35455
- // enriquecimiento (Apollo.io) trae <ul>/<li>/<h4> y con KEEP_CONTENT el
35456
- // texto se hoisteaba al padre: lista corrida, heading fundido en el cuerpo.
35457
- // Espejo inline en core/co-rich-text-viewer.tsx (ALLOWED_TAGS.comment).
35458
- comment: {
35459
- ALLOWED_TAGS: [...BASE_INLINE, 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4'],
35460
- ALLOWED_ATTR: [...BASE_ATTR],
35461
- ALLOW_DATA_ATTR: false,
35462
- },
35463
- task: {
35464
- ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'input', 'label'],
35465
- ALLOWED_ATTR: [...BASE_ATTR, 'type', 'checked', 'disabled', 'data-type', 'data-checked', 'data-variant'],
35466
- ALLOW_DATA_ATTR: false,
35467
- },
35468
- // Lock-step con getExtensions('notes'): task sin checklists + TextStyle/Color
35469
- // (`style` capado a STYLE_ALLOWED_PROPS) + Highlight multicolor (`mark` con
35470
- // `data-color`).
35471
- notes: {
35472
- ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'mark'],
35473
- ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-color'],
35474
- ALLOW_DATA_ATTR: false,
35475
- },
35476
- email: {
35477
- ALLOWED_TAGS: [
35478
- ...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
35479
- 'h2', 'h3', 'div', 'img',
35480
- ],
35481
- ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout'],
35482
- ALLOW_DATA_ATTR: false,
35483
- },
35484
- document: {
35485
- ALLOWED_TAGS: [
35486
- ...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
35487
- 'h1', 'h2', 'h3', 'h4', 'hr', 'div', 'mark', 'img',
35488
- 'table', 'thead', 'tbody', 'tr', 'th', 'td',
35489
- 'input', 'label', 'iframe',
35490
- ],
35491
- ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'colspan', 'rowspan', 'src', 'alt', 'width', 'height', 'type', 'checked', 'disabled', 'allowfullscreen', 'frameborder', 'allow', 'loading'],
35492
- ALLOW_DATA_ATTR: true,
35493
- },
35494
- 'block-email': {
35495
- ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'h2', 'h3', 'div', 'img'],
35496
- ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout', 'data-type', 'data-label', 'data-href', 'data-bg', 'data-color', 'data-height'],
35497
- ALLOW_DATA_ATTR: false,
35498
- },
35499
- };
35500
- /**
35501
- * `<iframe>`s are permitted only with an `https:` source (blocks javascript:,
35502
- * data:, and plain http: embeds). This is what makes allowing iframes safe-ish
35503
- * for a trusted-author document; YouTube embeds satisfy it too.
35504
- */
35505
- const SAFE_IFRAME_SRC_RE = /^https:\/\/[^\s"'<>]+$/i;
35506
- /** Tags forbidden in every preset, regardless of the allow-list. */
35507
- const FORBID_TAGS = ['script', 'object', 'embed', 'form', 'textarea', 'style'];
35508
- /** Attributes forbidden in every preset (event handlers handled by DOMPurify itself). */
35509
- const FORBID_ATTR = ['onerror', 'onload', 'onclick'];
35510
- /**
35511
- * Resolve the effective config for a preset + feature overrides. Features can
35512
- * only ADD capabilities (mirroring `getExtensions`, where they register extra
35513
- * nodes); they never narrow a preset's base whitelist.
35514
- */
35515
- function configFor(preset, features) {
35516
- const cfg = SANITIZE_CONFIGS[preset] ?? SANITIZE_CONFIGS.task;
35517
- if (!features)
35518
- return cfg;
35519
- const tags = new Set(cfg.ALLOWED_TAGS);
35520
- const attr = new Set(cfg.ALLOWED_ATTR);
35521
- if (features.image) {
35522
- tags.add('img');
35523
- ['src', 'alt', 'width', 'height'].forEach((a) => attr.add(a));
35524
- }
35525
- if (features.variables)
35526
- attr.add('data-variable');
35527
- if (features.mentions) {
35528
- // data-mention-id/label ya están en BASE_ATTR. Los attrs del markup V1
35529
- // (quill-mention) se suman porque el BACKEND los parsea para notificar —
35530
- // re-editar una nota no debe destruirlos.
35531
- // Espejo inline en core/co-rich-text-viewer.tsx (el viewer no importa este módulo para no cargar el engine) — si cambias esta lista, cambia la del viewer.
35532
- ['data-id', 'data-value', 'data-denotation-char', 'data-index'].forEach((a) => attr.add(a));
36785
+ function computePageBreaks(atoms, pageContentHeight) {
36786
+ const breaks = [];
36787
+ if (!atoms.length || !(pageContentHeight > 0))
36788
+ return { breaks, pageCount: 1 };
36789
+ let page = 1;
36790
+ let start = 0;
36791
+ let pageTop = atoms[0].top;
36792
+ let i = 0;
36793
+ while (i < atoms.length) {
36794
+ const atom = atoms[i];
36795
+ const bottom = atom.top + atom.height;
36796
+ if (bottom - pageTop <= pageContentHeight) {
36797
+ i += 1;
36798
+ continue;
36799
+ }
36800
+ if (i === start) {
36801
+ // Más alto que una hoja: ocupa las que necesite; no hay frontera adentro.
36802
+ const extra = Math.ceil((bottom - pageTop) / pageContentHeight) - 1;
36803
+ page += extra;
36804
+ pageTop += extra * pageContentHeight;
36805
+ i += 1;
36806
+ continue;
36807
+ }
36808
+ let b = i;
36809
+ while (b - 1 > start && atoms[b - 1].keepWithNext)
36810
+ b -= 1;
36811
+ page += 1;
36812
+ breaks.push({ pos: atoms[b].pos, page });
36813
+ start = b;
36814
+ pageTop = atoms[b].top;
36815
+ i = b;
35533
36816
  }
35534
- return { ...cfg, ALLOWED_TAGS: [...tags], ALLOWED_ATTR: [...attr] };
36817
+ return { breaks, pageCount: page };
35535
36818
  }
35536
36819
  /**
35537
- * `style` is only allowed in notes/email/document, and even there we cap it to
35538
- * the properties our extensions actually emit (TextStyle/Color/TextAlign,
35539
- * ListStyleExtension's `list-style-type`). Everything else — position,
35540
- * background-image url(), etc. — is UI-redressing/tracking surface.
36820
+ * Resta a cada átomo la altura de las bandas de salto que ya están dibujadas
36821
+ * por encima (V1 medía con las bandas viejas en el flujo y cortaba antes).
35541
36822
  */
35542
- const STYLE_ALLOWED_PROPS = new Set(['color', 'background-color', 'text-align', 'list-style-type']);
35543
- /**
35544
- * Sanitize an HTML string for the given preset (+ feature overrides — pass the
35545
- * same `features` you gave `getExtensions`/`createEditor` so the whitelist
35546
- * stays in lock-step with the schema). Always strips script/object/embed/style/
35547
- * form/event-handlers and `javascript:` URLs (DOMPurify default). `<iframe>` is
35548
- * allowed ONLY for the document preset and ONLY with an `https:` source
35549
- * (YouTube, Vimeo, Loom, Slides, … survive save/render; unsafe embeds are
35550
- * dropped). `style` is capped to color/background-color/text-align.
35551
- */
35552
- function sanitize(html, preset = 'task', features) {
35553
- if (!html)
35554
- return '';
35555
- const cfg = configFor(preset, features);
35556
- purify_es.purify.addHook('uponSanitizeElement', (node, data) => {
35557
- // Only allow <input type="checkbox"> (task list checkboxes); strip others.
35558
- if (data.tagName === 'input' && node.type !== 'checkbox') {
35559
- node.parentNode?.removeChild(node);
35560
- }
35561
- // Allow only https iframes (YouTube and other embeds); drop anything else.
35562
- if (data.tagName === 'iframe') {
35563
- const src = node.getAttribute('src') || '';
35564
- if (!SAFE_IFRAME_SRC_RE.test(src))
35565
- node.parentNode?.removeChild(node);
36823
+ function stripBandOffsets(atoms, bands) {
36824
+ if (!bands.length)
36825
+ return atoms;
36826
+ const sorted = [...bands].sort((a, b) => a.top - b.top);
36827
+ return atoms.map((atom) => {
36828
+ let shift = 0;
36829
+ for (const band of sorted) {
36830
+ if (band.top < atom.top)
36831
+ shift += band.height;
36832
+ else
36833
+ break;
35566
36834
  }
36835
+ return shift ? { ...atom, top: atom.top - shift } : atom;
35567
36836
  });
35568
- // Cap `style` to the properties our extensions actually emit; strip the rest
35569
- // (position, background-image url(), expression(), …). Drop the attr entirely
35570
- // when nothing survives.
35571
- purify_es.purify.addHook('uponSanitizeAttribute', (_node, data) => {
35572
- if (data.attrName !== 'style')
35573
- return;
35574
- const safe = data.attrValue
35575
- .split(';')
35576
- .map((d) => d.trim())
35577
- .filter((d) => {
35578
- const colon = d.indexOf(':');
35579
- if (colon <= 0)
35580
- return false;
35581
- const prop = d.slice(0, colon).trim().toLowerCase();
35582
- return STYLE_ALLOWED_PROPS.has(prop) && !/url\s*\(|expression\s*\(/i.test(d);
35583
- });
35584
- data.attrValue = safe.join('; ');
35585
- if (!data.attrValue)
35586
- data.keepAttr = false;
36837
+ }
36838
+ const ATOM_TYPES = new Set(['listItem', 'tableRow']);
36839
+ const CONTAINER_TYPES = new Set(['bulletList', 'orderedList', 'table']);
36840
+ function classifyPaginationNode(node) {
36841
+ const name = node?.type?.name;
36842
+ if (!name || name === 'doc')
36843
+ return 'skip';
36844
+ if (CONTAINER_TYPES.has(name))
36845
+ return 'container';
36846
+ if (ATOM_TYPES.has(name))
36847
+ return 'atom';
36848
+ if (node?.isBlock)
36849
+ return 'atom';
36850
+ return 'skip';
36851
+ }
36852
+ function isKeepWithNext(node) {
36853
+ return node.type.name === 'heading' && Number(node.attrs?.level) >= 2;
36854
+ }
36855
+ /** Columnas de una tabla = suma de colspan de su primera fila (banda-fila que cruza la tabla). */
36856
+ function tableColumnCount(tableNode) {
36857
+ const firstRow = tableNode && typeof tableNode.child === 'function' ? tableNode.child(0) : null;
36858
+ if (!firstRow || typeof firstRow.forEach !== 'function')
36859
+ return 1;
36860
+ let cols = 0;
36861
+ firstRow.forEach((cell) => {
36862
+ cols += cell?.attrs?.colspan || 1;
35587
36863
  });
35588
- try {
35589
- const clean = purify_es.purify.sanitize(html, {
35590
- ALLOWED_TAGS: cfg.ALLOWED_TAGS,
35591
- ALLOWED_ATTR: cfg.ALLOWED_ATTR,
35592
- ALLOW_DATA_ATTR: cfg.ALLOW_DATA_ATTR ?? false,
35593
- FORBID_TAGS,
35594
- FORBID_ATTR,
35595
- ADD_ATTR: ['target', 'allowfullscreen', 'frameborder', 'allow'],
35596
- });
35597
- return clean;
35598
- }
35599
- finally {
35600
- purify_es.purify.removeHook('uponSanitizeElement');
35601
- purify_es.purify.removeHook('uponSanitizeAttribute');
35602
- }
36864
+ return cols || 1;
35603
36865
  }
35604
36866
 
35605
- /** Schema-affecting extensions only (no Placeholder/CharacterCount). */
35606
- function schemaExtensions(preset, features) {
35607
- return getExtensions(preset, { includeUiExtensions: false, features });
35608
- }
35609
- function isEmptyDoc(doc) {
35610
- if (!doc)
35611
- return true;
35612
- const content = doc.content;
35613
- if (!Array.isArray(content) || content.length === 0)
35614
- return true;
35615
- // A single empty paragraph counts as empty.
35616
- return content.every((n) => n?.type === 'paragraph' && (!n.content || n.content.length === 0));
35617
- }
35618
- /** ProseMirror JSON → sanitized HTML for the given preset (+ feature overrides). */
35619
- function jsonToHtml(doc, preset = 'task', features) {
35620
- if (isEmptyDoc(doc))
35621
- return '';
35622
- const html = generateHTML(doc, schemaExtensions(preset, features));
35623
- return sanitize(html, preset, features);
35624
- }
35625
- /** HTML string → ProseMirror JSON (tolerant; unknown nodes are dropped by the schema). */
35626
- function htmlToJson(html, preset = 'task', features) {
35627
- const safe = sanitize(html ?? '', preset, features);
35628
- return generateJSON(safe, schemaExtensions(preset, features));
36867
+ /** px a 96 dpi. */
36868
+ const PAGE_SIZES = {
36869
+ letter: { width: 816, height: 1056 },
36870
+ a4: { width: 794, height: 1123 },
36871
+ legal: { width: 816, height: 1344 },
36872
+ };
36873
+ /** Separación visual entre hojas (no existe en el PDF). */
36874
+ const PAGE_GAP_PX = 24;
36875
+ const PAGINATION_META = 'coPagination';
36876
+ function resolvePageSize(page) {
36877
+ if (!page)
36878
+ return PAGE_SIZES.letter;
36879
+ if (typeof page === 'string')
36880
+ return PAGE_SIZES[page] ?? PAGE_SIZES.letter;
36881
+ return { width: Number(page.width), height: Number(page.height) };
36882
+ }
36883
+ function pageContentHeight(o) {
36884
+ return o.page.height - o.margins.top - o.margins.bottom - o.header.height - o.footer.height;
35629
36885
  }
35630
36886
  /**
35631
- * ProseMirror JSON → plain text. Walks the document directly (no engine), so
35632
- * it stays cheap and dependency-light. Block nodes are separated by newlines.
36887
+ * Top relativo a `root` sumando `offsetTop` por la cadena de offsetParent.
36888
+ * `root` tiene que ser posicionado (la extensión le pone `position: relative`).
36889
+ * Son px de LAYOUT: un `transform: scale()` de zoom no los altera.
35633
36890
  */
35634
- function jsonToText(doc) {
35635
- if (!doc)
35636
- return '';
35637
- const BLOCK = new Set([
35638
- 'paragraph', 'heading', 'blockquote', 'listItem', 'bulletList',
35639
- 'orderedList', 'codeBlock', 'horizontalRule',
35640
- ]);
35641
- const out = [];
35642
- const walk = (node) => {
35643
- if (!node)
35644
- return;
35645
- if (node.type === 'text' && typeof node.text === 'string') {
35646
- out.push(node.text);
35647
- return;
35648
- }
35649
- if (node.type === 'variable') {
35650
- out.push(`{{${node.attrs?.name ?? ''}}}`);
35651
- return;
35652
- }
35653
- if (node.type === 'mention') {
35654
- out.push(`@${node.attrs?.label ?? ''}`);
35655
- return;
35656
- }
35657
- if (node.type === 'hardBreak') {
35658
- out.push('\n');
35659
- return;
35660
- }
35661
- if (Array.isArray(node.content))
35662
- node.content.forEach(walk);
35663
- if (BLOCK.has(node.type))
35664
- out.push('\n');
36891
+ function layoutBox(el, root) {
36892
+ let top = 0;
36893
+ let node = el;
36894
+ while (node && node !== root) {
36895
+ top += node.offsetTop;
36896
+ node = node.offsetParent;
36897
+ }
36898
+ return { top, height: el.offsetHeight };
36899
+ }
36900
+ const defaultSchedule = (cb) => {
36901
+ if (typeof requestAnimationFrame === 'function')
36902
+ requestAnimationFrame(() => cb());
36903
+ else
36904
+ setTimeout(cb, 16);
36905
+ };
36906
+ function toLayoutOptions(o) {
36907
+ return {
36908
+ page: resolvePageSize(o.page),
36909
+ margins: { ...o.margins },
36910
+ header: { height: o.header?.height ?? 0 },
36911
+ footer: { height: o.footer?.height ?? 0 },
36912
+ gap: o.gap ?? PAGE_GAP_PX,
35665
36913
  };
35666
- walk(doc);
35667
- return out.join('').replace(/\n{3,}/g, '\n\n').trim();
35668
- }
35669
-
35670
- var RichText = /*#__PURE__*/Object.freeze({
35671
- __proto__: null,
35672
- COLOR_PALETTE: toolbarConfig.COLOR_PALETTE,
35673
- CalloutNode: CalloutNode,
35674
- CobaltTaskItem: CobaltTaskItem,
35675
- CobaltTaskList: CobaltTaskList,
35676
- FontFamilyExtension: FontFamilyExtension,
35677
- FontSizeExtension: FontSizeExtension,
35678
- FontWeightExtension: FontWeightExtension,
35679
- IndentExtension: IndentExtension,
35680
- LetterSpacingExtension: LetterSpacingExtension,
35681
- LineHeightExtension: LineHeightExtension,
35682
- ListStyleExtension: ListStyleExtension,
35683
- MentionNode: MentionNode,
35684
- PRESETS: PRESETS,
35685
- SANITIZE_CONFIGS: SANITIZE_CONFIGS,
35686
- TABLE_CONTEXT_ITEMS: toolbarConfig.TABLE_CONTEXT_ITEMS,
35687
- VariableNode: VariableNode,
35688
- createEditor: createEditor,
35689
- defaultToolbarForPreset: defaultToolbarForPreset,
35690
- getExtensions: getExtensions,
35691
- htmlToJson: htmlToJson,
35692
- jsonToHtml: jsonToHtml,
35693
- jsonToText: jsonToText,
35694
- maxLengthForPreset: maxLengthForPreset,
35695
- sanitize: sanitize,
35696
- toolbarItems: toolbarConfig.toolbarItems
36914
+ }
36915
+ /**
36916
+ * Banda de salto: margen inferior (+ pie) de la hoja que termina, separación
36917
+ * entre hojas y margen superior (+ encabezado) de la que empieza. Dentro de una
36918
+ * tabla va envuelta en una fila con el colspan de la tabla (un div entre `tr`
36919
+ * lo expulsaría el navegador).
36920
+ */
36921
+ function buildPageGap(page, pageCount, o, header, cols = 0) {
36922
+ const foot = o.margins.bottom + o.footer.height;
36923
+ const head = o.margins.top + o.header.height;
36924
+ const band = document.createElement('div');
36925
+ band.className = 'co-doc-page-gap';
36926
+ band.setAttribute('contenteditable', 'false');
36927
+ band.style.height = `${foot + o.gap + head}px`;
36928
+ const bottom = document.createElement('div');
36929
+ bottom.className = 'co-doc-page-gap__foot';
36930
+ bottom.style.height = `${foot}px`;
36931
+ const between = document.createElement('div');
36932
+ between.className = 'co-doc-page-gap__between';
36933
+ between.style.height = `${o.gap}px`;
36934
+ const top = document.createElement('div');
36935
+ top.className = 'co-doc-page-gap__head';
36936
+ top.style.height = `${head}px`;
36937
+ top.style.paddingTop = `${o.margins.top}px`;
36938
+ top.style.boxSizing = 'border-box';
36939
+ if (header)
36940
+ top.appendChild(header);
36941
+ band.append(bottom, between, top);
36942
+ band.setAttribute('data-page', String(page));
36943
+ band.setAttribute('data-page-count', String(pageCount));
36944
+ if (!cols) {
36945
+ band.setAttribute('data-co-page-gap', String(page));
36946
+ return band;
36947
+ }
36948
+ const tr = document.createElement('tr');
36949
+ tr.className = 'co-doc-page-gap-row';
36950
+ tr.setAttribute('contenteditable', 'false');
36951
+ tr.setAttribute('data-co-page-gap', String(page));
36952
+ const td = document.createElement('td');
36953
+ td.setAttribute('colspan', String(cols));
36954
+ td.appendChild(band);
36955
+ tr.appendChild(td);
36956
+ return tr;
36957
+ }
36958
+ function measureLayout(view, opts, measure) {
36959
+ const root = view.dom;
36960
+ const atoms = [];
36961
+ view.state.doc.descendants((node, pos) => {
36962
+ const kind = classifyPaginationNode(node);
36963
+ if (kind === 'container')
36964
+ return true;
36965
+ if (kind === 'skip')
36966
+ return false;
36967
+ const dom = view.nodeDOM(pos);
36968
+ if (!(dom instanceof HTMLElement))
36969
+ return false;
36970
+ const box = measure(dom, root);
36971
+ if (box.height > 0)
36972
+ atoms.push({ pos, top: box.top, height: box.height, keepWithNext: isKeepWithNext(node) });
36973
+ return false;
36974
+ });
36975
+ const bands = Array.from(root.querySelectorAll('[data-co-page-gap]')).map((el) => measure(el, root));
36976
+ return computePageBreaks(stripBandOffsets(atoms, bands), pageContentHeight(opts));
36977
+ }
36978
+ const paginationKey = new PluginKey('coPagination');
36979
+ const Pagination = Extension.create({
36980
+ name: 'pagination',
36981
+ addOptions() {
36982
+ return {
36983
+ page: 'letter',
36984
+ margins: { top: 38, right: 38, bottom: 38, left: 38 },
36985
+ header: { height: 0 },
36986
+ footer: { height: 0 },
36987
+ gap: PAGE_GAP_PX,
36988
+ renderHeader: null,
36989
+ onPagesChange: null,
36990
+ measure: layoutBox,
36991
+ schedule: defaultSchedule,
36992
+ };
36993
+ },
36994
+ addStorage() {
36995
+ return { pageCount: 1 };
36996
+ },
36997
+ addCommands() {
36998
+ return {
36999
+ setPaginationOptions: (patch) => ({ tr, dispatch }) => {
37000
+ if (dispatch)
37001
+ tr.setMeta(PAGINATION_META, { patch });
37002
+ return true;
37003
+ },
37004
+ remeasurePages: () => ({ tr, dispatch }) => {
37005
+ if (dispatch)
37006
+ tr.setMeta(PAGINATION_META, { remeasure: true });
37007
+ return true;
37008
+ },
37009
+ };
37010
+ },
37011
+ addProseMirrorPlugins() {
37012
+ const options = this.options;
37013
+ const storage = this.storage;
37014
+ let lastEmitted = 0;
37015
+ const decorationsFor = (state, st) => {
37016
+ const decos = [];
37017
+ for (const br of st.layout.breaks) {
37018
+ if (br.pos < 0 || br.pos > state.doc.content.size)
37019
+ continue;
37020
+ // Nunca un widget de bloque dentro de contenido inline.
37021
+ if (state.doc.resolve(br.pos).parent.inlineContent)
37022
+ continue;
37023
+ const node = state.doc.nodeAt(br.pos);
37024
+ const cols = node?.type.name === 'tableRow' ? tableColumnCount(state.doc.resolve(br.pos).parent) : 0;
37025
+ decos.push(Decoration.widget(br.pos, () => buildPageGap(br.page, st.layout.pageCount, st.opts, options.renderHeader?.(br.page, st.layout.pageCount) ?? null, cols), { side: -1, key: `co-pg-${br.page}-${st.layout.pageCount}-v${st.version}-c${cols}` }));
37026
+ }
37027
+ return DecorationSet.create(state.doc, decos);
37028
+ };
37029
+ return [
37030
+ new Plugin({
37031
+ key: paginationKey,
37032
+ state: {
37033
+ init: () => ({ layout: { breaks: [], pageCount: 1 }, opts: toLayoutOptions(options), version: 0, dirty: true }),
37034
+ apply(tr, prev) {
37035
+ const meta = tr.getMeta(PAGINATION_META);
37036
+ let next = prev;
37037
+ if (tr.docChanged) {
37038
+ next = {
37039
+ ...next,
37040
+ dirty: true,
37041
+ // Un salto cuya frontera se borró (p. ej. unir párrafos en el borde de una hoja)
37042
+ // se descarta: mapearlo lo dejaría dentro de un textblock. La medición siguiente
37043
+ // lo recalcula.
37044
+ layout: {
37045
+ ...next.layout,
37046
+ breaks: next.layout.breaks.flatMap((b) => {
37047
+ const r = tr.mapping.mapResult(b.pos);
37048
+ return r.deleted ? [] : [{ ...b, pos: r.pos }];
37049
+ }),
37050
+ },
37051
+ };
37052
+ }
37053
+ if (meta?.patch) {
37054
+ const merged = toLayoutOptions({ ...next.opts, ...meta.patch, page: meta.patch.page ?? next.opts.page });
37055
+ next = { ...next, opts: merged, version: next.version + 1, dirty: true };
37056
+ }
37057
+ if (meta?.remeasure)
37058
+ next = { ...next, dirty: true };
37059
+ if (meta?.layout)
37060
+ next = { ...next, layout: meta.layout, dirty: false };
37061
+ return next;
37062
+ },
37063
+ },
37064
+ props: {
37065
+ decorations(state) {
37066
+ const st = paginationKey.getState(state);
37067
+ return st ? decorationsFor(state, st) : DecorationSet.empty;
37068
+ },
37069
+ },
37070
+ view(view) {
37071
+ const root = view.dom;
37072
+ if (!root.style.position)
37073
+ root.style.position = 'relative';
37074
+ let scheduled = false;
37075
+ let alive = true;
37076
+ const run = () => {
37077
+ scheduled = false;
37078
+ if (!alive || view.isDestroyed)
37079
+ return;
37080
+ const st = paginationKey.getState(view.state);
37081
+ if (!st)
37082
+ return;
37083
+ const layout = measureLayout(view, st.opts, options.measure);
37084
+ storage.pageCount = layout.pageCount;
37085
+ view.dispatch(view.state.tr.setMeta(PAGINATION_META, { layout }));
37086
+ if (layout.pageCount !== lastEmitted) {
37087
+ lastEmitted = layout.pageCount;
37088
+ options.onPagesChange?.(layout.pageCount);
37089
+ }
37090
+ };
37091
+ const maybeSchedule = () => {
37092
+ const st = paginationKey.getState(view.state);
37093
+ if (!st?.dirty || scheduled)
37094
+ return;
37095
+ scheduled = true;
37096
+ options.schedule(run);
37097
+ };
37098
+ const remeasure = () => {
37099
+ if (alive && !view.isDestroyed) {
37100
+ view.dispatch(view.state.tr.setMeta(PAGINATION_META, { remeasure: true }));
37101
+ }
37102
+ };
37103
+ // Imágenes que cargan tarde cambian alturas (las de las bandas no: tienen alto fijo).
37104
+ const onLoad = (e) => {
37105
+ const t = e.target;
37106
+ if (!t || t.tagName !== 'IMG' || t.closest('[data-co-page-gap]'))
37107
+ return;
37108
+ remeasure();
37109
+ };
37110
+ root.addEventListener('load', onLoad, true);
37111
+ const fonts = document.fonts;
37112
+ fonts?.ready?.then(remeasure).catch(() => { });
37113
+ // Fuentes que cargan después (un peso o familia aplicado por primera vez).
37114
+ fonts?.addEventListener?.('loadingdone', remeasure);
37115
+ maybeSchedule();
37116
+ return {
37117
+ update: () => maybeSchedule(),
37118
+ destroy: () => {
37119
+ alive = false;
37120
+ root.removeEventListener('load', onLoad, true);
37121
+ fonts?.removeEventListener?.('loadingdone', remeasure);
37122
+ },
37123
+ };
37124
+ },
37125
+ }),
37126
+ ];
37127
+ },
35697
37128
  });
35698
37129
 
35699
- exports.RichText = RichText;
37130
+ exports.CalloutNode = CalloutNode;
37131
+ exports.CobaltTaskItem = CobaltTaskItem;
37132
+ exports.CobaltTaskList = CobaltTaskList;
37133
+ exports.FIELD_SYNC_META = FIELD_SYNC_META;
37134
+ exports.FontFamilyExtension = FontFamilyExtension;
37135
+ exports.FontSizeExtension = FontSizeExtension;
37136
+ exports.FontWeightExtension = FontWeightExtension;
37137
+ exports.IMAGE_LAYOUT_MODES = IMAGE_LAYOUT_MODES;
37138
+ exports.IndentExtension = IndentExtension;
37139
+ exports.LetterSpacingExtension = LetterSpacingExtension;
37140
+ exports.LineHeightExtension = LineHeightExtension;
37141
+ exports.ListStyleExtension = ListStyleExtension;
37142
+ exports.MentionNode = MentionNode;
37143
+ exports.MergeField = MergeField;
37144
+ exports.PAGE_GAP_PX = PAGE_GAP_PX;
37145
+ exports.PAGE_SIZES = PAGE_SIZES;
37146
+ exports.PAGINATION_META = PAGINATION_META;
37147
+ exports.PRESETS = PRESETS;
37148
+ exports.Pagination = Pagination;
37149
+ exports.SANITIZE_CONFIGS = SANITIZE_CONFIGS;
37150
+ exports.SIGNATURE_TOKEN_STYLE = SIGNATURE_TOKEN_STYLE;
37151
+ exports.SignatureSlot = SignatureSlot;
37152
+ exports.TRAILING_BREAK_CLASS = TRAILING_BREAK_CLASS;
37153
+ exports.VariableNode = VariableNode;
37154
+ exports.applyImageLayoutMode = applyImageLayoutMode;
37155
+ exports.collectFields = collectFields;
37156
+ exports.computePageBreaks = computePageBreaks;
37157
+ exports.createEditor = createEditor;
37158
+ exports.defaultToolbarForPreset = defaultToolbarForPreset;
37159
+ exports.generateHTML = generateHTML;
37160
+ exports.generateJSON = generateJSON;
37161
+ exports.getExtensions = getExtensions;
37162
+ exports.getImageLayoutMode = getImageLayoutMode;
37163
+ exports.getPrintExtensions = getPrintExtensions;
37164
+ exports.headerImageWidth = headerImageWidth;
37165
+ exports.isPrintPreset = isPrintPreset;
37166
+ exports.layoutBox = layoutBox;
37167
+ exports.maxLengthForPreset = maxLengthForPreset;
37168
+ exports.nextFreeSlot = nextFreeSlot;
37169
+ exports.normalizePrintHtml = normalizePrintHtml;
37170
+ exports.pageContentHeight = pageContentHeight;
37171
+ exports.parseFieldToken = parseFieldToken;
37172
+ exports.readPrintHtml = readPrintHtml;
37173
+ exports.resolvePageSize = resolvePageSize;
37174
+ exports.sanitize = sanitize;
37175
+ exports.sanitizeFieldName = sanitizeFieldName;
37176
+ exports.serializePrintHtml = serializePrintHtml;
37177
+ exports.setFieldValuesInHtml = setFieldValuesInHtml;
37178
+ exports.signatureBoxStyle = signatureBoxStyle;
37179
+ exports.signatureSlotHtml = signatureSlotHtml;
37180
+ exports.signatureToken = signatureToken;
37181
+ exports.stripBandOffsets = stripBandOffsets;
37182
+ exports.writePrintHtml = writePrintHtml;