@jackuait/blok 0.6.0-beta.13 → 0.6.0-beta.14

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 (246) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-DzeTRJ_i.mjs → blok-Cl30YOLl.mjs} +1398 -1132
  3. package/dist/chunks/{i18next-loader-CgW4H90H.mjs → i18next-loader-DbTDlMux.mjs} +1 -1
  4. package/dist/chunks/{index-BWKk7PIS.mjs → index-DJmaYswj.mjs} +1 -1
  5. package/dist/chunks/{inline-tool-convert-DrSwadw_.mjs → inline-tool-convert-MjSaP8r7.mjs} +161 -145
  6. package/dist/{messages-B1Aww8q7.mjs → chunks/messages-1mYyrppy.mjs} +1 -0
  7. package/dist/chunks/{messages-DnIhyAJk.mjs → messages-4gHfbcDp.mjs} +1 -0
  8. package/dist/{messages-CQwpzUFp.mjs → chunks/messages-6xYv-U8A.mjs} +1 -0
  9. package/dist/chunks/{messages-CMkNSDTo.mjs → messages-7jqF79FO.mjs} +1 -0
  10. package/dist/chunks/{messages-BSbjsyHY.mjs → messages-B3EUuA7o.mjs} +1 -0
  11. package/dist/{messages-LPVfA-8K.mjs → chunks/messages-B6srtRn7.mjs} +1 -0
  12. package/dist/chunks/{messages-DJDG55Vq.mjs → messages-B85OIs0E.mjs} +1 -0
  13. package/dist/{messages-_ErNTNhk.mjs → chunks/messages-BCYBBG_u.mjs} +1 -0
  14. package/dist/{messages-CZygwLwM.mjs → chunks/messages-BDLNPiaW.mjs} +1 -0
  15. package/dist/{messages-C2htQ_3F.mjs → chunks/messages-BKpNd1Zb.mjs} +1 -0
  16. package/dist/chunks/{messages-CnwibSvh.mjs → messages-BLFUid_o.mjs} +1 -0
  17. package/dist/{messages-CVw84KdI.mjs → chunks/messages-BNPTVKnc.mjs} +1 -0
  18. package/dist/{messages-BMv4xwIr.mjs → chunks/messages-BQPXSkri.mjs} +1 -0
  19. package/dist/{messages-Dz9L52ol.mjs → chunks/messages-BQu6VNDq.mjs} +1 -0
  20. package/dist/{messages-DprmQg6V.mjs → chunks/messages-BRodFKUo.mjs} +1 -0
  21. package/dist/{messages-CznZadDf.mjs → chunks/messages-BWIikA8H.mjs} +1 -0
  22. package/dist/{messages-CqWJcCbY.mjs → chunks/messages-BXQvMilx.mjs} +1 -0
  23. package/dist/chunks/{messages-Z9nEU2xK.mjs → messages-BZ92luiw.mjs} +1 -0
  24. package/dist/chunks/{messages-BC86qLvI.mjs → messages-Bg0Phlcj.mjs} +1 -0
  25. package/dist/chunks/{messages-DnXLrlHh.mjs → messages-Bh6RBIu5.mjs} +1 -0
  26. package/dist/chunks/{messages-DhLKYm2j.mjs → messages-BnFHdIpg.mjs} +1 -0
  27. package/dist/{messages-BU2nlrLK.mjs → chunks/messages-Bq82EVsw.mjs} +1 -0
  28. package/dist/chunks/{messages-Diu6jAaR.mjs → messages-BxbcTiHh.mjs} +1 -0
  29. package/dist/{messages-BoJc_p1r.mjs → chunks/messages-ByO6bSV2.mjs} +1 -0
  30. package/dist/chunks/{messages-BrPFGbM-.mjs → messages-ByUNPiQ4.mjs} +1 -0
  31. package/dist/chunks/{messages-BB5z9Uba.mjs → messages-Byw0EHyf.mjs} +1 -0
  32. package/dist/chunks/{messages-D1Hv8XGo.mjs → messages-C-aP90zq.mjs} +1 -0
  33. package/dist/chunks/{messages-DBRw-7Zc.mjs → messages-C2f44jci.mjs} +1 -0
  34. package/dist/chunks/{messages-CJdUsQ-c.mjs → messages-CKYoAmm9.mjs} +1 -0
  35. package/dist/chunks/{messages-CvGLfqmV.mjs → messages-CSQJrJ_N.mjs} +1 -0
  36. package/dist/chunks/{messages-1fC8IMyX.mjs → messages-CX_o4Cgc.mjs} +1 -0
  37. package/dist/chunks/{messages-BdeLo0N9.mjs → messages-C_tfXllT.mjs} +1 -0
  38. package/dist/chunks/{messages-DBn76jVV.mjs → messages-Cj6TZ_By.mjs} +1 -0
  39. package/dist/{messages-CLhcMlTc.mjs → chunks/messages-CjdYkfzj.mjs} +1 -0
  40. package/dist/{messages-7W4d0DwD.mjs → chunks/messages-CmvWFWR6.mjs} +1 -0
  41. package/dist/{messages-CzTufCHu.mjs → chunks/messages-CnV-kxh6.mjs} +1 -0
  42. package/dist/chunks/{messages-BMXCuEKO.mjs → messages-CpuDfpdi.mjs} +1 -0
  43. package/dist/chunks/{messages-DT4dP5uK.mjs → messages-Cspe1oXk.mjs} +1 -0
  44. package/dist/{messages-D-ZtY5v0.mjs → chunks/messages-D2_d-Jt4.mjs} +1 -0
  45. package/dist/{messages-BELRf6DU.mjs → chunks/messages-DADSbW8l.mjs} +1 -0
  46. package/dist/chunks/{messages-O5tQus_0.mjs → messages-DHSeTQ4S.mjs} +1 -0
  47. package/dist/{messages-BFG6Wlgy.mjs → chunks/messages-DKeO2RsW.mjs} +1 -0
  48. package/dist/chunks/{messages-9SihnaXQ.mjs → messages-DLdlX_dY.mjs} +1 -0
  49. package/dist/chunks/{messages-BL0tXcDf.mjs → messages-DVxlJ4DU.mjs} +1 -0
  50. package/dist/chunks/{messages-CY8_RyFE.mjs → messages-DWSxENRk.mjs} +1 -0
  51. package/dist/{messages-Q7AO_FLv.mjs → chunks/messages-D_bVNZ12.mjs} +1 -0
  52. package/dist/chunks/{messages-BYyy6Wqf.mjs → messages-DdzjVwmG.mjs} +1 -0
  53. package/dist/chunks/{messages-DLfR5bMd.mjs → messages-DhyBKTi0.mjs} +1 -0
  54. package/dist/chunks/{messages-DvFLX36Q.mjs → messages-DlC9jDXa.mjs} +1 -0
  55. package/dist/chunks/{messages-D5C3J9qr.mjs → messages-DmBGk8ed.mjs} +1 -0
  56. package/dist/chunks/{messages-R3hUSvr3.mjs → messages-Dm_VqpU6.mjs} +1 -0
  57. package/dist/chunks/{messages-w7v1GNaE.mjs → messages-Dn9hI_ER.mjs} +1 -0
  58. package/dist/{messages-uKX8WBaD.mjs → chunks/messages-Dssp4AXT.mjs} +1 -0
  59. package/dist/chunks/{messages-Xq8UmkVs.mjs → messages-DzCc0JgS.mjs} +1 -0
  60. package/dist/chunks/{messages-JELdtT6E.mjs → messages-N6THNxo0.mjs} +1 -0
  61. package/dist/chunks/{messages-DqM1LFg5.mjs → messages-OctOxF2l.mjs} +1 -0
  62. package/dist/chunks/{messages-_ncGrKHh.mjs → messages-QT3JA95K.mjs} +1 -0
  63. package/dist/{messages-C9eaarcK.mjs → chunks/messages-QqWK83BF.mjs} +1 -0
  64. package/dist/chunks/{messages-BogRq8lt.mjs → messages-RsGaDzbb.mjs} +1 -0
  65. package/dist/chunks/{messages-Dzwxv9v1.mjs → messages-c7YlI6Wm.mjs} +1 -0
  66. package/dist/{messages-D5iv1Kox.mjs → chunks/messages-lZ8aF-4r.mjs} +1 -0
  67. package/dist/chunks/{messages-7QoX8DkW.mjs → messages-uGDrchjb.mjs} +1 -0
  68. package/dist/chunks/{messages-CKI54h6O.mjs → messages-xc2yNvog.mjs} +1 -0
  69. package/dist/{messages-Bmu_S7GM.mjs → chunks/messages-y5Q-ymIx.mjs} +1 -0
  70. package/dist/{messages-BWF-zUpY.mjs → chunks/messages-yJnyedAd.mjs} +1 -0
  71. package/dist/{messages-kep5wtm4.mjs → chunks/messages-yQ_4upHh.mjs} +1 -0
  72. package/dist/chunks/{messages-C99mq906.mjs → messages-ysbWD56Q.mjs} +1 -0
  73. package/dist/full.mjs +2 -2
  74. package/dist/locales.mjs +68 -67
  75. package/dist/{chunks/messages-B1Aww8q7.mjs → messages-1mYyrppy.mjs} +1 -0
  76. package/dist/{messages-DnIhyAJk.mjs → messages-4gHfbcDp.mjs} +1 -0
  77. package/dist/{chunks/messages-CQwpzUFp.mjs → messages-6xYv-U8A.mjs} +1 -0
  78. package/dist/{messages-CMkNSDTo.mjs → messages-7jqF79FO.mjs} +1 -0
  79. package/dist/{messages-BSbjsyHY.mjs → messages-B3EUuA7o.mjs} +1 -0
  80. package/dist/{chunks/messages-LPVfA-8K.mjs → messages-B6srtRn7.mjs} +1 -0
  81. package/dist/{messages-DJDG55Vq.mjs → messages-B85OIs0E.mjs} +1 -0
  82. package/dist/{chunks/messages-_ErNTNhk.mjs → messages-BCYBBG_u.mjs} +1 -0
  83. package/dist/{chunks/messages-CZygwLwM.mjs → messages-BDLNPiaW.mjs} +1 -0
  84. package/dist/{chunks/messages-C2htQ_3F.mjs → messages-BKpNd1Zb.mjs} +1 -0
  85. package/dist/{messages-CnwibSvh.mjs → messages-BLFUid_o.mjs} +1 -0
  86. package/dist/{chunks/messages-CVw84KdI.mjs → messages-BNPTVKnc.mjs} +1 -0
  87. package/dist/{chunks/messages-BMv4xwIr.mjs → messages-BQPXSkri.mjs} +1 -0
  88. package/dist/{chunks/messages-Dz9L52ol.mjs → messages-BQu6VNDq.mjs} +1 -0
  89. package/dist/{chunks/messages-DprmQg6V.mjs → messages-BRodFKUo.mjs} +1 -0
  90. package/dist/{chunks/messages-CznZadDf.mjs → messages-BWIikA8H.mjs} +1 -0
  91. package/dist/{chunks/messages-CqWJcCbY.mjs → messages-BXQvMilx.mjs} +1 -0
  92. package/dist/{messages-Z9nEU2xK.mjs → messages-BZ92luiw.mjs} +1 -0
  93. package/dist/{messages-BC86qLvI.mjs → messages-Bg0Phlcj.mjs} +1 -0
  94. package/dist/{messages-DnXLrlHh.mjs → messages-Bh6RBIu5.mjs} +1 -0
  95. package/dist/{messages-DhLKYm2j.mjs → messages-BnFHdIpg.mjs} +1 -0
  96. package/dist/{chunks/messages-BU2nlrLK.mjs → messages-Bq82EVsw.mjs} +1 -0
  97. package/dist/{messages-Diu6jAaR.mjs → messages-BxbcTiHh.mjs} +1 -0
  98. package/dist/{chunks/messages-BoJc_p1r.mjs → messages-ByO6bSV2.mjs} +1 -0
  99. package/dist/{messages-BrPFGbM-.mjs → messages-ByUNPiQ4.mjs} +1 -0
  100. package/dist/{messages-BB5z9Uba.mjs → messages-Byw0EHyf.mjs} +1 -0
  101. package/dist/{messages-D1Hv8XGo.mjs → messages-C-aP90zq.mjs} +1 -0
  102. package/dist/{messages-DBRw-7Zc.mjs → messages-C2f44jci.mjs} +1 -0
  103. package/dist/{messages-CJdUsQ-c.mjs → messages-CKYoAmm9.mjs} +1 -0
  104. package/dist/{messages-CvGLfqmV.mjs → messages-CSQJrJ_N.mjs} +1 -0
  105. package/dist/{messages-1fC8IMyX.mjs → messages-CX_o4Cgc.mjs} +1 -0
  106. package/dist/{messages-BdeLo0N9.mjs → messages-C_tfXllT.mjs} +1 -0
  107. package/dist/{messages-DBn76jVV.mjs → messages-Cj6TZ_By.mjs} +1 -0
  108. package/dist/{chunks/messages-CLhcMlTc.mjs → messages-CjdYkfzj.mjs} +1 -0
  109. package/dist/{chunks/messages-7W4d0DwD.mjs → messages-CmvWFWR6.mjs} +1 -0
  110. package/dist/{chunks/messages-CzTufCHu.mjs → messages-CnV-kxh6.mjs} +1 -0
  111. package/dist/{messages-BMXCuEKO.mjs → messages-CpuDfpdi.mjs} +1 -0
  112. package/dist/{messages-DT4dP5uK.mjs → messages-Cspe1oXk.mjs} +1 -0
  113. package/dist/{chunks/messages-D-ZtY5v0.mjs → messages-D2_d-Jt4.mjs} +1 -0
  114. package/dist/{chunks/messages-BELRf6DU.mjs → messages-DADSbW8l.mjs} +1 -0
  115. package/dist/{messages-O5tQus_0.mjs → messages-DHSeTQ4S.mjs} +1 -0
  116. package/dist/{chunks/messages-BFG6Wlgy.mjs → messages-DKeO2RsW.mjs} +1 -0
  117. package/dist/{messages-9SihnaXQ.mjs → messages-DLdlX_dY.mjs} +1 -0
  118. package/dist/{messages-BL0tXcDf.mjs → messages-DVxlJ4DU.mjs} +1 -0
  119. package/dist/{messages-CY8_RyFE.mjs → messages-DWSxENRk.mjs} +1 -0
  120. package/dist/{chunks/messages-Q7AO_FLv.mjs → messages-D_bVNZ12.mjs} +1 -0
  121. package/dist/{messages-BYyy6Wqf.mjs → messages-DdzjVwmG.mjs} +1 -0
  122. package/dist/{messages-DLfR5bMd.mjs → messages-DhyBKTi0.mjs} +1 -0
  123. package/dist/{messages-DvFLX36Q.mjs → messages-DlC9jDXa.mjs} +1 -0
  124. package/dist/{messages-D5C3J9qr.mjs → messages-DmBGk8ed.mjs} +1 -0
  125. package/dist/{messages-R3hUSvr3.mjs → messages-Dm_VqpU6.mjs} +1 -0
  126. package/dist/{messages-w7v1GNaE.mjs → messages-Dn9hI_ER.mjs} +1 -0
  127. package/dist/{chunks/messages-uKX8WBaD.mjs → messages-Dssp4AXT.mjs} +1 -0
  128. package/dist/{messages-Xq8UmkVs.mjs → messages-DzCc0JgS.mjs} +1 -0
  129. package/dist/{messages-JELdtT6E.mjs → messages-N6THNxo0.mjs} +1 -0
  130. package/dist/{messages-DqM1LFg5.mjs → messages-OctOxF2l.mjs} +1 -0
  131. package/dist/{messages-_ncGrKHh.mjs → messages-QT3JA95K.mjs} +1 -0
  132. package/dist/{chunks/messages-C9eaarcK.mjs → messages-QqWK83BF.mjs} +1 -0
  133. package/dist/{messages-BogRq8lt.mjs → messages-RsGaDzbb.mjs} +1 -0
  134. package/dist/{messages-Dzwxv9v1.mjs → messages-c7YlI6Wm.mjs} +1 -0
  135. package/dist/{chunks/messages-D5iv1Kox.mjs → messages-lZ8aF-4r.mjs} +1 -0
  136. package/dist/{messages-7QoX8DkW.mjs → messages-uGDrchjb.mjs} +1 -0
  137. package/dist/{messages-CKI54h6O.mjs → messages-xc2yNvog.mjs} +1 -0
  138. package/dist/{chunks/messages-Bmu_S7GM.mjs → messages-y5Q-ymIx.mjs} +1 -0
  139. package/dist/{chunks/messages-BWF-zUpY.mjs → messages-yJnyedAd.mjs} +1 -0
  140. package/dist/{chunks/messages-kep5wtm4.mjs → messages-yQ_4upHh.mjs} +1 -0
  141. package/dist/{messages-C99mq906.mjs → messages-ysbWD56Q.mjs} +1 -0
  142. package/dist/tools.mjs +887 -701
  143. package/package.json +2 -1
  144. package/src/components/block/style-manager.ts +5 -1
  145. package/src/components/blocks.ts +109 -9
  146. package/src/components/i18n/locales/am/messages.json +1 -0
  147. package/src/components/i18n/locales/ar/messages.json +1 -0
  148. package/src/components/i18n/locales/az/messages.json +1 -0
  149. package/src/components/i18n/locales/bg/messages.json +1 -0
  150. package/src/components/i18n/locales/bn/messages.json +1 -0
  151. package/src/components/i18n/locales/bs/messages.json +1 -0
  152. package/src/components/i18n/locales/cs/messages.json +1 -0
  153. package/src/components/i18n/locales/da/messages.json +1 -0
  154. package/src/components/i18n/locales/de/messages.json +1 -0
  155. package/src/components/i18n/locales/dv/messages.json +1 -0
  156. package/src/components/i18n/locales/el/messages.json +1 -0
  157. package/src/components/i18n/locales/en/messages.json +1 -0
  158. package/src/components/i18n/locales/es/messages.json +1 -0
  159. package/src/components/i18n/locales/et/messages.json +1 -0
  160. package/src/components/i18n/locales/fa/messages.json +1 -0
  161. package/src/components/i18n/locales/fi/messages.json +1 -0
  162. package/src/components/i18n/locales/fil/messages.json +1 -0
  163. package/src/components/i18n/locales/fr/messages.json +1 -0
  164. package/src/components/i18n/locales/gu/messages.json +1 -0
  165. package/src/components/i18n/locales/he/messages.json +1 -0
  166. package/src/components/i18n/locales/hi/messages.json +1 -0
  167. package/src/components/i18n/locales/hr/messages.json +1 -0
  168. package/src/components/i18n/locales/hu/messages.json +1 -0
  169. package/src/components/i18n/locales/hy/messages.json +1 -0
  170. package/src/components/i18n/locales/id/messages.json +1 -0
  171. package/src/components/i18n/locales/it/messages.json +1 -0
  172. package/src/components/i18n/locales/ja/messages.json +1 -0
  173. package/src/components/i18n/locales/ka/messages.json +1 -0
  174. package/src/components/i18n/locales/km/messages.json +1 -0
  175. package/src/components/i18n/locales/kn/messages.json +1 -0
  176. package/src/components/i18n/locales/ko/messages.json +1 -0
  177. package/src/components/i18n/locales/ku/messages.json +1 -0
  178. package/src/components/i18n/locales/lo/messages.json +1 -0
  179. package/src/components/i18n/locales/lt/messages.json +1 -0
  180. package/src/components/i18n/locales/lv/messages.json +1 -0
  181. package/src/components/i18n/locales/mk/messages.json +1 -0
  182. package/src/components/i18n/locales/ml/messages.json +1 -0
  183. package/src/components/i18n/locales/mn/messages.json +1 -0
  184. package/src/components/i18n/locales/mr/messages.json +1 -0
  185. package/src/components/i18n/locales/ms/messages.json +1 -0
  186. package/src/components/i18n/locales/my/messages.json +1 -0
  187. package/src/components/i18n/locales/ne/messages.json +1 -0
  188. package/src/components/i18n/locales/nl/messages.json +1 -0
  189. package/src/components/i18n/locales/no/messages.json +1 -0
  190. package/src/components/i18n/locales/pa/messages.json +1 -0
  191. package/src/components/i18n/locales/pl/messages.json +1 -0
  192. package/src/components/i18n/locales/ps/messages.json +1 -0
  193. package/src/components/i18n/locales/pt/messages.json +1 -0
  194. package/src/components/i18n/locales/ro/messages.json +1 -0
  195. package/src/components/i18n/locales/ru/messages.json +1 -0
  196. package/src/components/i18n/locales/sd/messages.json +1 -0
  197. package/src/components/i18n/locales/si/messages.json +1 -0
  198. package/src/components/i18n/locales/sk/messages.json +1 -0
  199. package/src/components/i18n/locales/sl/messages.json +1 -0
  200. package/src/components/i18n/locales/sq/messages.json +1 -0
  201. package/src/components/i18n/locales/sr/messages.json +1 -0
  202. package/src/components/i18n/locales/sv/messages.json +1 -0
  203. package/src/components/i18n/locales/sw/messages.json +1 -0
  204. package/src/components/i18n/locales/ta/messages.json +1 -0
  205. package/src/components/i18n/locales/te/messages.json +1 -0
  206. package/src/components/i18n/locales/th/messages.json +1 -0
  207. package/src/components/i18n/locales/tr/messages.json +1 -0
  208. package/src/components/i18n/locales/ug/messages.json +1 -0
  209. package/src/components/i18n/locales/uk/messages.json +1 -0
  210. package/src/components/i18n/locales/ur/messages.json +1 -0
  211. package/src/components/i18n/locales/vi/messages.json +1 -0
  212. package/src/components/i18n/locales/yi/messages.json +1 -0
  213. package/src/components/i18n/locales/zh/messages.json +1 -0
  214. package/src/components/icons/index.ts +8 -0
  215. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +51 -10
  216. package/src/components/modules/blockEvents/index.ts +2 -5
  217. package/src/components/modules/blockManager/blockManager.ts +10 -0
  218. package/src/components/modules/blockManager/operations.ts +11 -0
  219. package/src/components/modules/blockManager/repository.ts +22 -0
  220. package/src/components/modules/blockManager/yjs-sync.ts +148 -31
  221. package/src/components/modules/crossBlockSelection.ts +11 -3
  222. package/src/components/modules/drag/preview/DragPreview.ts +8 -0
  223. package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
  224. package/src/components/modules/paste/handlers/base.ts +3 -4
  225. package/src/components/modules/paste/index.ts +1 -1
  226. package/src/components/modules/rectangleSelection.ts +5 -2
  227. package/src/components/modules/toolbar/blockSettings.ts +52 -44
  228. package/src/components/modules/toolbar/index.ts +27 -7
  229. package/src/components/modules/toolbar/inline/index.ts +1 -1
  230. package/src/components/modules/uiControllers/controllers/blockHover.ts +16 -2
  231. package/src/components/modules/uiControllers/handlers/touch.ts +83 -10
  232. package/src/components/modules/yjs/block-observer.ts +9 -3
  233. package/src/components/modules/yjs/document-store.ts +4 -2
  234. package/src/components/modules/yjs/types.ts +8 -6
  235. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -4
  236. package/src/components/utils/popover/popover-desktop.ts +12 -0
  237. package/src/stories/Popover.stories.ts +0 -2
  238. package/src/styles/main.css +9 -1
  239. package/src/tools/list/caret-manager.ts +28 -10
  240. package/src/tools/table/index.ts +180 -37
  241. package/src/tools/table/table-add-controls.ts +51 -14
  242. package/src/tools/table/table-cell-blocks.ts +41 -2
  243. package/src/tools/table/table-cell-selection.ts +27 -1
  244. package/src/tools/table/table-operations.ts +12 -15
  245. package/src/tools/table/table-row-col-controls.ts +69 -6
  246. package/src/tools/table/table-scroll-haze.ts +152 -0
