@jackuait/blok 0.4.3-beta.10 → 0.4.3-beta.3

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 (227) hide show
  1. package/README.md +5 -7
  2. package/dist/blok.mjs +2 -2
  3. package/dist/chunks/{blok-D85C_iyk.mjs → blok-BmjQP37u.mjs} +1726 -1849
  4. package/dist/chunks/{i18next-loader-exc8oN3J.mjs → i18next-loader-DjtwmuRK.mjs} +1 -1
  5. package/dist/chunks/{index-fqgWb6Ue.mjs → index-TdePW2Yb.mjs} +1 -1
  6. package/dist/chunks/{inline-tool-convert-CYkcoF1r.mjs → inline-tool-convert-CreNXc4T.mjs} +8 -8
  7. package/dist/{messages-82j7Sb1f.mjs → chunks/messages-2434tVOK.mjs} +1 -1
  8. package/dist/chunks/{messages-D-tDNAzW.mjs → messages-3DcCwXMF.mjs} +1 -1
  9. package/dist/{messages-DIbeBo-6.mjs → chunks/messages-4kMwVAKY.mjs} +1 -1
  10. package/dist/{messages-CjksZqgf.mjs → chunks/messages-57uL5htT.mjs} +1 -1
  11. package/dist/chunks/{messages-BgmPDL9Z.mjs → messages-76-iJV9Q.mjs} +1 -1
  12. package/dist/{messages-DkJ5aV3V.mjs → chunks/messages-8p86Eyf2.mjs} +1 -1
  13. package/dist/chunks/{messages-TulYnz1f.mjs → messages-BBX0p0Pi.mjs} +1 -1
  14. package/dist/chunks/{messages-CVvHbBlx.mjs → messages-BCm2eudQ.mjs} +1 -1
  15. package/dist/chunks/{messages--yMo5vYp.mjs → messages-BFiUomgG.mjs} +1 -1
  16. package/dist/chunks/{messages-BXsoyz5-.mjs → messages-BIPNHHAV.mjs} +1 -1
  17. package/dist/chunks/{messages-DhdzbzrS.mjs → messages-BUlwu9mo.mjs} +1 -1
  18. package/dist/chunks/{messages-DRTt_xBc.mjs → messages-BX-DPa-z.mjs} +1 -1
  19. package/dist/chunks/{messages-Bi0X1QMU.mjs → messages-BextV3Qh.mjs} +1 -1
  20. package/dist/{messages-D9xzl8Wn.mjs → chunks/messages-BiPSFlUG.mjs} +1 -1
  21. package/dist/chunks/{messages-CoY-hJgp.mjs → messages-BiXe9G-O.mjs} +1 -1
  22. package/dist/{messages-Dw5GZ4YT.mjs → chunks/messages-Bl5z_Igo.mjs} +1 -1
  23. package/dist/{messages-KLzTvDED.mjs → chunks/messages-BnsE97ku.mjs} +1 -1
  24. package/dist/chunks/{messages-DG2QXu_f.mjs → messages-BoO8gsVD.mjs} +1 -1
  25. package/dist/{messages-CbtBGtJT.mjs → chunks/messages-BqWaOGMn.mjs} +1 -1
  26. package/dist/chunks/{messages-CcYGSGRh.mjs → messages-BqkL2_Ro.mjs} +1 -1
  27. package/dist/{messages-qFesO1Lu.mjs → chunks/messages-BvCkXKX-.mjs} +1 -1
  28. package/dist/{messages-Df6LYOt5.mjs → chunks/messages-C6tbPLoj.mjs} +1 -1
  29. package/dist/chunks/{messages-dIzxSHR2.mjs → messages-CA6T3-gQ.mjs} +1 -1
  30. package/dist/{messages-zs9AgeBF.mjs → chunks/messages-CFFPFdWP.mjs} +1 -1
  31. package/dist/{messages-Cm4WhO4g.mjs → chunks/messages-CFrKE-TN.mjs} +1 -1
  32. package/dist/chunks/{messages-D8sk1mxH.mjs → messages-CHz8VlG-.mjs} +1 -1
  33. package/dist/chunks/{messages-HSxl9MoN.mjs → messages-CLixzySl.mjs} +1 -1
  34. package/dist/{messages-DT43ZUKr.mjs → chunks/messages-CV7OM_qk.mjs} +1 -1
  35. package/dist/chunks/{messages-BYeiscyc.mjs → messages-CXHt3eCC.mjs} +1 -1
  36. package/dist/chunks/{messages-CTeYgNo1.mjs → messages-CbmsBrB0.mjs} +1 -1
  37. package/dist/chunks/{messages-DiyoZ_Oa.mjs → messages-Ceo1KtFx.mjs} +1 -1
  38. package/dist/{messages-D8VsV_Ro.mjs → chunks/messages-Cm0LJLtB.mjs} +1 -1
  39. package/dist/chunks/{messages-BaaIMBL8.mjs → messages-CmymP_Ar.mjs} +1 -1
  40. package/dist/chunks/{messages-Uexhy7C9.mjs → messages-D0ohMB5H.mjs} +1 -1
  41. package/dist/{messages-CbP4KoKV.mjs → chunks/messages-D3GrDwXh.mjs} +1 -1
  42. package/dist/{messages-CNRsIuSS.mjs → chunks/messages-D3vTzIpL.mjs} +1 -1
  43. package/dist/{messages-B-b_IFZh.mjs → chunks/messages-D5WeksbV.mjs} +1 -1
  44. package/dist/chunks/{messages-DHdkT1vy.mjs → messages-DGaab4EP.mjs} +1 -1
  45. package/dist/{messages-CwYueRo5.mjs → chunks/messages-DKha57ZU.mjs} +1 -1
  46. package/dist/chunks/{messages-JztkG3tZ.mjs → messages-DOaujgMW.mjs} +1 -1
  47. package/dist/chunks/{messages-DR0sRlko.mjs → messages-DVbPLd_0.mjs} +1 -1
  48. package/dist/chunks/{messages-BnmcUH66.mjs → messages-D_FCyfW6.mjs} +1 -1
  49. package/dist/chunks/{messages-BgbVziWf.mjs → messages-Dd5iZN3c.mjs} +1 -1
  50. package/dist/{messages-D2h_bTrn.mjs → chunks/messages-DehM7135.mjs} +1 -1
  51. package/dist/chunks/{messages-CbepBt3K.mjs → messages-Dg1OHftD.mjs} +1 -1
  52. package/dist/{messages-DT5djAjs.mjs → chunks/messages-Di6Flq-b.mjs} +1 -1
  53. package/dist/chunks/{messages-ctRNTfv5.mjs → messages-Dqhhex6e.mjs} +1 -1
  54. package/dist/chunks/{messages-Bo9JrN9m.mjs → messages-DueVe0F1.mjs} +1 -1
  55. package/dist/chunks/{messages-DvwZEFTL.mjs → messages-Dx3eFwI0.mjs} +1 -1
  56. package/dist/chunks/{messages-jmh1Gbfd.mjs → messages-FOtiUoKl.mjs} +1 -1
  57. package/dist/{messages-B7zIiLTq.mjs → chunks/messages-FTOZNhRD.mjs} +1 -1
  58. package/dist/chunks/{messages-D5J2Xlpx.mjs → messages-IQxGfQIV.mjs} +1 -1
  59. package/dist/chunks/{messages-BCidD-VB.mjs → messages-JF2fzCkK.mjs} +1 -1
  60. package/dist/chunks/{messages-D8tlQmPj.mjs → messages-MOGl7I5v.mjs} +1 -1
  61. package/dist/chunks/{messages-BjZll4R7.mjs → messages-QgYhPL-3.mjs} +1 -1
  62. package/dist/{messages-BWDnoNq0.mjs → chunks/messages-WYWIbQwo.mjs} +1 -1
  63. package/dist/chunks/{messages-oO_lJ-_I.mjs → messages-a6A_LgDv.mjs} +1 -1
  64. package/dist/chunks/{messages-g7Njot5w.mjs → messages-bSf31LJi.mjs} +1 -1
  65. package/dist/chunks/{messages-sSYZ0Mz9.mjs → messages-diGozhTn.mjs} +1 -1
  66. package/dist/chunks/{messages-BZ-Ia4tk.mjs → messages-er-kd-VO.mjs} +1 -1
  67. package/dist/chunks/{messages-B5OIvtYB.mjs → messages-ez3w5NBn.mjs} +1 -1
  68. package/dist/chunks/{messages-BuKgyEeU.mjs → messages-f3uXjegd.mjs} +1 -1
  69. package/dist/{messages-CJQt8nzO.mjs → chunks/messages-ohwI1UGv.mjs} +1 -1
  70. package/dist/{messages-9-pnvSWZ.mjs → chunks/messages-p9BZJaFV.mjs} +1 -1
  71. package/dist/{messages-CpkO-V0C.mjs → chunks/messages-qIQ4L4rw.mjs} +1 -1
  72. package/dist/{messages-CPdlHIEi.mjs → chunks/messages-qWkXPggi.mjs} +1 -1
  73. package/dist/chunks/{messages-iNIhRBkQ.mjs → messages-w5foGze_.mjs} +1 -1
  74. package/dist/full.mjs +2 -2
  75. package/dist/locales.mjs +68 -68
  76. package/dist/{chunks/messages-82j7Sb1f.mjs → messages-2434tVOK.mjs} +1 -1
  77. package/dist/{messages-D-tDNAzW.mjs → messages-3DcCwXMF.mjs} +1 -1
  78. package/dist/{chunks/messages-DIbeBo-6.mjs → messages-4kMwVAKY.mjs} +1 -1
  79. package/dist/{chunks/messages-CjksZqgf.mjs → messages-57uL5htT.mjs} +1 -1
  80. package/dist/{messages-BgmPDL9Z.mjs → messages-76-iJV9Q.mjs} +1 -1
  81. package/dist/{chunks/messages-DkJ5aV3V.mjs → messages-8p86Eyf2.mjs} +1 -1
  82. package/dist/{messages-TulYnz1f.mjs → messages-BBX0p0Pi.mjs} +1 -1
  83. package/dist/{messages-CVvHbBlx.mjs → messages-BCm2eudQ.mjs} +1 -1
  84. package/dist/{messages--yMo5vYp.mjs → messages-BFiUomgG.mjs} +1 -1
  85. package/dist/{messages-BXsoyz5-.mjs → messages-BIPNHHAV.mjs} +1 -1
  86. package/dist/{messages-DhdzbzrS.mjs → messages-BUlwu9mo.mjs} +1 -1
  87. package/dist/{messages-DRTt_xBc.mjs → messages-BX-DPa-z.mjs} +1 -1
  88. package/dist/{messages-Bi0X1QMU.mjs → messages-BextV3Qh.mjs} +1 -1
  89. package/dist/{chunks/messages-D9xzl8Wn.mjs → messages-BiPSFlUG.mjs} +1 -1
  90. package/dist/{messages-CoY-hJgp.mjs → messages-BiXe9G-O.mjs} +1 -1
  91. package/dist/{chunks/messages-Dw5GZ4YT.mjs → messages-Bl5z_Igo.mjs} +1 -1
  92. package/dist/{chunks/messages-KLzTvDED.mjs → messages-BnsE97ku.mjs} +1 -1
  93. package/dist/{messages-DG2QXu_f.mjs → messages-BoO8gsVD.mjs} +1 -1
  94. package/dist/{chunks/messages-CbtBGtJT.mjs → messages-BqWaOGMn.mjs} +1 -1
  95. package/dist/{messages-CcYGSGRh.mjs → messages-BqkL2_Ro.mjs} +1 -1
  96. package/dist/{chunks/messages-qFesO1Lu.mjs → messages-BvCkXKX-.mjs} +1 -1
  97. package/dist/{chunks/messages-Df6LYOt5.mjs → messages-C6tbPLoj.mjs} +1 -1
  98. package/dist/{messages-dIzxSHR2.mjs → messages-CA6T3-gQ.mjs} +1 -1
  99. package/dist/{chunks/messages-zs9AgeBF.mjs → messages-CFFPFdWP.mjs} +1 -1
  100. package/dist/{chunks/messages-Cm4WhO4g.mjs → messages-CFrKE-TN.mjs} +1 -1
  101. package/dist/{messages-D8sk1mxH.mjs → messages-CHz8VlG-.mjs} +1 -1
  102. package/dist/{messages-HSxl9MoN.mjs → messages-CLixzySl.mjs} +1 -1
  103. package/dist/{chunks/messages-DT43ZUKr.mjs → messages-CV7OM_qk.mjs} +1 -1
  104. package/dist/{messages-BYeiscyc.mjs → messages-CXHt3eCC.mjs} +1 -1
  105. package/dist/{messages-CTeYgNo1.mjs → messages-CbmsBrB0.mjs} +1 -1
  106. package/dist/{messages-DiyoZ_Oa.mjs → messages-Ceo1KtFx.mjs} +1 -1
  107. package/dist/{chunks/messages-D8VsV_Ro.mjs → messages-Cm0LJLtB.mjs} +1 -1
  108. package/dist/{messages-BaaIMBL8.mjs → messages-CmymP_Ar.mjs} +1 -1
  109. package/dist/{messages-Uexhy7C9.mjs → messages-D0ohMB5H.mjs} +1 -1
  110. package/dist/{chunks/messages-CbP4KoKV.mjs → messages-D3GrDwXh.mjs} +1 -1
  111. package/dist/{chunks/messages-CNRsIuSS.mjs → messages-D3vTzIpL.mjs} +1 -1
  112. package/dist/{chunks/messages-B-b_IFZh.mjs → messages-D5WeksbV.mjs} +1 -1
  113. package/dist/{messages-DHdkT1vy.mjs → messages-DGaab4EP.mjs} +1 -1
  114. package/dist/{chunks/messages-CwYueRo5.mjs → messages-DKha57ZU.mjs} +1 -1
  115. package/dist/{messages-JztkG3tZ.mjs → messages-DOaujgMW.mjs} +1 -1
  116. package/dist/{messages-DR0sRlko.mjs → messages-DVbPLd_0.mjs} +1 -1
  117. package/dist/{messages-BnmcUH66.mjs → messages-D_FCyfW6.mjs} +1 -1
  118. package/dist/{messages-BgbVziWf.mjs → messages-Dd5iZN3c.mjs} +1 -1
  119. package/dist/{chunks/messages-D2h_bTrn.mjs → messages-DehM7135.mjs} +1 -1
  120. package/dist/{messages-CbepBt3K.mjs → messages-Dg1OHftD.mjs} +1 -1
  121. package/dist/{chunks/messages-DT5djAjs.mjs → messages-Di6Flq-b.mjs} +1 -1
  122. package/dist/{messages-ctRNTfv5.mjs → messages-Dqhhex6e.mjs} +1 -1
  123. package/dist/{messages-Bo9JrN9m.mjs → messages-DueVe0F1.mjs} +1 -1
  124. package/dist/{messages-DvwZEFTL.mjs → messages-Dx3eFwI0.mjs} +1 -1
  125. package/dist/{messages-jmh1Gbfd.mjs → messages-FOtiUoKl.mjs} +1 -1
  126. package/dist/{chunks/messages-B7zIiLTq.mjs → messages-FTOZNhRD.mjs} +1 -1
  127. package/dist/{messages-D5J2Xlpx.mjs → messages-IQxGfQIV.mjs} +1 -1
  128. package/dist/{messages-BCidD-VB.mjs → messages-JF2fzCkK.mjs} +1 -1
  129. package/dist/{messages-D8tlQmPj.mjs → messages-MOGl7I5v.mjs} +1 -1
  130. package/dist/{messages-BjZll4R7.mjs → messages-QgYhPL-3.mjs} +1 -1
  131. package/dist/{chunks/messages-BWDnoNq0.mjs → messages-WYWIbQwo.mjs} +1 -1
  132. package/dist/{messages-oO_lJ-_I.mjs → messages-a6A_LgDv.mjs} +1 -1
  133. package/dist/{messages-g7Njot5w.mjs → messages-bSf31LJi.mjs} +1 -1
  134. package/dist/{messages-sSYZ0Mz9.mjs → messages-diGozhTn.mjs} +1 -1
  135. package/dist/{messages-BZ-Ia4tk.mjs → messages-er-kd-VO.mjs} +1 -1
  136. package/dist/{messages-B5OIvtYB.mjs → messages-ez3w5NBn.mjs} +1 -1
  137. package/dist/{messages-BuKgyEeU.mjs → messages-f3uXjegd.mjs} +1 -1
  138. package/dist/{chunks/messages-CJQt8nzO.mjs → messages-ohwI1UGv.mjs} +1 -1
  139. package/dist/{chunks/messages-9-pnvSWZ.mjs → messages-p9BZJaFV.mjs} +1 -1
  140. package/dist/{chunks/messages-CpkO-V0C.mjs → messages-qIQ4L4rw.mjs} +1 -1
  141. package/dist/{chunks/messages-CPdlHIEi.mjs → messages-qWkXPggi.mjs} +1 -1
  142. package/dist/{messages-iNIhRBkQ.mjs → messages-w5foGze_.mjs} +1 -1
  143. package/dist/tools.mjs +90 -131
  144. package/package.json +1 -1
  145. package/src/components/i18n/locales/am/messages.json +1 -1
  146. package/src/components/i18n/locales/ar/messages.json +1 -1
  147. package/src/components/i18n/locales/az/messages.json +1 -1
  148. package/src/components/i18n/locales/bg/messages.json +1 -1
  149. package/src/components/i18n/locales/bn/messages.json +1 -1
  150. package/src/components/i18n/locales/bs/messages.json +1 -1
  151. package/src/components/i18n/locales/cs/messages.json +1 -1
  152. package/src/components/i18n/locales/da/messages.json +1 -1
  153. package/src/components/i18n/locales/de/messages.json +1 -1
  154. package/src/components/i18n/locales/dv/messages.json +1 -1
  155. package/src/components/i18n/locales/el/messages.json +1 -1
  156. package/src/components/i18n/locales/en/messages.json +1 -1
  157. package/src/components/i18n/locales/es/messages.json +1 -1
  158. package/src/components/i18n/locales/et/messages.json +1 -1
  159. package/src/components/i18n/locales/fa/messages.json +1 -1
  160. package/src/components/i18n/locales/fi/messages.json +1 -1
  161. package/src/components/i18n/locales/fil/messages.json +1 -1
  162. package/src/components/i18n/locales/fr/messages.json +1 -1
  163. package/src/components/i18n/locales/gu/messages.json +1 -1
  164. package/src/components/i18n/locales/he/messages.json +1 -1
  165. package/src/components/i18n/locales/hi/messages.json +1 -1
  166. package/src/components/i18n/locales/hr/messages.json +1 -1
  167. package/src/components/i18n/locales/hu/messages.json +1 -1
  168. package/src/components/i18n/locales/hy/messages.json +1 -1
  169. package/src/components/i18n/locales/id/messages.json +1 -1
  170. package/src/components/i18n/locales/it/messages.json +1 -1
  171. package/src/components/i18n/locales/ja/messages.json +1 -1
  172. package/src/components/i18n/locales/ka/messages.json +1 -1
  173. package/src/components/i18n/locales/km/messages.json +1 -1
  174. package/src/components/i18n/locales/kn/messages.json +1 -1
  175. package/src/components/i18n/locales/ko/messages.json +1 -1
  176. package/src/components/i18n/locales/ku/messages.json +1 -1
  177. package/src/components/i18n/locales/lo/messages.json +1 -1
  178. package/src/components/i18n/locales/lt/messages.json +1 -1
  179. package/src/components/i18n/locales/lv/messages.json +1 -1
  180. package/src/components/i18n/locales/mk/messages.json +1 -1
  181. package/src/components/i18n/locales/ml/messages.json +1 -1
  182. package/src/components/i18n/locales/mn/messages.json +1 -1
  183. package/src/components/i18n/locales/mr/messages.json +1 -1
  184. package/src/components/i18n/locales/ms/messages.json +1 -1
  185. package/src/components/i18n/locales/my/messages.json +1 -1
  186. package/src/components/i18n/locales/ne/messages.json +1 -1
  187. package/src/components/i18n/locales/nl/messages.json +1 -1
  188. package/src/components/i18n/locales/no/messages.json +1 -1
  189. package/src/components/i18n/locales/pa/messages.json +1 -1
  190. package/src/components/i18n/locales/pl/messages.json +1 -1
  191. package/src/components/i18n/locales/ps/messages.json +1 -1
  192. package/src/components/i18n/locales/pt/messages.json +1 -1
  193. package/src/components/i18n/locales/ro/messages.json +1 -1
  194. package/src/components/i18n/locales/ru/messages.json +1 -1
  195. package/src/components/i18n/locales/sd/messages.json +1 -1
  196. package/src/components/i18n/locales/si/messages.json +1 -1
  197. package/src/components/i18n/locales/sk/messages.json +1 -1
  198. package/src/components/i18n/locales/sl/messages.json +1 -1
  199. package/src/components/i18n/locales/sq/messages.json +1 -1
  200. package/src/components/i18n/locales/sr/messages.json +1 -1
  201. package/src/components/i18n/locales/sv/messages.json +1 -1
  202. package/src/components/i18n/locales/sw/messages.json +1 -1
  203. package/src/components/i18n/locales/ta/messages.json +1 -1
  204. package/src/components/i18n/locales/te/messages.json +1 -1
  205. package/src/components/i18n/locales/th/messages.json +1 -1
  206. package/src/components/i18n/locales/tr/messages.json +1 -1
  207. package/src/components/i18n/locales/ug/messages.json +1 -1
  208. package/src/components/i18n/locales/uk/messages.json +1 -1
  209. package/src/components/i18n/locales/ur/messages.json +1 -1
  210. package/src/components/i18n/locales/vi/messages.json +1 -1
  211. package/src/components/i18n/locales/yi/messages.json +1 -1
  212. package/src/components/i18n/locales/zh/messages.json +1 -1
  213. package/src/components/modules/api/i18n.ts +0 -1
  214. package/src/components/modules/dragManager.ts +13 -71
  215. package/src/components/modules/i18n.ts +11 -6
  216. package/src/components/modules/rectangleSelection.ts +19 -62
  217. package/src/components/modules/toolbar/index.ts +2 -2
  218. package/src/components/modules/tools.ts +3 -39
  219. package/src/components/modules/ui.ts +18 -83
  220. package/src/components/tools/base.ts +2 -29
  221. package/src/components/tools/block.ts +3 -20
  222. package/src/components/tools/factory.ts +1 -50
  223. package/src/tools/header/index.ts +0 -82
  224. package/src/tools/index.ts +6 -13
  225. package/src/tools/list/index.ts +2 -2
  226. package/types/api/i18n.d.ts +0 -8
  227. package/types/tools/tool-settings.d.ts +4 -62
