@jackuait/blok 0.6.0-beta.9 → 0.6.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 (320) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-Bn6Q_o8h.mjs → blok-BAh1rvUC.mjs} +3410 -2927
  3. package/dist/chunks/i18next-B47TKgbU.mjs +1303 -0
  4. package/dist/chunks/{i18next-loader-DjR4d8M7.mjs → i18next-loader-CHtGO6IK.mjs} +2 -2
  5. package/dist/chunks/{index-oe38cp86.mjs → index-DBWWKrDe.mjs} +12 -12
  6. package/dist/chunks/{inline-tool-convert-SRTkyaZn.mjs → inline-tool-convert-DduRc0fF.mjs} +1467 -951
  7. package/dist/chunks/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
  8. package/dist/chunks/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
  9. package/dist/{messages-DnXLrlHh.mjs → chunks/messages-4v4MuVEc.mjs} +6 -0
  10. package/dist/chunks/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
  11. package/dist/chunks/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
  12. package/dist/chunks/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
  13. package/dist/{messages-uKX8WBaD.mjs → chunks/messages-96kNZDll.mjs} +6 -0
  14. package/dist/chunks/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
  15. package/dist/{messages-DBn76jVV.mjs → chunks/messages-B217znr-.mjs} +8 -2
  16. package/dist/{messages-DT4dP5uK.mjs → chunks/messages-B8WNljW3.mjs} +6 -0
  17. package/dist/chunks/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
  18. package/dist/{messages-CZygwLwM.mjs → chunks/messages-BI43k_BD.mjs} +6 -0
  19. package/dist/{messages-CzTufCHu.mjs → chunks/messages-BJ6zrz2j.mjs} +6 -0
  20. package/dist/{messages-BoJc_p1r.mjs → chunks/messages-BUl_Rcnj.mjs} +6 -0
  21. package/dist/chunks/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
  22. package/dist/{messages-C2htQ_3F.mjs → chunks/messages-BcpCubnC.mjs} +6 -0
  23. package/dist/{messages-D5C3J9qr.mjs → chunks/messages-Bm-E4iRC.mjs} +6 -0
  24. package/dist/chunks/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
  25. package/dist/chunks/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
  26. package/dist/chunks/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
  27. package/dist/{messages-Dz9L52ol.mjs → chunks/messages-CRJ_mchV.mjs} +6 -0
  28. package/dist/chunks/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
  29. package/dist/chunks/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
  30. package/dist/{messages-R3hUSvr3.mjs → chunks/messages-CfiyT2Wi.mjs} +6 -0
  31. package/dist/{messages-CJdUsQ-c.mjs → chunks/messages-CgTq3QhU.mjs} +6 -0
  32. package/dist/chunks/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
  33. package/dist/{messages-Q7AO_FLv.mjs → chunks/messages-Cjjo7yHR.mjs} +6 -0
  34. package/dist/{messages-C99mq906.mjs → chunks/messages-Cl6ayUaq.mjs} +6 -0
  35. package/dist/chunks/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
  36. package/dist/chunks/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
  37. package/dist/chunks/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
  38. package/dist/{messages-BWF-zUpY.mjs → chunks/messages-CrCYPCk3.mjs} +6 -0
  39. package/dist/{messages-D-ZtY5v0.mjs → chunks/messages-Cs8zmZ3L.mjs} +6 -0
  40. package/dist/{messages-DprmQg6V.mjs → chunks/messages-CzK0LEhb.mjs} +6 -0
  41. package/dist/chunks/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
  42. package/dist/chunks/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
  43. package/dist/chunks/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
  44. package/dist/{messages-kep5wtm4.mjs → chunks/messages-D4qqwVgQ.mjs} +6 -0
  45. package/dist/chunks/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
  46. package/dist/{messages-CY8_RyFE.mjs → chunks/messages-D7u2bmP2.mjs} +6 -0
  47. package/dist/chunks/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
  48. package/dist/{messages-DLfR5bMd.mjs → chunks/messages-D9ndgBnU.mjs} +6 -0
  49. package/dist/{messages-CVw84KdI.mjs → chunks/messages-DDTQgImT.mjs} +6 -0
  50. package/dist/{messages-_ErNTNhk.mjs → chunks/messages-DH_jBeED.mjs} +6 -0
  51. package/dist/chunks/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
  52. package/dist/chunks/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
  53. package/dist/chunks/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
  54. package/dist/chunks/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
  55. package/dist/chunks/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
  56. package/dist/chunks/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
  57. package/dist/{messages-Z9nEU2xK.mjs → chunks/messages-DviiFSv2.mjs} +6 -0
  58. package/dist/chunks/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
  59. package/dist/{messages-w7v1GNaE.mjs → chunks/messages-Dzzn6XoD.mjs} +6 -0
  60. package/dist/{messages-CqWJcCbY.mjs → chunks/messages-GSByFygY.mjs} +6 -0
  61. package/dist/chunks/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
  62. package/dist/chunks/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
  63. package/dist/{messages-BU2nlrLK.mjs → chunks/messages-RonBBCnh.mjs} +6 -0
  64. package/dist/{messages-Bmu_S7GM.mjs → chunks/messages-VDriF5Qy.mjs} +6 -0
  65. package/dist/{messages-CLhcMlTc.mjs → chunks/messages-ZjUAIWb1.mjs} +6 -0
  66. package/dist/{messages-9SihnaXQ.mjs → chunks/messages-b1EdvUm0.mjs} +6 -0
  67. package/dist/{messages-DvFLX36Q.mjs → chunks/messages-begYOTgC.mjs} +6 -0
  68. package/dist/{messages-BMv4xwIr.mjs → chunks/messages-jrncnb-H.mjs} +6 -0
  69. package/dist/{messages-D5iv1Kox.mjs → chunks/messages-nefz1S71.mjs} +6 -0
  70. package/dist/{messages-CQwpzUFp.mjs → chunks/messages-ucTVgS5G.mjs} +6 -0
  71. package/dist/chunks/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
  72. package/dist/{messages-C9eaarcK.mjs → chunks/messages-wmi-iFkH.mjs} +6 -0
  73. package/dist/chunks/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
  74. package/dist/full.mjs +2 -2
  75. package/dist/locales.mjs +90 -84
  76. package/dist/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
  77. package/dist/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
  78. package/dist/{chunks/messages-DnXLrlHh.mjs → messages-4v4MuVEc.mjs} +6 -0
  79. package/dist/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
  80. package/dist/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
  81. package/dist/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
  82. package/dist/{chunks/messages-uKX8WBaD.mjs → messages-96kNZDll.mjs} +6 -0
  83. package/dist/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
  84. package/dist/{chunks/messages-DBn76jVV.mjs → messages-B217znr-.mjs} +8 -2
  85. package/dist/{chunks/messages-DT4dP5uK.mjs → messages-B8WNljW3.mjs} +6 -0
  86. package/dist/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
  87. package/dist/{chunks/messages-CZygwLwM.mjs → messages-BI43k_BD.mjs} +6 -0
  88. package/dist/{chunks/messages-CzTufCHu.mjs → messages-BJ6zrz2j.mjs} +6 -0
  89. package/dist/{chunks/messages-BoJc_p1r.mjs → messages-BUl_Rcnj.mjs} +6 -0
  90. package/dist/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
  91. package/dist/{chunks/messages-C2htQ_3F.mjs → messages-BcpCubnC.mjs} +6 -0
  92. package/dist/{chunks/messages-D5C3J9qr.mjs → messages-Bm-E4iRC.mjs} +6 -0
  93. package/dist/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
  94. package/dist/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
  95. package/dist/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
  96. package/dist/{chunks/messages-Dz9L52ol.mjs → messages-CRJ_mchV.mjs} +6 -0
  97. package/dist/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
  98. package/dist/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
  99. package/dist/{chunks/messages-R3hUSvr3.mjs → messages-CfiyT2Wi.mjs} +6 -0
  100. package/dist/{chunks/messages-CJdUsQ-c.mjs → messages-CgTq3QhU.mjs} +6 -0
  101. package/dist/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
  102. package/dist/{chunks/messages-Q7AO_FLv.mjs → messages-Cjjo7yHR.mjs} +6 -0
  103. package/dist/{chunks/messages-C99mq906.mjs → messages-Cl6ayUaq.mjs} +6 -0
  104. package/dist/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
  105. package/dist/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
  106. package/dist/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
  107. package/dist/{chunks/messages-BWF-zUpY.mjs → messages-CrCYPCk3.mjs} +6 -0
  108. package/dist/{chunks/messages-D-ZtY5v0.mjs → messages-Cs8zmZ3L.mjs} +6 -0
  109. package/dist/{chunks/messages-DprmQg6V.mjs → messages-CzK0LEhb.mjs} +6 -0
  110. package/dist/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
  111. package/dist/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
  112. package/dist/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
  113. package/dist/{chunks/messages-kep5wtm4.mjs → messages-D4qqwVgQ.mjs} +6 -0
  114. package/dist/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
  115. package/dist/{chunks/messages-CY8_RyFE.mjs → messages-D7u2bmP2.mjs} +6 -0
  116. package/dist/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
  117. package/dist/{chunks/messages-DLfR5bMd.mjs → messages-D9ndgBnU.mjs} +6 -0
  118. package/dist/{chunks/messages-CVw84KdI.mjs → messages-DDTQgImT.mjs} +6 -0
  119. package/dist/{chunks/messages-_ErNTNhk.mjs → messages-DH_jBeED.mjs} +6 -0
  120. package/dist/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
  121. package/dist/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
  122. package/dist/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
  123. package/dist/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
  124. package/dist/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
  125. package/dist/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
  126. package/dist/{chunks/messages-Z9nEU2xK.mjs → messages-DviiFSv2.mjs} +6 -0
  127. package/dist/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
  128. package/dist/{chunks/messages-w7v1GNaE.mjs → messages-Dzzn6XoD.mjs} +6 -0
  129. package/dist/{chunks/messages-CqWJcCbY.mjs → messages-GSByFygY.mjs} +6 -0
  130. package/dist/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
  131. package/dist/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
  132. package/dist/{chunks/messages-BU2nlrLK.mjs → messages-RonBBCnh.mjs} +6 -0
  133. package/dist/{chunks/messages-Bmu_S7GM.mjs → messages-VDriF5Qy.mjs} +6 -0
  134. package/dist/{chunks/messages-CLhcMlTc.mjs → messages-ZjUAIWb1.mjs} +6 -0
  135. package/dist/{chunks/messages-9SihnaXQ.mjs → messages-b1EdvUm0.mjs} +6 -0
  136. package/dist/{chunks/messages-DvFLX36Q.mjs → messages-begYOTgC.mjs} +6 -0
  137. package/dist/{chunks/messages-BMv4xwIr.mjs → messages-jrncnb-H.mjs} +6 -0
  138. package/dist/{chunks/messages-D5iv1Kox.mjs → messages-nefz1S71.mjs} +6 -0
  139. package/dist/{chunks/messages-CQwpzUFp.mjs → messages-ucTVgS5G.mjs} +6 -0
  140. package/dist/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
  141. package/dist/{chunks/messages-C9eaarcK.mjs → messages-wmi-iFkH.mjs} +6 -0
  142. package/dist/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
  143. package/dist/tools.mjs +3190 -1690
  144. package/dist/vendor.LICENSE.txt +109 -109
  145. package/package.json +43 -57
  146. package/src/blok.ts +12 -0
  147. package/src/components/__module.ts +21 -0
  148. package/src/components/block/api.ts +17 -0
  149. package/src/components/block/style-manager.ts +6 -2
  150. package/src/components/block/tool-renderer.ts +33 -30
  151. package/src/components/blocks.ts +132 -15
  152. package/src/components/i18n/locales/am/messages.json +6 -0
  153. package/src/components/i18n/locales/ar/messages.json +6 -0
  154. package/src/components/i18n/locales/az/messages.json +6 -0
  155. package/src/components/i18n/locales/bg/messages.json +6 -0
  156. package/src/components/i18n/locales/bn/messages.json +6 -0
  157. package/src/components/i18n/locales/bs/messages.json +6 -0
  158. package/src/components/i18n/locales/cs/messages.json +6 -0
  159. package/src/components/i18n/locales/da/messages.json +6 -0
  160. package/src/components/i18n/locales/de/messages.json +6 -0
  161. package/src/components/i18n/locales/dv/messages.json +6 -0
  162. package/src/components/i18n/locales/el/messages.json +6 -0
  163. package/src/components/i18n/locales/en/messages.json +6 -0
  164. package/src/components/i18n/locales/es/messages.json +6 -0
  165. package/src/components/i18n/locales/et/messages.json +6 -0
  166. package/src/components/i18n/locales/fa/messages.json +6 -0
  167. package/src/components/i18n/locales/fi/messages.json +6 -0
  168. package/src/components/i18n/locales/fil/messages.json +6 -0
  169. package/src/components/i18n/locales/fr/messages.json +6 -0
  170. package/src/components/i18n/locales/gu/messages.json +6 -0
  171. package/src/components/i18n/locales/he/messages.json +6 -0
  172. package/src/components/i18n/locales/hi/messages.json +6 -0
  173. package/src/components/i18n/locales/hr/messages.json +6 -0
  174. package/src/components/i18n/locales/hu/messages.json +6 -0
  175. package/src/components/i18n/locales/hy/messages.json +6 -0
  176. package/src/components/i18n/locales/id/messages.json +6 -0
  177. package/src/components/i18n/locales/it/messages.json +6 -0
  178. package/src/components/i18n/locales/ja/messages.json +6 -0
  179. package/src/components/i18n/locales/ka/messages.json +6 -0
  180. package/src/components/i18n/locales/km/messages.json +6 -0
  181. package/src/components/i18n/locales/kn/messages.json +6 -0
  182. package/src/components/i18n/locales/ko/messages.json +6 -0
  183. package/src/components/i18n/locales/ku/messages.json +6 -0
  184. package/src/components/i18n/locales/lo/messages.json +6 -0
  185. package/src/components/i18n/locales/lt/messages.json +6 -0
  186. package/src/components/i18n/locales/lv/messages.json +6 -0
  187. package/src/components/i18n/locales/mk/messages.json +6 -0
  188. package/src/components/i18n/locales/ml/messages.json +6 -0
  189. package/src/components/i18n/locales/mn/messages.json +6 -0
  190. package/src/components/i18n/locales/mr/messages.json +6 -0
  191. package/src/components/i18n/locales/ms/messages.json +6 -0
  192. package/src/components/i18n/locales/my/messages.json +6 -0
  193. package/src/components/i18n/locales/ne/messages.json +6 -0
  194. package/src/components/i18n/locales/nl/messages.json +6 -0
  195. package/src/components/i18n/locales/no/messages.json +6 -0
  196. package/src/components/i18n/locales/pa/messages.json +6 -0
  197. package/src/components/i18n/locales/pl/messages.json +6 -0
  198. package/src/components/i18n/locales/ps/messages.json +6 -0
  199. package/src/components/i18n/locales/pt/messages.json +6 -0
  200. package/src/components/i18n/locales/ro/messages.json +6 -0
  201. package/src/components/i18n/locales/ru/messages.json +6 -0
  202. package/src/components/i18n/locales/sd/messages.json +6 -0
  203. package/src/components/i18n/locales/si/messages.json +6 -0
  204. package/src/components/i18n/locales/sk/messages.json +6 -0
  205. package/src/components/i18n/locales/sl/messages.json +6 -0
  206. package/src/components/i18n/locales/sq/messages.json +6 -0
  207. package/src/components/i18n/locales/sr/messages.json +6 -0
  208. package/src/components/i18n/locales/sv/messages.json +6 -0
  209. package/src/components/i18n/locales/sw/messages.json +6 -0
  210. package/src/components/i18n/locales/ta/messages.json +6 -0
  211. package/src/components/i18n/locales/te/messages.json +6 -0
  212. package/src/components/i18n/locales/th/messages.json +6 -0
  213. package/src/components/i18n/locales/tr/messages.json +6 -0
  214. package/src/components/i18n/locales/ug/messages.json +6 -0
  215. package/src/components/i18n/locales/uk/messages.json +6 -0
  216. package/src/components/i18n/locales/ur/messages.json +6 -0
  217. package/src/components/i18n/locales/vi/messages.json +6 -0
  218. package/src/components/i18n/locales/yi/messages.json +6 -0
  219. package/src/components/i18n/locales/zh/messages.json +6 -0
  220. package/src/components/icons/index.ts +17 -0
  221. package/src/components/inline-tools/inline-tool-link.ts +1 -1
  222. package/src/components/inline-tools/inline-tool-marker.ts +737 -0
  223. package/src/components/inline-tools/utils/formatting-range-utils.ts +6 -3
  224. package/src/components/inline-tools/utils/marker-dom-utils.ts +17 -0
  225. package/src/components/modules/api/blocks.ts +34 -9
  226. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +75 -29
  227. package/src/components/modules/blockEvents/index.ts +13 -5
  228. package/src/components/modules/blockManager/blockManager.ts +81 -2
  229. package/src/components/modules/blockManager/hierarchy.ts +20 -2
  230. package/src/components/modules/blockManager/operations.ts +70 -35
  231. package/src/components/modules/blockManager/repository.ts +22 -0
  232. package/src/components/modules/blockManager/types.ts +3 -1
  233. package/src/components/modules/blockManager/yjs-sync.ts +173 -39
  234. package/src/components/modules/blockSelection.ts +3 -0
  235. package/src/components/modules/crossBlockSelection.ts +11 -3
  236. package/src/components/modules/drag/preview/DragPreview.ts +10 -2
  237. package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
  238. package/src/components/modules/drag/utils/drag.constants.ts +1 -1
  239. package/src/components/modules/normalizeInlineImages.ts +263 -0
  240. package/src/components/modules/paste/google-docs-preprocessor.ts +197 -0
  241. package/src/components/modules/paste/handlers/base.ts +43 -2
  242. package/src/components/modules/paste/handlers/html-handler.ts +1 -1
  243. package/src/components/modules/paste/handlers/index.ts +1 -0
  244. package/src/components/modules/paste/handlers/table-cells-handler.ts +104 -0
  245. package/src/components/modules/paste/index.ts +20 -3
  246. package/src/components/modules/readonly.ts +8 -2
  247. package/src/components/modules/rectangleSelection.ts +5 -2
  248. package/src/components/modules/renderer.ts +35 -0
  249. package/src/components/modules/saver.ts +52 -2
  250. package/src/components/modules/toolbar/blockSettings.ts +52 -44
  251. package/src/components/modules/toolbar/index.ts +124 -17
  252. package/src/components/modules/toolbar/inline/index.ts +4 -4
  253. package/src/components/modules/toolbar/plus-button.ts +3 -3
  254. package/src/components/modules/toolbar/settings-toggler.ts +3 -3
  255. package/src/components/modules/toolbar/styles.ts +7 -7
  256. package/src/components/modules/ui.ts +6 -6
  257. package/src/components/modules/uiControllers/controllers/blockHover.ts +16 -2
  258. package/src/components/modules/uiControllers/handlers/touch.ts +83 -10
  259. package/src/components/modules/yjs/block-observer.ts +9 -3
  260. package/src/components/modules/yjs/document-store.ts +10 -7
  261. package/src/components/modules/yjs/types.ts +8 -6
  262. package/src/components/modules/yjs/undo-history.ts +90 -11
  263. package/src/components/selection/fake-background/shadows.ts +1 -1
  264. package/src/components/shared/color-picker.ts +211 -0
  265. package/src/components/shared/color-presets.ts +25 -0
  266. package/src/components/ui/toolbox.ts +19 -11
  267. package/src/components/utils/color-mapping.ts +241 -0
  268. package/src/components/utils/notifier/draw.ts +9 -9
  269. package/src/components/utils/placeholder.ts +24 -8
  270. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -2
  271. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +14 -12
  272. package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
  273. package/src/components/utils/popover/popover-abstract.ts +27 -3
  274. package/src/components/utils/popover/popover-desktop.ts +26 -3
  275. package/src/components/utils/popover/popover-inline.ts +14 -1
  276. package/src/components/utils/popover/popover-mobile.ts +4 -4
  277. package/src/components/utils/popover/popover.const.ts +2 -2
  278. package/src/components/utils/sanitizer.ts +24 -3
  279. package/src/components/utils/tw.ts +17 -5
  280. package/src/stories/Header.stories.ts +106 -0
  281. package/src/stories/MarkerColors.stories.ts +730 -0
  282. package/src/stories/Popover.stories.ts +1 -3
  283. package/src/stories/Table.stories.ts +1662 -0
  284. package/src/styles/main.css +207 -37
  285. package/src/tools/header/index.ts +1 -1
  286. package/src/tools/index.ts +3 -1
  287. package/src/tools/list/caret-manager.ts +28 -10
  288. package/src/tools/list/constants.ts +2 -2
  289. package/src/tools/list/dom-builder.ts +3 -3
  290. package/src/tools/list/static-configs.ts +0 -1
  291. package/src/tools/paragraph/index.ts +9 -5
  292. package/src/tools/table/core/table-commands.ts +99 -0
  293. package/src/tools/table/core/table-controller.ts +231 -0
  294. package/src/tools/table/core/table-events.ts +102 -0
  295. package/src/tools/table/index.ts +1070 -174
  296. package/src/tools/table/ownership/table-event-broker.ts +74 -0
  297. package/src/tools/table/ownership/table-ownership-registry.ts +126 -0
  298. package/src/tools/table/table-add-controls.ts +85 -15
  299. package/src/tools/table/table-cell-blocks.ts +336 -38
  300. package/src/tools/table/table-cell-clipboard.ts +415 -0
  301. package/src/tools/table/table-cell-color-picker.ts +34 -0
  302. package/src/tools/table/table-cell-selection.ts +264 -15
  303. package/src/tools/table/table-core.ts +3 -42
  304. package/src/tools/table/table-heading-toggle.ts +2 -2
  305. package/src/tools/table/table-model.ts +623 -0
  306. package/src/tools/table/table-operations.ts +59 -78
  307. package/src/tools/table/table-resize.ts +15 -11
  308. package/src/tools/table/table-restrictions.ts +69 -3
  309. package/src/tools/table/table-row-col-action-handler.ts +22 -7
  310. package/src/tools/table/table-row-col-controls.ts +129 -12
  311. package/src/tools/table/table-row-col-drag.ts +14 -0
  312. package/src/tools/table/table-scroll-haze.ts +152 -0
  313. package/src/tools/table/types.ts +22 -1
  314. package/src/tools/table/view/table-cell-blocks-adapter.ts +47 -0
  315. package/src/variants/blok-minimum.ts +13 -0
  316. package/types/api/block.d.ts +13 -0
  317. package/types/api/blocks.d.ts +16 -0
  318. package/types/tools/table.d.ts +2 -0
  319. package/dist/chunks/i18next-CugVlwWp.mjs +0 -1292
  320. package/src/tools/table/data-normalizer.ts +0 -32