@@ -188,7 +188,7 @@ export class InlineToolbar extends Module<InlineToolbarNodes> {
188
188
  await this.openingPromise;
189
189
  this.openingPromise = null;
190
190
 
191
- this.Blok.Toolbar.close();
191
+ this.Blok.Toolbar.hideBlockActions();
192
192
  }
193
193
 
194
194
  /**
@@ -157,13 +157,27 @@ export class BlockHoverController extends Controller {
157
157
  return null;
158
158
  }
159
159
 
160
- const result = blocks.reduce<{ block: Block; distance: number }>((nearest, block) => {
160
+ /**
161
+ * Filter out blocks whose holders are inside a table cell container.
162
+ * Cell blocks should not participate in nearest-block detection —
163
+ * the parent table block should be found instead.
164
+ * This matches the direct-hit path which also resolves cell blocks to their parent table block.
165
+ */
166
+ const topLevelBlocks = blocks.filter(block =>
167
+ block.holder.closest('[data-blok-table-cell-blocks]') === null
168
+ );
169
+
170
+ if (topLevelBlocks.length === 0) {
171
+ return null;
172
+ }
173
+
174
+ const result = topLevelBlocks.reduce<{ block: Block; distance: number }>((nearest, block) => {
161
175
  const rect = block.holder.getBoundingClientRect();
162
176
  const centerY = (rect.top + rect.bottom) / 2;
163
177
  const distance = Math.abs(clientY - centerY);
164
178
 
165
179
  return distance < nearest.distance ? { block, distance } : nearest;
166
- }, { block: blocks[0], distance: Infinity });
180
+ }, { block: topLevelBlocks[0], distance: Infinity });
167
181
 
