@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
@@ -1,5 +1,6 @@
1
1
  import type { I18n } from '../../../types/api';
2
- import { IconCross } from '../../components/icons';
2
+ import { IconCopy, IconCross } from '../../components/icons';
3
+ import { MODIFIER_KEY } from '../../components/constants';
3
4
  import { PopoverDesktop } from '../../components/utils/popover';
4
5
  import { twMerge } from '../../components/utils/tw';
5
6
 
@@ -59,6 +60,8 @@ interface CellSelectionOptions {
59
60
  onClearContent?: (cells: HTMLElement[]) => void;
60
61
  onCopy?: (cells: HTMLElement[], clipboardData: DataTransfer) => void;
61
62
  onCut?: (cells: HTMLElement[], clipboardData: DataTransfer) => void;
63
+ onCopyViaButton?: (cells: HTMLElement[]) => void;
64
+ isPopoverOpen?: () => boolean;
62
65
  i18n: I18n;
63
66
  }
64
67
 
@@ -79,6 +82,8 @@ export class TableCellSelection {
79
82
 
80
83
  private onCopy: ((cells: HTMLElement[], clipboardData: DataTransfer) => void) | undefined;
81
84
  private onCut: ((cells: HTMLElement[], clipboardData: DataTransfer) => void) | undefined;
85
+ private onCopyViaButton: ((cells: HTMLElement[]) => void) | undefined;
86
+ private isPopoverOpen: (() => boolean) | undefined;
82
87
 
83
88
  private boundPointerDown: (e: PointerEvent) => void;
84
89
  private boundPointerMove: (e: PointerEvent) => void;
@@ -96,6 +101,8 @@ export class TableCellSelection {
96
101
  this.onClearContent = options.onClearContent;
97
102
  this.onCopy = options.onCopy;
98
103
  this.onCut = options.onCut;
104
+ this.onCopyViaButton = options.onCopyViaButton;
105
+ this.isPopoverOpen = options.isPopoverOpen;
99
106
  this.i18n = options.i18n;
100
107
  this.grid.style.position = 'relative';
101
108
 
@@ -296,6 +303,13 @@ export class TableCellSelection {
296
303
  return;
297
304
  }
298
305
 
306
+ // Don't clear while a grip popover is open — clicking a popover
307
+ // action fires pointerdown before the click handler that performs
308
+ // the action and re-establishes the selection.
309
+ if (this.isPopoverOpen?.()) {
310
+ return;
311
+ }
312
+
299
313
  document.removeEventListener('pointerdown', this.boundClearSelection);
300
314
  this.clearSelection();
301
315
  }
@@ -518,10 +532,22 @@ export class TableCellSelection {
518
532
 
519
533
  this.expandPill();
520
534
 
535
+ const copyShortcut = MODIFIER_KEY === 'Meta' ? '⌘C' : 'Ctrl+C';
536
+
521
537
  const items: PopoverItemParams[] = [
538
+ {
539
+ icon: IconCopy,
540
+ title: this.i18n.t('tools.table.copySelection'),
541
+ secondaryLabel: copyShortcut,
542
+ closeOnActivate: true,
543
+ onActivate: (): void => {
544
+ this.onCopyViaButton?.([...this.selectedCells]);
545
+ },
546
+ },
522
547
  {
523
548
  icon: IconCross,
524
549
  title: this.i18n.t('tools.table.clearSelection'),
550
+ secondaryLabel: 'Del',
525
551
  closeOnActivate: true,
526
552
  onActivate: (): void => {
527
553
  this.onClearContent?.([...this.selectedCells]);
@@ -310,6 +310,15 @@ export const mountCellBlocksReadOnly = (
310
310
 
311
311
  container.appendChild(block.holder);
312
312
  }
313
+
314
+ // Strip placeholder attributes so paragraphs inside table cells
315
+ // don't show standalone-paragraph placeholders in readonly mode.
316
+ container.querySelectorAll<HTMLElement>('[data-blok-placeholder-active]').forEach(el => {
317
+ el.removeAttribute('data-blok-placeholder-active');
318
+ });
319
+ container.querySelectorAll<HTMLElement>('[data-placeholder]').forEach(el => {
320
+ el.removeAttribute('data-placeholder');
321
+ });
313
322
  });
314
323
  });
315
324
  };
