@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
@@ -0,0 +1,415 @@
1
+ import type { SanitizerConfig } from '../../../types/configs/sanitizer-config';
2
+ import type { ClipboardBlockData, TableCellsClipboard } from './types';
3
+ import { mapToNearestPresetColor } from '../../components/utils/color-mapping';
4
+ import { clean } from '../../components/utils/sanitizer';
5
+
6
+ /** Attribute name used to embed clipboard data on the HTML table element. */
7
+ const DATA_ATTR = 'data-blok-table-cells';
8
+
9
+ /**
10
+ * Resolve the background-color style value for clipboard markup.
11
+ * When the cell has an explicit background, use it; when it only has a text
12
+ * color, force a transparent background so the mark element doesn't inherit
13
+ * an unwanted default; otherwise return an empty string (no style needed).
14
+ */
15
+ function resolveBackgroundStyle(hasBgColor: boolean, hasColor: boolean, mappedBg: string): string {
16
+ if (hasBgColor) {
17
+ return `background-color: ${mappedBg}`;
18
+ }
19
+
20
+ if (hasColor) {
21
+ return 'background-color: transparent';
22
+ }
23
+
24
+ return '';
25
+ }
26
+
27
+ /**
28
+ * Entry describing one cell to be serialized for the clipboard.
29
+ */
30
+ interface CellEntry {
31
+ row: number;
32
+ col: number;
33
+ blocks: ClipboardBlockData[];
34
+ color?: string;
35
+ textColor?: string;
36
+ }
37
+
38
+ /**
39
+ * Build a {@link TableCellsClipboard} payload from a flat list of cell entries.
40
+ *
41
+ * Row/col indices are normalized so the minimum becomes 0.
42
+ * Empty input produces `{ rows: 0, cols: 0, cells: [] }`.
43
+ */
44
+ export function serializeCellsToClipboard(entries: CellEntry[]): TableCellsClipboard {
45
+ if (entries.length === 0) {
46
+ return { rows: 0, cols: 0, cells: [] };
47
+ }
48
+
49
+ const minRow = Math.min(...entries.map((e) => e.row));
50
+ const minCol = Math.min(...entries.map((e) => e.col));
51
+
52
+ const maxRow = Math.max(...entries.map((e) => e.row));
53
+ const maxCol = Math.max(...entries.map((e) => e.col));
54
+
55
+ const rows = maxRow - minRow + 1;
56
+ const cols = maxCol - minCol + 1;
57
+
58
+ // Pre-fill with empty cells
59
+ const cells: TableCellsClipboard['cells'] = Array.from({ length: rows }, () =>
60
+ Array.from({ length: cols }, () => ({ blocks: [] as ClipboardBlockData[] }))
61
+ );
62
+
63
+ for (const entry of entries) {
64
+ const r = entry.row - minRow;
65
+ const c = entry.col - minCol;
66
+
67
+ cells[r][c] = { blocks: entry.blocks };
68
+
69
+ if (entry.color !== undefined) {
70
+ cells[r][c].color = entry.color;
71
+ }
72
+
73
+ if (entry.textColor !== undefined) {
74
+ cells[r][c].textColor = entry.textColor;
75
+ }
76
+ }
77
+
78
+ return { rows, cols, cells };
79
+ }
80
+
81
+ /**
82
+ * Extract a plain-text representation from a single block's data.
83
+ *
84
+ * Looks for `data.text` (string), then `data.items` (array of strings),
85
+ * and falls back to an empty string.
86
+ */
87
+ function extractBlockText(block: ClipboardBlockData): string {
88
+ const { data } = block;
89
+
90
+ if (typeof data.text === 'string') {
91
+ return data.text;
92
+ }
93
+
94
+ if (Array.isArray(data.items)) {
95
+ return (data.items as unknown[])
96
+ .filter((item): item is string => typeof item === 'string')
97
+ .join(' ');
98
+ }
99
+
100
+ return '';
101
+ }
102
+
103
+ /**
104
+ * Build an HTML `<table>` string that carries the clipboard payload in a
105
+ * `data-blok-table-cells` attribute.
106
+ *
107
+ * External apps receive a clean HTML table, while Blok's paste handler can
108
+ * detect and extract the structured JSON.
109
+ */
110
+ export function buildClipboardHtml(payload: TableCellsClipboard): string {
111
+ // Use single-quoted attribute so JSON double quotes don't break the HTML.
112
+ // Escape any literal single quotes inside the JSON with &#39;.
113
+ const json = JSON.stringify(payload).replace(/'/g, '&#39;');
114
+
115
+ const rowsHtml = payload.cells
116
+ .map((row) => {
117
+ const cellsHtml = row
118
+ .map((cell) => {
119
+ const text = cell.blocks.map(extractBlockText).join(' ');
120
+
121
+ const styles = [
122
+ cell.color ? `background-color: ${cell.color}` : '',
123
+ cell.textColor ? `color: ${cell.textColor}` : '',
124
+ ].filter(Boolean).join('; ');
125
+
126
+ const styleAttr = styles ? ` style="${styles}"` : '';
127
+
128
+ return `<td${styleAttr}>${text}</td>`;
129
+ })
130
+ .join('');
131
+
132
+ return `<tr>${cellsHtml}</tr>`;
133
+ })
134
+ .join('');
135
+
136
+ return `<table ${DATA_ATTR}='${json}'>${rowsHtml}</table>`;
137
+ }
138
+
139
+ /**
140
+ * Build a plain-text representation of the clipboard payload.
141
+ *
142
+ * Cells are separated by tabs (`\t`), rows by newlines (`\n`).
143
+ * Multiple blocks within a cell are joined with spaces.
144
+ */
145
+ export function buildClipboardPlainText(payload: TableCellsClipboard): string {
146
+ return payload.cells
147
+ .map((row) =>
148
+ row.map((cell) => cell.blocks.map(extractBlockText).join(' ')).join('\t')
149
+ )
150
+ .join('\n');
151
+ }
152
+
153
+ /**
154
+ * CSS properties allowed on <mark> elements inside table cells.
155
+ * Matches MarkerInlineTool.ALLOWED_STYLE_PROPS.
156
+ */
157
+ const ALLOWED_MARK_STYLE_PROPS = new Set(['color', 'background-color']);
158
+
159
+ /**
160
+ * Sanitizer config for cell content: allows bold, italic, line breaks, links,
161
+ * and color markers (<mark> with color/background-color styles only).
162
+ */
163
+ const CELL_SANITIZE_CONFIG: SanitizerConfig = {
164
+ b: true,
165
+ strong: true,
166
+ i: true,
167
+ em: true,
168
+ br: true,
169
+ a: { href: true },
170
+ mark: (node: Element): { [attr: string]: boolean | string } => {
171
+ const el = node as HTMLElement;
172
+ const style = el.style;
173
+
174
+ const props = Array.from({ length: style.length }, (_, i) => style.item(i));
175
+
176
+ for (const prop of props) {
177
+ if (!ALLOWED_MARK_STYLE_PROPS.has(prop)) {
178
+ style.removeProperty(prop);
179
+ }
180
+ }
181
+
182
+ return style.length > 0 ? { style: true } : {};
183
+ },
184
+ };
185
+
186
+ /**
187
+ * Check whether a CSS color value is the default black text color.
188
+ * Google Docs uses different formats: `rgb(0, 0, 0)`, `rgb(0,0,0)`, or `#000000`.
189
+ * Spans with only this color should not be converted to `<mark>`.
190
+ */
191
+ export function isDefaultBlack(color: string): boolean {
192
+ const normalized = color.replace(/\s/g, '');
193
+
194
+ return normalized === 'rgb(0,0,0)' || normalized === '#000000';
195
+ }
196
+
197
+ /**
198
+ * Extract HTML content from a `<td>`/`<th>` element, converting Google Docs
199
+ * style-based spans to semantic tags and sanitizing to allowed formatting only.
200
+ *
201
+ * - `<span style="font-weight:700">` or `font-weight:bold` → `<b>`
202
+ * - `<span style="font-style:italic">` → `<i>`
203
+ * - `<span style="color:...">` → `<mark style="color: ...">`
204
+ * - `<span style="background-color:...">` → `<mark style="background-color: ...">`
205
+ * - `<p>` boundaries → `<br>` line breaks
206
+ * - Everything else stripped except `<b>`, `<strong>`, `<i>`, `<em>`, `<br>`, `<a href>`, `<mark style>`
207
+ */
208
+ function sanitizeCellHtml(td: Element): string {
209
+ const clone = td.cloneNode(true) as HTMLElement;
210
+
211
+ // Convert style-based spans to semantic tags
212
+ for (const span of Array.from(clone.querySelectorAll('span'))) {
213
+ const style = span.getAttribute('style') ?? '';
214
+ const isBold = /font-weight\s*:\s*(700|bold)/i.test(style);
215
+ const isItalic = /font-style\s*:\s*italic/i.test(style);
216
+
217
+ const colorMatch = /(?<![a-z-])color\s*:\s*([^;]+)/i.exec(style);
218
+ const bgMatch = /background-color\s*:\s*([^;]+)/i.exec(style);
219
+
220
+ const color = colorMatch?.[1]?.trim();
221
+ const bgColor = bgMatch?.[1]?.trim();
222
+
223
+ const hasColor = color !== undefined && !isDefaultBlack(color);
224
+ const hasBgColor = bgColor !== undefined && bgColor !== 'transparent';
225
+
226
+ if (!isBold && !isItalic && !hasColor && !hasBgColor) {
227
+ continue;
228
+ }
229
+
230
+ const mappedColor = hasColor ? mapToNearestPresetColor(color, 'text') : '';
231
+ const mappedBg = hasBgColor ? mapToNearestPresetColor(bgColor, 'bg') : '';
232
+
233
+ const colorStyles = [
234
+ hasColor ? `color: ${mappedColor}` : '',
235
+ resolveBackgroundStyle(hasBgColor, hasColor, mappedBg),
236
+ ].filter(Boolean).join('; ');
237
+
238
+ const inner = span.innerHTML;
239
+ const marked = colorStyles
240
+ ? `<mark style="${colorStyles};">${inner}</mark>`
241
+ : inner;
242
+
243
+ const italic = isItalic ? `<i>${marked}</i>` : marked;
244
+ const wrapped = isBold ? `<b>${italic}</b>` : italic;
245
+
246
+ span.replaceWith(document.createRange().createContextualFragment(wrapped));
247
+ }
248
+
249
+ // Move color/background-color from <a> tags into <mark> wrappers.
250
+ // The sanitizer only allows href on <a>, so inline color styles would be lost.
251
+ for (const anchor of Array.from(clone.querySelectorAll('a[style]'))) {
252
+ const style = anchor.getAttribute('style') ?? '';
253
+
254
+ const colorMatch = /(?<![a-z-])color\s*:\s*([^;]+)/i.exec(style);
255
+ const bgMatch = /background-color\s*:\s*([^;]+)/i.exec(style);
256
+
257
+ const color = colorMatch?.[1]?.trim();
258
+ const bgColor = bgMatch?.[1]?.trim();
259
+
260
+ const hasColor = color !== undefined && !isDefaultBlack(color) && color !== 'inherit';
261
+ const hasBgColor = bgColor !== undefined && bgColor !== 'transparent' && bgColor !== 'inherit';
262
+
263
+ if (!hasColor && !hasBgColor) {
264
+ continue;
265
+ }
266
+
267
+ const mappedColor = hasColor ? mapToNearestPresetColor(color, 'text') : '';
268
+ const mappedBg = hasBgColor ? mapToNearestPresetColor(bgColor, 'bg') : '';
269
+
270
+ const colorStyles = [
271
+ hasColor ? `color: ${mappedColor}` : '',
272
+ resolveBackgroundStyle(hasBgColor, hasColor, mappedBg),
273
+ ].filter(Boolean).join('; ');
274
+
275
+ const el = anchor as HTMLElement;
276
+
277
+ el.innerHTML = `<mark style="${colorStyles};">${el.innerHTML}</mark>`;
278
+ el.style.removeProperty('color');
279
+ el.style.removeProperty('background-color');
280
+ }
281
+
282
+ // Convert <p> boundaries to <br> line breaks
283
+ for (const p of Array.from(clone.querySelectorAll('p'))) {
284
+ const fragment = document.createRange().createContextualFragment(p.innerHTML + '<br>');
285
+
286
+ p.replaceWith(fragment);
287
+ }
288
+
289
+ const html = clean(clone.innerHTML, CELL_SANITIZE_CONFIG)
290
+ .replace(/(<br\s*\/?>|\s)+$/i, '')
291
+ .trim();
292
+
293
+ return html;
294
+ }
295
+
296
+ /**
297
+ * Parse a generic HTML table (e.g. from Google Docs, Word, Excel) into a
298
+ * {@link TableCellsClipboard} payload.
299
+ *
300
+ * Each `<td>`/`<th>` becomes one or more paragraph blocks (split by line breaks).
301
+ * content. Returns `null` when the HTML does not contain a `<table>`, when
302
+ * the table has no rows, or when the table already carries our custom
303
+ * `data-blok-table-cells` attribute (those should be handled by
304
+ * {@link parseClipboardHtml} instead).
305
+ */
306
+ export function parseGenericHtmlTable(html: string): TableCellsClipboard | null {
307
+ if (!html) {
308
+ return null;
309
+ }
310
+
311
+ const doc = new DOMParser().parseFromString(html, 'text/html');
312
+ const table = doc.querySelector('table');
313
+
314
+ if (!table) {
315
+ return null;
316
+ }
317
+
318
+ // Defer to parseClipboardHtml for our own format
319
+ if (table.hasAttribute(DATA_ATTR)) {
320
+ return null;
321
+ }
322
+
323
+ const rows = table.querySelectorAll('tr');
324
+
325
+ if (rows.length === 0) {
326
+ return null;
327
+ }
328
+
329
+ type CellPayload = TableCellsClipboard['cells'][number][number];
330
+
331
+ const cellGrid: CellPayload[][] = [];
332
+
333
+ rows.forEach((row) => {
334
+ const tds = row.querySelectorAll('td, th');
335
+ const rowCells: CellPayload[] = [];
336
+
337
+ tds.forEach((td) => {
338
+ const text = sanitizeCellHtml(td);
339
+ const segments = text.split(/<br\s*\/?>/i).map(s => s.trim()).filter(Boolean);
340
+ const blocks = segments.length > 0
341
+ ? segments.map(s => ({ tool: 'paragraph' as const, data: { text: s } }))
342
+ : [{ tool: 'paragraph' as const, data: { text: '' } }];
343
+
344
+ const cell: CellPayload = { blocks };
345
+
346
+ // Extract cell-level colors from td/th style attribute
347
+ const tdStyle = td.getAttribute('style') ?? '';
348
+ const cellBgMatch = /background-color\s*:\s*([^;]+)/i.exec(tdStyle);
349
+
350
+ if (cellBgMatch?.[1]) {
351
+ cell.color = mapToNearestPresetColor(cellBgMatch[1].trim(), 'bg');
352
+ }
353
+
354
+ const cellTextColorMatch = /(?<![a-z-])color\s*:\s*([^;]+)/i.exec(tdStyle);
355
+
356
+ if (cellTextColorMatch?.[1] && !isDefaultBlack(cellTextColorMatch[1].trim())) {
357
+ cell.textColor = mapToNearestPresetColor(cellTextColorMatch[1].trim(), 'text');
358
+ }
359
+
360
+ rowCells.push(cell);
361
+ });
362
+
363
+ cellGrid.push(rowCells);
364
+ });
365
+
366
+ const maxCols = Math.max(0, ...cellGrid.map((row) => row.length));
367
+
368
+ if (cellGrid.length === 0 || maxCols === 0) {
369
+ return null;
370
+ }
371
+
372
+ // Normalize: ensure all rows have the same number of columns
373
+ for (const row of cellGrid) {
374
+ while (row.length < maxCols) {
375
+ row.push({ blocks: [{ tool: 'paragraph', data: { text: '' } }] });
376
+ }
377
+ }
378
+
379
+ return {
380
+ rows: cellGrid.length,
381
+ cols: maxCols,
382
+ cells: cellGrid,
383
+ };
384
+ }
385
+
386
+ /**
387
+ * Attempt to parse a {@link TableCellsClipboard} from an HTML string.
388
+ *
389
+ * Returns `null` if the HTML does not contain a `<table>` with the expected
390
+ * data attribute, or if the JSON within is invalid.
391
+ */
392
+ export function parseClipboardHtml(html: string): TableCellsClipboard | null {
393
+ // Match both single-quoted and double-quoted attribute values
394
+ const pattern = new RegExp(`${DATA_ATTR}='([^']*)'|${DATA_ATTR}="([^"]*)"`, 's');
395
+ const match = pattern.exec(html);
396
+
397
+ if (!match) {
398
+ return null;
399
+ }
400
+
401
+ try {
402
+ // Group 1 = single-quoted value, group 2 = double-quoted value
403
+ const raw = match[1] ?? match[2];
404
+
405
+ if (raw === undefined) {
406
+ return null;
407
+ }
408
+
409
+ const jsonStr = raw.replace(/&#39;/g, "'").replace(/&quot;/g, '"');
410
+
411
+ return JSON.parse(jsonStr) as TableCellsClipboard;
412
+ } catch {
413
+ return null;
414
+ }
415
+ }
@@ -0,0 +1,34 @@
1
+ import type { I18n } from '../../../types/api';
2
+ import { createColorPicker } from '../../components/shared/color-picker';
3
+
4
+ export type CellColorMode = 'textColor' | 'backgroundColor';
5
+
6
+ interface CellColorPickerOptions {
7
+ i18n: I18n;
8
+ onColorSelect: (color: string | null, mode: CellColorMode) => void;
9
+ }
10
+
11
+ interface CellColorPickerResult {
12
+ element: HTMLDivElement;
13
+ }
14
+
15
+ /**
16
+ * Creates a cell color picker for the table cell popover.
17
+ * Thin wrapper around the shared color picker component.
18
+ */
19
+ export const createCellColorPicker = (options: CellColorPickerOptions): CellColorPickerResult => {
20
+ const handle = createColorPicker({
21
+ i18n: options.i18n,
22
+ testIdPrefix: 'cell-color',
23
+ defaultModeIndex: 1,
24
+ modes: [
25
+ { key: 'textColor', labelKey: 'tools.marker.textColor', presetField: 'text' },
26
+ { key: 'backgroundColor', labelKey: 'tools.marker.background', presetField: 'bg' },
27
+ ],
28
+ onColorSelect: (color, modeKey) => {
29
+ options.onColorSelect(color, modeKey as CellColorMode);
30
+ },
31
+ });
32
+
33
+ return { element: handle.element };
34
+ };