168
182
  return result.block;
169
183
  }
@@ -35,15 +35,34 @@ export const createRedactorTouchHandler = (
35
35
  /**
36
36
  * Select clicked Block as Current
37
37
  */
38
- try {
39
- deps.Blok.BlockManager.setCurrentBlockByChildNode(clickedNode);
40
- } catch (_e) {
41
- /**
42
- * If clicked outside first-level Blocks and it is not RectSelection, set Caret to the last empty Block
43
- */
44
- if (!deps.Blok.RectangleSelection.isRectActivated()) {
45
- deps.Blok.Caret.setToTheLastBlock();
46
- }
38
+ const block = deps.Blok.BlockManager.setCurrentBlockByChildNode(clickedNode);
39
+
40
+ /**
41
+ * If clicked outside first-level Blocks and it is not RectSelection, set Caret to the last empty Block
42
+ */
43
+ if (!block && !deps.Blok.RectangleSelection.isRectActivated()) {
44
+ deps.Blok.Caret.setToTheLastBlock();
45
+ }
46
+
47
+ /**
48
+ * If the click landed below the last block's content area (in the holder padding zone),
49
+ * create/focus a new paragraph instead of keeping the block selected.
50
+ */
51
+ const isBelowLastBlock = block !== undefined
52
+ && block === deps.Blok.BlockManager.lastBlock
53
+ && isClickBelowLastBlockContent(block.holder, event);
54
+
55
+ if (isBelowLastBlock && !deps.Blok.ReadOnly.isEnabled) {
56
+ deps.Blok.Caret.setToTheLastBlock();
57
+ deps.Blok.Toolbar.moveAndOpen(deps.Blok.BlockManager.lastBlock);
58
+
59
+ return;
60
+ }
61
+
62
+ if (isBelowLastBlock) {
63
+ deps.Blok.Caret.setToTheLastBlock();
64
+
65
+ return;
47
66
  }
48
67
 
49
68
  /**
@@ -51,7 +70,19 @@ export const createRedactorTouchHandler = (
51
70
  * (used for showing Block Settings toggler after opening and closing Inline Toolbar)
52
71
  */
53
72
  if (!deps.Blok.ReadOnly.isEnabled && !deps.Blok.Toolbar.contains(initialTarget)) {
54
- deps.Blok.Toolbar.moveAndOpen(undefined, clickedNode);
73
+ /**
74
+ * When the clicked node is inside a table cell, resolve to the parent table block
75
+ * so moveAndOpen receives the table block (not undefined / the inner cell paragraph).
76
+ * Without this, moveAndOpen falls back to currentBlock (the cell paragraph), detects
77
+ * it's inside a table cell, and hides the plus button and settings toggler.
78
+ */
79
+ const tableCellContainer = clickedNode.closest?.('[data-blok-table-cell-blocks]');
80
+ const tableBlockWrapper = tableCellContainer?.closest('[data-blok-testid="block-wrapper"]');
81
+ const resolvedBlock = tableBlockWrapper
82
+ ? deps.Blok.BlockManager.getBlockByChildNode(tableBlockWrapper)
83
+ : undefined;
84
+
85
+ deps.Blok.Toolbar.moveAndOpen(resolvedBlock, clickedNode);
55
86
  }
56
87
  };
57
88
  }