@@ -0,0 +1,730 @@
1
+ import type { Meta, StoryObj } from '@storybook/html-vite';
2
+ import { waitFor, expect } from 'storybook/test';
3
+
4
+ import { Marker } from '../tools';
5
+
6
+ import { createEditorContainer, defaultTools, simulateClick, waitForToolbar, selectTextInBlock, waitForPointerEvents } from './helpers';
7
+ import type { EditorFactoryOptions } from './helpers';
8
+
9
+ import type { OutputData } from '@/types';
10
+
11
+
12
+ interface MarkerColorArgs extends EditorFactoryOptions {
13
+ minHeight: number;
14
+ data: OutputData | undefined;
15
+ }
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Tools configuration — include the marker inline tool
19
+ // ---------------------------------------------------------------------------
20
+
21
+ const markerTools = {
22
+ ...defaultTools,
23
+ marker: Marker,
24
+ };
25
+
26
+ const createEditor = (args: MarkerColorArgs): HTMLElement =>
27
+ createEditorContainer({ ...args, tools: markerTools });
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Color presets (mirrors src/components/shared/color-presets.ts)
31
+ // ---------------------------------------------------------------------------
32
+
33
+ interface Preset {
34
+ name: string;
35
+ text: string;
36
+ bg: string;
37
+ }
38
+
39
+ const PRESETS: Preset[] = [
40
+ { name: 'gray', text: '#787774', bg: '#f1f1ef' },
41
+ { name: 'brown', text: '#9f6b53', bg: '#f4eeee' },
42
+ { name: 'orange', text: '#d9730d', bg: '#fbecdd' },
43
+ { name: 'yellow', text: '#cb9b00', bg: '#fbf3db' },
44
+ { name: 'green', text: '#448361', bg: '#edf3ec' },
45
+ { name: 'teal', text: '#2b9a8f', bg: '#e4f5f3' },
46
+ { name: 'blue', text: '#337ea9', bg: '#e7f3f8' },
47
+ { name: 'purple', text: '#9065b0', bg: '#f6f3f9' },
48
+ { name: 'pink', text: '#c14c8a', bg: '#f9f0f5' },
49
+ { name: 'red', text: '#d44c47', bg: '#fdebec' },
50
+ ];
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Mark-HTML helpers
54
+ // ---------------------------------------------------------------------------
55
+
56
+ /** Wrap `label` in a text-color-only mark. */
57
+ const textMark = (hex: string, label: string): string =>
58
+ `<mark style="color: ${hex}; background-color: transparent">${label}</mark>`;
59
+
60
+ /** Wrap `label` in a background-color mark. */
61
+ const bgMark = (hex: string, label: string): string =>
62
+ `<mark style="background-color: ${hex}">${label}</mark>`;
63
+
64
+ /** Wrap `label` in a dual-color (text + background) mark. */
65
+ const dualMark = (textHex: string, bgHex: string, label: string): string =>
66
+ `<mark style="color: ${textHex}; background-color: ${bgHex}">${label}</mark>`;
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Meta
70
+ // ---------------------------------------------------------------------------
71
+
72
+ const meta: Meta<MarkerColorArgs> = {
73
+ title: 'Components/Marker Colors',
74
+ tags: ['autodocs'],
75
+ args: {
76
+ minHeight: 200,
77
+ data: undefined,
78
+ },
79
+ render: createEditor,
80
+ };
81
+
82
+ export default meta;
83
+
84
+
85
+ type Story = StoryObj<MarkerColorArgs>;
86
+
87
+ // ---------------------------------------------------------------------------
88
+ // Interaction constants & helpers
89
+ // ---------------------------------------------------------------------------
90
+
91
+ const BLOCK_TESTID = '[data-blok-testid="block-wrapper"]';
92
+ const INLINE_TOOLBAR_TESTID = '[data-blok-testid="inline-toolbar"]';
93
+ const CONTENTEDITABLE_SELECTOR = '[contenteditable="true"]';
94
+ const MARKER_TOOL_SELECTOR = '[data-blok-item-name="marker"]';
95
+ const MARKER_PICKER_SELECTOR = '[data-blok-testid="marker-picker"]';
96
+ const MARKER_TAB_BG_SELECTOR = '[data-blok-testid="marker-tab-background-color"]';
97
+ const MARKER_GRID_SELECTOR = '[data-blok-testid="marker-grid"]';
98
+ const TIMEOUT_INIT = { timeout: 5000 };
99
+ const TIMEOUT_ACTION = { timeout: 5000 };
100
+
101
+ /**
102
+ * Shared helper: waits for the editor to initialize, selects text in the
103
+ * first block's contenteditable, opens the inline toolbar, then clicks the
104
+ * marker tool to reveal the color picker.
105
+ */
106
+ const openMarkerPicker = async (canvasElement: HTMLElement): Promise<void> => {
107
+ // 1. Wait for the editor block to appear
108
+ await waitFor(
109
+ () => {
110
+ const block = canvasElement.querySelector(BLOCK_TESTID);
111
+
112
+ expect(block).toBeInTheDocument();
113
+ },
114
+ TIMEOUT_INIT
115
+ );
116
+
117
+ // 2. Wait for toolbar initialization via requestIdleCallback
118
+ await waitForToolbar(canvasElement);
119
+
120
+ // 3. Select text in the first block's contenteditable
121
+ const block = canvasElement.querySelector(BLOCK_TESTID);
122
+ const contentEditable = block?.querySelector(CONTENTEDITABLE_SELECTOR);
123
+
124
+ if (contentEditable) {
125
+ simulateClick(contentEditable);
126
+
127
+ const range = document.createRange();
128
+
129
+ range.selectNodeContents(contentEditable);
130
+
131
+ const selection = window.getSelection();
132
+
133
+ selection?.removeAllRanges();
134
+ selection?.addRange(range);
135
+
136
+ (contentEditable as HTMLElement).focus();
137
+
138
+ // 4. Dispatch selectionchange event
139
+ document.dispatchEvent(new Event('selectionchange'));
140
+ }
141
+
142
+ // 5. Wait for debounced selection handler (180ms) plus popover creation
143
+ await new Promise((resolve) => setTimeout(resolve, 300));
144
+
145
+ // 6. Wait for inline toolbar to appear
146
+ await waitFor(
147
+ () => {
148
+ const inlineToolbar = document.querySelector(INLINE_TOOLBAR_TESTID);
149
+
150
+ expect(inlineToolbar).toBeInTheDocument();
151
+ },
152
+ TIMEOUT_ACTION
153
+ );
154
+
155
+ // 7. Wait for pointer events on the popover container
156
+ await waitForPointerEvents(`${INLINE_TOOLBAR_TESTID} [data-blok-testid="popover-container"]`);
157
+
158
+ // Small delay for CSS animation to complete
159
+ await new Promise((resolve) => setTimeout(resolve, 150));
160
+
161
+ // 8. Click the marker tool to open the picker
162
+ const markerTool = document.querySelector(MARKER_TOOL_SELECTOR);
163
+
164
+ expect(markerTool).toBeInTheDocument();
165
+
166
+ if (markerTool) {
167
+ simulateClick(markerTool);
168
+ }
169
+
170
+ // 9. Wait for the picker element to appear
171
+ await waitFor(
172
+ () => {
173
+ const picker = document.querySelector(MARKER_PICKER_SELECTOR);
174
+
175
+ expect(picker).toBeInTheDocument();
176
+ },
177
+ TIMEOUT_ACTION
178
+ );
179
+ };
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // Interaction data fixtures
183
+ // ---------------------------------------------------------------------------
184
+
185
+ /** Plain text paragraph for picker interaction tests. */
186
+ const pickerData: OutputData = {
187
+ time: Date.now(),
188
+ version: '1.0.0',
189
+ blocks: [
190
+ {
191
+ id: 'picker-block-1',
192
+ type: 'paragraph',
193
+ data: { text: 'Select this text to open the marker color picker.' },
194
+ },
195
+ ],
196
+ };
197
+
198
+ /** Paragraph with pre-applied red text color for active-swatch tests. */
199
+ const preColoredTextData: OutputData = {
200
+ time: Date.now(),
201
+ version: '1.0.0',
202
+ blocks: [
203
+ {
204
+ id: 'pre-color-text-1',
205
+ type: 'paragraph',
206
+ data: {
207
+ text: '<mark style="color: #d44c47; background-color: transparent">Red colored text</mark>',
208
+ },
209
+ },
210
+ ],
211
+ };
212
+
213
+ /** Paragraph with pre-applied orange background color for active-swatch tests. */
214
+ const preColoredBgData: OutputData = {
215
+ time: Date.now(),
216
+ version: '1.0.0',
217
+ blocks: [
218
+ {
219
+ id: 'pre-color-bg-1',
220
+ type: 'paragraph',
221
+ data: {
222
+ text: '<mark style="background-color: #fbecdd">Orange highlighted text</mark>',
223
+ },
224
+ },
225
+ ],
226
+ };
227
+
228
+ // ---------------------------------------------------------------------------
229
+ // Static stories
230
+ // ---------------------------------------------------------------------------
231
+
232
+ /**
233
+ * Single paragraph showing all 10 text-color presets.
234
+ * Each color name is rendered with its corresponding foreground hex value.
235
+ */
236
+ export const AllTextColors: Story = {
237
+ args: {
238
+ data: {
239
+ time: Date.now(),
240
+ version: '1.0.0',
241
+ blocks: [
242
+ {
243
+ id: 'text-colors-1',
244
+ type: 'paragraph',
245
+ data: {
246
+ text: PRESETS.map((p) => textMark(p.text, p.name)).join(' '),
247
+ },
248
+ },
249
+ ],
250
+ },
251
+ },
252
+ };
253
+
254
+ /**
255
+ * Single paragraph showing all 10 background-color presets.
256
+ * Each color name is highlighted with its corresponding background hex value.
257
+ */
258
+ export const AllBackgroundColors: Story = {
259
+ args: {
260
+ data: {
261
+ time: Date.now(),
262
+ version: '1.0.0',
263
+ blocks: [
264
+ {
265
+ id: 'bg-colors-1',
266
+ type: 'paragraph',
267
+ data: {
268
+ text: PRESETS.map((p) => bgMark(p.bg, p.name)).join(' '),
269
+ },
270
+ },
271
+ ],
272
+ },
273
+ },
274
+ };
275
+
276
+ /**
277
+ * Ten paragraphs — one per preset — each showing the same-preset text + background
278
+ * combo applied to a full sentence.
279
+ */
280
+ export const DualColorMatrix: Story = {
281
+ args: {
282
+ data: {
283
+ time: Date.now(),
284
+ version: '1.0.0',
285
+ blocks: PRESETS.map((p) => ({
286
+ id: `dual-${p.name}`,
287
+ type: 'paragraph',
288
+ data: {
289
+ text: dualMark(
290
+ p.text,
291
+ p.bg,
292
+ `This sentence uses the ${p.name} preset with text and background color.`
293
+ ),
294
+ },
295
+ })),
296
+ },
297
+ },
298
+ };
299
+
300
+ /**
301
+ * Bold text rendered with each of the 10 text-color presets.
302
+ * Verifies that marker styles compose correctly with the bold inline tool.
303
+ */
304
+ export const ColorWithBold: Story = {
305
+ args: {
306
+ data: {
307
+ time: Date.now(),
308
+ version: '1.0.0',
309
+ blocks: [
310
+ {
311
+ id: 'bold-colors-1',
312
+ type: 'paragraph',
313
+ data: {
314
+ text: PRESETS.map(
315
+ (p) => textMark(p.text, `<strong>Bold ${p.name}</strong>`)
316
+ ).join(' '),
317
+ },
318
+ },
319
+ ],
320
+ },
321
+ },
322
+ };
323
+
324
+ /**
325
+ * Italic text rendered with each of the 10 text-color presets.
326
+ * Verifies that marker styles compose correctly with the italic inline tool.
327
+ */
328
+ export const ColorWithItalic: Story = {
329
+ args: {
330
+ data: {
331
+ time: Date.now(),
332
+ version: '1.0.0',
333
+ blocks: [
334
+ {
335
+ id: 'italic-colors-1',
336
+ type: 'paragraph',
337
+ data: {
338
+ text: PRESETS.map(
339
+ (p) => textMark(p.text, `<em>Italic ${p.name}</em>`)
340
+ ).join(' '),
341
+ },
342
+ },
343
+ ],
344
+ },
345
+ },
346
+ };
347
+
348
+ /**
349
+ * Linked text rendered with each of the 10 text-color presets.
350
+ * Verifies that marker styles compose correctly with link formatting.
351
+ */
352
+ export const ColorWithLink: Story = {
353
+ args: {
354
+ data: {
355
+ time: Date.now(),
356
+ version: '1.0.0',
357
+ blocks: [
358
+ {
359
+ id: 'link-colors-1',
360
+ type: 'paragraph',
361
+ data: {
362
+ text: PRESETS.map(
363
+ (p) => textMark(p.text, `<a href="#">Link ${p.name}</a>`)
364
+ ).join(' '),
365
+ },
366
+ },
367
+ ],
368
+ },
369
+ },
370
+ };
371
+
372
+ /**
373
+ * Ten paragraphs showing colored text within plain surrounding text.
374
+ * Verifies visual rendering when only a word mid-sentence is colored.
375
+ */
376
+ export const PartialTextColor: Story = {
377
+ args: {
378
+ data: {
379
+ time: Date.now(),
380
+ version: '1.0.0',
381
+ blocks: PRESETS.map((p) => ({
382
+ id: `partial-${p.name}`,
383
+ type: 'paragraph',
384
+ data: {
385
+ text: `The word ${textMark(p.text, p.name)} appears mid-sentence with surrounding plain text.`,
386
+ },
387
+ })),
388
+ },
389
+ },
390
+ };
391
+
392
+ // ---------------------------------------------------------------------------
393
+ // PICKER UI — Interaction stories with play functions
394
+ // ---------------------------------------------------------------------------
395
+
396
+ /**
397
+ * Opens the marker picker on the text-color tab and verifies the grid
398
+ * contains exactly 10 color swatches.
399
+ */
400
+ export const PickerTextTab: Story = {
401
+ args: {
402
+ data: pickerData,
403
+ },
404
+ play: async ({ canvasElement, step }) => {
405
+ await step('Open marker picker on text tab', async () => {
406
+ await openMarkerPicker(canvasElement);
407
+
408
+ await waitFor(
409
+ () => {
410
+ const grid = document.querySelector(MARKER_GRID_SELECTOR);
411
+ const swatches = grid?.querySelectorAll('button');
412
+
413
+ expect(swatches?.length).toBe(10);
414
+ },
415
+ TIMEOUT_ACTION
416
+ );
417
+ });
418
+ },
419
+ };
420
+
421
+ /**
422
+ * Opens the marker picker, switches to the background-color tab, and
423
+ * verifies the grid contains exactly 10 color swatches.
424
+ */
425
+ export const PickerBackgroundTab: Story = {
426
+ args: {
427
+ data: pickerData,
428
+ },
429
+ play: async ({ canvasElement, step }) => {
430
+ await step('Open marker picker', async () => {
431
+ await openMarkerPicker(canvasElement);
432
+ });
433
+
434
+ await step('Switch to background tab', async () => {
435
+ const bgTab = document.querySelector(MARKER_TAB_BG_SELECTOR);
436
+
437
+ expect(bgTab).toBeInTheDocument();
438
+
439
+ if (bgTab) {
440
+ simulateClick(bgTab);
441
+ }
442
+
443
+ await waitFor(
444
+ () => {
445
+ const grid = document.querySelector(MARKER_GRID_SELECTOR);
446
+
447
+ expect(grid?.querySelectorAll('button')?.length).toBe(10);
448
+ },
449
+ TIMEOUT_ACTION
450
+ );
451
+ });
452
+ },
453
+ };
454
+
455
+ /**
456
+ * Opens the marker picker and verifies the "Default" reset button is visible.
457
+ */
458
+ export const PickerDefaultButton: Story = {
459
+ args: {
460
+ data: pickerData,
461
+ },
462
+ play: async ({ canvasElement, step }) => {
463
+ await step('Open marker picker and verify default button', async () => {
464
+ await openMarkerPicker(canvasElement);
465
+
466
+ await waitFor(
467
+ () => {
468
+ const defaultBtn = document.querySelector('[data-blok-testid="marker-default-btn"]');
469
+
470
+ expect(defaultBtn).toBeInTheDocument();
471
+ },
472
+ TIMEOUT_ACTION
473
+ );
474
+ });
475
+ },
476
+ };
477
+
478
+ /**
479
+ * Opens the marker picker on uncolored text and verifies no swatch
480
+ * has an active ring indicator.
481
+ */
482
+ export const PickerNoActiveSwatch: Story = {
483
+ args: {
484
+ data: pickerData,
485
+ },
486
+ play: async ({ canvasElement, step }) => {
487
+ await step('Open marker picker and verify no active swatch', async () => {
488
+ await openMarkerPicker(canvasElement);
489
+
490
+ await waitFor(
491
+ () => {
492
+ const grid = document.querySelector(MARKER_GRID_SELECTOR);
493
+ const swatches = grid?.querySelectorAll('button');
494
+
495
+ expect(swatches?.length).toBe(10);
496
+
497
+ swatches?.forEach((swatch) => {
498
+ expect(swatch.className).not.toContain('ring-black/30');
499
+ });
500
+ },
501
+ TIMEOUT_ACTION
502
+ );
503
+ });
504
+ },
505
+ };
506
+
507
+ /**
508
+ * Selects pre-colored red text, opens the marker picker, and verifies the
509
+ * red swatch shows an active ring indicator.
510
+ */
511
+ export const PickerActiveTextSwatch: Story = {
512
+ args: {
513
+ data: preColoredTextData,
514
+ },
515
+ play: async ({ canvasElement, step }) => {
516
+ await step('Select pre-colored text and open picker', async () => {
517
+ // Wait for the editor block to appear
518
+ await waitFor(
519
+ () => {
520
+ const block = canvasElement.querySelector(BLOCK_TESTID);
521
+
522
+ expect(block).toBeInTheDocument();
523
+ },
524
+ TIMEOUT_INIT
525
+ );
526
+
527
+ // Wait for toolbar initialization
528
+ await waitForToolbar(canvasElement);
529
+
530
+ // Select the <mark> element text
531
+ const block = canvasElement.querySelector(BLOCK_TESTID);
532
+
533
+ if (block) {
534
+ selectTextInBlock(block, 'mark');
535
+ }
536
+
537
+ // Wait for debounced selection handler
538
+ await new Promise((resolve) => setTimeout(resolve, 300));
539
+
540
+ // Wait for inline toolbar
541
+ await waitFor(
542
+ () => {
543
+ const inlineToolbar = document.querySelector(INLINE_TOOLBAR_TESTID);
544
+
545
+ expect(inlineToolbar).toBeInTheDocument();
546
+ },
547
+ TIMEOUT_ACTION
548
+ );
549
+
550
+ // Wait for pointer events
551
+ await waitForPointerEvents(`${INLINE_TOOLBAR_TESTID} [data-blok-testid="popover-container"]`);
552
+ await new Promise((resolve) => setTimeout(resolve, 150));
553
+
554
+ // Click the marker tool to open the picker
555
+ const markerTool = document.querySelector(MARKER_TOOL_SELECTOR);
556
+
557
+ expect(markerTool).toBeInTheDocument();
558
+
559
+ if (markerTool) {
560
+ simulateClick(markerTool);
561
+ }
562
+
563
+ // Wait for the picker
564
+ await waitFor(
565
+ () => {
566
+ const picker = document.querySelector(MARKER_PICKER_SELECTOR);
567
+
568
+ expect(picker).toBeInTheDocument();
569
+ },
570
+ TIMEOUT_ACTION
571
+ );
572
+
573
+ // Verify the red swatch has the active ring
574
+ await waitFor(
575
+ () => {
576
+ const redSwatch = document.querySelector('[data-blok-testid="marker-swatch-red"]');
577
+
578
+ expect(redSwatch?.className).toContain('ring-black/30');
579
+ },
580
+ TIMEOUT_ACTION
581
+ );
582
+ });
583
+ },
584
+ };
585
+
586
+ /**
587
+ * Selects pre-colored orange background text, opens the marker picker,
588
+ * switches to the background tab, and verifies the orange swatch shows
589
+ * an active ring indicator.
590
+ */
591
+ export const PickerActiveBackgroundSwatch: Story = {
592
+ args: {
593
+ data: preColoredBgData,
594
+ },
595
+ play: async ({ canvasElement, step }) => {
596
+ await step('Select pre-colored background text and open picker', async () => {
597
+ // Wait for the editor block to appear
598
+ await waitFor(
599
+ () => {
600
+ const block = canvasElement.querySelector(BLOCK_TESTID);
601
+
602
+ expect(block).toBeInTheDocument();
603
+ },
604
+ TIMEOUT_INIT
605
+ );
606
+
607
+ // Wait for toolbar initialization
608
+ await waitForToolbar(canvasElement);
609
+
610
+ // Select the <mark> element text
611
+ const block = canvasElement.querySelector(BLOCK_TESTID);
612
+
613
+ if (block) {
614
+ selectTextInBlock(block, 'mark');
615
+ }
616
+
617
+ // Wait for debounced selection handler
618
+ await new Promise((resolve) => setTimeout(resolve, 300));
619
+
620
+ // Wait for inline toolbar
621
+ await waitFor(
622
+ () => {
623
+ const inlineToolbar = document.querySelector(INLINE_TOOLBAR_TESTID);
624
+
625
+ expect(inlineToolbar).toBeInTheDocument();
626
+ },
627
+ TIMEOUT_ACTION
628
+ );
629
+
630
+ // Wait for pointer events
631
+ await waitForPointerEvents(`${INLINE_TOOLBAR_TESTID} [data-blok-testid="popover-container"]`);
632
+ await new Promise((resolve) => setTimeout(resolve, 150));
633
+
634
+ // Click the marker tool to open the picker
635
+ const markerTool = document.querySelector(MARKER_TOOL_SELECTOR);
636
+
637
+ expect(markerTool).toBeInTheDocument();
638
+
639
+ if (markerTool) {
640
+ simulateClick(markerTool);
641
+ }
642
+
643
+ // Wait for the picker
644
+ await waitFor(
645
+ () => {
646
+ const picker = document.querySelector(MARKER_PICKER_SELECTOR);
647
+
648
+ expect(picker).toBeInTheDocument();
649
+ },
650
+ TIMEOUT_ACTION
651
+ );
652
+
653
+ // Switch to background tab
654
+ const bgTab = document.querySelector(MARKER_TAB_BG_SELECTOR);
655
+
656
+ expect(bgTab).toBeInTheDocument();
657
+
658
+ if (bgTab) {
659
+ simulateClick(bgTab);
660
+ }
661
+
662
+ // Verify the orange swatch has the active ring
663
+ await waitFor(
664
+ () => {
665
+ const orangeSwatch = document.querySelector('[data-blok-testid="marker-swatch-orange"]');
666
+
667
+ expect(orangeSwatch?.className).toContain('ring-black/30');
668
+ },
669
+ TIMEOUT_ACTION
670
+ );
671
+ });
672
+ },
673
+ };
674
+
675
+ /**
676
+ * Selects pre-colored text and verifies the marker tool button shows its
677
+ * active state (data-blok-popover-item-active="true") without opening
678
+ * the picker.
679
+ */
680
+ export const MarkerButtonActive: Story = {
681
+ args: {
682
+ data: preColoredTextData,
683
+ },
684
+ play: async ({ canvasElement, step }) => {
685
+ await step('Select pre-colored text to show marker active state', async () => {
686
+ // Wait for the editor block to appear
687
+ await waitFor(
688
+ () => {
689
+ const block = canvasElement.querySelector(BLOCK_TESTID);
690
+
691
+ expect(block).toBeInTheDocument();
692
+ },
693
+ TIMEOUT_INIT
694
+ );
695
+
696
+ // Wait for toolbar initialization
697
+ await waitForToolbar(canvasElement);
698
+
699
+ // Select the <mark> element text
700
+ const block = canvasElement.querySelector(BLOCK_TESTID);
701
+
702
+ if (block) {
703
+ selectTextInBlock(block, 'mark');
704
+ }
705
+
706
+ // Wait for debounced selection handler
707
+ await new Promise((resolve) => setTimeout(resolve, 300));
708
+
709
+ // Wait for inline toolbar
710
+ await waitFor(
711
+ () => {
712
+ const inlineToolbar = document.querySelector(INLINE_TOOLBAR_TESTID);
713
+
714
+ expect(inlineToolbar).toBeInTheDocument();
715
+ },
716
+ TIMEOUT_ACTION
717
+ );
718
+
719
+ // Verify the marker tool button is active
720
+ await waitFor(
721
+ () => {
722
+ const markerTool = document.querySelector(MARKER_TOOL_SELECTOR);
723
+
724
+ expect(markerTool).toHaveAttribute('data-blok-popover-item-active', 'true');
725
+ },
726
+ TIMEOUT_ACTION
727
+ );
728
+ });
729
+ },
730
+ };