@jackuait/blok 0.6.0-beta.4 → 0.6.0-beta.5

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 (233) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-DK-97ZTf.mjs → blok-XA2L0_-K.mjs} +1216 -1178
  3. package/dist/chunks/{i18next-loader-CRollibS.mjs → i18next-loader-Ci2zhA-n.mjs} +1 -1
  4. package/dist/chunks/{index-jgHmMDND.mjs → index-R38OiQ_d.mjs} +1 -1
  5. package/dist/chunks/{inline-tool-convert-BIwvipPw.mjs → inline-tool-convert-e3PyuxB6.mjs} +88 -73
  6. package/dist/chunks/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
  7. package/dist/{messages-BPqWKx5Z.mjs → chunks/messages-49thXXGz.mjs} +16 -2
  8. package/dist/{messages-LvFKBBPa.mjs → chunks/messages-7W4d0DwD.mjs} +15 -1
  9. package/dist/{messages-Bn253WWC.mjs → chunks/messages-9SihnaXQ.mjs} +14 -0
  10. package/dist/{messages-Bf6Y3_GI.mjs → chunks/messages-B1Aww8q7.mjs} +16 -2
  11. package/dist/{messages-D00OjS2n.mjs → chunks/messages-B9fe4dQJ.mjs} +15 -1
  12. package/dist/{messages-pA5TvcAj.mjs → chunks/messages-BB5z9Uba.mjs} +14 -0
  13. package/dist/chunks/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
  14. package/dist/chunks/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
  15. package/dist/chunks/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
  16. package/dist/chunks/{messages-CQj2JU2j.mjs → messages-BGxiFoZf.mjs} +15 -1
  17. package/dist/{messages-B5puUm7R.mjs → chunks/messages-BL0tXcDf.mjs} +15 -1
  18. package/dist/{messages-CyDU5lz9.mjs → chunks/messages-BMv4xwIr.mjs} +16 -2
  19. package/dist/chunks/{messages-CkFT2gle.mjs → messages-BNe6LuHW.mjs} +14 -0
  20. package/dist/chunks/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
  21. package/dist/chunks/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
  22. package/dist/{messages-CXHd9SUK.mjs → chunks/messages-BYyy6Wqf.mjs} +14 -0
  23. package/dist/{messages-Cyi2AMmz.mjs → chunks/messages-Bfiw5w_W.mjs} +16 -2
  24. package/dist/chunks/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
  25. package/dist/chunks/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
  26. package/dist/chunks/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
  27. package/dist/chunks/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
  28. package/dist/chunks/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
  29. package/dist/chunks/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
  30. package/dist/{messages-CrsJ1TEJ.mjs → chunks/messages-CLhcMlTc.mjs} +15 -1
  31. package/dist/{messages-CnvW8Slp.mjs → chunks/messages-CMkNSDTo.mjs} +17 -3
  32. package/dist/chunks/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
  33. package/dist/chunks/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
  34. package/dist/chunks/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
  35. package/dist/chunks/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
  36. package/dist/{messages-Dg92dXZ5.mjs → chunks/messages-CvGLfqmV.mjs} +14 -0
  37. package/dist/{messages-AHESHJm_.mjs → chunks/messages-CzTufCHu.mjs} +14 -0
  38. package/dist/chunks/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
  39. package/dist/chunks/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
  40. package/dist/chunks/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
  41. package/dist/chunks/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
  42. package/dist/chunks/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
  43. package/dist/{messages-zSzDzXej.mjs → chunks/messages-DBRw-7Zc.mjs} +16 -2
  44. package/dist/chunks/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
  45. package/dist/{messages-DOlC_Tty.mjs → chunks/messages-DChXyvh2.mjs} +15 -1
  46. package/dist/chunks/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
  47. package/dist/{messages-DDLgIPDF.mjs → chunks/messages-DLfR5bMd.mjs} +16 -2
  48. package/dist/{messages-CbhuIWRJ.mjs → chunks/messages-DT4dP5uK.mjs} +15 -1
  49. package/dist/chunks/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
  50. package/dist/{messages-BlpqL8vG.mjs → chunks/messages-DjvaFRqx.mjs} +16 -2
  51. package/dist/{messages-BA0rcTCY.mjs → chunks/messages-DnIhyAJk.mjs} +18 -4
  52. package/dist/chunks/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
  53. package/dist/chunks/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
  54. package/dist/{messages-CJoBtXU6.mjs → chunks/messages-DqM1LFg5.mjs} +14 -0
  55. package/dist/chunks/{messages-CySyfkMU.mjs → messages-DsVNtdgM.mjs} +15 -1
  56. package/dist/chunks/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
  57. package/dist/chunks/{messages-Cu08aLS3.mjs → messages-EL5ARzmK.mjs} +16 -2
  58. package/dist/chunks/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
  59. package/dist/{messages-DY94ykcE.mjs → chunks/messages-LPVfA-8K.mjs} +14 -0
  60. package/dist/{messages-Cr-RJ7YB.mjs → chunks/messages-O5tQus_0.mjs} +14 -0
  61. package/dist/chunks/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
  62. package/dist/chunks/{messages-GC2PhgV3.mjs → messages-QtoE8uEv.mjs} +15 -1
  63. package/dist/chunks/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
  64. package/dist/chunks/{messages-zS1AXZ0y.mjs → messages-UX4gkere.mjs} +15 -1
  65. package/dist/{messages-CUy1vn-b.mjs → chunks/messages-Xq8UmkVs.mjs} +14 -0
  66. package/dist/chunks/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
  67. package/dist/chunks/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
  68. package/dist/chunks/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
  69. package/dist/chunks/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
  70. package/dist/chunks/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
  71. package/dist/chunks/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
  72. package/dist/{messages-BeUhMpsr.mjs → chunks/messages-wp_1b1hD.mjs} +15 -1
  73. package/dist/full.mjs +2 -2
  74. package/dist/locales.mjs +102 -88
  75. package/dist/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
  76. package/dist/{chunks/messages-BPqWKx5Z.mjs → messages-49thXXGz.mjs} +16 -2
  77. package/dist/{chunks/messages-LvFKBBPa.mjs → messages-7W4d0DwD.mjs} +15 -1
  78. package/dist/{chunks/messages-Bn253WWC.mjs → messages-9SihnaXQ.mjs} +14 -0
  79. package/dist/{chunks/messages-Bf6Y3_GI.mjs → messages-B1Aww8q7.mjs} +16 -2
  80. package/dist/{chunks/messages-D00OjS2n.mjs → messages-B9fe4dQJ.mjs} +15 -1
  81. package/dist/{chunks/messages-pA5TvcAj.mjs → messages-BB5z9Uba.mjs} +14 -0
  82. package/dist/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
  83. package/dist/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
  84. package/dist/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
  85. package/dist/{messages-CQj2JU2j.mjs → messages-BGxiFoZf.mjs} +15 -1
  86. package/dist/{chunks/messages-B5puUm7R.mjs → messages-BL0tXcDf.mjs} +15 -1
  87. package/dist/{chunks/messages-CyDU5lz9.mjs → messages-BMv4xwIr.mjs} +16 -2
  88. package/dist/{messages-CkFT2gle.mjs → messages-BNe6LuHW.mjs} +14 -0
  89. package/dist/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
  90. package/dist/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
  91. package/dist/{chunks/messages-CXHd9SUK.mjs → messages-BYyy6Wqf.mjs} +14 -0
  92. package/dist/{chunks/messages-Cyi2AMmz.mjs → messages-Bfiw5w_W.mjs} +16 -2
  93. package/dist/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
  94. package/dist/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
  95. package/dist/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
  96. package/dist/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
  97. package/dist/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
  98. package/dist/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
  99. package/dist/{chunks/messages-CrsJ1TEJ.mjs → messages-CLhcMlTc.mjs} +15 -1
  100. package/dist/{chunks/messages-CnvW8Slp.mjs → messages-CMkNSDTo.mjs} +17 -3
  101. package/dist/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
  102. package/dist/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
  103. package/dist/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
  104. package/dist/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
  105. package/dist/{chunks/messages-Dg92dXZ5.mjs → messages-CvGLfqmV.mjs} +14 -0
  106. package/dist/{chunks/messages-AHESHJm_.mjs → messages-CzTufCHu.mjs} +14 -0
  107. package/dist/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
  108. package/dist/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
  109. package/dist/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
  110. package/dist/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
  111. package/dist/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
  112. package/dist/{chunks/messages-zSzDzXej.mjs → messages-DBRw-7Zc.mjs} +16 -2
  113. package/dist/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
  114. package/dist/{chunks/messages-DOlC_Tty.mjs → messages-DChXyvh2.mjs} +15 -1
  115. package/dist/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
  116. package/dist/{chunks/messages-DDLgIPDF.mjs → messages-DLfR5bMd.mjs} +16 -2
  117. package/dist/{chunks/messages-CbhuIWRJ.mjs → messages-DT4dP5uK.mjs} +15 -1
  118. package/dist/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
  119. package/dist/{chunks/messages-BlpqL8vG.mjs → messages-DjvaFRqx.mjs} +16 -2
  120. package/dist/{chunks/messages-BA0rcTCY.mjs → messages-DnIhyAJk.mjs} +18 -4
  121. package/dist/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
  122. package/dist/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
  123. package/dist/{chunks/messages-CJoBtXU6.mjs → messages-DqM1LFg5.mjs} +14 -0
  124. package/dist/{messages-CySyfkMU.mjs → messages-DsVNtdgM.mjs} +15 -1
  125. package/dist/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
  126. package/dist/{messages-Cu08aLS3.mjs → messages-EL5ARzmK.mjs} +16 -2
  127. package/dist/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
  128. package/dist/{chunks/messages-DY94ykcE.mjs → messages-LPVfA-8K.mjs} +14 -0
  129. package/dist/{chunks/messages-Cr-RJ7YB.mjs → messages-O5tQus_0.mjs} +14 -0
  130. package/dist/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
  131. package/dist/{messages-GC2PhgV3.mjs → messages-QtoE8uEv.mjs} +15 -1
  132. package/dist/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
  133. package/dist/{messages-zS1AXZ0y.mjs → messages-UX4gkere.mjs} +15 -1
  134. package/dist/{chunks/messages-CUy1vn-b.mjs → messages-Xq8UmkVs.mjs} +14 -0
  135. package/dist/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
  136. package/dist/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
  137. package/dist/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
  138. package/dist/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
  139. package/dist/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
  140. package/dist/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
  141. package/dist/{chunks/messages-BeUhMpsr.mjs → messages-wp_1b1hD.mjs} +15 -1
  142. package/dist/tools.mjs +854 -719
  143. package/package.json +5 -9
  144. package/src/components/i18n/locales/am/messages.json +15 -1
  145. package/src/components/i18n/locales/ar/messages.json +14 -0
  146. package/src/components/i18n/locales/az/messages.json +14 -0
  147. package/src/components/i18n/locales/bg/messages.json +14 -0
  148. package/src/components/i18n/locales/bn/messages.json +15 -1
  149. package/src/components/i18n/locales/bs/messages.json +15 -1
  150. package/src/components/i18n/locales/cs/messages.json +14 -0
  151. package/src/components/i18n/locales/da/messages.json +14 -0
  152. package/src/components/i18n/locales/de/messages.json +14 -0
  153. package/src/components/i18n/locales/dv/messages.json +15 -1
  154. package/src/components/i18n/locales/el/messages.json +15 -1
  155. package/src/components/i18n/locales/en/messages.json +14 -0
  156. package/src/components/i18n/locales/es/messages.json +14 -0
  157. package/src/components/i18n/locales/et/messages.json +14 -0
  158. package/src/components/i18n/locales/fa/messages.json +15 -1
  159. package/src/components/i18n/locales/fi/messages.json +15 -1
  160. package/src/components/i18n/locales/fil/messages.json +14 -0
  161. package/src/components/i18n/locales/fr/messages.json +15 -1
  162. package/src/components/i18n/locales/gu/messages.json +15 -1
  163. package/src/components/i18n/locales/he/messages.json +14 -0
  164. package/src/components/i18n/locales/hi/messages.json +15 -1
  165. package/src/components/i18n/locales/hr/messages.json +14 -0
  166. package/src/components/i18n/locales/hu/messages.json +14 -0
  167. package/src/components/i18n/locales/hy/messages.json +16 -2
  168. package/src/components/i18n/locales/id/messages.json +16 -2
  169. package/src/components/i18n/locales/it/messages.json +14 -0
  170. package/src/components/i18n/locales/ja/messages.json +14 -0
  171. package/src/components/i18n/locales/ka/messages.json +15 -1
  172. package/src/components/i18n/locales/km/messages.json +16 -2
  173. package/src/components/i18n/locales/kn/messages.json +16 -2
  174. package/src/components/i18n/locales/ko/messages.json +14 -0
  175. package/src/components/i18n/locales/ku/messages.json +16 -2
  176. package/src/components/i18n/locales/lo/messages.json +15 -1
  177. package/src/components/i18n/locales/lt/messages.json +15 -1
  178. package/src/components/i18n/locales/lv/messages.json +15 -1
  179. package/src/components/i18n/locales/mk/messages.json +16 -2
  180. package/src/components/i18n/locales/ml/messages.json +16 -2
  181. package/src/components/i18n/locales/mn/messages.json +16 -2
  182. package/src/components/i18n/locales/mr/messages.json +15 -1
  183. package/src/components/i18n/locales/ms/messages.json +16 -2
  184. package/src/components/i18n/locales/my/messages.json +16 -2
  185. package/src/components/i18n/locales/ne/messages.json +15 -1
  186. package/src/components/i18n/locales/nl/messages.json +15 -1
  187. package/src/components/i18n/locales/no/messages.json +16 -2
  188. package/src/components/i18n/locales/pa/messages.json +15 -1
  189. package/src/components/i18n/locales/pl/messages.json +14 -0
  190. package/src/components/i18n/locales/ps/messages.json +17 -3
  191. package/src/components/i18n/locales/pt/messages.json +14 -0
  192. package/src/components/i18n/locales/ro/messages.json +15 -1
  193. package/src/components/i18n/locales/ru/messages.json +14 -0
  194. package/src/components/i18n/locales/sd/messages.json +16 -2
  195. package/src/components/i18n/locales/si/messages.json +15 -1
  196. package/src/components/i18n/locales/sk/messages.json +15 -1
  197. package/src/components/i18n/locales/sl/messages.json +16 -2
  198. package/src/components/i18n/locales/sq/messages.json +16 -2
  199. package/src/components/i18n/locales/sr/messages.json +16 -2
  200. package/src/components/i18n/locales/sv/messages.json +16 -2
  201. package/src/components/i18n/locales/sw/messages.json +16 -2
  202. package/src/components/i18n/locales/ta/messages.json +16 -2
  203. package/src/components/i18n/locales/te/messages.json +15 -1
  204. package/src/components/i18n/locales/th/messages.json +15 -1
  205. package/src/components/i18n/locales/tr/messages.json +15 -1
  206. package/src/components/i18n/locales/ug/messages.json +16 -2
  207. package/src/components/i18n/locales/uk/messages.json +15 -1
  208. package/src/components/i18n/locales/ur/messages.json +15 -1
  209. package/src/components/i18n/locales/vi/messages.json +16 -2
  210. package/src/components/i18n/locales/yi/messages.json +16 -2
  211. package/src/components/i18n/locales/zh/messages.json +15 -1
  212. package/src/components/modules/api/blocks.ts +17 -2
  213. package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +12 -1
  214. package/src/components/modules/toolbar/index.ts +29 -7
  215. package/src/components/modules/ui.ts +46 -68
  216. package/src/components/modules/uiControllers/controllers/blockHover.ts +40 -61
  217. package/src/components/ui/toolbox.ts +41 -6
  218. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +3 -1
  219. package/src/components/utils/popover/popover-desktop.ts +27 -8
  220. package/src/tools/table/index.ts +67 -70
  221. package/src/tools/table/table-add-controls.ts +25 -7
  222. package/src/tools/table/table-cell-blocks.ts +62 -0
  223. package/src/tools/table/table-cell-selection.ts +70 -46
  224. package/src/tools/table/table-core.ts +20 -15
  225. package/src/tools/table/table-grip-visuals.ts +4 -4
  226. package/src/tools/table/table-operations.ts +22 -12
  227. package/src/tools/table/table-restrictions.ts +64 -0
  228. package/src/tools/table/table-row-col-action-handler.ts +190 -0
  229. package/src/tools/table/table-row-col-controls.ts +91 -182
  230. package/src/tools/table/table-row-col-drag.ts +4 -4
  231. package/src/tools/table/table-row-col-popover.ts +225 -0
  232. package/src/tools/table/types.ts +2 -0
  233. package/types/utils/popover/popover.d.ts +7 -0