@@ -93,3 +124,45 @@ export const getClickedNode = (
93
124
 
94
125
  return initialTarget;
95
126
  }
127
+
128
+ /**
129
+ * Extracts the clientY coordinate from a mouse or touch event
130
+ *
131
+ * @param event - The event to extract clientY from
132
+ * @returns The clientY value, or null if not available
133
+ */
134
+ const getClientY = (event: Event): number | null => {
135
+ if (event instanceof MouseEvent) {
136
+ return event.clientY;
137
+ }
138
+
139
+ if (event instanceof TouchEvent && event.touches.length > 0) {
140
+ return event.touches[0].clientY;
141
+ }
142
+
143
+ return null;
144
+ }
145
+
146
+ /**
147
+ * Checks whether a click event landed below a block's content area.
148
+ * Used to detect clicks in the holder padding zone below the last block.
149
+ *
150
+ * @param blockHolder - The block's holder element
151
+ * @param event - The mouse or touch event
152
+ * @returns True if the click was below the block content's bottom edge
153
+ */
154
+ const isClickBelowLastBlockContent = (
155
+ blockHolder: HTMLElement,
156
+ event: Event
157
+ ): boolean => {
158
+ const clientY = getClientY(event);
159
+
160
+ if (clientY === null) {
161
+ return false;
162
+ }
163
+
164
+ const contentEl = blockHolder.querySelector('[data-blok-element-content]');
165
+ const contentRect = contentEl?.getBoundingClientRect();
166
+
167
+ return contentRect !== undefined && clientY > contentRect.bottom;
168
+ };
@@ -169,9 +169,15 @@ export class BlockObserver {
169
169
  this.emitChange({ type: 'move', blockId, origin });
170
170
  }