@@ -368,7 +377,7 @@ export const setupKeyboardNavigation = (
368
377
  });
369
378
  };
370
379
 
371
- export const SCROLL_OVERFLOW_CLASSES = ['overflow-x-auto', 'pt-[9px]', 'pl-[9px]'];
380
+ export const SCROLL_OVERFLOW_CLASSES = ['overflow-x-auto', 'overflow-y-hidden'];
372
381
 
373
382
  export const enableScrollOverflow = (element: HTMLDivElement | null): void => {
374
383
  element?.classList.add(...SCROLL_OVERFLOW_CLASSES);
@@ -376,13 +385,7 @@ export const enableScrollOverflow = (element: HTMLDivElement | null): void => {
376
385
 
377
386
  // ─── Heading styles ─────────────────────────────────────────────────
378
387
 
379
- export const updateHeadingStyles = (element: HTMLDivElement | null, withHeadings: boolean): void => {
380
- if (!element) {
381
- return;
382
- }
383
-
384
- const gridEl = element.firstElementChild as HTMLElement;
385
-
388
+ export const updateHeadingStyles = (gridEl: HTMLElement | null, withHeadings: boolean): void => {
386
389
  if (!gridEl) {
387
390
  return;
388
391
  }
@@ -398,13 +401,7 @@ export const updateHeadingStyles = (element: HTMLDivElement | null, withHeadings
398
401
  }
399
402
  };
400
403
 
401
- export const updateHeadingColumnStyles = (element: HTMLDivElement | null, withHeadingColumn: boolean): void => {
402
- if (!element) {
403
- return;
404
- }
405
-
406
- const gridEl = element.firstElementChild as HTMLElement;
407
-
404
+ export const updateHeadingColumnStyles = (gridEl: HTMLElement | null, withHeadingColumn: boolean): void => {
408
405
  if (!gridEl) {
409
406
  return;
410
407
  }
@@ -33,6 +33,8 @@ export type RowColAction =
33
33
 
34
34
  export interface TableRowColControlsOptions {
35
35
  grid: HTMLElement;
36
+ overlay?: HTMLElement;
37
+ scrollContainer?: HTMLElement;
36
38
  getColumnCount: () => number;
37
39
  getRowCount: () => number;
38
40
  isHeadingRow: () => boolean;
@@ -83,6 +85,8 @@ const GRIP_ACTIVE_CLASSES = [
83
85
  */
84
86
  export class TableRowColControls {
85
87
  private grid: HTMLElement;
88
+ private overlay: HTMLElement | undefined;
89
+ private scrollContainer: HTMLElement | undefined;
86
90
  private getColumnCount: () => number;
87
91
  private getRowCount: () => number;
88
92
  private isHeadingRow: () => boolean;
@@ -108,9 +112,12 @@ export class TableRowColControls {
108
112
  private boundMouseOver: (e: MouseEvent) => void;
109
113
  private boundMouseLeave: (e: MouseEvent) => void;
110
114
  private boundPointerDown: (e: PointerEvent) => void;
115
+ private boundScrollHandler: (() => void) | null = null;
111
116
 
112
117
  constructor(options: TableRowColControlsOptions) {
113
118
  this.grid = options.grid;
119
+ this.overlay = options.overlay;
120
+ this.scrollContainer = options.scrollContainer;
114
121
  this.getColumnCount = options.getColumnCount;
115
122
  this.getRowCount = options.getRowCount;
116
123
  this.isHeadingRow = options.isHeadingRow;
@@ -177,13 +184,29 @@ export class TableRowColControls {
177
184
  document.addEventListener('pointerdown', this.boundUnlockGrip);
178
185
  }
179
186
 
180
- private handleUnlockGrip(): void {
187
+ private handleUnlockGrip(e: PointerEvent): void {
181
188
  document.removeEventListener('pointerdown', this.boundUnlockGrip);
182
189
 
183
190
  if (this.lockedGrip) {
184
191
  this.applyIdleClasses(this.lockedGrip);
185
192
  this.lockedGrip = null;
186
193
  }
194
+
195
+ // Re-evaluate grip visibility: the preceding mouseover was blocked
196
+ // by isGripInteractionLocked(). Check if pointer is over a table cell.
197
+ const target = e.target instanceof HTMLElement ? e.target : null;
198
+ const cell = target?.closest<HTMLElement>(`[${CELL_ATTR}]`);
199
+
200
+ if (cell) {
201
+ const position = this.getCellPosition(cell);
202
+
203
+ if (position) {
204
+ this.clearHideTimeout();
205
+ this.showColGrip(position.col);
206
+ this.showRowGrip(position.row);
207
+ this.isInsideTable = true;
208
+ }
209
+ }
187
210
  }
188
211
 
189
212
  private unlockGrip(): void {
@@ -191,6 +214,10 @@ export class TableRowColControls {
191
214
  this.lockedGrip = null;
192
215
  }
193
216
 
217
+ public get isPopoverOpen(): boolean {
218
+ return this.popoverState.popover !== null;
219
+ }
220
+
194
221
  public destroy(): void {
195
222
  this.destroyPopover();
196
223
  this.unlockGrip();
@@ -204,28 +231,45 @@ export class TableRowColControls {
204
231
  private createGrips(): void {
205
232
  const colCount = this.getColumnCount();
206
233
  const rowCount = this.getRowCount();
234
+ const gripContainer = this.overlay ?? this.grid;
207
235
 
208
236
  Array.from({ length: colCount }).forEach((_, i) => {
209
237
  const grip = this.createGripElement('col', i);
210
238
 
211
239
  this.colGrips.push(grip);
212
- this.grid.appendChild(grip);
240
+ gripContainer.appendChild(grip);
213
241
  });
214
242
 
215
243
  Array.from({ length: rowCount }).forEach((_, i) => {
216
244
  const grip = this.createGripElement('row', i);
217
245
 
218
246
  this.rowGrips.push(grip);
219
- this.grid.appendChild(grip);
247
+ gripContainer.appendChild(grip);
220
248
  });
221
249
 
222
250
  this.positionGrips();
223
251
  this.observeRowHeights();
252
+ this.attachScrollListener();
253
+ }
254
+
255
+ private attachScrollListener(): void {
256
+ if (this.overlay && this.scrollContainer) {
257
+ this.boundScrollHandler = () => this.positionGrips();
258
+ this.scrollContainer.addEventListener('scroll', this.boundScrollHandler);
259
+ }
260
+ }
261
+
262
+ private detachScrollListener(): void {
263
+ if (this.boundScrollHandler && this.scrollContainer) {
264
+ this.scrollContainer.removeEventListener('scroll', this.boundScrollHandler);
265
+ this.boundScrollHandler = null;
266
+ }
224
267
  }
225
268
 
226
269
  private destroyGrips(): void {
227
270
  this.rowResizeObserver?.disconnect();
228
271
  this.rowResizeObserver = null;
272
+ this.detachScrollListener();
229
273
  this.colGrips.forEach(g => g.remove());
230
274
  this.rowGrips.forEach(g => g.remove());
231
275
  this.colGrips = [];
@@ -256,13 +300,20 @@ export class TableRowColControls {
256
300
 
257
301
  grip.addEventListener('pointerdown', this.boundPointerDown);
258
302
  grip.addEventListener('mouseenter', () => {
303
+ if (this.overlay) {
304
+ this.clearHideTimeout();
305
+ }
259
306
  if (!this.isGripInteractionLocked()) {
260
307
  expandGrip(grip, type);
261
308
  }
262
309
  });
263
310
  grip.addEventListener('mouseleave', () => {
264
- if (!this.isGripInteractionLocked()) {
265
- collapseGrip(grip, type, pillSize);
311
+ if (this.isGripInteractionLocked()) {
312
+ return;
313
+ }
314
+ collapseGrip(grip, type, pillSize);
315
+ if (this.overlay) {
316
+ this.scheduleHideAll();
266
317
  }
267
318
  });
268
319
 
@@ -282,6 +333,12 @@ export class TableRowColControls {
282
333
  }
283
334
 
284
335
  const edges = getCumulativeColEdges(this.grid);
336
+ const scrollLeft = this.overlay && this.scrollContainer
337
+ ? this.scrollContainer.scrollLeft
338
+ : 0;
339
+ const containerWidth = this.overlay && this.scrollContainer
340
+ ? this.scrollContainer.clientWidth
341
+ : Infinity;
285
342
 
286
343
  this.colGrips.forEach((grip, i) => {
287
344
  if (i + 1 >= edges.length) {
@@ -289,10 +346,16 @@ export class TableRowColControls {
289
346
  }
290
347
 
291
348
  const centerX = (edges[i] + edges[i + 1]) / 2;
349
+ const adjustedX = centerX - scrollLeft;
292
350
  const style = grip.style;
293
351
 
294
352
  style.top = `${-BORDER_WIDTH / 2}px`;
295
- style.left = `${centerX}px`;
353
+ style.left = `${adjustedX}px`;
354
+
355
+ // Hide grips scrolled out of the visible area
356
+ if (this.overlay) {
357
+ style.visibility = (adjustedX < 0 || adjustedX > containerWidth) ? 'hidden' : '';
358
+ }
296
359
  });
297
360
 
298
361
  this.rowGrips.forEach((grip, i) => {
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Scroll haze overlays for the Table tool.
3
+ *
4
+ * Adds gradient overlays on the left/right edges of the table wrapper
5
+ * to indicate that the table content is horizontally scrollable.
6
+ * Uses a passive scroll event listener with rAF throttling.
7
+ */
8
+
9
+ const HAZE_ATTR = 'data-blok-table-haze';
10
+ const HAZE_VISIBLE_ATTR = 'data-blok-table-haze-visible';
11
+
12
+ /** Minimum scrollLeft delta to consider "scrolled" (avoids sub-pixel flicker). */
13
+ const SCROLL_THRESHOLD = 1;
14
+
15
+ const HAZE_CLASSES = [
16
+ 'absolute',
17
+ 'top-0',
18
+ 'bottom-0',
19
+ 'w-12',
20
+ 'pointer-events-none',
21
+ 'opacity-0',
22
+ 'transition-opacity',
23
+ 'duration-150',
24
+ 'z-[1]',
25
+ ];
26
+
27
+ const LEFT_HAZE_CLASSES = [
28
+ 'left-0',
29
+ 'bg-gradient-to-r',
30
+ 'from-white/80',
31
+ 'to-transparent',
32
+ ];
33
+
34
+ const RIGHT_HAZE_CLASSES = [
35
+ 'right-5',
36
+ 'bg-gradient-to-l',
37
+ 'from-white/80',
38
+ 'to-transparent',
39
+ ];
40
+
41
+ /**
42
+ * Manages left/right gradient haze overlays that indicate
43
+ * the table can be scrolled horizontally.
44
+ */
45
+ export class TableScrollHaze {
46
+ private leftHaze: HTMLDivElement | null = null;
47
+ private rightHaze: HTMLDivElement | null = null;
48
+ private scrollContainer: HTMLElement | null = null;
49
+ private boundOnScroll: (() => void) | null = null;
50
+ private ticking = false;
51
+
52
+ /**
53
+ * Create haze overlay elements and attach the scroll listener.
54
+ *
55
+ * @param wrapper - The table wrapper element (position: relative)
56
+ * @param scrollContainer - The scroll container with overflow-x: auto
57
+ */
58
+ public init(wrapper: HTMLElement, scrollContainer: HTMLElement): void {
59
+ this.scrollContainer = scrollContainer;
60
+
61
+ this.leftHaze = this.createHazeElement('left');
62
+ this.rightHaze = this.createHazeElement('right');
63
+
64
+ wrapper.appendChild(this.leftHaze);
65
+ wrapper.appendChild(this.rightHaze);
66
+
67
+ this.boundOnScroll = (): void => {
68
+ if (!this.ticking) {
69
+ requestAnimationFrame(() => {
70
+ this.syncVisibility();
71
+ this.ticking = false;
72
+ });
73
+ this.ticking = true;
74
+ }
75
+ };
76
+
77
+ scrollContainer.addEventListener('scroll', this.boundOnScroll, { passive: true });
78
+
79
+ this.syncVisibility();
80
+ }
81
+
82
+ /**
83
+ * Recalculate haze visibility (e.g. after column resize or add/delete).
84
+ */
85
+ public update(): void {
86
+ this.syncVisibility();
87
+ }
88
+
89
+ /**
90
+ * Remove overlay elements and detach the scroll listener.
91
+ */
92
+ public destroy(): void {
93
+ if (this.boundOnScroll && this.scrollContainer) {
94
+ this.scrollContainer.removeEventListener('scroll', this.boundOnScroll);
95
+ }
96
+
97
+ this.leftHaze?.remove();
98
+ this.rightHaze?.remove();
99
+
100
+ this.leftHaze = null;
101
+ this.rightHaze = null;
102
+ this.scrollContainer = null;
103
+ this.boundOnScroll = null;
104
+ this.ticking = false;
105
+ }
106
+
107
+ private createHazeElement(side: 'left' | 'right'): HTMLDivElement {
108
+ const el = document.createElement('div');
109
+
110
+ el.setAttribute(HAZE_ATTR, side);
111
+ el.setAttribute('aria-hidden', 'true');
112
+ el.classList.add(...HAZE_CLASSES, ...(side === 'left' ? LEFT_HAZE_CLASSES : RIGHT_HAZE_CLASSES));
113
+
114
+ return el;
115
+ }
116
+
117
+ private syncVisibility(): void {
118
+ const sc = this.scrollContainer;
119
+
120
+ if (!sc) {
121
+ return;
122
+ }
123
+
124
+ const { overflowX } = getComputedStyle(sc);
125
+ const canScroll = overflowX === 'auto' || overflowX === 'scroll';
126
+
127
+ if (!canScroll) {
128
+ this.setVisible(this.leftHaze, false);
129
+ this.setVisible(this.rightHaze, false);
130
+
131
+ return;
132
+ }
133
+
134
+ const { scrollLeft, scrollWidth, clientWidth } = sc;
135
+ const maxScroll = scrollWidth - clientWidth;
136
+
137
+ this.setVisible(this.leftHaze, scrollLeft > SCROLL_THRESHOLD);
138
+ this.setVisible(this.rightHaze, maxScroll > SCROLL_THRESHOLD && scrollLeft < maxScroll - SCROLL_THRESHOLD);
139
+ }
140
+
141
+ private setVisible(el: HTMLElement | null, visible: boolean): void {
142
+ if (!el) {
143
+ return;
144
+ }
145
+
146
+ if (visible) {
147
+ el.setAttribute(HAZE_VISIBLE_ATTR, '');
148
+ } else {
149
+ el.removeAttribute(HAZE_VISIBLE_ATTR);
150
+ }
151
+ }
152
+ }