@@ -1,6 +1,7 @@
1
1
  import type { BlockToolData, OutputBlockData, OutputData, ToolConfig } from '../../../../types';
2
2
  import type { BlockAPI as BlockAPIInterface, Blocks } from '../../../../types/api';
3
3
  import type { BlockTuneData } from '../../../../types/block-tunes/block-tune-data';
4
+ import { isInsideTableCell, isRestrictedInTableCell } from '../../../tools/table/table-restrictions';
4
5
  import { Module } from '../../__module';
5
6
  import { Block } from '../../block';
6
7
  import { BlockAPI } from '../../block/api';
@@ -114,7 +115,7 @@ export class BlocksAPI extends Module {
114
115
  const block = this.Blok.BlockManager.getBlock(element);
115
116
 
116
117
  if (block === undefined) {
117
- logLabeled(`There is no block corresponding to element <${element.tagName.toLowerCase()}>`, 'warn');
118
+ logLabeled(`There is no block corresponding to element <${element.tagName?.toLowerCase() ?? 'unknown'}>`, 'warn');
118
119
 
119
120
  return;
120
121
  }
@@ -242,7 +243,21 @@ export class BlocksAPI extends Module {
242
243
  replace?: boolean,
243
244
  id?: string
244
245
  ): BlockAPIInterface => {
245
- const tool = type ?? (this.config.defaultBlock);
246
+ const defaultTool = type ?? (this.config.defaultBlock);
247
+ const tool = (() => {
248
+ if (!defaultTool) {
249
+ return defaultTool;
250
+ }
251
+
252
+ const targetIndex = index ?? this.Blok.BlockManager.currentBlockIndex;
253
+ const targetBlock = this.Blok.BlockManager.getBlockByIndex(targetIndex);
254
+
255
+ if (targetBlock !== undefined && isInsideTableCell(targetBlock) && isRestrictedInTableCell(defaultTool)) {
256
+ return 'paragraph';
257
+ }
258
+
259
+ return defaultTool;
260
+ })();
246
261
 
247
262
  const insertedBlock = this.Blok.BlockManager.insert({
248
263
  id,
@@ -153,7 +153,18 @@ export class MarkdownShortcuts extends BlockEventComposer {
153
153
  const { BlockManager, Tools } = this.Blok;
154
154
  const currentBlock = BlockManager.currentBlock;
155
155
 
156
- if (!currentBlock?.tool.isDefault) {
156
+ if (!currentBlock) {
157
+ return false;
158
+ }
159
+
160
+ // Check if inside table cell
161
+ const isInsideTableCell = currentBlock.holder.closest('[data-blok-table-cell-blocks]') !== null;
162
+
163
+ if (isInsideTableCell) {
164
+ return false; // Don't convert to header
165
+ }
166
+
167
+ if (!currentBlock.tool.isDefault) {
157
168
  return false;
158
169
  }
159
170
 
@@ -320,17 +320,15 @@ export class Toolbar extends Module<ToolbarNodes> {
320
320
  /**
321
321
  * If no one Block selected as a Current
322
322
  */
323
- const targetBlock = block ?? this.Blok.BlockManager.currentBlock;
323
+ const unresolvedBlock = block ?? this.Blok.BlockManager.currentBlock;
324
324
 
325
- if (!targetBlock) {
325
+ if (!unresolvedBlock) {
326
326
  return;
327
327
  }
328
328
 
329
- /**
330
- * Don't show toolbar for blocks inside table cells.
331
- * Uses the DOM attribute directly to avoid cross-module dependency on the table tool.
332
- */
333
- if (targetBlock.holder.closest('[data-blok-table-cell-blocks]')) {
329
+ const targetBlock = this.resolveTableCellBlock(unresolvedBlock);
330
+
331
+ if (!targetBlock) {
334
332
  this.close();
335
333
 
336
334
  return;
@@ -562,6 +560,30 @@ export class Toolbar extends Module<ToolbarNodes> {
562
560
  this.explicitlyClosed = false;
563
561
  }
564
562
 
563
+ /**
564
+ * If the block is inside a table cell, resolve to the parent table block.
565
+ * This ensures the toolbar shows for the table when clicking/focusing inside cells.
566
+ * Uses the DOM attribute directly to avoid cross-module dependency on the table tool.
567
+ *
568
+ * @param block - the block to resolve
569
+ * @returns the parent table block if inside a cell, the original block otherwise, or null if resolution fails
570
+ */
571
+ private resolveTableCellBlock(block: Block): Block | null {
572
+ const cellBlocksContainer = block.holder.closest('[data-blok-table-cell-blocks]');
573
+
574
+ if (!cellBlocksContainer) {
575
+ return block;
576
+ }
577
+
578
+ const tableBlockHolder = cellBlocksContainer.closest('[data-blok-testid="block-wrapper"]');
579
+
580
+ if (!tableBlockHolder) {
581
+ return null;
582
+ }
583
+
584
+ return this.Blok.BlockManager.getBlockByChildNode(tableBlockHolder) ?? null;
585
+ }
586
+
565
587
  /**
566
588
  * Reset the Toolbar position to prevent DOM height growth, for example after blocks deletion
567
589
  */
@@ -30,6 +30,7 @@ interface UINodes extends Record<string, unknown> {
30
30
  holder: HTMLElement;
31
31
  wrapper: HTMLElement;
32
32
  redactor: HTMLElement;
33
+ bottomZone: HTMLElement;
33
34
  }
34
35
 
35
36
  /**
@@ -191,12 +192,11 @@ export class UI extends Module<UINodes> {
191
192
  this.selectionController.setWrapperElement(this.nodes.wrapper);
192
193
 
193
194
  /**
194
- * Block hover controller needs content rect getter
195
+ * Block hover controller detects hover over blocks and finds nearest block
195
196
  */
196
197
  this.blockHoverController = new BlockHoverController({
197
198
  config: this.config,
198
199
  eventsDispatcher: this.eventsDispatcher,
199
- contentRectGetter: () => this.contentRect,
200
200
  });
201
201
  this.blockHoverController.state = this.Blok;
202
202
 
@@ -452,11 +452,15 @@ export class UI extends Module<UINodes> {
452
452
  }
453
453
 
454
454
  /**
455
- * Set customizable bottom zone height
455
+ * Create dedicated bottom zone element
456
456
  */
457
- this.nodes.redactor.style.paddingBottom = this.config.minHeight + 'px';
457
+ this.nodes.bottomZone = $.make('div', ['cursor-text']);
458
+ this.nodes.bottomZone.setAttribute('data-blok-bottom-zone', '');
459
+ this.nodes.bottomZone.setAttribute('data-blok-testid', 'bottom-zone');
460
+ this.nodes.bottomZone.style.minHeight = this.config.minHeight + 'px';
458
461
 
459
462
  this.nodes.wrapper.appendChild(this.nodes.redactor);
463
+ this.nodes.wrapper.appendChild(this.nodes.bottomZone);
460
464
  this.nodes.holder.appendChild(this.nodes.wrapper);
461
465
 
462
466
  this.bindReadOnlyInsensitiveListeners();
@@ -541,7 +545,16 @@ export class UI extends Module<UINodes> {
541
545
  */
542
546
  private bindReadOnlySensitiveListeners(): void {
543
547
  /**
544
- * Redactor click handler for bottom zone clicks
548
+ * Bottom zone click handler creates new block when clicking below last block
549
+ */
550
+ this.readOnlyMutableListeners.on(this.nodes.bottomZone, 'click', (event: Event) => {
551
+ if (event instanceof MouseEvent) {
552
+ this.bottomZoneClicked(event);
553
+ }
554
+ }, false);
555
+
556
+ /**
557
+ * Redactor click handler for Ctrl+click anchor navigation
545
558
  */
546
559
  this.readOnlyMutableListeners.on(this.nodes.redactor, 'click', (event: Event) => {
547
560
  if (event instanceof MouseEvent) {
@@ -610,98 +623,63 @@ export class UI extends Module<UINodes> {
610
623
  }
611
624
 
612
625
  /**
613
- * All clicks on the redactor zone
614
- * @param {MouseEvent} event - click event
615
- * @description
616
- * - By clicks on the Blok's bottom zone:
617
- * - if last Block is empty, set a Caret to this
618
- * - otherwise, add a new empty Block and set a Caret to that
626
+ * Handle click on the bottom zone element below the last block.
627
+ * Creates a new default block if needed, focuses the last block, and opens the toolbar.
619
628
  */
620
- private redactorClicked(event: MouseEvent): void {
629
+ private bottomZoneClicked(event: MouseEvent): void {
621
630
  if (!Selection.isCollapsed) {
622
631
  return;
623
632
  }
624
633
 
625
- /**
626
- * case when user clicks on anchor element
627
- * if it is clicked via ctrl key, then we open new window with url
628
- */
629
- const element = event.target as Element;
630
- const ctrlKey = event.metaKey || event.ctrlKey;
631
- const shouldOpenAnchorInNewTab = $.isAnchor(element) && ctrlKey;
634
+ const { BlockSelection, BlockManager, Caret, Toolbar } = this.Blok;
632
635
 
633
- if (!shouldOpenAnchorInNewTab) {
634
- this.processBottomZoneClick(event);
636
+ if (BlockSelection.anyBlockSelected) {
637
+ return;
638
+ }
635
639
 
640
+ if (!BlockManager.lastBlock) {
636
641
  return;
637
642
  }
638
643
 
639
644
  event.stopImmediatePropagation();
640
645
  event.stopPropagation();
641
646
 
642
- const href = element.getAttribute('href');
643
-
644
- if (!href) {
645
- return;
647
+ /**
648
+ * Insert a default-block at the bottom if:
649
+ * - last-block is not a default-block (Text)
650
+ * - Or, default-block is not empty
651
+ */
652
+ if (!BlockManager.lastBlock.tool.isDefault || !BlockManager.lastBlock.isEmpty) {
653
+ BlockManager.insertAtEnd();
646
654
  }
647
655
 
648
- const validUrl = getValidUrl(href);
649
-
650
- openTab(validUrl);
656
+ Caret.setToTheLastBlock();
657
+ Toolbar.moveAndOpen(BlockManager.lastBlock);
651
658
  }
652
659
 
653
660
  /**
654
- * Check if user clicks on the Blok's bottom zone:
655
- * - set caret to the last block
656
- * - or add new empty block
657
- * @param event - click event
661
+ * Handle Ctrl+click on anchor elements to open in new tab
658
662
  */
659
- private processBottomZoneClick(event: MouseEvent): void {
660
- const lastBlock = this.Blok.BlockManager.getBlockByIndex(-1);
661
-
662
- if (lastBlock === undefined) {
663
- return;
664
- }
665
-
666
- const lastBlockBottomCoord = $.offset(lastBlock.holder).bottom;
667
- const clickedCoord = event.pageY;
668
- const { BlockSelection } = this.Blok;
669
- const isClickedBottom = event.target instanceof Element &&
670
- event.target.isEqualNode(this.nodes.redactor) &&
671
- /**
672
- * If there is cross block selection started, target will be equal to redactor so we need additional check
673
- */
674
- !BlockSelection.anyBlockSelected &&
675
-
676
- /**
677
- * Prevent caret jumping (to last block) when clicking between blocks
678
- */
679
- lastBlockBottomCoord < clickedCoord;
663
+ private redactorClicked(event: MouseEvent): void {
664
+ const element = event.target as Element;
665
+ const ctrlKey = event.metaKey || event.ctrlKey;
680
666
 
681
- if (!isClickedBottom) {
667
+ if (!$.isAnchor(element) || !ctrlKey) {
682
668
  return;
683
669
  }
684
670
 
685
671
  event.stopImmediatePropagation();
686
672
  event.stopPropagation();
687
673
 
688
- const { BlockManager, Caret, Toolbar } = this.Blok;
674
+ const href = element.getAttribute('href');
689
675
 
690
- /**
691
- * Insert a default-block at the bottom if:
692
- * - last-block is not a default-block (Text)
693
- * to prevent unnecessary tree-walking on Tools with many nodes (for ex. Table)
694
- * - Or, default-block is not empty
695
- */
696
- if (!BlockManager.lastBlock?.tool.isDefault || !BlockManager.lastBlock?.isEmpty) {
697
- BlockManager.insertAtEnd();
676
+ if (!href) {
677
+ return;
698
678
  }
699
679
 
700
- /**
701
- * Set the caret and toolbar to empty Block
702
- */
703
- Caret.setToTheLastBlock();
704
- Toolbar.moveAndOpen(BlockManager.lastBlock);
680
+ const validUrl = getValidUrl(href);
681
+
682
+ openTab(validUrl);
705
683
  }
706
684
 
707
685
  /**
@@ -5,20 +5,15 @@ import { throttle } from '../../../utils';
5
5
  import { Controller } from './_base';
6
6
 
7
7
  /**
8
- * BlockHoverController detects when user hovers over blocks, including extended hover zone.
8
+ * BlockHoverController detects when user hovers over blocks or finds nearest block.
9
9
  *
10
10
  * Responsibilities:
11
11
  * - Listen to mousemove events (throttled)
12
- * - Find block by element hit or extended zone
12
+ * - Find block by element hit or nearest by Y distance
13
13
  * - Emit BlockHovered events
14
14
  * - Track last hovered block to avoid duplicate events
15
15
  */
16
16
  export class BlockHoverController extends Controller {
17
- /**
18
- * Getter function for content rect
19
- */
20
- private contentRectGetter: () => DOMRect;
21
-
22
17
  /**
23
18
  * Used to not emit the same block multiple times to the 'block-hovered' event on every mousemove.
24
19
  * Stores block ID to ensure consistent comparison regardless of how the block was detected.
@@ -42,10 +37,8 @@ export class BlockHoverController extends Controller {
42
37
  constructor(options: {
43
38
  config: Controller['config'];
44
39
  eventsDispatcher: Controller['eventsDispatcher'];
45
- contentRectGetter: () => DOMRect;
46
40
  }) {
47
41
  super(options);
48
- this.contentRectGetter = options.contentRectGetter;
49
42
  }
50
43
 
51
44
  /**
@@ -83,35 +76,11 @@ export class BlockHoverController extends Controller {
83
76
  : closestBlockWrapper;
84
77
 
85
78
  /**
86
- * If no block element found directly, try the extended hover zone
79
+ * If no block element found directly, find the nearest block by Y distance
87
80
  */
88
- const zoneBlock = !hoveredBlockElement
89
- ? this.findBlockInHoverZone(event.clientX, event.clientY)
90
- : null;
91
-
92
- if (zoneBlock !== null && this.blockHoveredState.lastHoveredBlockId !== zoneBlock.id) {
93
- /**
94
- * Emit the event but DON'T set lastHoveredBlockId for hover zone events.
95
- * This allows the event to be emitted again when the mouse enters the actual block element,
96
- * which is important for proper toolbar positioning after cross-block selection.
97
- */
98
- this.eventsDispatcher.emit(BlockHovered, {
99
- block: zoneBlock,
100
- target: zoneBlock.holder,
101
- });
102
- }
103
-
104
- if (zoneBlock !== null) {
105
- return;
106
- }
107
-
108
81
  if (!hoveredBlockElement) {
109
- /**
110
- * When no block is found (mouse left the editor area), reset the hover state.
111
- * This allows hover events to be emitted again when re-entering a block,
112
- * which is important after cross-block selection completes.
113
- */
114
- this.blockHoveredState.lastHoveredBlockId = null;
82
+ this.emitNearestBlockHovered(event.clientY);
83
+
115
84
  return;
116
85
  }
117
86
 
@@ -143,9 +112,8 @@ export class BlockHoverController extends Controller {
143
112
  );
144
113
 
145
114
  /**
146
- * Listen on document to detect hover in the extended zone
147
- * which is outside the wrapper's bounds.
148
- * We filter events to only process those over the editor or in the hover zone.
115
+ * Listen on document to detect hover anywhere on the page.
116
+ * When cursor is not directly on a block, finds the nearest block by Y distance.
149
117
  */
150
118
  this.readOnlyMutableListeners.on(document, 'mousemove', (event: Event) => {
151
119
  throttledHandleBlockHovered(event);
@@ -155,38 +123,49 @@ export class BlockHoverController extends Controller {
155
123
  }
156
124
 
157
125
  /**
158
- * Finds a block by vertical position when cursor is in the hover zone.
159
- * The hover zone extends indefinitely on both sides of the content (left and right),
160
- * allowing the toolbar to follow hover anywhere outside the content area horizontally.
161
- * @param clientX - Cursor X position
126
+ * Finds and emits a BlockHovered event for the nearest block by Y distance.
127
+ * Deduplicates by lastHoveredBlockId to avoid redundant events.
162
128
  * @param clientY - Cursor Y position
163
- * @returns Block at the vertical position, or null if not in hover zone or no block found
164
129
  */
165
- private findBlockInHoverZone(clientX: number, clientY: number): Block | null {
166
- const contentRect = this.contentRectGetter();
130
+ private emitNearestBlockHovered(clientY: number): void {
131
+ const nearestBlock = this.findNearestBlock(clientY);
167
132
 
168
- /**
169
- * Check if cursor is outside the content area horizontally (either left OR right side).
170
- * The zone extends indefinitely on both sides, not limited to HOVER_ZONE_SIZE.
171
- */
172
- const isInHoverZone = clientX < contentRect.left || clientX > contentRect.right;
133
+ if (nearestBlock === null || this.blockHoveredState.lastHoveredBlockId === nearestBlock.id) {
134
+ return;
135
+ }
173
136
 
174
- if (!isInHoverZone) {
137
+ this.blockHoveredState.lastHoveredBlockId = nearestBlock.id;
138
+
139
+ this.eventsDispatcher.emit(BlockHovered, {
140
+ block: nearestBlock,
141
+ target: nearestBlock.holder,
142
+ });
143
+ }
144
+
145
+ /**
146
+ * Finds the nearest block by vertical distance to cursor position.
147
+ * Returns the block whose vertical center is closest to the cursor Y position.
148
+ * If cursor is above all blocks, returns the first block.
149
+ * If cursor is below all blocks, returns the last block.
150
+ * @param clientY - Cursor Y position
151
+ * @returns Nearest block, or null if no blocks exist
152
+ */
153
+ private findNearestBlock(clientY: number): Block | null {
154
+ const blocks = this.Blok.BlockManager.blocks;
155
+
156
+ if (blocks.length === 0) {
175
157
  return null;
176
158
  }
177
159
 
178
- /**
179
- * Find block by Y position
180
- */
181
- for (const block of this.Blok.BlockManager.blocks) {
160
+ const result = blocks.reduce<{ block: Block; distance: number }>((nearest, block) => {
182
161
  const rect = block.holder.getBoundingClientRect();
162
+ const centerY = (rect.top + rect.bottom) / 2;
163
+ const distance = Math.abs(clientY - centerY);
183
164
 
184
- if (clientY >= rect.top && clientY <= rect.bottom) {
185
- return block;
186
- }
187
- }
165
+ return distance < nearest.distance ? { block, distance } : nearest;
166
+ }, { block: blocks[0], distance: Infinity });
188
167
 
189
- return null;
168
+ return result.block;
190
169
  }
191
170
 
192
171
  /**
@@ -1,5 +1,7 @@
1
+ import { RESTRICTED_TOOLS } from '../../tools/table/table-restrictions';
1
2
  import { Dom } from '../dom';
2
3
  import { BlokMobileLayoutToggled } from '../events';
4
+ import { SelectionUtils } from '../selection';
3
5
  import type { BlockToolAdapter } from '../tools/block';
4
6
  import type { ToolsCollection } from '../tools/collection';
5
7
  import { beautifyShortcut, capitalize, isMobileScreen } from '../utils';
@@ -155,7 +157,7 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
155
157
 
156
158
  /**
157
159
  * Whether the toolbox was opened inside a table cell.
158
- * Used to restore the table item visibility on close.
160
+ * Used to restore restricted tool visibility on close.
159
161
  */
160
162
  private isInsideTableCell = false;
161
163
 
@@ -273,17 +275,28 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
273
275
  const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
274
276
 
275
277
  /**
276
- * Hide the table tool when the caret is inside a table cell
277
- * to prevent nested tables.
278
+ * Hide restricted tools (headers, tables) when the caret is inside a table cell.
278
279
  */
279
280
  this.isInsideTableCell = currentBlock !== undefined
280
281
  && currentBlock.holder.closest('[data-blok-table-cell-blocks]') !== null;
281
282
 
282
283
  if (this.isInsideTableCell) {
283
- this.popover?.toggleItemHiddenByName('table', true);
284
+ this.toggleRestrictedToolsHidden(true);
284
285
  }
285
286
 
286
287
  this.popover?.show();
288
+
289
+ /**
290
+ * When opening toolbox inside a table cell, position it at the caret
291
+ * instead of at the trigger element (which is outside the table).
292
+ * Must be called after show() so the popover is in the DOM.
293
+ */
294
+ if (this.isInsideTableCell && this.popover instanceof PopoverDesktop) {
295
+ const caretRect = SelectionUtils.rect;
296
+
297
+ this.popover.updatePosition(caretRect);
298
+ }
299
+
287
300
  this.opened = true;
288
301
  this.emit(ToolboxEvent.Opened);
289
302
  this.startListeningToBlockInput();
@@ -294,7 +307,7 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
294
307
  */
295
308
  public close(): void {
296
309
  if (this.isInsideTableCell) {
297
- this.popover?.toggleItemHiddenByName('table', false);
310
+ this.toggleRestrictedToolsHidden(false);
298
311
  this.isInsideTableCell = false;
299
312
  }
300
313
 
@@ -364,7 +377,7 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
364
377
  */
365
378
  private onPopoverClose = (): void => {
366
379
  if (this.isInsideTableCell) {
367
- this.popover?.toggleItemHiddenByName('table', false);
380
+ this.toggleRestrictedToolsHidden(false);
368
381
  this.isInsideTableCell = false;
369
382
  }
370
383
 
@@ -373,6 +386,28 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
373
386
  this.emit(ToolboxEvent.Closed);
374
387
  };
375
388
 
389
+ /**
390
+ * Toggles hidden state for all popover items belonging to restricted tools.
391
+ * Handles tools like header that have multiple entries with custom names (header-1, header-2, etc.)
392
+ * by matching item names that equal or start with a restricted tool name.
393
+ */
394
+ private toggleRestrictedToolsHidden(isHidden: boolean): void {
395
+ for (const item of this.toolboxItemsToBeDisplayed) {
396
+ if (!('name' in item) || item.name === undefined) {
397
+ continue;
398
+ }
399
+
400
+ const { name } = item;
401
+ const isRestricted = RESTRICTED_TOOLS.some(
402
+ restricted => name === restricted || name.startsWith(`${restricted}-`)
403
+ );
404
+
405
+ if (isRestricted) {
406
+ this.popover?.toggleItemHiddenByName(name, isHidden);
407
+ }
408
+ }
409
+ }
410
+
376
411
  /**
377
412
  * Returns list of tools that enables the Toolbox (by specifying the 'toolbox' getter)
378
413
  */
@@ -324,6 +324,8 @@ export class PopoverItemDefault extends PopoverItem {
324
324
 
325
325
  return twMerge(
326
326
  css.item,
327
+ // Asymmetric padding for vertical popovers (better visual balance)
328
+ !isInline && !isNestedInline && 'pl-2 pr-8',
327
329
  isInline && cssInline.item,
328
330
  isNestedInline && cssNestedInline.item,
329
331
  this.params.isDisabled && css.itemDisabled
@@ -338,7 +340,7 @@ export class PopoverItemDefault extends PopoverItem {
338
340
  css.icon,
339
341
  isInline && 'w-auto h-auto [&_svg]:w-icon [&_svg]:h-icon mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile',
340
342
  isNestedInline && 'w-toolbox-btn h-toolbox-btn',
341
- iconWithGap && 'mr-2',
343
+ iconWithGap && 'mr-3',
342
344
  iconWithGap && isInline && 'shadow-none bg-transparent !mr-0',
343
345
  iconWithGap && isNestedInline && '!mr-2',
344
346
  isWobbling && 'animate-wobble'
@@ -217,31 +217,50 @@ export class PopoverDesktop extends PopoverAbstract {
217
217
  this.flipper?.focusItem(0, { skipNextTab: true });
218
218
  }
219
219
 
220
+ /**
221
+ * Updates the popover position dynamically.
222
+ * Used when the trigger position changes or when positioning at caret location.
223
+ * @param position - new DOMRect position for the popover
224
+ */
225
+ public updatePosition(position: DOMRect): void {
226
+ this.params.position = position;
227
+
228
+ // Recalculate and apply position if already shown
229
+ if (this.nodes.popover.hasAttribute('data-blok-popover-opened')) {
230
+ const { top, left } = this.calculatePosition();
231
+
232
+ this.nodes.popover.style.top = `${top}px`;
233
+ this.nodes.popover.style.left = `${left}px`;
234
+ }
235
+ }
236
+
220
237
  /**
221
238
  * Calculates position for the popover
222
239
  */
223
240
  private calculatePosition(): { top: number; left: number } {
224
- if (!this.trigger) {
241
+ // Use provided position if available, otherwise fall back to trigger element
242
+ const rect = this.params.position ?? this.trigger?.getBoundingClientRect();
243
+
244
+ if (!rect) {
225
245
  return {
226
246
  top: 0,
227
247
  left: 0,
228
248
  };
229
249
  }
230
250
 
231
- const triggerRect = this.trigger.getBoundingClientRect();
232
251
  const popoverRect = this.size;
233
252
  const windowWidth = window.innerWidth;
234
253
  const windowHeight = window.innerHeight;
235
254
  const offset = 8;
236
255
 
237
- const initialTop = triggerRect.bottom + offset + window.scrollY;
238
- const shouldFlipTop = (triggerRect.bottom + offset + popoverRect.height > windowHeight + window.scrollY) &&
239
- (triggerRect.top - offset - popoverRect.height > window.scrollY);
240
- const top = shouldFlipTop ? triggerRect.top - offset - popoverRect.height + window.scrollY : initialTop;
256
+ const initialTop = rect.bottom + offset + window.scrollY;
257
+ const shouldFlipTop = (rect.bottom + offset + popoverRect.height > windowHeight + window.scrollY) &&
258
+ (rect.top - offset - popoverRect.height > window.scrollY);
259
+ const top = shouldFlipTop ? rect.top - offset - popoverRect.height + window.scrollY : initialTop;
241
260
 
242
- const initialLeft = triggerRect.left + window.scrollX;
261
+ const initialLeft = rect.left + window.scrollX;
243
262
  const shouldFlipLeft = initialLeft + popoverRect.width > windowWidth + window.scrollX;
244
- const left = shouldFlipLeft ? Math.max(0, triggerRect.right - popoverRect.width + window.scrollX) : initialLeft;
263
+ const left = shouldFlipLeft ? Math.max(0, rect.right - popoverRect.width + window.scrollX) : initialLeft;
245
264
 
246
265
  return {
247
266
  top,