@@ -35,8 +35,6 @@ const DRAG_CONFIG = {
35
35
  autoScrollSpeed: 10,
36
36
  /** Throttle delay for drop position announcements (ms) */
37
37
  announcementThrottleMs: 300,
38
- /** Horizontal distance to the left of blocks where drop is still valid */
39
- leftDropZone: 50,
40
38
  };
41
39
 
42
40
  /**
@@ -426,10 +424,20 @@ export class DragManager extends Module {
426
424
  return;
427
425
  }
428
426
 
429
- // Find block holder - first try direct hit, then left drop zone fallback
430
- const { block: targetBlock, holder: blockHolder } = this.findDropTargetBlock(elementUnderCursor, clientX, clientY);
427
+ // Find block holder
428
+ const blockHolder = elementUnderCursor.closest(createSelector(DATA_ATTR.element)) as HTMLElement | null;
431
429
 
432
- if (!blockHolder || !targetBlock || targetBlock === this.dragState.sourceBlock) {
430
+ if (!blockHolder) {
431
+ this.dragState.targetBlock = null;
432
+ this.dragState.targetEdge = null;
433
+
434
+ return;
435
+ }
436
+
437
+ // Find the block instance
438
+ const targetBlock = this.Blok.BlockManager.blocks.find(b => b.holder === blockHolder);
439
+
440
+ if (!targetBlock || targetBlock === this.dragState.sourceBlock) {
433
441
  this.dragState.targetBlock = null;
434
442
  this.dragState.targetEdge = null;
435
443
 
@@ -1124,72 +1132,6 @@ export class DragManager extends Module {
1124
1132
  return collectDescendants(blockIndex + 1, []);
1125
1133
  }
1126
1134
 
1127
- /**
1128
- * Finds the drop target block from an element or by checking the left drop zone.
1129
- * @param elementUnderCursor - Element directly under the cursor
1130
- * @param clientX - Cursor X position
1131
- * @param clientY - Cursor Y position
1132
- * @returns Object with block and holder, or nulls if no valid target found
1133
- */
1134
- private findDropTargetBlock(
1135
- elementUnderCursor: Element,
1136
- clientX: number,
1137
- clientY: number
1138
- ): { block: Block | undefined; holder: HTMLElement | null } {
1139
- // First try: find block holder directly under cursor
1140
- const directHolder = elementUnderCursor.closest(createSelector(DATA_ATTR.element)) as HTMLElement | null;
1141
-
1142
- if (directHolder) {
1143
- const block = this.Blok.BlockManager.blocks.find(b => b.holder === directHolder);
1144
-
1145
- return { block, holder: directHolder };
1146
- }
1147
-
1148
- // Fallback: check if cursor is in the left drop zone
1149
- const leftZoneBlock = this.findBlockInLeftDropZone(clientX, clientY);
1150
-
1151
- if (leftZoneBlock) {
1152
- return { block: leftZoneBlock, holder: leftZoneBlock.holder };
1153
- }
1154
-
1155
- return { block: undefined, holder: null };
1156
- }
1157
-
1158
- /**
1159
- * Finds a block by vertical position when cursor is in the left drop zone.
1160
- * Used as a fallback when elementFromPoint doesn't find a block directly.
1161
- * @param clientX - Cursor X position
1162
- * @param clientY - Cursor Y position
1163
- * @returns Block at the vertical position, or null if not in left zone or no block found
1164
- */
1165
- private findBlockInLeftDropZone(clientX: number, clientY: number): Block | null {
1166
- const contentRect = this.Blok.UI.contentRect;
1167
- const leftEdge = contentRect.left;
1168
-
1169
- // Check if cursor is within left drop zone (between leftEdge - leftDropZone and leftEdge)
1170
- const distanceFromEdge = leftEdge - clientX;
1171
-
1172
- if (distanceFromEdge < 0 || distanceFromEdge > DRAG_CONFIG.leftDropZone) {
1173
- return null;
1174
- }
1175
-
1176
- // Find block by Y position
1177
- for (const block of this.Blok.BlockManager.blocks) {
1178
- // Skip source blocks
1179
- if (this.dragState?.sourceBlocks.includes(block)) {
1180
- continue;
1181
- }
1182
-
1183
- const rect = block.holder.getBoundingClientRect();
1184
-
1185
- if (clientY >= rect.top && clientY <= rect.bottom) {
1186
- return block;
1187
- }
1188
- }
1189
-
1190
- return null;
1191
- }
1192
-
1193
1135
  /**
1194
1136
  * Module destruction
1195
1137
  */