171
171
 
172
- // Emit pure adds
173
- for (const blockId of pureAdds) {
174
- this.emitChange({ type: 'add', blockId, origin });
172
+ // Emit pure adds — batch when there are multiple so that parent and
173
+ // child blocks can be registered in BlockManager before any lifecycle
174
+ // hooks (like Table.rendered initializeCells) fire.
175
+ if (pureAdds.length === 1) {
176
+ this.emitChange({ type: 'add', blockId: pureAdds[0], origin });
177
+ }
178
+
179
+ if (pureAdds.length > 1) {
180
+ this.emitChange({ type: 'batch-add', blockIds: pureAdds, origin });
175
181
  }
176
182
 
177
183
  // Emit pure removes
@@ -2,6 +2,7 @@ import * as Y from 'yjs';
2
2
 
3
3
  import type { YBlockSerializer, YjsOutputBlockData } from './serializer';
4
4
  import type { TransactionOrigin } from './types';
5
+ import { equals } from '../../utils/object';
5
6
 
6
7
  // Re-export YjsOutputBlockData as DocumentStoreBlockData for consistency
7
8
  type DocumentStoreBlockData = YjsOutputBlockData;
@@ -162,8 +163,9 @@ export class DocumentStore {
162
163
 
163
164
  // Skip if value hasn't changed - this prevents creating unnecessary undo entries
164
165
  // when block data is synced after mutations that don't actually change data
165
- // (e.g., marker updates in list items during undo/redo)
166
- if (currentValue === value) {
166
+ // (e.g., marker updates in list items during undo/redo, or table content
167
+ // arrays that are reference-different but structurally identical)
168
+ if (equals(currentValue, value)) {
167
169
  return;
168
170
  }
169
171
 
@@ -1,11 +1,13 @@
1
1
  /**
2
- * Event emitted when blocks change
2
+ * Event emitted when blocks change.
3
+ *
4
+ * Most events carry a single `blockId`. The `batch-add` type carries
5
+ * multiple IDs so that parent and child blocks can be created together
6
+ * before any lifecycle hooks fire.
3
7
  */
4
- export interface BlockChangeEvent {
5
- type: 'add' | 'remove' | 'update' | 'move';
6
- blockId: string;
7
- origin: TransactionOrigin;
8
- }
8
+ export type BlockChangeEvent =
9
+ | { type: 'add' | 'remove' | 'update' | 'move'; blockId: string; origin: TransactionOrigin }
10
+ | { type: 'batch-add'; blockIds: string[]; origin: TransactionOrigin };
9
11
 
10
12
  /**
11
13
  * Transaction origin types.
@@ -257,7 +257,9 @@ export class PopoverItemDefault extends PopoverItem {
257
257
  if (title !== undefined) {
258
258
  const titleEl = document.createElement('div');
259
259
 
260
- titleEl.className = 'mr-auto truncate text-sm font-medium leading-5';
260
+ titleEl.className = params.secondaryLabel
261
+ ? 'flex-grow truncate text-sm font-medium leading-5'
262
+ : 'mr-auto truncate text-sm font-medium leading-5';
261
263
  titleEl.setAttribute(DATA_ATTR.popoverItemTitle, '');
262
264
  titleEl.setAttribute('data-blok-testid', 'popover-item-title');
263
265
  titleEl.textContent = title;
@@ -270,7 +272,7 @@ export class PopoverItemDefault extends PopoverItem {
270
272
  if (params.secondaryLabel) {
271
273
  const secondaryEl = document.createElement('div');
272
274
 
273
- secondaryEl.className = 'whitespace-nowrap pr-1.5 text-xs font-light tracking-[0.25px] text-text-secondary opacity-60';
275
+ secondaryEl.className = 'min-w-[3.5rem] text-right whitespace-nowrap pl-3 pr-1.5 text-xs font-light tracking-[0.25px] text-text-secondary opacity-60';
274
276
  secondaryEl.setAttribute(DATA_ATTR.popoverItemSecondaryTitle, '');
275
277
  secondaryEl.setAttribute('data-blok-testid', 'popover-item-secondary-title');
276
278
  secondaryEl.textContent = params.secondaryLabel;
@@ -324,8 +326,8 @@ export class PopoverItemDefault extends PopoverItem {
324
326
 
325
327
  return twMerge(
326
328
  css.item,
327
- // Asymmetric padding for vertical popovers (better visual balance)
328
- !isInline && !isNestedInline && 'pl-2 pr-8',
329
+ // Asymmetric padding: pr-8 for visual balance, pr-2 when secondary label occupies right edge
330
+ !isInline && !isNestedInline && (this.params.secondaryLabel ? 'pl-2 pr-2' : 'pl-2 pr-8'),
329
331
  isInline && cssInline.item,
330
332
  isNestedInline && cssNestedInline.item,
331
333
  this.params.isDisabled && css.itemDisabled
@@ -138,6 +138,18 @@ export class PopoverDesktop extends PopoverAbstract {
138
138
  return this.flipper.hasFocus();
139
139
  }
140
140
 
141
+ /**
142
+ * Toggles hidden state of all items matching the given name.
143
+ * Invalidates the cached size so the next access re-measures the popover.
144
+ * @param name - name of the items to toggle
145
+ * @param isHidden - true to hide, false to show
146
+ */
147
+ public override toggleItemHiddenByName(name: string, isHidden: boolean): void {
148
+ super.toggleItemHiddenByName(name, isHidden);
149
+
150
+ this._size = undefined;
151
+ }
152
+
141
153
  /**
142
154
  * Scroll position inside items container of the popover
143
155
  */
@@ -351,7 +351,6 @@ export const ConfirmationState: Story = {
351
351
  deleteButton.setAttribute('data-blok-popover-item-confirmation', 'true');
352
352
  deleteButton.setAttribute('data-blok-popover-item-no-hover', 'true');
353
353
  deleteButton.setAttribute('data-blok-popover-item-no-focus', 'true');
354
- // eslint-disable-next-line internal-storybook/no-class-selectors
355
354
  deleteButton.classList.add('!bg-item-confirm-bg', '!text-white');
356
355
  }
357
356
 
@@ -516,7 +515,6 @@ export const DisabledItem: Story = {
516
515
  // Add the proper disabled classes and attribute that match the real implementation
517
516
  // The itemDisabled class from popover-item-default.const.ts is:
518
517
  // 'cursor-default pointer-events-none text-text-secondary'
519
- // eslint-disable-next-line internal-storybook/no-class-selectors
520
518
  popoverItem.classList.add('cursor-default', 'pointer-events-none', 'text-text-secondary');
521
519
  popoverItem.setAttribute('data-blok-disabled', 'true');
522
520
  }
@@ -135,7 +135,7 @@
135
135
  }
136
136
 
137
137
  [data-blok-table-cell-blocks] .blok-block {
138
- @apply p-0 m-0;
138
+ @apply p-0 m-0 min-h-[1.6em];
139
139
  }
140
140
 
141
141
  /**
@@ -146,3 +146,11 @@
146
146
  [data-blok-table-heading-col] {
147
147
  @apply font-semibold bg-gray-50;
148
148
  }
149
+
150
+ /**
151
+ * Table scroll haze overlays
152
+ * Gradient indicators that show horizontal scroll availability
153
+ */
154
+ [data-blok-table-haze][data-blok-table-haze-visible] {
155
+ @apply opacity-100;
156
+ }
@@ -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
  }