@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.
- package/README.md +5 -7
- package/dist/blok.mjs +2 -2
- package/dist/chunks/{blok-D85C_iyk.mjs → blok-BmjQP37u.mjs} +1726 -1849
- package/dist/chunks/{i18next-loader-exc8oN3J.mjs → i18next-loader-DjtwmuRK.mjs} +1 -1
- package/dist/chunks/{index-fqgWb6Ue.mjs → index-TdePW2Yb.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-CYkcoF1r.mjs → inline-tool-convert-CreNXc4T.mjs} +8 -8
- package/dist/{messages-82j7Sb1f.mjs → chunks/messages-2434tVOK.mjs} +1 -1
- package/dist/chunks/{messages-D-tDNAzW.mjs → messages-3DcCwXMF.mjs} +1 -1
- package/dist/{messages-DIbeBo-6.mjs → chunks/messages-4kMwVAKY.mjs} +1 -1
- package/dist/{messages-CjksZqgf.mjs → chunks/messages-57uL5htT.mjs} +1 -1
- package/dist/chunks/{messages-BgmPDL9Z.mjs → messages-76-iJV9Q.mjs} +1 -1
- package/dist/{messages-DkJ5aV3V.mjs → chunks/messages-8p86Eyf2.mjs} +1 -1
- package/dist/chunks/{messages-TulYnz1f.mjs → messages-BBX0p0Pi.mjs} +1 -1
- package/dist/chunks/{messages-CVvHbBlx.mjs → messages-BCm2eudQ.mjs} +1 -1
- package/dist/chunks/{messages--yMo5vYp.mjs → messages-BFiUomgG.mjs} +1 -1
- package/dist/chunks/{messages-BXsoyz5-.mjs → messages-BIPNHHAV.mjs} +1 -1
- package/dist/chunks/{messages-DhdzbzrS.mjs → messages-BUlwu9mo.mjs} +1 -1
- package/dist/chunks/{messages-DRTt_xBc.mjs → messages-BX-DPa-z.mjs} +1 -1
- package/dist/chunks/{messages-Bi0X1QMU.mjs → messages-BextV3Qh.mjs} +1 -1
- package/dist/{messages-D9xzl8Wn.mjs → chunks/messages-BiPSFlUG.mjs} +1 -1
- package/dist/chunks/{messages-CoY-hJgp.mjs → messages-BiXe9G-O.mjs} +1 -1
- package/dist/{messages-Dw5GZ4YT.mjs → chunks/messages-Bl5z_Igo.mjs} +1 -1
- package/dist/{messages-KLzTvDED.mjs → chunks/messages-BnsE97ku.mjs} +1 -1
- package/dist/chunks/{messages-DG2QXu_f.mjs → messages-BoO8gsVD.mjs} +1 -1
- package/dist/{messages-CbtBGtJT.mjs → chunks/messages-BqWaOGMn.mjs} +1 -1
- package/dist/chunks/{messages-CcYGSGRh.mjs → messages-BqkL2_Ro.mjs} +1 -1
- package/dist/{messages-qFesO1Lu.mjs → chunks/messages-BvCkXKX-.mjs} +1 -1
- package/dist/{messages-Df6LYOt5.mjs → chunks/messages-C6tbPLoj.mjs} +1 -1
- package/dist/chunks/{messages-dIzxSHR2.mjs → messages-CA6T3-gQ.mjs} +1 -1
- package/dist/{messages-zs9AgeBF.mjs → chunks/messages-CFFPFdWP.mjs} +1 -1
- package/dist/{messages-Cm4WhO4g.mjs → chunks/messages-CFrKE-TN.mjs} +1 -1
- package/dist/chunks/{messages-D8sk1mxH.mjs → messages-CHz8VlG-.mjs} +1 -1
- package/dist/chunks/{messages-HSxl9MoN.mjs → messages-CLixzySl.mjs} +1 -1
- package/dist/{messages-DT43ZUKr.mjs → chunks/messages-CV7OM_qk.mjs} +1 -1
- package/dist/chunks/{messages-BYeiscyc.mjs → messages-CXHt3eCC.mjs} +1 -1
- package/dist/chunks/{messages-CTeYgNo1.mjs → messages-CbmsBrB0.mjs} +1 -1
- package/dist/chunks/{messages-DiyoZ_Oa.mjs → messages-Ceo1KtFx.mjs} +1 -1
- package/dist/{messages-D8VsV_Ro.mjs → chunks/messages-Cm0LJLtB.mjs} +1 -1
- package/dist/chunks/{messages-BaaIMBL8.mjs → messages-CmymP_Ar.mjs} +1 -1
- package/dist/chunks/{messages-Uexhy7C9.mjs → messages-D0ohMB5H.mjs} +1 -1
- package/dist/{messages-CbP4KoKV.mjs → chunks/messages-D3GrDwXh.mjs} +1 -1
- package/dist/{messages-CNRsIuSS.mjs → chunks/messages-D3vTzIpL.mjs} +1 -1
- package/dist/{messages-B-b_IFZh.mjs → chunks/messages-D5WeksbV.mjs} +1 -1
- package/dist/chunks/{messages-DHdkT1vy.mjs → messages-DGaab4EP.mjs} +1 -1
- package/dist/{messages-CwYueRo5.mjs → chunks/messages-DKha57ZU.mjs} +1 -1
- package/dist/chunks/{messages-JztkG3tZ.mjs → messages-DOaujgMW.mjs} +1 -1
- package/dist/chunks/{messages-DR0sRlko.mjs → messages-DVbPLd_0.mjs} +1 -1
- package/dist/chunks/{messages-BnmcUH66.mjs → messages-D_FCyfW6.mjs} +1 -1
- package/dist/chunks/{messages-BgbVziWf.mjs → messages-Dd5iZN3c.mjs} +1 -1
- package/dist/{messages-D2h_bTrn.mjs → chunks/messages-DehM7135.mjs} +1 -1
- package/dist/chunks/{messages-CbepBt3K.mjs → messages-Dg1OHftD.mjs} +1 -1
- package/dist/{messages-DT5djAjs.mjs → chunks/messages-Di6Flq-b.mjs} +1 -1
- package/dist/chunks/{messages-ctRNTfv5.mjs → messages-Dqhhex6e.mjs} +1 -1
- package/dist/chunks/{messages-Bo9JrN9m.mjs → messages-DueVe0F1.mjs} +1 -1
- package/dist/chunks/{messages-DvwZEFTL.mjs → messages-Dx3eFwI0.mjs} +1 -1
- package/dist/chunks/{messages-jmh1Gbfd.mjs → messages-FOtiUoKl.mjs} +1 -1
- package/dist/{messages-B7zIiLTq.mjs → chunks/messages-FTOZNhRD.mjs} +1 -1
- package/dist/chunks/{messages-D5J2Xlpx.mjs → messages-IQxGfQIV.mjs} +1 -1
- package/dist/chunks/{messages-BCidD-VB.mjs → messages-JF2fzCkK.mjs} +1 -1
- package/dist/chunks/{messages-D8tlQmPj.mjs → messages-MOGl7I5v.mjs} +1 -1
- package/dist/chunks/{messages-BjZll4R7.mjs → messages-QgYhPL-3.mjs} +1 -1
- package/dist/{messages-BWDnoNq0.mjs → chunks/messages-WYWIbQwo.mjs} +1 -1
- package/dist/chunks/{messages-oO_lJ-_I.mjs → messages-a6A_LgDv.mjs} +1 -1
- package/dist/chunks/{messages-g7Njot5w.mjs → messages-bSf31LJi.mjs} +1 -1
- package/dist/chunks/{messages-sSYZ0Mz9.mjs → messages-diGozhTn.mjs} +1 -1
- package/dist/chunks/{messages-BZ-Ia4tk.mjs → messages-er-kd-VO.mjs} +1 -1
- package/dist/chunks/{messages-B5OIvtYB.mjs → messages-ez3w5NBn.mjs} +1 -1
- package/dist/chunks/{messages-BuKgyEeU.mjs → messages-f3uXjegd.mjs} +1 -1
- package/dist/{messages-CJQt8nzO.mjs → chunks/messages-ohwI1UGv.mjs} +1 -1
- package/dist/{messages-9-pnvSWZ.mjs → chunks/messages-p9BZJaFV.mjs} +1 -1
- package/dist/{messages-CpkO-V0C.mjs → chunks/messages-qIQ4L4rw.mjs} +1 -1
- package/dist/{messages-CPdlHIEi.mjs → chunks/messages-qWkXPggi.mjs} +1 -1
- package/dist/chunks/{messages-iNIhRBkQ.mjs → messages-w5foGze_.mjs} +1 -1
- package/dist/full.mjs +2 -2
- package/dist/locales.mjs +68 -68
- package/dist/{chunks/messages-82j7Sb1f.mjs → messages-2434tVOK.mjs} +1 -1
- package/dist/{messages-D-tDNAzW.mjs → messages-3DcCwXMF.mjs} +1 -1
- package/dist/{chunks/messages-DIbeBo-6.mjs → messages-4kMwVAKY.mjs} +1 -1
- package/dist/{chunks/messages-CjksZqgf.mjs → messages-57uL5htT.mjs} +1 -1
- package/dist/{messages-BgmPDL9Z.mjs → messages-76-iJV9Q.mjs} +1 -1
- package/dist/{chunks/messages-DkJ5aV3V.mjs → messages-8p86Eyf2.mjs} +1 -1
- package/dist/{messages-TulYnz1f.mjs → messages-BBX0p0Pi.mjs} +1 -1
- package/dist/{messages-CVvHbBlx.mjs → messages-BCm2eudQ.mjs} +1 -1
- package/dist/{messages--yMo5vYp.mjs → messages-BFiUomgG.mjs} +1 -1
- package/dist/{messages-BXsoyz5-.mjs → messages-BIPNHHAV.mjs} +1 -1
- package/dist/{messages-DhdzbzrS.mjs → messages-BUlwu9mo.mjs} +1 -1
- package/dist/{messages-DRTt_xBc.mjs → messages-BX-DPa-z.mjs} +1 -1
- package/dist/{messages-Bi0X1QMU.mjs → messages-BextV3Qh.mjs} +1 -1
- package/dist/{chunks/messages-D9xzl8Wn.mjs → messages-BiPSFlUG.mjs} +1 -1
- package/dist/{messages-CoY-hJgp.mjs → messages-BiXe9G-O.mjs} +1 -1
- package/dist/{chunks/messages-Dw5GZ4YT.mjs → messages-Bl5z_Igo.mjs} +1 -1
- package/dist/{chunks/messages-KLzTvDED.mjs → messages-BnsE97ku.mjs} +1 -1
- package/dist/{messages-DG2QXu_f.mjs → messages-BoO8gsVD.mjs} +1 -1
- package/dist/{chunks/messages-CbtBGtJT.mjs → messages-BqWaOGMn.mjs} +1 -1
- package/dist/{messages-CcYGSGRh.mjs → messages-BqkL2_Ro.mjs} +1 -1
- package/dist/{chunks/messages-qFesO1Lu.mjs → messages-BvCkXKX-.mjs} +1 -1
- package/dist/{chunks/messages-Df6LYOt5.mjs → messages-C6tbPLoj.mjs} +1 -1
- package/dist/{messages-dIzxSHR2.mjs → messages-CA6T3-gQ.mjs} +1 -1
- package/dist/{chunks/messages-zs9AgeBF.mjs → messages-CFFPFdWP.mjs} +1 -1
- package/dist/{chunks/messages-Cm4WhO4g.mjs → messages-CFrKE-TN.mjs} +1 -1
- package/dist/{messages-D8sk1mxH.mjs → messages-CHz8VlG-.mjs} +1 -1
- package/dist/{messages-HSxl9MoN.mjs → messages-CLixzySl.mjs} +1 -1
- package/dist/{chunks/messages-DT43ZUKr.mjs → messages-CV7OM_qk.mjs} +1 -1
- package/dist/{messages-BYeiscyc.mjs → messages-CXHt3eCC.mjs} +1 -1
- package/dist/{messages-CTeYgNo1.mjs → messages-CbmsBrB0.mjs} +1 -1
- package/dist/{messages-DiyoZ_Oa.mjs → messages-Ceo1KtFx.mjs} +1 -1
- package/dist/{chunks/messages-D8VsV_Ro.mjs → messages-Cm0LJLtB.mjs} +1 -1
- package/dist/{messages-BaaIMBL8.mjs → messages-CmymP_Ar.mjs} +1 -1
- package/dist/{messages-Uexhy7C9.mjs → messages-D0ohMB5H.mjs} +1 -1
- package/dist/{chunks/messages-CbP4KoKV.mjs → messages-D3GrDwXh.mjs} +1 -1
- package/dist/{chunks/messages-CNRsIuSS.mjs → messages-D3vTzIpL.mjs} +1 -1
- package/dist/{chunks/messages-B-b_IFZh.mjs → messages-D5WeksbV.mjs} +1 -1
- package/dist/{messages-DHdkT1vy.mjs → messages-DGaab4EP.mjs} +1 -1
- package/dist/{chunks/messages-CwYueRo5.mjs → messages-DKha57ZU.mjs} +1 -1
- package/dist/{messages-JztkG3tZ.mjs → messages-DOaujgMW.mjs} +1 -1
- package/dist/{messages-DR0sRlko.mjs → messages-DVbPLd_0.mjs} +1 -1
- package/dist/{messages-BnmcUH66.mjs → messages-D_FCyfW6.mjs} +1 -1
- package/dist/{messages-BgbVziWf.mjs → messages-Dd5iZN3c.mjs} +1 -1
- package/dist/{chunks/messages-D2h_bTrn.mjs → messages-DehM7135.mjs} +1 -1
- package/dist/{messages-CbepBt3K.mjs → messages-Dg1OHftD.mjs} +1 -1
- package/dist/{chunks/messages-DT5djAjs.mjs → messages-Di6Flq-b.mjs} +1 -1
- package/dist/{messages-ctRNTfv5.mjs → messages-Dqhhex6e.mjs} +1 -1
- package/dist/{messages-Bo9JrN9m.mjs → messages-DueVe0F1.mjs} +1 -1
- package/dist/{messages-DvwZEFTL.mjs → messages-Dx3eFwI0.mjs} +1 -1
- package/dist/{messages-jmh1Gbfd.mjs → messages-FOtiUoKl.mjs} +1 -1
- package/dist/{chunks/messages-B7zIiLTq.mjs → messages-FTOZNhRD.mjs} +1 -1
- package/dist/{messages-D5J2Xlpx.mjs → messages-IQxGfQIV.mjs} +1 -1
- package/dist/{messages-BCidD-VB.mjs → messages-JF2fzCkK.mjs} +1 -1
- package/dist/{messages-D8tlQmPj.mjs → messages-MOGl7I5v.mjs} +1 -1
- package/dist/{messages-BjZll4R7.mjs → messages-QgYhPL-3.mjs} +1 -1
- package/dist/{chunks/messages-BWDnoNq0.mjs → messages-WYWIbQwo.mjs} +1 -1
- package/dist/{messages-oO_lJ-_I.mjs → messages-a6A_LgDv.mjs} +1 -1
- package/dist/{messages-g7Njot5w.mjs → messages-bSf31LJi.mjs} +1 -1
- package/dist/{messages-sSYZ0Mz9.mjs → messages-diGozhTn.mjs} +1 -1
- package/dist/{messages-BZ-Ia4tk.mjs → messages-er-kd-VO.mjs} +1 -1
- package/dist/{messages-B5OIvtYB.mjs → messages-ez3w5NBn.mjs} +1 -1
- package/dist/{messages-BuKgyEeU.mjs → messages-f3uXjegd.mjs} +1 -1
- package/dist/{chunks/messages-CJQt8nzO.mjs → messages-ohwI1UGv.mjs} +1 -1
- package/dist/{chunks/messages-9-pnvSWZ.mjs → messages-p9BZJaFV.mjs} +1 -1
- package/dist/{chunks/messages-CpkO-V0C.mjs → messages-qIQ4L4rw.mjs} +1 -1
- package/dist/{chunks/messages-CPdlHIEi.mjs → messages-qWkXPggi.mjs} +1 -1
- package/dist/{messages-iNIhRBkQ.mjs → messages-w5foGze_.mjs} +1 -1
- package/dist/tools.mjs +90 -131
- package/package.json +1 -1
- package/src/components/i18n/locales/am/messages.json +1 -1
- package/src/components/i18n/locales/ar/messages.json +1 -1
- package/src/components/i18n/locales/az/messages.json +1 -1
- package/src/components/i18n/locales/bg/messages.json +1 -1
- package/src/components/i18n/locales/bn/messages.json +1 -1
- package/src/components/i18n/locales/bs/messages.json +1 -1
- package/src/components/i18n/locales/cs/messages.json +1 -1
- package/src/components/i18n/locales/da/messages.json +1 -1
- package/src/components/i18n/locales/de/messages.json +1 -1
- package/src/components/i18n/locales/dv/messages.json +1 -1
- package/src/components/i18n/locales/el/messages.json +1 -1
- package/src/components/i18n/locales/en/messages.json +1 -1
- package/src/components/i18n/locales/es/messages.json +1 -1
- package/src/components/i18n/locales/et/messages.json +1 -1
- package/src/components/i18n/locales/fa/messages.json +1 -1
- package/src/components/i18n/locales/fi/messages.json +1 -1
- package/src/components/i18n/locales/fil/messages.json +1 -1
- package/src/components/i18n/locales/fr/messages.json +1 -1
- package/src/components/i18n/locales/gu/messages.json +1 -1
- package/src/components/i18n/locales/he/messages.json +1 -1
- package/src/components/i18n/locales/hi/messages.json +1 -1
- package/src/components/i18n/locales/hr/messages.json +1 -1
- package/src/components/i18n/locales/hu/messages.json +1 -1
- package/src/components/i18n/locales/hy/messages.json +1 -1
- package/src/components/i18n/locales/id/messages.json +1 -1
- package/src/components/i18n/locales/it/messages.json +1 -1
- package/src/components/i18n/locales/ja/messages.json +1 -1
- package/src/components/i18n/locales/ka/messages.json +1 -1
- package/src/components/i18n/locales/km/messages.json +1 -1
- package/src/components/i18n/locales/kn/messages.json +1 -1
- package/src/components/i18n/locales/ko/messages.json +1 -1
- package/src/components/i18n/locales/ku/messages.json +1 -1
- package/src/components/i18n/locales/lo/messages.json +1 -1
- package/src/components/i18n/locales/lt/messages.json +1 -1
- package/src/components/i18n/locales/lv/messages.json +1 -1
- package/src/components/i18n/locales/mk/messages.json +1 -1
- package/src/components/i18n/locales/ml/messages.json +1 -1
- package/src/components/i18n/locales/mn/messages.json +1 -1
- package/src/components/i18n/locales/mr/messages.json +1 -1
- package/src/components/i18n/locales/ms/messages.json +1 -1
- package/src/components/i18n/locales/my/messages.json +1 -1
- package/src/components/i18n/locales/ne/messages.json +1 -1
- package/src/components/i18n/locales/nl/messages.json +1 -1
- package/src/components/i18n/locales/no/messages.json +1 -1
- package/src/components/i18n/locales/pa/messages.json +1 -1
- package/src/components/i18n/locales/pl/messages.json +1 -1
- package/src/components/i18n/locales/ps/messages.json +1 -1
- package/src/components/i18n/locales/pt/messages.json +1 -1
- package/src/components/i18n/locales/ro/messages.json +1 -1
- package/src/components/i18n/locales/ru/messages.json +1 -1
- package/src/components/i18n/locales/sd/messages.json +1 -1
- package/src/components/i18n/locales/si/messages.json +1 -1
- package/src/components/i18n/locales/sk/messages.json +1 -1
- package/src/components/i18n/locales/sl/messages.json +1 -1
- package/src/components/i18n/locales/sq/messages.json +1 -1
- package/src/components/i18n/locales/sr/messages.json +1 -1
- package/src/components/i18n/locales/sv/messages.json +1 -1
- package/src/components/i18n/locales/sw/messages.json +1 -1
- package/src/components/i18n/locales/ta/messages.json +1 -1
- package/src/components/i18n/locales/te/messages.json +1 -1
- package/src/components/i18n/locales/th/messages.json +1 -1
- package/src/components/i18n/locales/tr/messages.json +1 -1
- package/src/components/i18n/locales/ug/messages.json +1 -1
- package/src/components/i18n/locales/uk/messages.json +1 -1
- package/src/components/i18n/locales/ur/messages.json +1 -1
- package/src/components/i18n/locales/vi/messages.json +1 -1
- package/src/components/i18n/locales/yi/messages.json +1 -1
- package/src/components/i18n/locales/zh/messages.json +1 -1
- package/src/components/modules/api/i18n.ts +0 -1
- package/src/components/modules/dragManager.ts +13 -71
- package/src/components/modules/i18n.ts +11 -6
- package/src/components/modules/rectangleSelection.ts +19 -62
- package/src/components/modules/toolbar/index.ts +2 -2
- package/src/components/modules/tools.ts +3 -39
- package/src/components/modules/ui.ts +18 -83
- package/src/components/tools/base.ts +2 -29
- package/src/components/tools/block.ts +3 -20
- package/src/components/tools/factory.ts +1 -50
- package/src/tools/header/index.ts +0 -82
- package/src/tools/index.ts +6 -13
- package/src/tools/list/index.ts +2 -2
- package/types/api/i18n.d.ts +0 -8
- 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
|
|
430
|
-
const
|
|
427
|
+
// Find block holder
|
|
428
|
+
const blockHolder = elementUnderCursor.closest(createSelector(DATA_ATTR.element)) as HTMLElement | null;
|
|
431
429
|
|
|
432
|
-
if (!blockHolder
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
1001
|
+
* Do not move toolbar during drag operations
|
|
1002
1002
|
*/
|
|
1003
|
-
if (this.Blok.DragManager.isDragging
|
|
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:
|
|
337
|
+
config: (settings.config ?? {}) as ToolConfig,
|
|
338
338
|
};
|
|
339
339
|
|
|
340
340
|
const prepareFunction: ChainData['function'] = async (payload?: unknown) => {
|
|
341
|
-
const constructable = settings.class
|
|
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: {
|
|
467
|
-
|
|
458
|
+
const blockHoveredState: { lastHovered: Element | null } = {
|
|
459
|
+
lastHovered: null,
|
|
468
460
|
};
|
|
469
461
|
|
|
470
462
|
const handleBlockHovered = (event: Event): void => {
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
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
|
|
470
|
+
const hoveredBlock = (event.target as Element | null)?.closest('[data-blok-testid="block-wrapper"]');
|
|
502
471
|
|
|
503
|
-
if (!
|
|
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
|
-
|
|
480
|
+
|
|
481
|
+
if (blockHoveredState.lastHovered === hoveredBlock) {
|
|
512
482
|
return;
|
|
513
483
|
}
|
|
514
484
|
|
|
515
|
-
blockHoveredState.
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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
|