@@ -204,7 +204,17 @@ export class I18n extends Module {
204
204
  // Set default locale if configured
205
205
  this.applyDefaultLocale(i18nConfig?.defaultLocale);
206
206
 
207
- // Load base translations first
207
+ // Handle custom messages (highest priority)
208
+ if (i18nConfig?.messages !== undefined) {
209
+ // For custom messages, use lightweight implementation with overrides
210
+ this.lightweightI18n.setDictionary(i18nConfig.messages);
211
+ this.usingI18next = false;
212
+ // Set direction from config or default to 'ltr' for custom messages
213
+ this.updateConfigDirection(i18nConfig.direction ?? 'ltr');
214
+
215
+ return;
216
+ }
217
+
208
218
  const requestedLocale = i18nConfig?.locale;
209
219
 
210
220
  if (requestedLocale === undefined || requestedLocale === 'auto') {
@@ -213,11 +223,6 @@ export class I18n extends Module {
213
223
  await this.setLocale(requestedLocale);
214
224
  }
215
225
 
216
- // Merge custom messages on top of base translations (if provided)
217
- if (i18nConfig?.messages !== undefined) {
218
- this.setDictionary(i18nConfig.messages);
219
- }
220
-
221
226
  // Update config.i18n.direction so other modules can access it via isRtl getter
222
227
  this.updateConfigDirection(i18nConfig?.direction ?? this.getDirection());
223
228
  }
@@ -116,29 +116,11 @@ export class RectangleSelection extends Module {
116
116
  * Init rect params
117
117
  * @param {number} pageX - X coord of mouse
118
118
  * @param {number} pageY - Y coord of mouse
119
- * @param {boolean} shiftKey - whether Shift key is held for additive selection
120
119
  */
121
- public startSelection(pageX: number, pageY: number, shiftKey = false): void {
122
- const { UI } = this.Blok;
123
- const redactor = UI.nodes.redactor;
124
-
125
- if (!redactor) {
126
- return;
127
- }
128
-
129
- const editorRect = redactor.getBoundingClientRect();
130
- const scrollTop = this.getScrollTop();
131
- const pointerY = pageY - scrollTop;
132
-
133
- // Check if pointer is within editor's vertical bounds
134
- const withinEditorVertically = pointerY >= editorRect.top && pointerY <= editorRect.bottom;
135
-
136
- if (!withinEditorVertically) {
137
- return;
138
- }
139
-
120
+ public startSelection(pageX: number, pageY: number): void {
140
121
  const scrollLeft = this.getScrollLeft();
141
- const elemWhereSelectionStart = document.elementFromPoint(pageX - scrollLeft, pointerY);
122
+ const scrollTop = this.getScrollTop();
123
+ const elemWhereSelectionStart = document.elementFromPoint(pageX - scrollLeft, pageY - scrollTop);
142
124
 
143
125
  if (!elemWhereSelectionStart) {
144
126
  return;
@@ -150,11 +132,7 @@ export class RectangleSelection extends Module {
150
132
  */
151
133
  const startsInsideToolbar = elemWhereSelectionStart.closest(createSelector(DATA_ATTR.toolbar));
152
134
 
153
- /**
154
- * When Shift is held, preserve existing selection for additive behavior.
155
- * Otherwise, clear selection state.
156
- */
157
- if (!startsInsideToolbar && !shiftKey) {
135
+ if (!startsInsideToolbar) {
158
136
  this.Blok.BlockSelection.allBlocksSelected = false;
159
137
  this.clearSelection();
160
138
  this.stackOfSelected = [];
@@ -163,16 +141,16 @@ export class RectangleSelection extends Module {
163
141
  const selectorsToAvoid = [
164
142
  createSelector(DATA_ATTR.elementContent),
165
143
  createSelector(DATA_ATTR.toolbar),
166
- createSelector(DATA_ATTR.popover),
167
144
  INLINE_TOOLBAR_INTERFACE_SELECTOR,
168
145
  ];
169
146
 
147
+ const startsInsideBlok = elemWhereSelectionStart.closest(createSelector(DATA_ATTR.editor));
170
148
  const startsInSelectorToAvoid = selectorsToAvoid.some((selector) => !!elemWhereSelectionStart.closest(selector));
171
149
 
172
150
  /**
173
- * If selection starts inside the blocks content or on Blok UI elements, do not handle it
151
+ * If selection starts outside of the blok or inside the blocks or on Blok UI elements, do not handle it
174
152
  */
175
- if (startsInSelectorToAvoid) {
153
+ if (!startsInsideBlok || startsInSelectorToAvoid) {
176
154
  return;
177
155
  }
178
156
 
@@ -216,9 +194,9 @@ export class RectangleSelection extends Module {
216
194
  * Sets Module necessary event handlers
217
195
  */
218
196
  private enableModuleBindings(): void {
219
- this.genHTML();
197
+ const { container } = this.genHTML();
220
198
 
221
- this.listeners.on(document.body, 'mousedown', (event: Event) => {
199
+ this.listeners.on(container, 'mousedown', (event: Event) => {
222
200
  this.processMouseDown(event as MouseEvent);
223
201
  }, false);
224
202
 
@@ -267,7 +245,7 @@ export class RectangleSelection extends Module {
267
245
  const startedFromContentEditable = (mouseEvent.target as Element).closest($.allInputsSelector) !== null;
268
246
 
269
247
  if (!startedFromContentEditable) {
270
- this.startSelection(mouseEvent.pageX, mouseEvent.pageY, mouseEvent.shiftKey);
248
+ this.startSelection(mouseEvent.pageX, mouseEvent.pageY);
271
249
  }
272
250
  }
273
251
 
@@ -424,38 +402,21 @@ export class RectangleSelection extends Module {
424
402
  this.mouseY = event.pageY;
425
403
  }
426
404
 
405
+ const { rightPos, leftPos, index } = this.genInfoForMouseSelection();
406
+ // There is not new block in selection
407
+
408
+ const rectIsOnRighSideOfredactor = this.startX > rightPos && this.mouseX > rightPos;
409
+ const rectISOnLeftSideOfRedactor = this.startX < leftPos && this.mouseX < leftPos;
410
+
411
+ this.rectCrossesBlocks = !(rectIsOnRighSideOfredactor || rectISOnLeftSideOfRedactor);
412
+
427
413
  if (!this.isRectSelectionActivated) {
414
+ this.rectCrossesBlocks = false;
428
415
  this.isRectSelectionActivated = true;
429
416
  this.shrinkRectangleToPoint();
430
417
  overlayRectangle.style.display = 'block';
431
418
  }
432
419
 
433
- const { index } = this.genInfoForMouseSelection();
434
-
435
- /**
436
- * Check if the selection rectangle intersects the block holder horizontally.
437
- * For page-wide selection, we need to verify the rectangle actually reaches the block,
438
- * not just that the mouse Y position is at the same height as a block.
439
- */
440
- this.rectCrossesBlocks = false;
441
- const block = index !== undefined ? this.Blok.BlockManager.getBlockByIndex(index) : undefined;
442
-
443
- if (block) {
444
- const holderRect = block.holder.getBoundingClientRect();
445
- const scrollLeft = this.getScrollLeft();
446
-
447
- // Selection rectangle horizontal bounds (in page coordinates)
448
- const rectLeft = Math.min(this.startX, this.mouseX);
449
- const rectRight = Math.max(this.startX, this.mouseX);
450
-
451
- // Block holder horizontal bounds (convert from viewport to page coordinates)
452
- const holderLeft = holderRect.left + scrollLeft;
453
- const holderRight = holderRect.right + scrollLeft;
454
-
455
- // Check for horizontal intersection
456
- this.rectCrossesBlocks = rectRight >= holderLeft && rectLeft <= holderRight;
457
- }
458
-
459
420
  this.updateRectangleSize();
460
421
 
461
422
  /**
@@ -556,7 +517,6 @@ export class RectangleSelection extends Module {
556
517
 
557
518
  /**
558
519
  * Collects information needed to determine the behavior of the rectangle
559
- * For page-wide selection, we check blocks at the center X position but at the actual mouse Y position
560
520
  * @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border
561
521
  */
562
522
  private genInfoForMouseSelection(): {index: number | undefined; leftPos: number; rightPos: number} {
@@ -564,9 +524,6 @@ export class RectangleSelection extends Module {
564
524
  const centerOfRedactor = widthOfRedactor / 2;
565
525
  const scrollTop = this.getScrollTop();
566
526
  const y = this.mouseY - scrollTop;
567
-
568
- // For page-wide selection: check what block is at the center X, but at the mouse's Y position
569
- // This allows selection to work even when mouse is in the left/right margins
570
527
  const elementUnderMouse = document.elementFromPoint(centerOfRedactor, y);
571
528
  const lastBlockHolder = this.Blok.BlockManager.lastBlock?.holder;
572
529
  const contentElement = lastBlockHolder?.querySelector(createSelector(DATA_ATTR.elementContent));
@@ -998,9 +998,9 @@ export class Toolbar extends Module<ToolbarNodes> {
998
998
  */
999
999
  this.eventsDispatcher.on(BlockHovered, (data) => {
1000
1000
  /**
1001
- * Do not move toolbar during drag or rectangle selection operations
1001
+ * Do not move toolbar during drag operations
1002
1002
  */
1003
- if (this.Blok.DragManager.isDragging || this.Blok.RectangleSelection.isRectActivated()) {
1003
+ if (this.Blok.DragManager.isDragging) {
1004
1004
  return;
1005
1005
  }
1006
1006
 
@@ -334,18 +334,18 @@ export class Tools extends Module {
334
334
  .map(([toolName, settings]): ChainData => {
335
335
  const toolData: ToolPrepareData = {
336
336
  toolName,
337
- config: this.extractToolConfig(settings),
337
+ config: (settings.config ?? {}) as ToolConfig,
338
338
  };
339
339
 
340
340
  const prepareFunction: ChainData['function'] = async (payload?: unknown) => {
341
- const constructable = settings.class as ToolConstructable | undefined;
341
+ const constructable = settings.class;
342
342
 
343
343
  if (!constructable || !isFunction(constructable.prepare)) {
344
344
  return;
345
345
  }
346
346
 
347
347
  const data = (payload ?? toolData) as ToolPrepareData;
348
- const prepareMethod = constructable.prepare as ToolPrepareFunction;
348
+ const prepareMethod = constructable.prepare as unknown as ToolPrepareFunction;
349
349
 
350
350
  return prepareMethod.call(constructable, data);
351
351
  };
@@ -357,42 +357,6 @@ export class Tools extends Module {
357
357
  });
358
358
  }
359
359
 
360
- /**
361
- * Keys that are Blok-level settings (not passed to tool constructor)
362
- */
363
- private static readonly BLOK_SETTINGS_KEYS = new Set([
364
- 'class',
365
- 'inlineToolbar',
366
- 'tunes',
367
- 'shortcut',
368
- 'toolbox',
369
- 'config',
370
- 'isInternal',
371
- ]);
372
-
373
- /**
374
- * Extracts tool configuration from settings.
375
- * Merges nested config with flat tool-specific options (flat takes precedence).
376
- * @param settings - Tool settings from user config
377
- * @returns Merged tool configuration
378
- */
379
- private extractToolConfig(settings: ToolSettings): ToolConfig {
380
- // eslint-disable-next-line @typescript-eslint/no-deprecated -- Internal: reading legacy config for backwards compatibility
381
- const nestedConfig = (settings.config ?? {}) as ToolConfig;
382
-
383
- // Extract non-Blok keys as tool-specific config
384
- const flatConfig: Record<string, unknown> = {};
385
-
386
- for (const key of Object.keys(settings)) {
387
- if (!Tools.BLOK_SETTINGS_KEYS.has(key)) {
388
- flatConfig[key] = settings[key as keyof typeof settings];
389
- }
390
- }
391
-
392
- // Merge: nested config first, flat config overrides
393
- return { ...nestedConfig, ...flatConfig } as ToolConfig;
394
- }
395
-
396
360
  /**
397
361
  * Assign enabled Inline Tools and Block Tunes for Block Tool
398
362
  */
@@ -9,15 +9,8 @@ import { debounce, getValidUrl, isEmpty, openTab, throttle } from '../utils';
9
9
 
10
10
  import { SelectionUtils as Selection } from '../selection';
11
11
  import { Flipper } from '../flipper';
12
- import type { Block } from '../block';
13
12
  import { mobileScreenBreakpoint } from '../utils';
14
13
 
15
- /**
16
- * Horizontal distance from the content edge where block hover is still detected.
17
- * Extends to the left for LTR layouts, to the right for RTL.
18
- */
19
- const HOVER_ZONE_SIZE = 100;
20
-
21
14
  import styles from '../../styles/main.css?inline';
22
15
  import { BlockHovered } from '../events/BlockHovered';
23
16
  import {
@@ -460,47 +453,23 @@ export class UI extends Module<UINodes> {
460
453
  */
461
454
  private watchBlockHoveredEvents(): void {
462
455
  /**
463
- * Used to not emit the same block multiple times to the 'block-hovered' event on every mousemove.
464
- * Stores block ID to ensure consistent comparison regardless of how the block was detected.
456
+ * Used to not emit the same block multiple times to the 'block-hovered' event on every mousemove
465
457
  */
466
- const blockHoveredState: { lastHoveredBlockId: string | null } = {
467
- lastHoveredBlockId: null,
458
+ const blockHoveredState: { lastHovered: Element | null } = {
459
+ lastHovered: null,
468
460
  };
469
461
 
470
462
  const handleBlockHovered = (event: Event): void => {
471
- if (!(event instanceof MouseEvent)) {
472
- return;
473
- }
474
-
475
- const hoveredBlockElement = (event.target as Element | null)?.closest('[data-blok-testid="block-wrapper"]');
476
-
477
- /**
478
- * If no block element found directly, try the extended hover zone
479
- */
480
- const zoneBlock = !hoveredBlockElement
481
- ? this.findBlockInHoverZone(event.clientX, event.clientY)
482
- : null;
483
-
484
- if (zoneBlock !== null && blockHoveredState.lastHoveredBlockId !== zoneBlock.id) {
485
- blockHoveredState.lastHoveredBlockId = zoneBlock.id;
463
+ const isMouseEvent = typeof MouseEvent !== 'undefined' && event instanceof MouseEvent;
464
+ const isTouchEvent = typeof TouchEvent !== 'undefined' && event instanceof TouchEvent;
486
465
 
487
- this.eventsDispatcher.emit(BlockHovered, {
488
- block: zoneBlock,
489
- target: zoneBlock.holder,
490
- });
491
- }
492
-
493
- if (zoneBlock !== null) {
494
- return;
495
- }
496
-
497
- if (!hoveredBlockElement) {
466
+ if (!isMouseEvent && !isTouchEvent) {
498
467
  return;
499
468
  }
500
469
 
501
- const block = this.Blok.BlockManager.getBlockByChildNode(hoveredBlockElement);
470
+ const hoveredBlock = (event.target as Element | null)?.closest('[data-blok-testid="block-wrapper"]');
502
471
 
503
- if (!block) {
472
+ if (!hoveredBlock) {
504
473
  return;
505
474
  }
506
475
 
@@ -508,11 +477,18 @@ export class UI extends Module<UINodes> {
508
477
  * For multi-block selection, still emit 'block-hovered' event so toolbar can follow the hovered block.
509
478
  * The toolbar module will handle the logic of whether to move or not.
510
479
  */
511
- if (blockHoveredState.lastHoveredBlockId === block.id) {
480
+
481
+ if (blockHoveredState.lastHovered === hoveredBlock) {
512
482
  return;
513
483
  }
514
484
 
515
- blockHoveredState.lastHoveredBlockId = block.id;
485
+ blockHoveredState.lastHovered = hoveredBlock;
486
+
487
+ const block = this.Blok.BlockManager.getBlockByChildNode(hoveredBlock);
488
+
489
+ if (!block) {
490
+ return;
491
+ }
516
492
 
517
493
  this.eventsDispatcher.emit(BlockHovered, {
518
494
  block,
@@ -526,54 +502,13 @@ export class UI extends Module<UINodes> {
526
502
  20
527
503
  );
528
504
 
529
- /**
530
- * Listen on document to detect hover in the extended zone
531
- * which is outside the wrapper's bounds.
532
- * We filter events to only process those over the editor or in the hover zone.
533
- */
534
- this.readOnlyMutableListeners.on(document, 'mousemove', (event: Event) => {
505
+ this.readOnlyMutableListeners.on(this.nodes.redactor, 'mousemove', (event: Event) => {
535
506
  throttledHandleBlockHovered(event);
536
507
  }, {
537
508
  passive: true,
538
509
  });
539
510
  }
540
511
 
541
- /**
542
- * Finds a block by vertical position when cursor is in the extended hover zone.
543
- * The zone extends HOVER_ZONE_SIZE pixels from the content edge (left for LTR, right for RTL).
544
- * @param clientX - Cursor X position
545
- * @param clientY - Cursor Y position
546
- * @returns Block at the vertical position, or null if not in hover zone or no block found
547
- */
548
- private findBlockInHoverZone(clientX: number, clientY: number): Block | null {
549
- const contentRect = this.contentRect;
550
-
551
- /**
552
- * For LTR: check if cursor is within hover zone to the left of content
553
- * For RTL: check if cursor is within hover zone to the right of content
554
- */
555
- const isInHoverZone = this.isRtl
556
- ? clientX > contentRect.right && clientX <= contentRect.right + HOVER_ZONE_SIZE
557
- : clientX < contentRect.left && clientX >= contentRect.left - HOVER_ZONE_SIZE;
558
-
559
- if (!isInHoverZone) {
560
- return null;
561
- }
562
-
563
- /**
564
- * Find block by Y position
565
- */
566
- for (const block of this.Blok.BlockManager.blocks) {
567
- const rect = block.holder.getBoundingClientRect();
568
-
569
- if (clientY >= rect.top && clientY <= rect.bottom) {
570
- return block;
571
- }
572
- }
573
-
574
- return null;
575
- }
576
-
577
512
  /**
578
513
  * Unbind events that should work only in read-only mode
579
514
  */
@@ -7,19 +7,6 @@ import type { InlineToolAdapter as InlineToolAdapterInterface } from '@/types/to
7
7
  import type { BlockToolAdapter as BlockToolAdapterInterface } from '@/types/tools/adapters/block-tool-adapter';
8
8
  import type { BlockTuneAdapter as BlockTuneAdapterInterface } from '@/types/tools/adapters/block-tune-adapter';
9
9
 
10
- /**
11
- * Keys that are Blok-level settings (not passed to tool constructor)
12
- */
13
- const BLOK_SETTINGS_KEYS = new Set([
14
- 'class',
15
- 'inlineToolbar',
16
- 'tunes',
17
- 'shortcut',
18
- 'toolbox',
19
- 'config',
20
- 'isInternal',
21
- ]);
22
-
23
10
  /**
24
11
  * Enum of Tool options provided by user
25
12
  */
@@ -201,24 +188,10 @@ export abstract class BaseToolAdapter<Type extends ToolType = ToolType, ToolClas
201
188
  }
202
189
 
203
190
  /**
204
- * Returns Tool user configuration.
205
- * Extracts tool-specific options from flat config and merges with nested config.
191
+ * Returns Tool user configuration
206
192
  */
207
193
  public get settings(): ToolConfig {
208
- // eslint-disable-next-line @typescript-eslint/no-deprecated -- Internal: reading legacy config for backwards compatibility
209
- const nestedConfig = (this.config[UserSettings.Config] ?? {}) as ToolConfig;
210
-
211
- // Extract non-Blok keys as tool-specific config
212
- const flatConfig: Record<string, unknown> = {};
213
-
214
- for (const key of Object.keys(this.config)) {
215
- if (!BLOK_SETTINGS_KEYS.has(key)) {
216
- flatConfig[key] = this.config[key as keyof typeof this.config];
217
- }
218
- }
219
-
220
- // Merge: nested config first, flat config overrides
221
- const config = { ...nestedConfig, ...flatConfig } as ToolConfig;
194
+ const config = (this.config[UserSettings.Config] ?? {}) as ToolConfig;
222
195
 
223
196
  if (this.isDefault && !('placeholder' in config) && this.defaultPlaceholder) {
224
197
  config.placeholder = this.defaultPlaceholder;
@@ -51,22 +51,13 @@ export class BlockToolAdapter extends BaseToolAdapter<ToolType.Block, IBlockTool
51
51
  * @param readOnly - True if Blok is in read-only mode
52
52
  */
53
53
  public create(data: BlockToolData, block: BlockAPI, readOnly: boolean): IBlockTool {
54
- const toolboxEntries = this.toolbox;
55
-
56
- /**
57
- * Inject merged toolbox entries into config so tools can use them in renderSettings().
58
- * This allows tools like Header to show the same options in block settings as in the toolbox.
59
- */
60
- const configWithToolbox = toolboxEntries !== undefined
61
- ? { ...this.settings, _toolboxEntries: toolboxEntries }
62
- : this.settings;
63
54
 
64
55
  return new this.constructable({
65
56
  data,
66
57
  block,
67
58
  readOnly,
68
59
  api: this.api,
69
- config: configWithToolbox,
60
+ config: this.settings,
70
61
  }) as IBlockTool;
71
62
  }
72
63
 
@@ -203,18 +194,10 @@ export class BlockToolAdapter extends BaseToolAdapter<ToolType.Block, IBlockTool
203
194
  }
204
195
 
205
196
  /**
206
- * Returns enabled inline tools for Tool.
207
- * Defaults to true (all inline tools) unless explicitly set to false or array.
197
+ * Returns enabled inline tools for Tool
208
198
  */
209
199
  public get enabledInlineTools(): boolean | string[] {
210
- const setting = this.config[UserSettings.EnabledInlineTools];
211
-
212
- // Default to true if not specified
213
- if (setting === undefined) {
214
- return true;
215
- }
216
-
217
- return setting;
200
+ return this.config[UserSettings.EnabledInlineTools] || false;
218
201
  }
219
202
 
220
203
  /**
@@ -5,7 +5,6 @@ import { BlockTuneAdapter } from './tune';
5
5
  import { BlockToolAdapter } from './block';
6
6
  import type { API as ApiModule } from '../modules/api';
7
7
  import type { BlokConfig } from '../../../types/configs';
8
- import type { API as ApiMethods, I18n } from '../../../types';
9
8
 
10
9
  type ToolConstructor = typeof InlineToolAdapter | typeof BlockToolAdapter | typeof BlockTuneAdapter;
11
10
 
@@ -57,66 +56,18 @@ export class ToolsFactory {
57
56
  }
58
57
 
59
58
  const Constructor = this.getConstructor(constructable);
60
- const toolApi = this.createToolApi(name);
61
59
 
62
60
  return new Constructor({
63
61
  name,
64
62
  constructable,
65
63
  config,
66
- api: toolApi,
64
+ api: this.api.methods,
67
65
  isDefault: name === this.blokConfig.defaultBlock,
68
66
  defaultPlaceholder: this.blokConfig.placeholder,
69
67
  isInternal,
70
68
  });
71
69
  }
72
70
 
73
- /**
74
- * Creates a tool-specific API with namespaced i18n.
75
- *
76
- * EditorJS tools expect `api.i18n.t('key')` to automatically look up
77
- * `tools.{toolName}.key`. This wrapper provides that behavior while
78
- * falling back to direct key lookup for Blok internal tools that use
79
- * fully-qualified keys like `tools.stub.error`.
80
- *
81
- * @param toolName - Name of the tool
82
- * @returns API object with tool-namespaced i18n
83
- */
84
- private createToolApi(toolName: string): ApiMethods {
85
- const baseApi = this.api.methods;
86
- const namespace = `tools.${toolName}`;
87
-
88
- const namespacedI18n: I18n = {
89
- t: (dictKey: string): string => {
90
- /**
91
- * Try namespaced key first for EditorJS compatibility.
92
- * External tools call t('Add row') expecting lookup of 'tools.table.Add row'.
93
- */
94
- const namespacedKey = `${namespace}.${dictKey}`;
95
-
96
- if (baseApi.i18n.has(namespacedKey)) {
97
- return baseApi.i18n.t(namespacedKey);
98
- }
99
-
100
- /**
101
- * Fall back to direct key lookup for Blok internal tools.
102
- * Internal tools use fully-qualified keys like 'tools.stub.error'.
103
- */
104
- return baseApi.i18n.t(dictKey);
105
- },
106
-
107
- has: (dictKey: string): boolean => {
108
- const namespacedKey = `${namespace}.${dictKey}`;
109
-
110
- return baseApi.i18n.has(namespacedKey) || baseApi.i18n.has(dictKey);
111
- },
112
- };
113
-
114
- return {
115
- ...baseApi,
116
- i18n: namespacedI18n,
117
- };
118
- }
119
-
120
71
  /**
121
72
  * Find appropriate Tool object constructor for Tool constructable
122
73
  * @param constructable - Tools constructable