@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.
- package/dist/blok.mjs +2 -2
- package/dist/chunks/{blok-DK-97ZTf.mjs → blok-XA2L0_-K.mjs} +1216 -1178
- package/dist/chunks/{i18next-loader-CRollibS.mjs → i18next-loader-Ci2zhA-n.mjs} +1 -1
- package/dist/chunks/{index-jgHmMDND.mjs → index-R38OiQ_d.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-BIwvipPw.mjs → inline-tool-convert-e3PyuxB6.mjs} +88 -73
- package/dist/chunks/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
- package/dist/{messages-BPqWKx5Z.mjs → chunks/messages-49thXXGz.mjs} +16 -2
- package/dist/{messages-LvFKBBPa.mjs → chunks/messages-7W4d0DwD.mjs} +15 -1
- package/dist/{messages-Bn253WWC.mjs → chunks/messages-9SihnaXQ.mjs} +14 -0
- package/dist/{messages-Bf6Y3_GI.mjs → chunks/messages-B1Aww8q7.mjs} +16 -2
- package/dist/{messages-D00OjS2n.mjs → chunks/messages-B9fe4dQJ.mjs} +15 -1
- package/dist/{messages-pA5TvcAj.mjs → chunks/messages-BB5z9Uba.mjs} +14 -0
- package/dist/chunks/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
- package/dist/chunks/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
- package/dist/chunks/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
- package/dist/chunks/{messages-CQj2JU2j.mjs → messages-BGxiFoZf.mjs} +15 -1
- package/dist/{messages-B5puUm7R.mjs → chunks/messages-BL0tXcDf.mjs} +15 -1
- package/dist/{messages-CyDU5lz9.mjs → chunks/messages-BMv4xwIr.mjs} +16 -2
- package/dist/chunks/{messages-CkFT2gle.mjs → messages-BNe6LuHW.mjs} +14 -0
- package/dist/chunks/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
- package/dist/chunks/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
- package/dist/{messages-CXHd9SUK.mjs → chunks/messages-BYyy6Wqf.mjs} +14 -0
- package/dist/{messages-Cyi2AMmz.mjs → chunks/messages-Bfiw5w_W.mjs} +16 -2
- package/dist/chunks/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
- package/dist/chunks/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
- package/dist/chunks/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
- package/dist/chunks/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
- package/dist/chunks/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
- package/dist/chunks/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
- package/dist/{messages-CrsJ1TEJ.mjs → chunks/messages-CLhcMlTc.mjs} +15 -1
- package/dist/{messages-CnvW8Slp.mjs → chunks/messages-CMkNSDTo.mjs} +17 -3
- package/dist/chunks/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
- package/dist/chunks/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
- package/dist/chunks/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
- package/dist/chunks/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
- package/dist/{messages-Dg92dXZ5.mjs → chunks/messages-CvGLfqmV.mjs} +14 -0
- package/dist/{messages-AHESHJm_.mjs → chunks/messages-CzTufCHu.mjs} +14 -0
- package/dist/chunks/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
- package/dist/chunks/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
- package/dist/chunks/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
- package/dist/chunks/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
- package/dist/chunks/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
- package/dist/{messages-zSzDzXej.mjs → chunks/messages-DBRw-7Zc.mjs} +16 -2
- package/dist/chunks/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
- package/dist/{messages-DOlC_Tty.mjs → chunks/messages-DChXyvh2.mjs} +15 -1
- package/dist/chunks/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
- package/dist/{messages-DDLgIPDF.mjs → chunks/messages-DLfR5bMd.mjs} +16 -2
- package/dist/{messages-CbhuIWRJ.mjs → chunks/messages-DT4dP5uK.mjs} +15 -1
- package/dist/chunks/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
- package/dist/{messages-BlpqL8vG.mjs → chunks/messages-DjvaFRqx.mjs} +16 -2
- package/dist/{messages-BA0rcTCY.mjs → chunks/messages-DnIhyAJk.mjs} +18 -4
- package/dist/chunks/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
- package/dist/chunks/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
- package/dist/{messages-CJoBtXU6.mjs → chunks/messages-DqM1LFg5.mjs} +14 -0
- package/dist/chunks/{messages-CySyfkMU.mjs → messages-DsVNtdgM.mjs} +15 -1
- package/dist/chunks/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
- package/dist/chunks/{messages-Cu08aLS3.mjs → messages-EL5ARzmK.mjs} +16 -2
- package/dist/chunks/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
- package/dist/{messages-DY94ykcE.mjs → chunks/messages-LPVfA-8K.mjs} +14 -0
- package/dist/{messages-Cr-RJ7YB.mjs → chunks/messages-O5tQus_0.mjs} +14 -0
- package/dist/chunks/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
- package/dist/chunks/{messages-GC2PhgV3.mjs → messages-QtoE8uEv.mjs} +15 -1
- package/dist/chunks/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
- package/dist/chunks/{messages-zS1AXZ0y.mjs → messages-UX4gkere.mjs} +15 -1
- package/dist/{messages-CUy1vn-b.mjs → chunks/messages-Xq8UmkVs.mjs} +14 -0
- package/dist/chunks/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
- package/dist/chunks/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
- package/dist/chunks/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
- package/dist/chunks/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
- package/dist/chunks/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
- package/dist/chunks/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
- package/dist/{messages-BeUhMpsr.mjs → chunks/messages-wp_1b1hD.mjs} +15 -1
- package/dist/full.mjs +2 -2
- package/dist/locales.mjs +102 -88
- package/dist/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
- package/dist/{chunks/messages-BPqWKx5Z.mjs → messages-49thXXGz.mjs} +16 -2
- package/dist/{chunks/messages-LvFKBBPa.mjs → messages-7W4d0DwD.mjs} +15 -1
- package/dist/{chunks/messages-Bn253WWC.mjs → messages-9SihnaXQ.mjs} +14 -0
- package/dist/{chunks/messages-Bf6Y3_GI.mjs → messages-B1Aww8q7.mjs} +16 -2
- package/dist/{chunks/messages-D00OjS2n.mjs → messages-B9fe4dQJ.mjs} +15 -1
- package/dist/{chunks/messages-pA5TvcAj.mjs → messages-BB5z9Uba.mjs} +14 -0
- package/dist/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
- package/dist/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
- package/dist/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
- package/dist/{messages-CQj2JU2j.mjs → messages-BGxiFoZf.mjs} +15 -1
- package/dist/{chunks/messages-B5puUm7R.mjs → messages-BL0tXcDf.mjs} +15 -1
- package/dist/{chunks/messages-CyDU5lz9.mjs → messages-BMv4xwIr.mjs} +16 -2
- package/dist/{messages-CkFT2gle.mjs → messages-BNe6LuHW.mjs} +14 -0
- package/dist/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
- package/dist/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
- package/dist/{chunks/messages-CXHd9SUK.mjs → messages-BYyy6Wqf.mjs} +14 -0
- package/dist/{chunks/messages-Cyi2AMmz.mjs → messages-Bfiw5w_W.mjs} +16 -2
- package/dist/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
- package/dist/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
- package/dist/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
- package/dist/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
- package/dist/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
- package/dist/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
- package/dist/{chunks/messages-CrsJ1TEJ.mjs → messages-CLhcMlTc.mjs} +15 -1
- package/dist/{chunks/messages-CnvW8Slp.mjs → messages-CMkNSDTo.mjs} +17 -3
- package/dist/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
- package/dist/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
- package/dist/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
- package/dist/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
- package/dist/{chunks/messages-Dg92dXZ5.mjs → messages-CvGLfqmV.mjs} +14 -0
- package/dist/{chunks/messages-AHESHJm_.mjs → messages-CzTufCHu.mjs} +14 -0
- package/dist/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
- package/dist/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
- package/dist/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
- package/dist/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
- package/dist/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
- package/dist/{chunks/messages-zSzDzXej.mjs → messages-DBRw-7Zc.mjs} +16 -2
- package/dist/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
- package/dist/{chunks/messages-DOlC_Tty.mjs → messages-DChXyvh2.mjs} +15 -1
- package/dist/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
- package/dist/{chunks/messages-DDLgIPDF.mjs → messages-DLfR5bMd.mjs} +16 -2
- package/dist/{chunks/messages-CbhuIWRJ.mjs → messages-DT4dP5uK.mjs} +15 -1
- package/dist/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
- package/dist/{chunks/messages-BlpqL8vG.mjs → messages-DjvaFRqx.mjs} +16 -2
- package/dist/{chunks/messages-BA0rcTCY.mjs → messages-DnIhyAJk.mjs} +18 -4
- package/dist/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
- package/dist/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
- package/dist/{chunks/messages-CJoBtXU6.mjs → messages-DqM1LFg5.mjs} +14 -0
- package/dist/{messages-CySyfkMU.mjs → messages-DsVNtdgM.mjs} +15 -1
- package/dist/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
- package/dist/{messages-Cu08aLS3.mjs → messages-EL5ARzmK.mjs} +16 -2
- package/dist/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
- package/dist/{chunks/messages-DY94ykcE.mjs → messages-LPVfA-8K.mjs} +14 -0
- package/dist/{chunks/messages-Cr-RJ7YB.mjs → messages-O5tQus_0.mjs} +14 -0
- package/dist/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
- package/dist/{messages-GC2PhgV3.mjs → messages-QtoE8uEv.mjs} +15 -1
- package/dist/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
- package/dist/{messages-zS1AXZ0y.mjs → messages-UX4gkere.mjs} +15 -1
- package/dist/{chunks/messages-CUy1vn-b.mjs → messages-Xq8UmkVs.mjs} +14 -0
- package/dist/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
- package/dist/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
- package/dist/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
- package/dist/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
- package/dist/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
- package/dist/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
- package/dist/{chunks/messages-BeUhMpsr.mjs → messages-wp_1b1hD.mjs} +15 -1
- package/dist/tools.mjs +854 -719
- package/package.json +5 -9
- package/src/components/i18n/locales/am/messages.json +15 -1
- package/src/components/i18n/locales/ar/messages.json +14 -0
- package/src/components/i18n/locales/az/messages.json +14 -0
- package/src/components/i18n/locales/bg/messages.json +14 -0
- package/src/components/i18n/locales/bn/messages.json +15 -1
- package/src/components/i18n/locales/bs/messages.json +15 -1
- package/src/components/i18n/locales/cs/messages.json +14 -0
- package/src/components/i18n/locales/da/messages.json +14 -0
- package/src/components/i18n/locales/de/messages.json +14 -0
- package/src/components/i18n/locales/dv/messages.json +15 -1
- package/src/components/i18n/locales/el/messages.json +15 -1
- package/src/components/i18n/locales/en/messages.json +14 -0
- package/src/components/i18n/locales/es/messages.json +14 -0
- package/src/components/i18n/locales/et/messages.json +14 -0
- package/src/components/i18n/locales/fa/messages.json +15 -1
- package/src/components/i18n/locales/fi/messages.json +15 -1
- package/src/components/i18n/locales/fil/messages.json +14 -0
- package/src/components/i18n/locales/fr/messages.json +15 -1
- package/src/components/i18n/locales/gu/messages.json +15 -1
- package/src/components/i18n/locales/he/messages.json +14 -0
- package/src/components/i18n/locales/hi/messages.json +15 -1
- package/src/components/i18n/locales/hr/messages.json +14 -0
- package/src/components/i18n/locales/hu/messages.json +14 -0
- package/src/components/i18n/locales/hy/messages.json +16 -2
- package/src/components/i18n/locales/id/messages.json +16 -2
- package/src/components/i18n/locales/it/messages.json +14 -0
- package/src/components/i18n/locales/ja/messages.json +14 -0
- package/src/components/i18n/locales/ka/messages.json +15 -1
- package/src/components/i18n/locales/km/messages.json +16 -2
- package/src/components/i18n/locales/kn/messages.json +16 -2
- package/src/components/i18n/locales/ko/messages.json +14 -0
- package/src/components/i18n/locales/ku/messages.json +16 -2
- package/src/components/i18n/locales/lo/messages.json +15 -1
- package/src/components/i18n/locales/lt/messages.json +15 -1
- package/src/components/i18n/locales/lv/messages.json +15 -1
- package/src/components/i18n/locales/mk/messages.json +16 -2
- package/src/components/i18n/locales/ml/messages.json +16 -2
- package/src/components/i18n/locales/mn/messages.json +16 -2
- package/src/components/i18n/locales/mr/messages.json +15 -1
- package/src/components/i18n/locales/ms/messages.json +16 -2
- package/src/components/i18n/locales/my/messages.json +16 -2
- package/src/components/i18n/locales/ne/messages.json +15 -1
- package/src/components/i18n/locales/nl/messages.json +15 -1
- package/src/components/i18n/locales/no/messages.json +16 -2
- package/src/components/i18n/locales/pa/messages.json +15 -1
- package/src/components/i18n/locales/pl/messages.json +14 -0
- package/src/components/i18n/locales/ps/messages.json +17 -3
- package/src/components/i18n/locales/pt/messages.json +14 -0
- package/src/components/i18n/locales/ro/messages.json +15 -1
- package/src/components/i18n/locales/ru/messages.json +14 -0
- package/src/components/i18n/locales/sd/messages.json +16 -2
- package/src/components/i18n/locales/si/messages.json +15 -1
- package/src/components/i18n/locales/sk/messages.json +15 -1
- package/src/components/i18n/locales/sl/messages.json +16 -2
- package/src/components/i18n/locales/sq/messages.json +16 -2
- package/src/components/i18n/locales/sr/messages.json +16 -2
- package/src/components/i18n/locales/sv/messages.json +16 -2
- package/src/components/i18n/locales/sw/messages.json +16 -2
- package/src/components/i18n/locales/ta/messages.json +16 -2
- package/src/components/i18n/locales/te/messages.json +15 -1
- package/src/components/i18n/locales/th/messages.json +15 -1
- package/src/components/i18n/locales/tr/messages.json +15 -1
- package/src/components/i18n/locales/ug/messages.json +16 -2
- package/src/components/i18n/locales/uk/messages.json +15 -1
- package/src/components/i18n/locales/ur/messages.json +15 -1
- package/src/components/i18n/locales/vi/messages.json +16 -2
- package/src/components/i18n/locales/yi/messages.json +16 -2
- package/src/components/i18n/locales/zh/messages.json +15 -1
- package/src/components/modules/api/blocks.ts +17 -2
- package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +12 -1
- package/src/components/modules/toolbar/index.ts +29 -7
- package/src/components/modules/ui.ts +46 -68
- package/src/components/modules/uiControllers/controllers/blockHover.ts +40 -61
- package/src/components/ui/toolbox.ts +41 -6
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +3 -1
- package/src/components/utils/popover/popover-desktop.ts +27 -8
- package/src/tools/table/index.ts +67 -70
- package/src/tools/table/table-add-controls.ts +25 -7
- package/src/tools/table/table-cell-blocks.ts +62 -0
- package/src/tools/table/table-cell-selection.ts +70 -46
- package/src/tools/table/table-core.ts +20 -15
- package/src/tools/table/table-grip-visuals.ts +4 -4
- package/src/tools/table/table-operations.ts +22 -12
- package/src/tools/table/table-restrictions.ts +64 -0
- package/src/tools/table/table-row-col-action-handler.ts +190 -0
- package/src/tools/table/table-row-col-controls.ts +91 -182
- package/src/tools/table/table-row-col-drag.ts +4 -4
- package/src/tools/table/table-row-col-popover.ts +225 -0
- package/src/tools/table/types.ts +2 -0
- 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
|
|
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
|
|
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
|
|
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
|
|
323
|
+
const unresolvedBlock = block ?? this.Blok.BlockManager.currentBlock;
|
|
324
324
|
|
|
325
|
-
if (!
|
|
325
|
+
if (!unresolvedBlock) {
|
|
326
326
|
return;
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
|
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
|
-
*
|
|
455
|
+
* Create dedicated bottom zone element
|
|
456
456
|
*/
|
|
457
|
-
this.nodes.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
614
|
-
*
|
|
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
|
|
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 (
|
|
634
|
-
|
|
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
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
openTab(validUrl);
|
|
656
|
+
Caret.setToTheLastBlock();
|
|
657
|
+
Toolbar.moveAndOpen(BlockManager.lastBlock);
|
|
651
658
|
}
|
|
652
659
|
|
|
653
660
|
/**
|
|
654
|
-
*
|
|
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
|
|
660
|
-
const
|
|
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 (!
|
|
667
|
+
if (!$.isAnchor(element) || !ctrlKey) {
|
|
682
668
|
return;
|
|
683
669
|
}
|
|
684
670
|
|
|
685
671
|
event.stopImmediatePropagation();
|
|
686
672
|
event.stopPropagation();
|
|
687
673
|
|
|
688
|
-
const
|
|
674
|
+
const href = element.getAttribute('href');
|
|
689
675
|
|
|
690
|
-
|
|
691
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
|
147
|
-
*
|
|
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
|
|
159
|
-
*
|
|
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
|
|
166
|
-
const
|
|
130
|
+
private emitNearestBlockHovered(clientY: number): void {
|
|
131
|
+
const nearestBlock = this.findNearestBlock(clientY);
|
|
167
132
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
}
|
|
165
|
+
return distance < nearest.distance ? { block, distance } : nearest;
|
|
166
|
+
}, { block: blocks[0], distance: Infinity });
|
|
188
167
|
|
|
189
|
-
return
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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-
|
|
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
|
|
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 =
|
|
238
|
-
const shouldFlipTop = (
|
|
239
|
-
(
|
|
240
|
-
const top = shouldFlipTop ?
|
|
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 =
|
|
261
|
+
const initialLeft = rect.left + window.scrollX;
|
|
243
262
|
const shouldFlipLeft = initialLeft + popoverRect.width > windowWidth + window.scrollX;
|
|
244
|
-
const left = shouldFlipLeft ? Math.max(0,
|
|
263
|
+
const left = shouldFlipLeft ? Math.max(0, rect.right - popoverRect.width + window.scrollX) : initialLeft;
|
|
245
264
|
|
|
246
265
|
return {
|
|
247
266
|
top,
|