@jackuait/blok 0.6.0-beta.9 → 0.7.0-beta.1

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 (336) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-Bn6Q_o8h.mjs → blok-ob9Fwr1L.mjs} +3414 -2975
  3. package/dist/chunks/i18next-B47TKgbU.mjs +1303 -0
  4. package/dist/chunks/{i18next-loader-DjR4d8M7.mjs → i18next-loader-Bu3vFvye.mjs} +2 -2
  5. package/dist/chunks/{index-oe38cp86.mjs → index-CZmRzRIX.mjs} +12 -12
  6. package/dist/chunks/{inline-tool-convert-SRTkyaZn.mjs → inline-tool-convert-CvFW2iie.mjs} +1579 -961
  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 +30 -27
  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 +3537 -1710
  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/constants/data-attributes.ts +7 -0
  153. package/src/components/i18n/locales/am/messages.json +6 -0
  154. package/src/components/i18n/locales/ar/messages.json +6 -0
  155. package/src/components/i18n/locales/az/messages.json +6 -0
  156. package/src/components/i18n/locales/bg/messages.json +6 -0
  157. package/src/components/i18n/locales/bn/messages.json +6 -0
  158. package/src/components/i18n/locales/bs/messages.json +6 -0
  159. package/src/components/i18n/locales/cs/messages.json +6 -0
  160. package/src/components/i18n/locales/da/messages.json +6 -0
  161. package/src/components/i18n/locales/de/messages.json +6 -0
  162. package/src/components/i18n/locales/dv/messages.json +6 -0
  163. package/src/components/i18n/locales/el/messages.json +6 -0
  164. package/src/components/i18n/locales/en/messages.json +6 -0
  165. package/src/components/i18n/locales/es/messages.json +6 -0
  166. package/src/components/i18n/locales/et/messages.json +6 -0
  167. package/src/components/i18n/locales/fa/messages.json +6 -0
  168. package/src/components/i18n/locales/fi/messages.json +6 -0
  169. package/src/components/i18n/locales/fil/messages.json +6 -0
  170. package/src/components/i18n/locales/fr/messages.json +6 -0
  171. package/src/components/i18n/locales/gu/messages.json +6 -0
  172. package/src/components/i18n/locales/he/messages.json +6 -0
  173. package/src/components/i18n/locales/hi/messages.json +6 -0
  174. package/src/components/i18n/locales/hr/messages.json +6 -0
  175. package/src/components/i18n/locales/hu/messages.json +6 -0
  176. package/src/components/i18n/locales/hy/messages.json +6 -0
  177. package/src/components/i18n/locales/id/messages.json +6 -0
  178. package/src/components/i18n/locales/it/messages.json +6 -0
  179. package/src/components/i18n/locales/ja/messages.json +6 -0
  180. package/src/components/i18n/locales/ka/messages.json +6 -0
  181. package/src/components/i18n/locales/km/messages.json +6 -0
  182. package/src/components/i18n/locales/kn/messages.json +6 -0
  183. package/src/components/i18n/locales/ko/messages.json +6 -0
  184. package/src/components/i18n/locales/ku/messages.json +6 -0
  185. package/src/components/i18n/locales/lo/messages.json +6 -0
  186. package/src/components/i18n/locales/lt/messages.json +6 -0
  187. package/src/components/i18n/locales/lv/messages.json +6 -0
  188. package/src/components/i18n/locales/mk/messages.json +6 -0
  189. package/src/components/i18n/locales/ml/messages.json +6 -0
  190. package/src/components/i18n/locales/mn/messages.json +6 -0
  191. package/src/components/i18n/locales/mr/messages.json +6 -0
  192. package/src/components/i18n/locales/ms/messages.json +6 -0
  193. package/src/components/i18n/locales/my/messages.json +6 -0
  194. package/src/components/i18n/locales/ne/messages.json +6 -0
  195. package/src/components/i18n/locales/nl/messages.json +6 -0
  196. package/src/components/i18n/locales/no/messages.json +6 -0
  197. package/src/components/i18n/locales/pa/messages.json +6 -0
  198. package/src/components/i18n/locales/pl/messages.json +6 -0
  199. package/src/components/i18n/locales/ps/messages.json +6 -0
  200. package/src/components/i18n/locales/pt/messages.json +6 -0
  201. package/src/components/i18n/locales/ro/messages.json +6 -0
  202. package/src/components/i18n/locales/ru/messages.json +6 -0
  203. package/src/components/i18n/locales/sd/messages.json +6 -0
  204. package/src/components/i18n/locales/si/messages.json +6 -0
  205. package/src/components/i18n/locales/sk/messages.json +6 -0
  206. package/src/components/i18n/locales/sl/messages.json +6 -0
  207. package/src/components/i18n/locales/sq/messages.json +6 -0
  208. package/src/components/i18n/locales/sr/messages.json +6 -0
  209. package/src/components/i18n/locales/sv/messages.json +6 -0
  210. package/src/components/i18n/locales/sw/messages.json +6 -0
  211. package/src/components/i18n/locales/ta/messages.json +6 -0
  212. package/src/components/i18n/locales/te/messages.json +6 -0
  213. package/src/components/i18n/locales/th/messages.json +6 -0
  214. package/src/components/i18n/locales/tr/messages.json +6 -0
  215. package/src/components/i18n/locales/ug/messages.json +6 -0
  216. package/src/components/i18n/locales/uk/messages.json +6 -0
  217. package/src/components/i18n/locales/ur/messages.json +6 -0
  218. package/src/components/i18n/locales/vi/messages.json +6 -0
  219. package/src/components/i18n/locales/yi/messages.json +6 -0
  220. package/src/components/i18n/locales/zh/messages.json +6 -0
  221. package/src/components/icons/index.ts +61 -7
  222. package/src/components/inline-tools/inline-tool-link.ts +1 -1
  223. package/src/components/inline-tools/inline-tool-marker.ts +737 -0
  224. package/src/components/inline-tools/utils/formatting-range-utils.ts +6 -3
  225. package/src/components/inline-tools/utils/marker-dom-utils.ts +17 -0
  226. package/src/components/modules/api/blocks.ts +34 -9
  227. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +75 -29
  228. package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +54 -2
  229. package/src/components/modules/blockEvents/constants.ts +12 -0
  230. package/src/components/modules/blockEvents/index.ts +13 -5
  231. package/src/components/modules/blockManager/blockManager.ts +81 -2
  232. package/src/components/modules/blockManager/hierarchy.ts +20 -2
  233. package/src/components/modules/blockManager/operations.ts +70 -35
  234. package/src/components/modules/blockManager/repository.ts +22 -0
  235. package/src/components/modules/blockManager/types.ts +3 -1
  236. package/src/components/modules/blockManager/yjs-sync.ts +173 -39
  237. package/src/components/modules/blockSelection.ts +3 -0
  238. package/src/components/modules/crossBlockSelection.ts +11 -3
  239. package/src/components/modules/drag/preview/DragPreview.ts +10 -2
  240. package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
  241. package/src/components/modules/drag/utils/drag.constants.ts +1 -1
  242. package/src/components/modules/normalizeInlineImages.ts +263 -0
  243. package/src/components/modules/paste/google-docs-preprocessor.ts +197 -0
  244. package/src/components/modules/paste/handlers/base.ts +43 -2
  245. package/src/components/modules/paste/handlers/html-handler.ts +1 -1
  246. package/src/components/modules/paste/handlers/index.ts +1 -0
  247. package/src/components/modules/paste/handlers/table-cells-handler.ts +104 -0
  248. package/src/components/modules/paste/index.ts +20 -3
  249. package/src/components/modules/readonly.ts +8 -2
  250. package/src/components/modules/rectangleSelection.ts +5 -2
  251. package/src/components/modules/renderer.ts +35 -0
  252. package/src/components/modules/saver.ts +52 -2
  253. package/src/components/modules/toolbar/blockSettings.ts +52 -44
  254. package/src/components/modules/toolbar/index.ts +124 -17
  255. package/src/components/modules/toolbar/inline/index.ts +4 -4
  256. package/src/components/modules/toolbar/plus-button.ts +3 -3
  257. package/src/components/modules/toolbar/settings-toggler.ts +3 -3
  258. package/src/components/modules/toolbar/styles.ts +7 -7
  259. package/src/components/modules/ui.ts +6 -6
  260. package/src/components/modules/uiControllers/controllers/blockHover.ts +16 -2
  261. package/src/components/modules/uiControllers/handlers/touch.ts +83 -10
  262. package/src/components/modules/yjs/block-observer.ts +9 -3
  263. package/src/components/modules/yjs/document-store.ts +10 -7
  264. package/src/components/modules/yjs/types.ts +8 -6
  265. package/src/components/modules/yjs/undo-history.ts +90 -11
  266. package/src/components/selection/fake-background/shadows.ts +1 -1
  267. package/src/components/shared/color-picker.ts +211 -0
  268. package/src/components/shared/color-presets.ts +25 -0
  269. package/src/components/ui/toolbox.ts +27 -11
  270. package/src/components/utils/color-mapping.ts +241 -0
  271. package/src/components/utils/notifier/draw.ts +9 -9
  272. package/src/components/utils/placeholder.ts +24 -8
  273. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +3 -3
  274. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +15 -12
  275. package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
  276. package/src/components/utils/popover/popover-abstract.ts +30 -5
  277. package/src/components/utils/popover/popover-desktop.ts +26 -3
  278. package/src/components/utils/popover/popover-inline.ts +14 -1
  279. package/src/components/utils/popover/popover-mobile.ts +4 -4
  280. package/src/components/utils/popover/popover.const.ts +3 -3
  281. package/src/components/utils/sanitizer.ts +24 -3
  282. package/src/components/utils/tw.ts +17 -5
  283. package/src/full.ts +4 -0
  284. package/src/stories/Header.stories.ts +106 -0
  285. package/src/stories/MarkerColors.stories.ts +730 -0
  286. package/src/stories/Placeholder.stories.ts +7 -2
  287. package/src/stories/Popover.stories.ts +1 -3
  288. package/src/stories/Table.stories.ts +1662 -0
  289. package/src/stories/helpers.ts +2 -0
  290. package/src/styles/main.css +217 -39
  291. package/src/tools/header/index.ts +204 -26
  292. package/src/tools/index.ts +5 -1
  293. package/src/tools/list/caret-manager.ts +28 -10
  294. package/src/tools/list/constants.ts +2 -2
  295. package/src/tools/list/dom-builder.ts +3 -3
  296. package/src/tools/list/static-configs.ts +0 -1
  297. package/src/tools/paragraph/index.ts +9 -5
  298. package/src/tools/table/core/table-commands.ts +99 -0
  299. package/src/tools/table/core/table-controller.ts +231 -0
  300. package/src/tools/table/core/table-events.ts +102 -0
  301. package/src/tools/table/index.ts +1070 -174
  302. package/src/tools/table/ownership/table-event-broker.ts +74 -0
  303. package/src/tools/table/ownership/table-ownership-registry.ts +126 -0
  304. package/src/tools/table/table-add-controls.ts +85 -15
  305. package/src/tools/table/table-cell-blocks.ts +336 -38
  306. package/src/tools/table/table-cell-clipboard.ts +415 -0
  307. package/src/tools/table/table-cell-color-picker.ts +34 -0
  308. package/src/tools/table/table-cell-selection.ts +264 -15
  309. package/src/tools/table/table-core.ts +3 -42
  310. package/src/tools/table/table-heading-toggle.ts +2 -2
  311. package/src/tools/table/table-model.ts +623 -0
  312. package/src/tools/table/table-operations.ts +59 -78
  313. package/src/tools/table/table-resize.ts +15 -11
  314. package/src/tools/table/table-restrictions.ts +69 -3
  315. package/src/tools/table/table-row-col-action-handler.ts +22 -7
  316. package/src/tools/table/table-row-col-controls.ts +129 -12
  317. package/src/tools/table/table-row-col-drag.ts +14 -0
  318. package/src/tools/table/table-scroll-haze.ts +152 -0
  319. package/src/tools/table/types.ts +22 -1
  320. package/src/tools/table/view/table-cell-blocks-adapter.ts +47 -0
  321. package/src/tools/toggle/block-operations.ts +110 -0
  322. package/src/tools/toggle/constants.ts +49 -0
  323. package/src/tools/toggle/dom-builder.ts +125 -0
  324. package/src/tools/toggle/index.ts +280 -0
  325. package/src/tools/toggle/toggle-keyboard.ts +139 -0
  326. package/src/tools/toggle/toggle-lifecycle.ts +80 -0
  327. package/src/tools/toggle/toggle-shortcuts.ts +107 -0
  328. package/src/tools/toggle/types.ts +21 -0
  329. package/src/variants/blok-minimum.ts +13 -0
  330. package/types/api/block.d.ts +13 -0
  331. package/types/api/blocks.d.ts +16 -0
  332. package/types/full.d.ts +2 -0
  333. package/types/tools/table.d.ts +2 -0
  334. package/types/tools-entry.d.ts +2 -1
  335. package/dist/chunks/i18next-CugVlwWp.mjs +0 -1292
  336. package/src/tools/table/data-normalizer.ts +0 -32
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * @example
6
6
  * // Import specific tools
