@jackuait/blok 0.6.0-beta.0 → 0.6.0-beta.10

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 (286) hide show
  1. package/README.md +16 -169
  2. package/bin/blok.mjs +10 -0
  3. package/dist/blok.mjs +2 -2
  4. package/dist/chunks/{blok-Bu9S3SsR.mjs → blok-Buf0btS7.mjs} +2267 -2024
  5. package/dist/chunks/{i18next-loader-CKuXJ0Av.mjs → i18next-loader-CVf_ZfwA.mjs} +1 -1
  6. package/dist/chunks/{index-jtZaryNw.mjs → index-C6jsfLLp.mjs} +1 -1
  7. package/dist/chunks/{inline-tool-convert-CFjyrH30.mjs → inline-tool-convert-BKKEoOqB.mjs} +710 -570
  8. package/dist/chunks/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
  9. package/dist/chunks/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
  10. package/dist/{messages-LvFKBBPa.mjs → chunks/messages-7W4d0DwD.mjs} +15 -1
  11. package/dist/{messages-Bn253WWC.mjs → chunks/messages-9SihnaXQ.mjs} +14 -0
  12. package/dist/{messages-Bf6Y3_GI.mjs → chunks/messages-B1Aww8q7.mjs} +16 -2
  13. package/dist/{messages-pA5TvcAj.mjs → chunks/messages-BB5z9Uba.mjs} +14 -0
  14. package/dist/chunks/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
  15. package/dist/chunks/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
  16. package/dist/chunks/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
  17. package/dist/{messages-B5puUm7R.mjs → chunks/messages-BL0tXcDf.mjs} +15 -1
  18. package/dist/chunks/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
  19. package/dist/{messages-CyDU5lz9.mjs → chunks/messages-BMv4xwIr.mjs} +16 -2
  20. package/dist/chunks/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
  21. package/dist/chunks/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
  22. package/dist/chunks/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
  23. package/dist/{messages-CXHd9SUK.mjs → chunks/messages-BYyy6Wqf.mjs} +14 -0
  24. package/dist/chunks/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
  25. package/dist/chunks/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
  26. package/dist/chunks/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
  27. package/dist/chunks/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
  28. package/dist/chunks/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
  29. package/dist/chunks/{messages-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
  30. package/dist/chunks/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
  31. package/dist/chunks/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
  32. package/dist/chunks/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
  33. package/dist/chunks/messages-CKI54h6O.mjs +62 -0
  34. package/dist/{messages-CrsJ1TEJ.mjs → chunks/messages-CLhcMlTc.mjs} +15 -1
  35. package/dist/{messages-CnvW8Slp.mjs → chunks/messages-CMkNSDTo.mjs} +17 -3
  36. package/dist/{messages-BlpqL8vG.mjs → chunks/messages-CQwpzUFp.mjs} +19 -5
  37. package/dist/chunks/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
  38. package/dist/chunks/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
  39. package/dist/chunks/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
  40. package/dist/chunks/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
  41. package/dist/chunks/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
  42. package/dist/{messages-Dg92dXZ5.mjs → chunks/messages-CvGLfqmV.mjs} +14 -0
  43. package/dist/{messages-AHESHJm_.mjs → chunks/messages-CzTufCHu.mjs} +14 -0
  44. package/dist/chunks/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
  45. package/dist/chunks/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
  46. package/dist/chunks/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
  47. package/dist/chunks/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
  48. package/dist/chunks/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
  49. package/dist/{messages-zSzDzXej.mjs → chunks/messages-DBRw-7Zc.mjs} +16 -2
  50. package/dist/chunks/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
  51. package/dist/chunks/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
  52. package/dist/{messages-DDLgIPDF.mjs → chunks/messages-DLfR5bMd.mjs} +16 -2
  53. package/dist/{messages-CbhuIWRJ.mjs → chunks/messages-DT4dP5uK.mjs} +15 -1
  54. package/dist/chunks/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
  55. package/dist/{messages-BPqWKx5Z.mjs → chunks/messages-Diu6jAaR.mjs} +17 -3
  56. package/dist/{messages-BA0rcTCY.mjs → chunks/messages-DnIhyAJk.mjs} +18 -4
  57. package/dist/chunks/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
  58. package/dist/chunks/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
  59. package/dist/{messages-CJoBtXU6.mjs → chunks/messages-DqM1LFg5.mjs} +14 -0
  60. package/dist/chunks/{messages-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
  61. package/dist/chunks/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
  62. package/dist/chunks/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
  63. package/dist/chunks/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
  64. package/dist/{messages-DY94ykcE.mjs → chunks/messages-LPVfA-8K.mjs} +14 -0
  65. package/dist/{messages-Cr-RJ7YB.mjs → chunks/messages-O5tQus_0.mjs} +14 -0
  66. package/dist/chunks/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
  67. package/dist/chunks/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
  68. package/dist/{messages-CUy1vn-b.mjs → chunks/messages-Xq8UmkVs.mjs} +14 -0
  69. package/dist/chunks/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
  70. package/dist/chunks/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
  71. package/dist/chunks/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
  72. package/dist/chunks/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
  73. package/dist/chunks/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
  74. package/dist/chunks/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
  75. package/dist/cli.mjs +50 -0
  76. package/dist/full.mjs +15 -15
  77. package/dist/locales.mjs +102 -88
  78. package/dist/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
  79. package/dist/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
  80. package/dist/{chunks/messages-LvFKBBPa.mjs → messages-7W4d0DwD.mjs} +15 -1
  81. package/dist/{chunks/messages-Bn253WWC.mjs → messages-9SihnaXQ.mjs} +14 -0
  82. package/dist/{chunks/messages-Bf6Y3_GI.mjs → messages-B1Aww8q7.mjs} +16 -2
  83. package/dist/{chunks/messages-pA5TvcAj.mjs → messages-BB5z9Uba.mjs} +14 -0
  84. package/dist/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
  85. package/dist/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
  86. package/dist/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
  87. package/dist/{chunks/messages-B5puUm7R.mjs → messages-BL0tXcDf.mjs} +15 -1
  88. package/dist/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
  89. package/dist/{chunks/messages-CyDU5lz9.mjs → messages-BMv4xwIr.mjs} +16 -2
  90. package/dist/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
  91. package/dist/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
  92. package/dist/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
  93. package/dist/{chunks/messages-CXHd9SUK.mjs → messages-BYyy6Wqf.mjs} +14 -0
  94. package/dist/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
  95. package/dist/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
  96. package/dist/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
  97. package/dist/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
  98. package/dist/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
  99. package/dist/{messages-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
  100. package/dist/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
  101. package/dist/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
  102. package/dist/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
  103. package/dist/messages-CKI54h6O.mjs +62 -0
  104. package/dist/{chunks/messages-CrsJ1TEJ.mjs → messages-CLhcMlTc.mjs} +15 -1
  105. package/dist/{chunks/messages-CnvW8Slp.mjs → messages-CMkNSDTo.mjs} +17 -3
  106. package/dist/{chunks/messages-BlpqL8vG.mjs → messages-CQwpzUFp.mjs} +19 -5
  107. package/dist/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
  108. package/dist/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
  109. package/dist/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
  110. package/dist/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
  111. package/dist/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
  112. package/dist/{chunks/messages-Dg92dXZ5.mjs → messages-CvGLfqmV.mjs} +14 -0
  113. package/dist/{chunks/messages-AHESHJm_.mjs → messages-CzTufCHu.mjs} +14 -0
  114. package/dist/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
  115. package/dist/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
  116. package/dist/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
  117. package/dist/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
  118. package/dist/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
  119. package/dist/{chunks/messages-zSzDzXej.mjs → messages-DBRw-7Zc.mjs} +16 -2
  120. package/dist/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
  121. package/dist/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
  122. package/dist/{chunks/messages-DDLgIPDF.mjs → messages-DLfR5bMd.mjs} +16 -2
  123. package/dist/{chunks/messages-CbhuIWRJ.mjs → messages-DT4dP5uK.mjs} +15 -1
  124. package/dist/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
  125. package/dist/{chunks/messages-BPqWKx5Z.mjs → messages-Diu6jAaR.mjs} +17 -3
  126. package/dist/{chunks/messages-BA0rcTCY.mjs → messages-DnIhyAJk.mjs} +18 -4
  127. package/dist/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
  128. package/dist/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
  129. package/dist/{chunks/messages-CJoBtXU6.mjs → messages-DqM1LFg5.mjs} +14 -0
  130. package/dist/{messages-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
  131. package/dist/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
  132. package/dist/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
  133. package/dist/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
  134. package/dist/{chunks/messages-DY94ykcE.mjs → messages-LPVfA-8K.mjs} +14 -0
  135. package/dist/{chunks/messages-Cr-RJ7YB.mjs → messages-O5tQus_0.mjs} +14 -0
  136. package/dist/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
  137. package/dist/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
  138. package/dist/{chunks/messages-CUy1vn-b.mjs → messages-Xq8UmkVs.mjs} +14 -0
  139. package/dist/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
  140. package/dist/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
  141. package/dist/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
  142. package/dist/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
  143. package/dist/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
  144. package/dist/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
  145. package/dist/tools.mjs +2005 -1267
  146. package/dist/vendor.LICENSE.txt +1 -1
  147. package/package.json +15 -14
  148. package/src/cli/commands/migration.ts +16 -0
  149. package/src/cli/commands/migrationContent.ts +6 -0
  150. package/src/cli/index.ts +47 -0
  151. package/src/cli/utils/output.ts +10 -0
  152. package/src/components/block-tunes/block-tune-delete.ts +3 -2
  153. package/src/components/blocks.ts +23 -6
  154. package/src/components/constants/data-attributes.ts +2 -0
  155. package/src/components/i18n/locales/am/messages.json +15 -1
  156. package/src/components/i18n/locales/ar/messages.json +14 -0
  157. package/src/components/i18n/locales/az/messages.json +14 -0
  158. package/src/components/i18n/locales/bg/messages.json +14 -0
  159. package/src/components/i18n/locales/bn/messages.json +25 -11
  160. package/src/components/i18n/locales/bs/messages.json +15 -1
  161. package/src/components/i18n/locales/cs/messages.json +14 -0
  162. package/src/components/i18n/locales/da/messages.json +14 -0
  163. package/src/components/i18n/locales/de/messages.json +14 -0
  164. package/src/components/i18n/locales/dv/messages.json +15 -1
  165. package/src/components/i18n/locales/el/messages.json +15 -1
  166. package/src/components/i18n/locales/en/messages.json +14 -0
  167. package/src/components/i18n/locales/es/messages.json +14 -0
  168. package/src/components/i18n/locales/et/messages.json +14 -0
  169. package/src/components/i18n/locales/fa/messages.json +15 -1
  170. package/src/components/i18n/locales/fi/messages.json +15 -1
  171. package/src/components/i18n/locales/fil/messages.json +20 -6
  172. package/src/components/i18n/locales/fr/messages.json +15 -1
  173. package/src/components/i18n/locales/gu/messages.json +15 -1
  174. package/src/components/i18n/locales/he/messages.json +14 -0
  175. package/src/components/i18n/locales/hi/messages.json +23 -9
  176. package/src/components/i18n/locales/hr/messages.json +14 -0
  177. package/src/components/i18n/locales/hu/messages.json +14 -0
  178. package/src/components/i18n/locales/hy/messages.json +16 -2
  179. package/src/components/i18n/locales/id/messages.json +19 -5
  180. package/src/components/i18n/locales/it/messages.json +14 -0
  181. package/src/components/i18n/locales/ja/messages.json +14 -0
  182. package/src/components/i18n/locales/ka/messages.json +15 -1
  183. package/src/components/i18n/locales/km/messages.json +16 -2
  184. package/src/components/i18n/locales/kn/messages.json +16 -2
  185. package/src/components/i18n/locales/ko/messages.json +14 -0
  186. package/src/components/i18n/locales/ku/messages.json +16 -2
  187. package/src/components/i18n/locales/lo/messages.json +15 -1
  188. package/src/components/i18n/locales/lt/messages.json +15 -1
  189. package/src/components/i18n/locales/lv/messages.json +15 -1
  190. package/src/components/i18n/locales/mk/messages.json +16 -2
  191. package/src/components/i18n/locales/ml/messages.json +16 -2
  192. package/src/components/i18n/locales/mn/messages.json +16 -2
  193. package/src/components/i18n/locales/mr/messages.json +24 -10
  194. package/src/components/i18n/locales/ms/messages.json +17 -3
  195. package/src/components/i18n/locales/my/messages.json +16 -2
  196. package/src/components/i18n/locales/ne/messages.json +24 -10
  197. package/src/components/i18n/locales/nl/messages.json +15 -1
  198. package/src/components/i18n/locales/no/messages.json +16 -2
  199. package/src/components/i18n/locales/pa/messages.json +15 -1
  200. package/src/components/i18n/locales/pl/messages.json +14 -0
  201. package/src/components/i18n/locales/ps/messages.json +17 -3
  202. package/src/components/i18n/locales/pt/messages.json +14 -0
  203. package/src/components/i18n/locales/ro/messages.json +15 -1
  204. package/src/components/i18n/locales/ru/messages.json +14 -0
  205. package/src/components/i18n/locales/sd/messages.json +16 -2
  206. package/src/components/i18n/locales/si/messages.json +23 -9
  207. package/src/components/i18n/locales/sk/messages.json +15 -1
  208. package/src/components/i18n/locales/sl/messages.json +16 -2
  209. package/src/components/i18n/locales/sq/messages.json +16 -2
  210. package/src/components/i18n/locales/sr/messages.json +16 -2
  211. package/src/components/i18n/locales/sv/messages.json +16 -2
  212. package/src/components/i18n/locales/sw/messages.json +16 -2
  213. package/src/components/i18n/locales/ta/messages.json +21 -7
  214. package/src/components/i18n/locales/te/messages.json +40 -26
  215. package/src/components/i18n/locales/th/messages.json +19 -5
  216. package/src/components/i18n/locales/tr/messages.json +15 -1
  217. package/src/components/i18n/locales/ug/messages.json +16 -2
  218. package/src/components/i18n/locales/uk/messages.json +15 -1
  219. package/src/components/i18n/locales/ur/messages.json +15 -1
  220. package/src/components/i18n/locales/vi/messages.json +25 -11
  221. package/src/components/i18n/locales/yi/messages.json +16 -2
  222. package/src/components/i18n/locales/zh/messages.json +15 -1
  223. package/src/components/icons/index.ts +104 -83
  224. package/src/components/modules/api/blocks.ts +35 -2
  225. package/src/components/modules/api/history.ts +64 -0
  226. package/src/components/modules/api/index.ts +2 -0
  227. package/src/components/modules/api/readonly.ts +11 -1
  228. package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +12 -1
  229. package/src/components/modules/blockManager/blockManager.ts +7 -0
  230. package/src/components/modules/blockManager/operations.ts +3 -2
  231. package/src/components/modules/blockManager/types.ts +3 -1
  232. package/src/components/modules/blockManager/yjs-sync.ts +12 -2
  233. package/src/components/modules/index.ts +3 -0
  234. package/src/components/modules/normalizeInlineImages.ts +263 -0
  235. package/src/components/modules/readonly.ts +11 -0
  236. package/src/components/modules/rectangleSelection.ts +19 -3
  237. package/src/components/modules/saver.ts +7 -3
  238. package/src/components/modules/toolbar/blockSettings.ts +3 -3
  239. package/src/components/modules/toolbar/index.ts +72 -14
  240. package/src/components/modules/toolbar/plus-button.ts +24 -3
  241. package/src/components/modules/toolbar/settings-toggler.ts +3 -5
  242. package/src/components/modules/ui.ts +46 -68
  243. package/src/components/modules/uiControllers/controllers/blockHover.ts +49 -61
  244. package/src/components/modules/uiControllers/controllers/keyboard.ts +17 -11
  245. package/src/components/modules/uiControllers/handlers/click.ts +0 -12
  246. package/src/components/modules/yjs/index.ts +23 -0
  247. package/src/components/ui/toolbox.ts +41 -6
  248. package/src/components/utils/placeholder.ts +16 -0
  249. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -1
  250. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -1
  251. package/src/components/utils/popover/index.ts +1 -0
  252. package/src/components/utils/popover/popover-abstract.ts +11 -1
  253. package/src/components/utils/popover/popover-desktop.ts +27 -8
  254. package/src/components/utils/popover/popover-registry.ts +188 -0
  255. package/src/components/utils/sanitizer.ts +23 -2
  256. package/src/components/utils/tooltip.ts +2 -24
  257. package/src/styles/main.css +22 -0
  258. package/src/tools/paragraph/index.ts +12 -4
  259. package/src/tools/table/data-normalizer.ts +1 -0
  260. package/src/tools/table/index.ts +283 -346
  261. package/src/tools/table/table-add-controls.ts +353 -47
  262. package/src/tools/table/table-cell-blocks.ts +95 -7
  263. package/src/tools/table/table-cell-selection.ts +648 -0
  264. package/src/tools/table/table-core.ts +21 -32
  265. package/src/tools/table/table-grip-visuals.ts +96 -0
  266. package/src/tools/table/table-heading-toggle.ts +127 -0
  267. package/src/tools/table/table-operations.ts +475 -0
  268. package/src/tools/table/table-resize.ts +27 -6
  269. package/src/tools/table/table-restrictions.ts +64 -0
  270. package/src/tools/table/table-row-col-action-handler.ts +190 -0
  271. package/src/tools/table/table-row-col-controls.ts +265 -211
  272. package/src/tools/table/table-row-col-drag.ts +4 -4
  273. package/src/tools/table/table-row-col-popover.ts +225 -0
  274. package/src/tools/table/types.ts +4 -0
  275. package/src/types-internal/blok-modules.d.ts +2 -0
  276. package/types/api/blocks.d.ts +8 -0
  277. package/types/api/history.d.ts +33 -0
  278. package/types/api/index.d.ts +1 -0
  279. package/types/api/readonly.d.ts +12 -2
  280. package/types/index.d.ts +10 -0
  281. package/types/tools/table.d.ts +67 -0
  282. package/types/tools-entry.d.ts +4 -0
  283. package/types/utils/popover/popover-item.d.ts +6 -0
  284. package/types/utils/popover/popover.d.ts +7 -0
  285. package/dist/chunks/messages-CySyfkMU.mjs +0 -48
  286. package/dist/messages-CySyfkMU.mjs +0 -48
@@ -0,0 +1,475 @@
1
+ import type { API } from '../../../types';
2
+
3
+ import type { TableCellBlocks } from './table-cell-blocks';
4
+ import { CELL_BLOCKS_ATTR } from './table-cell-blocks';
5
+ import { BORDER_WIDTH, ROW_ATTR, CELL_ATTR } from './table-core';
6
+ import type { TableGrid } from './table-core';
7
+ import type { LegacyCellContent, TableData } from './types';
8
+ import { isCellWithBlocks } from './types';
9
+
10
+ // ─── Pure DOM helpers ───────────────────────────────────────────────
11
+
12
+ export const readPixelWidths = (gridEl: HTMLElement): number[] => {
13
+ const firstRow = gridEl.querySelector(`[${ROW_ATTR}]`);
14
+
15
+ if (!firstRow) {
16
+ return [];
17
+ }
18
+
19
+ const cells = firstRow.querySelectorAll(`[${CELL_ATTR}]`);
20
+
21
+ return Array.from(cells).map(cell =>
22
+ (cell as HTMLElement).getBoundingClientRect().width
23
+ );
24
+ };
25
+
26
+ export const applyPixelWidths = (gridEl: HTMLElement, widths: number[]): void => {
27
+ const totalWidth = widths.reduce((sum, w) => sum + w, 0);
28
+ const gridStyle: HTMLElement = gridEl;
29
+
30
+ gridStyle.style.width = `${totalWidth + BORDER_WIDTH}px`;
31
+
32
+ const rowEls = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
33
+
34
+ rowEls.forEach(row => {
35
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
36
+
37
+ cells.forEach((node, i) => {
38
+ if (i < widths.length) {
39
+ const cellEl = node as HTMLElement;
40
+
41
+ cellEl.style.width = `${widths[i]}px`;
42
+ }
43
+ });
44
+ });
45
+ };
46
+
47
+ export const getCellPosition = (gridEl: HTMLElement, cell: HTMLElement): { row: number; col: number } | null => {
48
+ const rows = Array.from(gridEl.querySelectorAll(`[${ROW_ATTR}]`));
49
+
50
+ const rowIndex = rows.findIndex(row => {
51
+ const cells = Array.from(row.querySelectorAll(`[${CELL_ATTR}]`));
52
+
53
+ return cells.includes(cell);
54
+ });
55
+
56
+ if (rowIndex === -1) {
57
+ return null;
58
+ }
59
+
60
+ const cells = Array.from(rows[rowIndex].querySelectorAll(`[${CELL_ATTR}]`));
61
+ const colIndex = cells.indexOf(cell);
62
+
63
+ return { row: rowIndex, col: colIndex };
64
+ };
65
+
66
+ // ─── Cell emptiness ─────────────────────────────────────────────────
67
+
68
+ export const isCellEmpty = (cell: HTMLElement): boolean => {
69
+ const container = cell.querySelector(`[${CELL_BLOCKS_ATTR}]`);
70
+
71
+ if (!container) {
72
+ return true;
73
+ }
74
+
75
+ return (container.textContent ?? '').trim().length === 0;
76
+ };
77
+
78
+ export const isRowEmpty = (gridEl: HTMLElement, rowIndex: number): boolean => {
79
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
80
+ const row = rows[rowIndex];
81
+
82
+ if (!row) {
83
+ return true;
84
+ }
85
+
86
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
87
+
88
+ return Array.from(cells).every(cell => isCellEmpty(cell as HTMLElement));
89
+ };
90
+
91
+ export const isColumnEmpty = (gridEl: HTMLElement, colIndex: number): boolean => {
92
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
93
+
94
+ return Array.from(rows).every(row => {
95
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
96
+ const cell = cells[colIndex] as HTMLElement | undefined;
97
+
98
+ return !cell || isCellEmpty(cell);
99
+ });
100
+ };
101
+
102
+ // ─── Percent-mode width redistribution ──────────────────────────────
103
+
104
+ export const redistributePercentWidths = (gridEl: HTMLElement): void => {
105
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
106
+ const firstRow = rows[0];
107
+
108
+ if (!firstRow) {
109
+ return;
110
+ }
111
+
112
+ const firstRowCells = firstRow.querySelectorAll(`[${CELL_ATTR}]`);
113
+ const currentTotal = Array.from(firstRowCells).reduce(
114
+ (sum, cell) => sum + (parseFloat((cell as HTMLElement).style.width) || 0),
115
+ 0,
116
+ );
117
+
118
+ if (currentTotal <= 0) {
119
+ return;
120
+ }
121
+
122
+ const scale = 100 / currentTotal;
123
+
124
+ rows.forEach(row => {
125
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
126
+
127
+ cells.forEach(cell => {
128
+ const el = cell as HTMLElement;
129
+ const oldWidth = parseFloat(el.style.width) || 0;
130
+
131
+ el.style.width = `${Math.round(oldWidth * scale * 100) / 100}%`;
132
+ });
133
+ });
134
+ };
135
+
136
+ // ─── Column width bookkeeping ───────────────────────────────────────
137
+
138
+ export const syncColWidthsAfterMove = (colWidths: number[] | undefined, fromIndex: number, toIndex: number): number[] | undefined => {
139
+ if (!colWidths) {
140
+ return colWidths;
141
+ }
142
+
143
+ const widths = [...colWidths];
144
+ const [moved] = widths.splice(fromIndex, 1);
145
+
146
+ widths.splice(toIndex, 0, moved);
147
+
148
+ return widths;
149
+ };
150
+
151
+ export const syncColWidthsAfterDeleteColumn = (colWidths: number[] | undefined, index: number): number[] | undefined => {
152
+ if (!colWidths) {
153
+ return colWidths;
154
+ }
155
+
156
+ const widths = [...colWidths];
157
+
158
+ widths.splice(index, 1);
159
+
160
+ return widths.length > 0 ? widths : undefined;
161
+ };
162
+
163
+ export const computeInsertColumnWidths = (
164
+ gridEl: HTMLElement,
165
+ index: number,
166
+ data: TableData,
167
+ grid: TableGrid,
168
+ ): number[] => {
169
+ const colWidths = data.colWidths ?? readPixelWidths(gridEl);
170
+
171
+ const halfWidth = data.initialColWidth !== undefined
172
+ ? Math.round((data.initialColWidth / 2) * 100) / 100
173
+ : computeHalfAvgWidth(colWidths);
174
+
175
+ grid.addColumn(gridEl, index, colWidths, halfWidth);
176
+
177
+ const newWidths = [...colWidths];
178
+
179
+ newWidths.splice(index, 0, halfWidth);
180
+
181
+ return newWidths;
182
+ };
183
+
184
+ export const computeHalfAvgWidth = (colWidths: number[]): number =>
185
+ Math.round(
186
+ (colWidths.reduce((sum, w) => sum + w, 0) / colWidths.length / 2) * 100
187
+ ) / 100;
188
+
189
+ export const computeInitialColWidth = (colWidths: number[]): number => {
190
+ if (colWidths.length === 0) {
191
+ return 0;
192
+ }
193
+
194
+ return Math.round((colWidths.reduce((sum, w) => sum + w, 0) / colWidths.length) * 100) / 100;
195
+ };
196
+
197
+ // ─── Block IDs from cells ───────────────────────────────────────────
198
+
199
+ export const getBlockIdsInRow = (element: HTMLElement | null, cellBlocks: TableCellBlocks | null, rowIndex: number): string[] => {
200
+ if (!element) {
201
+ return [];
202
+ }
203
+
204
+ const rows = element.querySelectorAll(`[${ROW_ATTR}]`);
205
+ const row = rows[rowIndex];
206
+
207
+ if (!row) {
208
+ return [];
209
+ }
210
+
211
+ return cellBlocks?.getBlockIdsFromCells(row.querySelectorAll(`[${CELL_ATTR}]`)) ?? [];
212
+ };
213
+
214
+ export const getBlockIdsInColumn = (element: HTMLElement | null, cellBlocks: TableCellBlocks | null, colIndex: number): string[] => {
215
+ if (!element) {
216
+ return [];
217
+ }
218
+
219
+ const rows = element.querySelectorAll(`[${ROW_ATTR}]`);
220
+ const cellsInColumn: Element[] = [];
221
+
222
+ rows.forEach(row => {
223
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
224
+
225
+ if (colIndex < cells.length) {
226
+ cellsInColumn.push(cells[colIndex]);
227
+ }
228
+ });
229
+
230
+ return cellBlocks?.getBlockIdsFromCells(cellsInColumn) ?? [];
231
+ };
232
+
233
+ // ─── Row/column deletion with block cleanup ─────────────────────────
234
+
235
+ export const deleteRowWithBlockCleanup = (
236
+ gridEl: HTMLElement,
237
+ rowIndex: number,
238
+ grid: TableGrid,
239
+ cellBlocks: TableCellBlocks | null,
240
+ ): void => {
241
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
242
+ const row = rows[rowIndex];
243
+
244
+ if (row && cellBlocks) {
245
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
246
+
247
+ cellBlocks.deleteBlocks(cellBlocks.getBlockIdsFromCells(cells));
248
+ }
249
+
250
+ grid.deleteRow(gridEl, rowIndex);
251
+ };
252
+
253
+ export const deleteColumnWithBlockCleanup = (
254
+ gridEl: HTMLElement,
255
+ colIndex: number,
256
+ colWidths: number[] | undefined,
257
+ grid: TableGrid,
258
+ cellBlocks: TableCellBlocks | null,
259
+ ): number[] | undefined => {
260
+ if (cellBlocks) {
261
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
262
+ const cellsInColumn: Element[] = [];
263
+
264
+ rows.forEach(row => {
265
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
266
+
267
+ if (colIndex < cells.length) {
268
+ cellsInColumn.push(cells[colIndex]);
269
+ }
270
+ });
271
+
272
+ cellBlocks.deleteBlocks(cellBlocks.getBlockIdsFromCells(cellsInColumn));
273
+ }
274
+
275
+ grid.deleteColumn(gridEl, colIndex);
276
+
277
+ return syncColWidthsAfterDeleteColumn(colWidths, colIndex);
278
+ };
279
+
280
+ // ─── Populate new cells ─────────────────────────────────────────────
281
+
282
+ export const populateNewCells = (gridEl: HTMLElement, cellBlocks: TableCellBlocks | null): void => {
283
+ const cells = gridEl.querySelectorAll(`[${CELL_ATTR}]`);
284
+
285
+ cells.forEach(cell => {
286
+ cellBlocks?.ensureCellHasBlock(cell as HTMLElement);
287
+ });
288
+ };
289
+
290
+ // ─── Readonly block mounting ────────────────────────────────────────
291
+
292
+ export const mountCellBlocksReadOnly = (
293
+ gridEl: HTMLElement,
294
+ content: LegacyCellContent[][],
295
+ api: API,
296
+ ): void => {
297
+ const rowElements = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
298
+
299
+ content.forEach((rowData, rowIndex) => {
300
+ const row = rowElements[rowIndex];
301
+
302
+ if (!row) {
303
+ return;
304
+ }
305
+
306
+ const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
307
+
308
+ rowData.forEach((cellContent, colIndex) => {
309
+ const cell = cells[colIndex] as HTMLElement | undefined;
310
+
311
+ if (!cell) {
312
+ return;
313
+ }
314
+
315
+ const container = cell.querySelector<HTMLElement>(`[${CELL_BLOCKS_ATTR}]`);
316
+
317
+ if (!container) {
318
+ return;
319
+ }
320
+
321
+ // Skip legacy cells that already have blocks (idempotency guard)
322
+ const hasExistingBlocks = container.querySelectorAll('[data-blok-id]').length > 0;
323
+
324
+ if (!isCellWithBlocks(cellContent) && hasExistingBlocks) {
325
+ return;
326
+ }
327
+
328
+ if (!isCellWithBlocks(cellContent)) {
329
+ // Handle legacy string content by creating a paragraph block
330
+ const legacyText = typeof cellContent === 'string' ? cellContent : '';
331
+ const insertedBlock = api.blocks.insert(
332
+ 'paragraph',
333
+ { text: legacyText },
334
+ {},
335
+ undefined,
336
+ true
337
+ );
338
+
339
+ insertedBlock?.holder && container.appendChild(insertedBlock.holder);
340
+
341
+ return;
342
+ }
343
+
344
+ for (const blockId of cellContent.blocks) {
345
+ const index = api.blocks.getBlockIndex(blockId);
346
+
347
+ if (index === undefined) {
348
+ continue;
349
+ }
350
+
351
+ const block = api.blocks.getBlockByIndex(index);
352
+
353
+ if (!block) {
354
+ continue;
355
+ }
356
+
357
+ container.appendChild(block.holder);
358
+ }
359
+ });
360
+ });
361
+ };
362
+
363
+ // ─── Data normalization ─────────────────────────────────────────────
364
+
365
+ export const normalizeTableData = (
366
+ data: TableData | Record<string, never>,
367
+ config: { withHeadings?: boolean; stretched?: boolean },
368
+ ): TableData => {
369
+ const isTableData = typeof data === 'object' && data !== null && 'content' in data;
370
+
371
+ if (!isTableData) {
372
+ return {
373
+ withHeadings: config.withHeadings ?? false,
374
+ withHeadingColumn: false,
375
+ stretched: config.stretched ?? false,
376
+ content: [],
377
+ };
378
+ }
379
+
380
+ const tableData = data as TableData;
381
+ const cols = tableData.content?.[0]?.length;
382
+ const colWidths = tableData.colWidths;
383
+ const validWidths = colWidths && cols && colWidths.length === cols ? colWidths : undefined;
384
+
385
+ return {
386
+ withHeadings: tableData.withHeadings ?? config.withHeadings ?? false,
387
+ withHeadingColumn: tableData.withHeadingColumn ?? false,
388
+ stretched: tableData.stretched ?? config.stretched ?? false,
389
+ content: tableData.content ?? [],
390
+ colWidths: validWidths,
391
+ initialColWidth: tableData.initialColWidth,
392
+ };
393
+ };
394
+
395
+ // ─── Keyboard navigation ────────────────────────────────────────────
396
+
397
+ export const setupKeyboardNavigation = (
398
+ gridEl: HTMLElement,
399
+ cellBlocks: TableCellBlocks | null,
400
+ ): void => {
401
+ gridEl.addEventListener('keydown', (event: KeyboardEvent) => {
402
+ const target = event.target as HTMLElement;
403
+ const cell = target.closest<HTMLElement>(`[${CELL_ATTR}]`);
404
+
405
+ if (!cell) {
406
+ return;
407
+ }
408
+
409
+ const position = getCellPosition(gridEl, cell);
410
+
411
+ if (position) {
412
+ cellBlocks?.handleKeyDown(event, position);
413
+ }
414
+ });
415
+ };
416
+
417
+ export const SCROLL_OVERFLOW_CLASSES = ['overflow-x-auto', 'pt-[9px]', 'pl-[9px]'];
418
+
419
+ export const enableScrollOverflow = (element: HTMLDivElement | null): void => {
420
+ element?.classList.add(...SCROLL_OVERFLOW_CLASSES);
421
+ };
422
+
423
+ // ─── Heading styles ─────────────────────────────────────────────────
424
+
425
+ export const updateHeadingStyles = (element: HTMLDivElement | null, withHeadings: boolean): void => {
426
+ if (!element) {
427
+ return;
428
+ }
429
+
430
+ const gridEl = element.firstElementChild as HTMLElement;
431
+
432
+ if (!gridEl) {
433
+ return;
434
+ }
435
+
436
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
437
+
438
+ rows.forEach(row => {
439
+ row.removeAttribute('data-blok-table-heading');
440
+ });
441
+
442
+ if (withHeadings && rows.length > 0) {
443
+ rows[0].setAttribute('data-blok-table-heading', '');
444
+ }
445
+ };
446
+
447
+ export const updateHeadingColumnStyles = (element: HTMLDivElement | null, withHeadingColumn: boolean): void => {
448
+ if (!element) {
449
+ return;
450
+ }
451
+
452
+ const gridEl = element.firstElementChild as HTMLElement;
453
+
454
+ if (!gridEl) {
455
+ return;
456
+ }
457
+
458
+ const allCells = gridEl.querySelectorAll(`[${CELL_ATTR}]`);
459
+
460
+ allCells.forEach(cell => {
461
+ cell.removeAttribute('data-blok-table-heading-col');
462
+ });
463
+
464
+ if (withHeadingColumn) {
465
+ const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
466
+
467
+ rows.forEach(row => {
468
+ const firstCell = row.querySelector(`[${CELL_ATTR}]`);
469
+
470
+ if (firstCell) {
471
+ firstCell.setAttribute('data-blok-table-heading-col', '');
472
+ }
473
+ });
474
+ }
475
+ };
@@ -17,11 +17,14 @@ export class TableResize {
17
17
  private gridEl: HTMLElement;
18
18
  private colWidths: number[];
19
19
  private onChange: (widths: number[]) => void;
20
+ private onDragStart: (() => void) | null;
21
+ private onDrag: (() => void) | null;
20
22
  private isDragging = false;
21
23
  private dragStartX = 0;
22
24
  private dragColIndex = -1;
23
25
  private startColWidth = 0;
24
26
  private handles: HTMLElement[] = [];
27
+ private needsInitialApply: boolean;
25
28
 
26
29
  private boundPointerDown: (e: PointerEvent) => void;
27
30
  private boundPointerMove: (e: PointerEvent) => void;
@@ -43,17 +46,24 @@ export class TableResize {
43
46
  });
44
47
  }
45
48
 
46
- constructor(gridEl: HTMLElement, colWidths: number[], onChange: (widths: number[]) => void) {
49
+ constructor(gridEl: HTMLElement, colWidths: number[], onChange: (widths: number[]) => void, onDragStart?: () => void, onDrag?: () => void, skipInitialApply = false) {
47
50
  this.gridEl = gridEl;
48
51
  this.colWidths = [...colWidths];
49
52
  this.onChange = onChange;
53
+ this.onDragStart = onDragStart ?? null;
54
+ this.onDrag = onDrag ?? null;
55
+ this.needsInitialApply = skipInitialApply;
50
56
 
51
57
  this.boundPointerDown = this.onPointerDown.bind(this);
52
58
  this.boundPointerMove = this.onPointerMove.bind(this);
53
59
  this.boundPointerUp = this.onPointerUp.bind(this);
54
60
 
55
61
  this.gridEl.style.position = 'relative';
56
- this.applyWidths();
62
+
63
+ if (!skipInitialApply) {
64
+ this.applyWidths();
65
+ }
66
+
57
67
  this.createHandles();
58
68
 
59
69
  this.gridEl.addEventListener('pointerdown', this.boundPointerDown);
@@ -96,17 +106,20 @@ export class TableResize {
96
106
  handle.style.left = `${leftPx - HANDLE_HIT_WIDTH / 2}px`;
97
107
  handle.style.cursor = 'col-resize';
98
108
  handle.style.zIndex = '2';
109
+ handle.style.background = 'linear-gradient(to right, transparent 7px, #3b82f6 7px, #3b82f6 9px, transparent 9px)';
110
+ handle.style.opacity = '0';
111
+ handle.style.transition = 'opacity 150ms ease';
99
112
  handle.setAttribute('contenteditable', 'false');
100
113
 
101
114
  handle.addEventListener('mouseenter', () => {
102
115
  if (!this.isDragging) {
103
- handle.style.background = 'linear-gradient(to right, transparent 7px, #3b82f6 7px, #3b82f6 9px, transparent 9px)';
116
+ handle.style.opacity = '1';
104
117
  }
105
118
  });
106
119
 
107
120
  handle.addEventListener('mouseleave', () => {
108
121
  if (!this.isDragging) {
109
- handle.style.background = '';
122
+ handle.style.opacity = '0';
110
123
  }
111
124
  });
112
125
 
@@ -139,6 +152,12 @@ export class TableResize {
139
152
 
140
153
  e.preventDefault();
141
154
 
155
+ if (this.needsInitialApply) {
156
+ this.applyWidths();
157
+ this.updateHandlePositions();
158
+ this.needsInitialApply = false;
159
+ }
160
+
142
161
  const colStr = target.getAttribute('data-col');
143
162
 
144
163
  if (colStr === null) {
@@ -150,9 +169,10 @@ export class TableResize {
150
169
  this.dragStartX = e.clientX;
151
170
  this.startColWidth = this.colWidths[this.dragColIndex];
152
171
 
172
+ this.onDragStart?.();
153
173
  this.gridEl.style.userSelect = 'none';
154
174
 
155
- target.style.background = 'linear-gradient(to right, transparent 7px, #3b82f6 7px, #3b82f6 9px, transparent 9px)';
175
+ target.style.opacity = '1';
156
176
 
157
177
  if (target.setPointerCapture) {
158
178
  target.setPointerCapture(e.pointerId);
@@ -174,6 +194,7 @@ export class TableResize {
174
194
  this.colWidths[this.dragColIndex] = newWidth;
175
195
  this.applyWidths();
176
196
  this.updateHandlePositions();
197
+ this.onDrag?.();
177
198
  }
178
199
 
179
200
  private onPointerUp(): void {
@@ -187,7 +208,7 @@ export class TableResize {
187
208
  const activeHandle = this.handles[this.dragColIndex];
188
209
 
189
210
  if (activeHandle) {
190
- activeHandle.style.background = '';
211
+ activeHandle.style.opacity = '0';
191
212
  }
192
213
 
193
214
  document.removeEventListener('pointermove', this.boundPointerMove);
@@ -0,0 +1,64 @@
1
+ import type { API } from '../../../types';
2
+ import type { Block } from '../../components/block';
3
+
4
+ /**
5
+ * List of block tools that are restricted from being inserted into table cells.
6
+ * These tools create semantic or structural issues when nested in table cells.
7
+ */
8
+ export const RESTRICTED_TOOLS = ['header', 'table'];
9
+
10
+ /**
11
+ * Check if a block or element is inside a table cell.
12
+ * Uses the data-blok-table-cell-blocks attribute to detect cell containers.
13
+ *
14
+ * @param block - Block instance or HTMLElement to check
15
+ * @returns true if inside a table cell, false otherwise
16
+ */
17
+ export const isInsideTableCell = (block: Block | HTMLElement | null | undefined): boolean => {
18
+ if (!block) {
19
+ return false;
20
+ }
21
+
22
+ const element = block instanceof HTMLElement ? block : block.holder;
23
+
24
+ return element.closest('[data-blok-table-cell-blocks]') !== null;
25
+ };
26
+
27
+ /**
28
+ * Check if a tool name is restricted inside table cells.
29
+ *
30
+ * @param toolName - Name of the block tool to check
31
+ * @returns true if the tool is restricted in table cells, false otherwise
32
+ */
33
+ export const isRestrictedInTableCell = (toolName: string): boolean => {
34
+ return RESTRICTED_TOOLS.includes(toolName);
35
+ };
36
+
37
+ /**
38
+ * Convert a restricted block to a paragraph block, preserving text content.
39
+ * Replaces the original block in place.
40
+ *
41
+ * @param block - The block to convert
42
+ * @param api - Blok API instance
43
+ * @returns The newly created paragraph block
44
+ * @throws Error if block index cannot be found
45
+ */
46
+ export const convertToParagraph = (block: Block, api: API): Block => {
47
+ const text = block.holder.textContent || '';
48
+ const blockIndex = api.blocks.getBlockIndex(block.id);
49
+
50
+ if (blockIndex === undefined) {
51
+ throw new Error('Block index not found');
52
+ }
53
+
54
+ // Replace with paragraph, preserving text
55
+ return api.blocks.insert(
56
+ 'paragraph',
57
+ { text },
58
+ {},
59
+ blockIndex,
60
+ false, // don't focus
61
+ true, // replace existing
62
+ block.id
63
+ ) as unknown as Block;
64
+ };