7
- * import { Paragraph, Header, List, Bold, Italic, Link } from '@jackuait/blok/tools';
7
+ * import { Paragraph, Header, List, Toggle, Bold, Italic, Link, Marker } from '@jackuait/blok/tools';
8
8
  *
9
9
  * // Use in Blok configuration (flat config style)
10
10
  * new Blok({
@@ -24,12 +24,14 @@ export { Paragraph } from './paragraph';
24
24
  export { Header } from './header';
25
25
  export { ListItem as List } from './list';
26
26
  export { Table } from './table';
27
+ export { ToggleItem as Toggle } from './toggle';
27
28
 
28
29
  // Inline tools
29
30
  export { BoldInlineTool as Bold } from '../components/inline-tools/inline-tool-bold';
30
31
  export { ItalicInlineTool as Italic } from '../components/inline-tools/inline-tool-italic';
31
32
  export { LinkInlineTool as Link } from '../components/inline-tools/inline-tool-link';
32
33
  export { ConvertInlineTool as Convert } from '../components/inline-tools/inline-tool-convert';
34
+ export { MarkerInlineTool as Marker } from '../components/inline-tools/inline-tool-marker';
33
35
 
34
36
  // Default tools configuration for convenience
35
37
  // Note: inlineToolbar defaults to true, so it doesn't need to be specified
@@ -38,10 +40,12 @@ export const defaultBlockTools = {
38
40
  header: {},
39
41
  list: {},
40
42
  table: {},
43
+ toggle: {},
41
44
  } as const;
42
45
 
43
46
  export const defaultInlineTools = {
44
47
  bold: {},
45
48
  italic: {},
46
49
  link: {},
50
+ marker: {},
47
51
  } as const;
@@ -7,8 +7,12 @@
7
7
  import type { API } from '../../../types';
8
8
 
9
9
  /**
10
- * Sets caret to the content element of a block after ensuring DOM is ready.
11
- * Uses requestAnimationFrame to wait for the browser to process DOM updates.
10
+ * Sets caret to the content element of a block.
11
+ * Operates synchronously so subsequent keystrokes land in the correct block
12
+ * (deferring via requestAnimationFrame causes a race where characters typed
13
+ * between the block split and the next animation frame go to the wrong element).
14
+ * Falls back to requestAnimationFrame only when the content element is not yet
15
+ * available (e.g. async rendering).
12
16
  *
13
17
  * @param api - The API instance
14
18
  * @param block - BlockAPI to set caret to
@@ -19,8 +23,7 @@ export const setCaretToBlockContent = (
19
23
  block: ReturnType<API['blocks']['insert']>,
20
24
  position: 'start' | 'end' = 'end'
21
25
  ): void => {
22
- // Use requestAnimationFrame to ensure DOM has been updated
23
- requestAnimationFrame(() => {
26
+ const applyFocus = (deferred: boolean): void => {
24
27
  const holder = block.holder;
25
28
  if (!holder) return;
26
29
 
@@ -29,8 +32,10 @@ export const setCaretToBlockContent = (
29
32
  if (!(contentEl instanceof HTMLElement)) {
30
33
  // Fallback to setToBlock if no content element found
31
34
  api.caret.setToBlock(block, position);
32
- // Update the caret "after" position for undo/redo since we're in requestAnimationFrame
33
- api.caret.updateLastCaretAfterPosition();
35
+
36
+ if (deferred) {
37
+ api.caret.updateLastCaretAfterPosition();
38
+ }
34
39
 
35
40
  return;
36
41
  }
@@ -55,8 +60,21 @@ export const setCaretToBlockContent = (
55
60
  selection.removeAllRanges();
56
61
  selection.addRange(range);
57
62
 
58
- // Update the caret "after" position for undo/redo since we moved the caret
59
- // asynchronously via requestAnimationFrame after the Yjs transaction committed
60
- api.caret.updateLastCaretAfterPosition();
61
- });
63
+ if (deferred) {
64
+ // Update the caret "after" position for undo/redo since we moved the caret
65
+ // asynchronously via requestAnimationFrame after the Yjs transaction committed
66
+ api.caret.updateLastCaretAfterPosition();
67
+ }
68
+ };
69
+
70
+ // Try synchronous focus first — the block is already in the DOM after insert()
71
+ const holder = block.holder;
72
+ const contentEl = holder?.querySelector('[contenteditable="true"]');
73
+
74
+ if (contentEl instanceof HTMLElement) {
75
+ applyFocus(false);
76
+ } else {
77
+ // Content element not available yet — fall back to next frame
78
+ requestAnimationFrame(() => applyFocus(true));
79
+ }
62
80
  }
@@ -12,12 +12,12 @@ export const INDENT_PER_LEVEL = 24;
12
12
  *
13
13
  * Matches paragraph spacing: py-[3px] from blok-block + mt-[2px] mb-px
14
14
  */
15
- export const BASE_STYLES = 'outline-none py-[3px] mt-[2px] mb-px';
15
+ export const BASE_STYLES = 'outline-hidden py-[3px] mt-[2px] mb-px';
16
16
 
17
17
  /**
18
18
  * Styles for standard list items (unordered, ordered)
19
19
  */
20
- export const ITEM_STYLES = 'outline-none pl-0.5 leading-[1.6em]';
20
+ export const ITEM_STYLES = 'outline-hidden pl-0.5 leading-[1.6em]';
21
21
 
22
22
  /**
23
23
  * Styles for checklist items
@@ -176,7 +176,7 @@ export const buildStandardContent = (context: DOMBuilderContext): HTMLElement =>
176
176
 
177
177
  // Create content container
178
178
  const contentContainer = document.createElement('div');
179
- contentContainer.className = twMerge('flex-1 min-w-0 outline-none', ...PLACEHOLDER_CLASSES);
179
+ contentContainer.className = twMerge('flex-1 min-w-0 outline-hidden', ...PLACEHOLDER_CLASSES);
180
180
  contentContainer.setAttribute('data-blok-testid', LIST_TEST_IDS.contentContainer);
181
181
  contentContainer.contentEditable = context.readOnly ? 'false' : 'true';
182
182
  contentContainer.innerHTML = data.text;
@@ -224,7 +224,7 @@ export const buildChecklistContent = (context: DOMBuilderContext): HTMLElement =
224
224
 
225
225
  const content = document.createElement('div');
226
226
  content.className = twMerge(
227
- 'flex-1 outline-none leading-[1.6em]',
227
+ 'flex-1 outline-hidden leading-[1.6em]',
228
228
  data.checked ? 'line-through opacity-60' : '',
229
229
  ...PLACEHOLDER_CLASSES
230
230
  );
@@ -251,7 +251,7 @@ export const buildChecklistContent = (context: DOMBuilderContext): HTMLElement =
251
251
  */
252
252
  export const createMarker = (style: ListItemStyle, depth: number): HTMLElement => {
253
253
  const marker = document.createElement('span');
254
- marker.className = 'flex-shrink-0 select-none';
254
+ marker.className = 'shrink-0 select-none';
255
255
  marker.setAttribute('aria-hidden', 'true');
256
256
  marker.contentEditable = 'false';
257
257
 
@@ -21,7 +21,6 @@ export const getListSanitizeConfig = (): ToolSanitizerConfig => ({
21
21
  },
22
22
  b: true,
23
23
  i: true,
24
- mark: true,
25
24
  },
26
25
  });
27
26
 
@@ -19,7 +19,7 @@ import type {
19
19
  import { DATA_ATTR } from '../../components/constants';
20
20
  import { IconText } from '../../components/icons';
21
21
  import { stripFakeBackgroundElements } from '../../components/utils';
22
- import { PLACEHOLDER_FOCUS_ONLY_CLASSES, setupPlaceholder } from '../../components/utils/placeholder';
22
+ import { PLACEHOLDER_EMPTY_EDITOR_CLASSES, PLACEHOLDER_FOCUS_ONLY_CLASSES, setupPlaceholder } from '../../components/utils/placeholder';
23
23
  import { twMerge } from '../../components/utils/tw';
24
24
 
25
25
  /**
@@ -200,7 +200,7 @@ export class Paragraph implements BlockTool {
200
200
  */
201
201
  private static readonly WRAPPER_CLASSES = [
202
202
  'leading-[1.6em]',
203
- 'outline-none',
203
+ 'outline-hidden',
204
204
  'mt-[2px]',
205
205
  'mb-px',
206
206
  '[&>p:first-of-type]:mt-0',
@@ -239,7 +239,8 @@ export class Paragraph implements BlockTool {
239
239
  div.className = twMerge(
240
240
  this.api.styles.block,
241
241
  Paragraph.WRAPPER_CLASSES,
242
- PLACEHOLDER_FOCUS_ONLY_CLASSES
242
+ PLACEHOLDER_FOCUS_ONLY_CLASSES,
243
+ PLACEHOLDER_EMPTY_EDITOR_CLASSES
243
244
  );
244
245
  div.setAttribute(DATA_ATTR.tool, 'paragraph');
245
246
  div.contentEditable = 'false';
@@ -255,14 +256,14 @@ export class Paragraph implements BlockTool {
255
256
 
256
257
  if (this._data.text) {
257
258
  div.innerHTML = this._data.text;
259
+ } else if (this.readOnly) {
260
+ div.innerHTML = '<br>';
258
261
  }
259
262
 
260
263
  if (!this.readOnly) {
261
264
  div.contentEditable = 'true';
262
265
  div.addEventListener('keyup', this.onKeyUp);
263
266
  setupPlaceholder(div, this.api.i18n.t(this._placeholder), 'data-blok-placeholder-active');
264
- } else {
265
- div.setAttribute('data-blok-placeholder-active', this.api.i18n.t(this._placeholder));
266
267
  }
267
268
 
268
269
  return div;
@@ -377,6 +378,9 @@ export class Paragraph implements BlockTool {
377
378
  src: true,
378
379
  style: true,
379
380
  },
381
+ p: true,
382
+ ul: true,
383
+ li: true,
380
384
  },
381
385
  };
382
386
  }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Typed table commands — the sole input vocabulary for table mutations.
3
+ * Every mutation must be expressible as one of these commands.
4
+ */
5
+ import type { TableData } from '../types';
6
+
7
+ export interface InsertRowCommand {
8
+ readonly type: 'insert-row';
9
+ /** Row index to insert at */
10
+ readonly index: number;
11
+ }
12
+
13
+ export interface DeleteRowCommand {
14
+ readonly type: 'delete-row';
15
+ readonly index: number;
16
+ }
17
+
18
+ export interface MoveRowCommand {
19
+ readonly type: 'move-row';
20
+ readonly fromIndex: number;
21
+ readonly toIndex: number;
22
+ }
23
+
24
+ export interface InsertColumnCommand {
25
+ readonly type: 'insert-column';
26
+ readonly index: number;
27
+ readonly width?: number;
28
+ }
29
+
30
+ export interface DeleteColumnCommand {
31
+ readonly type: 'delete-column';
32
+ readonly index: number;
33
+ }
34
+
35
+ export interface MoveColumnCommand {
36
+ readonly type: 'move-column';
37
+ readonly fromIndex: number;
38
+ readonly toIndex: number;
39
+ }
40
+
41
+ export interface ToggleHeadingCommand {
42
+ readonly type: 'toggle-heading';
43
+ }
44
+
45
+ export interface ToggleHeadingColumnCommand {
46
+ readonly type: 'toggle-heading-column';
47
+ }
48
+
49
+ export interface SetStretchedCommand {
50
+ readonly type: 'set-stretched';
51
+ readonly value: boolean;
52
+ }
53
+
54
+ export interface AddBlockToCellCommand {
55
+ readonly type: 'add-block-to-cell';
56
+ readonly row: number;
57
+ readonly col: number;
58
+ readonly blockId: string;
59
+ }
60
+
61
+ export interface RemoveBlockFromCellCommand {
62
+ readonly type: 'remove-block-from-cell';
63
+ readonly row: number;
64
+ readonly col: number;
65
+ readonly blockId: string;
66
+ }
67
+
68
+ export interface SetCellBlocksCommand {
69
+ readonly type: 'set-cell-blocks';
70
+ readonly row: number;
71
+ readonly col: number;
72
+ readonly blockIds: readonly string[];
73
+ }
74
+
75
+ export interface SetColWidthsCommand {
76
+ readonly type: 'set-col-widths';
77
+ readonly widths: readonly number[] | undefined;
78
+ }
79
+
80
+ export interface ReplaceAllCommand {
81
+ readonly type: 'replace-all';
82
+ readonly data: TableData;
83
+ }
84
+
85
+ export type TableCommand =
86
+ | InsertRowCommand
87
+ | DeleteRowCommand
88
+ | MoveRowCommand
89
+ | InsertColumnCommand
90
+ | DeleteColumnCommand
91
+ | MoveColumnCommand
92
+ | ToggleHeadingCommand
93
+ | ToggleHeadingColumnCommand
94
+ | SetStretchedCommand
95
+ | AddBlockToCellCommand
96
+ | RemoveBlockFromCellCommand
97
+ | SetCellBlocksCommand
98
+ | SetColWidthsCommand
99
+ | ReplaceAllCommand;
@@ -0,0 +1,231 @@
1
+ import type { TableModel } from '../table-model';
2
+ import type { TableData } from '../types';
3
+ import type { TableCommand } from './table-commands';
4
+ import type { TableDomainEvent } from './table-events';
5
+
6
+ /**
7
+ * Listener callback for domain events emitted by the controller.
8
+ */
9
+ export type TableEventListener = (event: TableDomainEvent) => void;
10
+
11
+ /**
12
+ * Central command executor for table mutations.
13
+ *
14
+ * All model mutations flow through `execute()`, which:
15
+ * 1. Applies the command to the model
16
+ * 2. Emits a corresponding domain event
17
+ *
18
+ * This is the sole mutation entrypoint — no direct model mutation
19
+ * should happen outside of the controller in the final architecture.
20
+ */
21
+ export class TableController {
22
+ private readonly model: TableModel;
23
+ private readonly listener: TableEventListener | undefined;
24
+
25
+ constructor(model: TableModel, listener?: TableEventListener) {
26
+ this.model = model;
27
+ this.listener = listener;
28
+ }
29
+
30
+ /**
31
+ * Execute a typed command against the model and emit the resulting event.
32
+ */
33
+ execute(command: TableCommand): void {
34
+ const event = this.applyCommand(command);
35
+
36
+ if (event !== null && this.listener) {
37
+ this.listener(event);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Apply a command to the model and return the domain event to emit.
43
+ * Returns null if the command was a no-op (e.g., out-of-bounds).
44
+ */
45
+ private applyCommand(command: TableCommand): TableDomainEvent | null {
46
+ switch (command.type) {
47
+ case 'insert-row':
48
+ return this.handleInsertRow(command.index);
49
+
50
+ case 'delete-row':
51
+ return this.handleDeleteRow(command.index);
52
+
53
+ case 'move-row':
54
+ return this.handleMoveRow(command.fromIndex, command.toIndex);
55
+
56
+ case 'insert-column':
57
+ return this.handleInsertColumn(command.index, command.width);
58
+
59
+ case 'delete-column':
60
+ return this.handleDeleteColumn(command.index);
61
+
62
+ case 'move-column':
63
+ return this.handleMoveColumn(command.fromIndex, command.toIndex);
64
+
65
+ case 'toggle-heading':
66
+ return this.handleToggleHeading();
67
+
68
+ case 'toggle-heading-column':
69
+ return this.handleToggleHeadingColumn();
70
+
71
+ case 'set-stretched':
72
+ return this.handleSetStretched(command.value);
73
+
74
+ case 'add-block-to-cell':
75
+ return this.handleAddBlockToCell(command.row, command.col, command.blockId);
76
+
77
+ case 'remove-block-from-cell':
78
+ return this.handleRemoveBlockFromCell(command.row, command.col, command.blockId);
79
+
80
+ case 'set-cell-blocks':
81
+ return this.handleSetCellBlocks(command.row, command.col, [...command.blockIds]);
82
+
83
+ case 'set-col-widths':
84
+ return this.handleSetColWidths(command.widths ? [...command.widths] : undefined);
85
+
86
+ case 'replace-all':
87
+ return this.handleReplaceAll(command.data);
88
+ }
89
+ }
90
+
91
+ // ─── Command handlers ──────────────────────────────────────────
92
+
93
+ private handleInsertRow(index: number): TableDomainEvent {
94
+ const result = this.model.addRow(index);
95
+
96
+ return {
97
+ type: 'row-inserted',
98
+ index: result.index,
99
+ cellsToPopulate: result.cellsToPopulate,
100
+ };
101
+ }
102
+
103
+ private handleDeleteRow(index: number): TableDomainEvent {
104
+ const result = this.model.deleteRow(index);
105
+
106
+ return {
107
+ type: 'row-deleted',
108
+ index: result.index,
109
+ blocksToDelete: result.blocksToDelete,
110
+ };
111
+ }
112
+
113
+ private handleMoveRow(fromIndex: number, toIndex: number): TableDomainEvent {
114
+ this.model.moveRow(fromIndex, toIndex);
115
+
116
+ return {
117
+ type: 'row-moved',
118
+ fromIndex,
119
+ toIndex,
120
+ };
121
+ }
122
+
123
+ private handleInsertColumn(index: number, width?: number): TableDomainEvent {
124
+ const result = this.model.addColumn(index, width);
125
+
126
+ return {
127
+ type: 'column-inserted',
128
+ index: result.index,
129
+ cellsToPopulate: result.cellsToPopulate,
130
+ };
131
+ }
132
+
133
+ private handleDeleteColumn(index: number): TableDomainEvent {
134
+ const result = this.model.deleteColumn(index);
135
+
136
+ return {
137
+ type: 'column-deleted',
138
+ index: result.index,
139
+ blocksToDelete: result.blocksToDelete,
140
+ };
141
+ }
142
+
143
+ private handleMoveColumn(fromIndex: number, toIndex: number): TableDomainEvent {
144
+ this.model.moveColumn(fromIndex, toIndex);
145
+
146
+ return {
147
+ type: 'column-moved',
148
+ fromIndex,
149
+ toIndex,
150
+ };
151
+ }
152
+
153
+ private handleToggleHeading(): TableDomainEvent {
154
+ const newValue = !this.model.withHeadings;
155
+
156
+ this.model.setWithHeadings(newValue);
157
+
158
+ return {
159
+ type: 'heading-toggled',
160
+ withHeadings: newValue,
161
+ };
162
+ }
163
+
164
+ private handleToggleHeadingColumn(): TableDomainEvent {
165
+ const newValue = !this.model.withHeadingColumn;
166
+
167
+ this.model.setWithHeadingColumn(newValue);
168
+
169
+ return {
170
+ type: 'heading-column-toggled',
171
+ withHeadingColumn: newValue,
172
+ };
173
+ }
174
+
175
+ private handleSetStretched(value: boolean): TableDomainEvent {
176
+ this.model.setStretched(value);
177
+
178
+ return {
179
+ type: 'stretched-changed',
180
+ stretched: value,
181
+ };
182
+ }
183
+
184
+ private handleAddBlockToCell(row: number, col: number, blockId: string): TableDomainEvent {
185
+ this.model.addBlockToCell(row, col, blockId);
186
+
187
+ return {
188
+ type: 'block-added-to-cell',
189
+ row,
190
+ col,
191
+ blockId,
192
+ };
193
+ }
194
+
195
+ private handleRemoveBlockFromCell(row: number, col: number, blockId: string): TableDomainEvent {
196
+ this.model.removeBlockFromCell(row, col, blockId);
197
+
198
+ return {
199
+ type: 'block-removed-from-cell',
200
+ row,
201
+ col,
202
+ blockId,
203
+ };
204
+ }
205
+
206
+ private handleSetCellBlocks(row: number, col: number, blockIds: string[]): TableDomainEvent {
207
+ this.model.setCellBlocks(row, col, blockIds);
208
+
209
+ return {
210
+ type: 'cell-blocks-set',
211
+ row,
212
+ col,
213
+ blockIds,
214
+ };
215
+ }
216
+
217
+ private handleSetColWidths(widths: number[] | undefined): TableDomainEvent {
218
+ this.model.setColWidths(widths);
219
+
220
+ return {
221
+ type: 'col-widths-changed',
222
+ widths,
223
+ };
224
+ }
225
+
226
+ private handleReplaceAll(data: TableData): TableDomainEvent {
227
+ this.model.replaceAll(data);
228
+
229
+ return { type: 'model-replaced' };
230
+ }
231
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Domain events emitted after successful table mutations.
3
+ * Payloads contain ONLY serializable data (IDs, indices, counts).
4
+ * No HTMLElement references — ever.
5
+ */
6
+
7
+ export interface RowInsertedEvent {
8
+ readonly type: 'row-inserted';
9
+ readonly index: number;
10
+ readonly cellsToPopulate: number;
11
+ }
12
+
13
+ export interface RowDeletedEvent {
14
+ readonly type: 'row-deleted';
15
+ readonly index: number;
16
+ readonly blocksToDelete: readonly string[];
17
+ }
18
+
19
+ export interface RowMovedEvent {
20
+ readonly type: 'row-moved';
21
+ readonly fromIndex: number;
22
+ readonly toIndex: number;
23
+ }
24
+
25
+ export interface ColumnInsertedEvent {
26
+ readonly type: 'column-inserted';
27
+ readonly index: number;
28
+ readonly cellsToPopulate: ReadonlyArray<{ row: number; col: number }>;
29
+ }
30
+
31
+ export interface ColumnDeletedEvent {
32
+ readonly type: 'column-deleted';
33
+ readonly index: number;
34
+ readonly blocksToDelete: readonly string[];
35
+ }
36
+
37
+ export interface ColumnMovedEvent {
38
+ readonly type: 'column-moved';
39
+ readonly fromIndex: number;
40
+ readonly toIndex: number;
41
+ }
42
+
43
+ export interface HeadingToggledEvent {
44
+ readonly type: 'heading-toggled';
45
+ readonly withHeadings: boolean;
46
+ }
47
+
48
+ export interface HeadingColumnToggledEvent {
49
+ readonly type: 'heading-column-toggled';
50
+ readonly withHeadingColumn: boolean;
51
+ }
52
+
53
+ export interface StretchedChangedEvent {
54
+ readonly type: 'stretched-changed';
55
+ readonly stretched: boolean;
56
+ }
57
+
58
+ export interface BlockAddedToCellEvent {
59
+ readonly type: 'block-added-to-cell';
60
+ readonly row: number;
61
+ readonly col: number;
62
+ readonly blockId: string;
63
+ }
64
+
65
+ export interface BlockRemovedFromCellEvent {
66
+ readonly type: 'block-removed-from-cell';
67
+ readonly row: number;
68
+ readonly col: number;
69
+ readonly blockId: string;
70
+ }
71
+
72
+ export interface CellBlocksSetEvent {
73
+ readonly type: 'cell-blocks-set';
74
+ readonly row: number;
75
+ readonly col: number;
76
+ readonly blockIds: readonly string[];
77
+ }
78
+
79
+ export interface ColWidthsChangedEvent {
80
+ readonly type: 'col-widths-changed';
81
+ readonly widths: readonly number[] | undefined;
82
+ }
83
+
84
+ export interface ModelReplacedEvent {
85
+ readonly type: 'model-replaced';
86
+ }
87
+
88
+ export type TableDomainEvent =
89
+ | RowInsertedEvent
90
+ | RowDeletedEvent
91
+ | RowMovedEvent
92
+ | ColumnInsertedEvent
93
+ | ColumnDeletedEvent
94
+ | ColumnMovedEvent
95
+ | HeadingToggledEvent
96
+ | HeadingColumnToggledEvent
97
+ | StretchedChangedEvent
98
+ | BlockAddedToCellEvent
99
+ | BlockRemovedFromCellEvent
100
+ | CellBlocksSetEvent
101
+ | ColWidthsChangedEvent
102
+ | ModelReplacedEvent;