@jackuait/blok 0.6.0-beta.0 → 0.6.0-beta.10
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 +16 -169
- package/bin/blok.mjs +10 -0
- package/dist/blok.mjs +2 -2
- package/dist/chunks/{blok-Bu9S3SsR.mjs → blok-Buf0btS7.mjs} +2267 -2024
- package/dist/chunks/{i18next-loader-CKuXJ0Av.mjs → i18next-loader-CVf_ZfwA.mjs} +1 -1
- package/dist/chunks/{index-jtZaryNw.mjs → index-C6jsfLLp.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-CFjyrH30.mjs → inline-tool-convert-BKKEoOqB.mjs} +710 -570
- package/dist/chunks/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
- package/dist/chunks/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
- 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-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/{messages-B5puUm7R.mjs → chunks/messages-BL0tXcDf.mjs} +15 -1
- package/dist/chunks/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
- package/dist/{messages-CyDU5lz9.mjs → chunks/messages-BMv4xwIr.mjs} +16 -2
- package/dist/chunks/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
- 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/chunks/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
- 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-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
- package/dist/chunks/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
- package/dist/chunks/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
- package/dist/chunks/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
- package/dist/chunks/messages-CKI54h6O.mjs +62 -0
- package/dist/{messages-CrsJ1TEJ.mjs → chunks/messages-CLhcMlTc.mjs} +15 -1
- package/dist/{messages-CnvW8Slp.mjs → chunks/messages-CMkNSDTo.mjs} +17 -3
- package/dist/{messages-BlpqL8vG.mjs → chunks/messages-CQwpzUFp.mjs} +19 -5
- package/dist/chunks/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
- 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/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-BPqWKx5Z.mjs → chunks/messages-Diu6jAaR.mjs} +17 -3
- 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-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
- package/dist/chunks/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
- package/dist/chunks/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
- 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-2_xedlYw.mjs → messages-R3hUSvr3.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/cli.mjs +50 -0
- package/dist/full.mjs +15 -15
- package/dist/locales.mjs +102 -88
- package/dist/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
- package/dist/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
- 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-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/{chunks/messages-B5puUm7R.mjs → messages-BL0tXcDf.mjs} +15 -1
- package/dist/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
- package/dist/{chunks/messages-CyDU5lz9.mjs → messages-BMv4xwIr.mjs} +16 -2
- package/dist/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
- 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/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
- 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-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
- package/dist/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
- package/dist/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
- package/dist/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
- package/dist/messages-CKI54h6O.mjs +62 -0
- package/dist/{chunks/messages-CrsJ1TEJ.mjs → messages-CLhcMlTc.mjs} +15 -1
- package/dist/{chunks/messages-CnvW8Slp.mjs → messages-CMkNSDTo.mjs} +17 -3
- package/dist/{chunks/messages-BlpqL8vG.mjs → messages-CQwpzUFp.mjs} +19 -5
- package/dist/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
- 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/{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-BPqWKx5Z.mjs → messages-Diu6jAaR.mjs} +17 -3
- 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-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
- package/dist/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
- package/dist/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
- 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-2_xedlYw.mjs → messages-R3hUSvr3.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/tools.mjs +2005 -1267
- package/dist/vendor.LICENSE.txt +1 -1
- package/package.json +15 -14
- package/src/cli/commands/migration.ts +16 -0
- package/src/cli/commands/migrationContent.ts +6 -0
- package/src/cli/index.ts +47 -0
- package/src/cli/utils/output.ts +10 -0
- package/src/components/block-tunes/block-tune-delete.ts +3 -2
- package/src/components/blocks.ts +23 -6
- package/src/components/constants/data-attributes.ts +2 -0
- 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 +25 -11
- 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 +20 -6
- 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 +23 -9
- 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 +19 -5
- 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 +24 -10
- package/src/components/i18n/locales/ms/messages.json +17 -3
- package/src/components/i18n/locales/my/messages.json +16 -2
- package/src/components/i18n/locales/ne/messages.json +24 -10
- 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 +23 -9
- 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 +21 -7
- package/src/components/i18n/locales/te/messages.json +40 -26
- package/src/components/i18n/locales/th/messages.json +19 -5
- 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 +25 -11
- package/src/components/i18n/locales/yi/messages.json +16 -2
- package/src/components/i18n/locales/zh/messages.json +15 -1
- package/src/components/icons/index.ts +104 -83
- package/src/components/modules/api/blocks.ts +35 -2
- package/src/components/modules/api/history.ts +64 -0
- package/src/components/modules/api/index.ts +2 -0
- package/src/components/modules/api/readonly.ts +11 -1
- package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +12 -1
- package/src/components/modules/blockManager/blockManager.ts +7 -0
- package/src/components/modules/blockManager/operations.ts +3 -2
- package/src/components/modules/blockManager/types.ts +3 -1
- package/src/components/modules/blockManager/yjs-sync.ts +12 -2
- package/src/components/modules/index.ts +3 -0
- package/src/components/modules/normalizeInlineImages.ts +263 -0
- package/src/components/modules/readonly.ts +11 -0
- package/src/components/modules/rectangleSelection.ts +19 -3
- package/src/components/modules/saver.ts +7 -3
- package/src/components/modules/toolbar/blockSettings.ts +3 -3
- package/src/components/modules/toolbar/index.ts +72 -14
- package/src/components/modules/toolbar/plus-button.ts +24 -3
- package/src/components/modules/toolbar/settings-toggler.ts +3 -5
- package/src/components/modules/ui.ts +46 -68
- package/src/components/modules/uiControllers/controllers/blockHover.ts +49 -61
- package/src/components/modules/uiControllers/controllers/keyboard.ts +17 -11
- package/src/components/modules/uiControllers/handlers/click.ts +0 -12
- package/src/components/modules/yjs/index.ts +23 -0
- package/src/components/ui/toolbox.ts +41 -6
- package/src/components/utils/placeholder.ts +16 -0
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -1
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -1
- package/src/components/utils/popover/index.ts +1 -0
- package/src/components/utils/popover/popover-abstract.ts +11 -1
- package/src/components/utils/popover/popover-desktop.ts +27 -8
- package/src/components/utils/popover/popover-registry.ts +188 -0
- package/src/components/utils/sanitizer.ts +23 -2
- package/src/components/utils/tooltip.ts +2 -24
- package/src/styles/main.css +22 -0
- package/src/tools/paragraph/index.ts +12 -4
- package/src/tools/table/data-normalizer.ts +1 -0
- package/src/tools/table/index.ts +283 -346
- package/src/tools/table/table-add-controls.ts +353 -47
- package/src/tools/table/table-cell-blocks.ts +95 -7
- package/src/tools/table/table-cell-selection.ts +648 -0
- package/src/tools/table/table-core.ts +21 -32
- package/src/tools/table/table-grip-visuals.ts +96 -0
- package/src/tools/table/table-heading-toggle.ts +127 -0
- package/src/tools/table/table-operations.ts +475 -0
- package/src/tools/table/table-resize.ts +27 -6
- 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 +265 -211
- 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 +4 -0
- package/src/types-internal/blok-modules.d.ts +2 -0
- package/types/api/blocks.d.ts +8 -0
- package/types/api/history.d.ts +33 -0
- package/types/api/index.d.ts +1 -0
- package/types/api/readonly.d.ts +12 -2
- package/types/index.d.ts +10 -0
- package/types/tools/table.d.ts +67 -0
- package/types/tools-entry.d.ts +4 -0
- package/types/utils/popover/popover-item.d.ts +6 -0
- package/types/utils/popover/popover.d.ts +7 -0
- package/dist/chunks/messages-CySyfkMU.mjs +0 -48
- package/dist/messages-CySyfkMU.mjs +0 -48
|
@@ -90,10 +90,10 @@ export class PlusButtonHandler {
|
|
|
90
90
|
const plusButton = $.make('div', [
|
|
91
91
|
twJoin(
|
|
92
92
|
// Base toolbox-button styles
|
|
93
|
-
'text-
|
|
93
|
+
'text-text-secondary cursor-pointer w-6 h-6 rounded-[5px] inline-flex justify-center items-center select-none',
|
|
94
94
|
'shrink-0',
|
|
95
95
|
// SVG sizing
|
|
96
|
-
'[&_svg]:h-
|
|
96
|
+
'[&_svg]:h-[22px] [&_svg]:w-[22px]',
|
|
97
97
|
// Hover (can-hover)
|
|
98
98
|
'can-hover:hover:bg-bg-light',
|
|
99
99
|
// Keep hover background when toolbox is open
|
|
@@ -173,12 +173,33 @@ export class PlusButtonHandler {
|
|
|
173
173
|
const hoveredBlockIndex = hoveredBlock !== null
|
|
174
174
|
? BlockManager.getBlockIndex(hoveredBlock)
|
|
175
175
|
: BlockManager.currentBlockIndex;
|
|
176
|
-
const
|
|
176
|
+
const baseInsertIndex = insertAbove ? hoveredBlockIndex : hoveredBlockIndex + 1;
|
|
177
|
+
|
|
178
|
+
// When inserting below, skip past any blocks nested inside another block's
|
|
179
|
+
// DOM (e.g. paragraph blocks inside table cells). The block array may
|
|
180
|
+
// interleave nested blocks from multiple parents, so check whether each
|
|
181
|
+
// block's holder lives inside any block-wrapper ancestor rather than only
|
|
182
|
+
// the hovered block's holder.
|
|
183
|
+
const blocksAfterInsert = BlockManager.blocks.slice(baseInsertIndex);
|
|
184
|
+
const isNested = (block: Block): boolean =>
|
|
185
|
+
block.holder.parentElement?.closest('[data-blok-testid="block-wrapper"]') !== null;
|
|
186
|
+
const firstNonNestedOffset = !insertAbove && hoveredBlock && blocksAfterInsert.length > 0
|
|
187
|
+
? blocksAfterInsert.findIndex((block) => !isNested(block))
|
|
188
|
+
: 0;
|
|
189
|
+
const insertIndex = baseInsertIndex + (firstNonNestedOffset === -1 ? blocksAfterInsert.length : firstNonNestedOffset);
|
|
177
190
|
|
|
178
191
|
const targetBlock = isEmptyParagraph || startsWithSlash
|
|
179
192
|
? hoveredBlock
|
|
180
193
|
: BlockManager.insertDefaultBlockAtIndex(insertIndex, true);
|
|
181
194
|
|
|
195
|
+
// The DOM insertion may place the new block's holder inside a nested
|
|
196
|
+
// container (e.g. a table cell) because the previous block in the array
|
|
197
|
+
// is inside another block's DOM. Move the holder to be a sibling after
|
|
198
|
+
// the hovered block so it becomes a top-level block.
|
|
199
|
+
if (targetBlock !== hoveredBlock && isNested(targetBlock)) {
|
|
200
|
+
hoveredBlock?.holder.after(targetBlock.holder);
|
|
201
|
+
}
|
|
202
|
+
|
|
182
203
|
// Insert "/" or position caret after existing one
|
|
183
204
|
if (startsWithSlash) {
|
|
184
205
|
Caret.setToBlock(targetBlock, Caret.positions.DEFAULT, 1);
|
|
@@ -113,9 +113,9 @@ export class SettingsTogglerHandler {
|
|
|
113
113
|
const settingsToggler = $.make('span', [
|
|
114
114
|
twJoin(
|
|
115
115
|
// Base toolbox-button styles
|
|
116
|
-
'text-
|
|
116
|
+
'text-text-secondary cursor-pointer w-[22px] h-6 rounded-[5px] inline-flex justify-center items-center select-none',
|
|
117
117
|
// SVG sizing
|
|
118
|
-
'[&_svg]:h-
|
|
118
|
+
'[&_svg]:h-[22px] [&_svg]:w-[22px]',
|
|
119
119
|
// Active state
|
|
120
120
|
'active:cursor-grabbing',
|
|
121
121
|
// Hover (can-hover)
|
|
@@ -127,9 +127,7 @@ export class SettingsTogglerHandler {
|
|
|
127
127
|
'group-data-[blok-block-settings-opened=true]:can-hover:hover:cursor-pointer',
|
|
128
128
|
// Mobile styles (static positioning with overlay-pane appearance)
|
|
129
129
|
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-[2]',
|
|
130
|
-
'mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile'
|
|
131
|
-
// Not-mobile styles
|
|
132
|
-
'not-mobile:w-6'
|
|
130
|
+
'mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile'
|
|
133
131
|
),
|
|
134
132
|
'group-data-[blok-dragging=true]:cursor-grabbing',
|
|
135
133
|
], {
|
|
@@ -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
|
/**
|
|
@@ -71,38 +64,23 @@ export class BlockHoverController extends Controller {
|
|
|
71
64
|
return;
|
|
72
65
|
}
|
|
73
66
|
|
|
74
|
-
const
|
|
67
|
+
const closestBlockWrapper = (event.target as Element | null)?.closest('[data-blok-testid="block-wrapper"]');
|
|
75
68
|
|
|
76
69
|
/**
|
|
77
|
-
* If
|
|
70
|
+
* If the hovered block is inside a table cell, resolve to the table block instead.
|
|
71
|
+
* Without this, the toolbar hides itself for nested cell blocks and the table's
|
|
72
|
+
* block tune settings become inaccessible.
|
|
78
73
|
*/
|
|
79
|
-
const
|
|
80
|
-
?
|
|
81
|
-
:
|
|
82
|
-
|
|
83
|
-
if (zoneBlock !== null && this.blockHoveredState.lastHoveredBlockId !== zoneBlock.id) {
|
|
84
|
-
/**
|
|
85
|
-
* Emit the event but DON'T set lastHoveredBlockId for hover zone events.
|
|
86
|
-
* This allows the event to be emitted again when the mouse enters the actual block element,
|
|
87
|
-
* which is important for proper toolbar positioning after cross-block selection.
|
|
88
|
-
*/
|
|
89
|
-
this.eventsDispatcher.emit(BlockHovered, {
|
|
90
|
-
block: zoneBlock,
|
|
91
|
-
target: zoneBlock.holder,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (zoneBlock !== null) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
74
|
+
const hoveredBlockElement = closestBlockWrapper?.closest('[data-blok-table-cell-blocks]')
|
|
75
|
+
? closestBlockWrapper.closest('[data-blok-table-cell-blocks]')?.closest('[data-blok-testid="block-wrapper"]') ?? null
|
|
76
|
+
: closestBlockWrapper;
|
|
98
77
|
|
|
78
|
+
/**
|
|
79
|
+
* If no block element found directly, find the nearest block by Y distance
|
|
80
|
+
*/
|
|
99
81
|
if (!hoveredBlockElement) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* This allows hover events to be emitted again when re-entering a block,
|
|
103
|
-
* which is important after cross-block selection completes.
|
|
104
|
-
*/
|
|
105
|
-
this.blockHoveredState.lastHoveredBlockId = null;
|
|
82
|
+
this.emitNearestBlockHovered(event.clientY);
|
|
83
|
+
|
|
106
84
|
return;
|
|
107
85
|
}
|
|
108
86
|
|
|
@@ -134,9 +112,8 @@ export class BlockHoverController extends Controller {
|
|
|
134
112
|
);
|
|
135
113
|
|
|
136
114
|
/**
|
|
137
|
-
* Listen on document to detect hover
|
|
138
|
-
*
|
|
139
|
-
* 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.
|
|
140
117
|
*/
|
|
141
118
|
this.readOnlyMutableListeners.on(document, 'mousemove', (event: Event) => {
|
|
142
119
|
throttledHandleBlockHovered(event);
|
|
@@ -146,38 +123,49 @@ export class BlockHoverController extends Controller {
|
|
|
146
123
|
}
|
|
147
124
|
|
|
148
125
|
/**
|
|
149
|
-
* Finds
|
|
150
|
-
*
|
|
151
|
-
* allowing the toolbar to follow hover anywhere outside the content area horizontally.
|
|
152
|
-
* @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.
|
|
153
128
|
* @param clientY - Cursor Y position
|
|
154
|
-
* @returns Block at the vertical position, or null if not in hover zone or no block found
|
|
155
129
|
*/
|
|
156
|
-
private
|
|
157
|
-
const
|
|
130
|
+
private emitNearestBlockHovered(clientY: number): void {
|
|
131
|
+
const nearestBlock = this.findNearestBlock(clientY);
|
|
158
132
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
*/
|
|
163
|
-
const isInHoverZone = clientX < contentRect.left || clientX > contentRect.right;
|
|
133
|
+
if (nearestBlock === null || this.blockHoveredState.lastHoveredBlockId === nearestBlock.id) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
164
136
|
|
|
165
|
-
|
|
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) {
|
|
166
157
|
return null;
|
|
167
158
|
}
|
|
168
159
|
|
|
169
|
-
|
|
170
|
-
* Find block by Y position
|
|
171
|
-
*/
|
|
172
|
-
for (const block of this.Blok.BlockManager.blocks) {
|
|
160
|
+
const result = blocks.reduce<{ block: Block; distance: number }>((nearest, block) => {
|
|
173
161
|
const rect = block.holder.getBoundingClientRect();
|
|
162
|
+
const centerY = (rect.top + rect.bottom) / 2;
|
|
163
|
+
const distance = Math.abs(clientY - centerY);
|
|
174
164
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
}
|
|
165
|
+
return distance < nearest.distance ? { block, distance } : nearest;
|
|
166
|
+
}, { block: blocks[0], distance: Infinity });
|
|
179
167
|
|
|
180
|
-
return
|
|
168
|
+
return result.block;
|
|
181
169
|
}
|
|
182
170
|
|
|
183
171
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SelectionUtils as Selection } from '../../../selection/index';
|
|
2
|
+
import { PopoverRegistry } from '../../../utils/popover/popover-registry';
|
|
2
3
|
import { KEYS_REQUIRING_CARET_CAPTURE } from '../constants';
|
|
3
4
|
|
|
4
5
|
import { Controller } from './_base';
|
|
@@ -258,28 +259,33 @@ export class KeyboardController extends Controller {
|
|
|
258
259
|
}
|
|
259
260
|
|
|
260
261
|
/**
|
|
261
|
-
*
|
|
262
|
-
*
|
|
262
|
+
* Toolbox needs specific Escape handling for caret restoration,
|
|
263
|
+
* so check it before the registry
|
|
263
264
|
*/
|
|
264
|
-
if (this.Blok.
|
|
265
|
-
this.Blok.
|
|
265
|
+
if (this.Blok.Toolbar.toolbox.opened) {
|
|
266
|
+
this.Blok.Toolbar.toolbox.close();
|
|
267
|
+
this.Blok.BlockManager.currentBlock &&
|
|
268
|
+
this.Blok.Caret.setToBlock(this.Blok.BlockManager.currentBlock, this.Blok.Caret.positions.END);
|
|
266
269
|
|
|
267
270
|
return;
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
/**
|
|
271
|
-
*
|
|
274
|
+
* Close any open popover via registry (BlockSettings, table grips, future popovers).
|
|
275
|
+
* Must come before block selection clearing to prevent navigation mode
|
|
276
|
+
* from being enabled when closing block settings.
|
|
272
277
|
*/
|
|
273
|
-
if (
|
|
274
|
-
|
|
278
|
+
if (PopoverRegistry.instance.hasOpenPopovers()) {
|
|
279
|
+
PopoverRegistry.instance.closeTopmost();
|
|
275
280
|
|
|
276
281
|
return;
|
|
277
282
|
}
|
|
278
283
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Clear blocks selection by ESC (but not when entering navigation mode)
|
|
286
|
+
*/
|
|
287
|
+
if (this.Blok.BlockSelection.anyBlockSelected) {
|
|
288
|
+
this.Blok.BlockSelection.clearSelection(event);
|
|
283
289
|
|
|
284
290
|
return;
|
|
285
291
|
}
|
|
@@ -68,8 +68,6 @@ export const analyzeClickContext = (
|
|
|
68
68
|
*
|
|
69
69
|
* Responsibilities:
|
|
70
70
|
* - Clear current block when clicking outside editor
|
|
71
|
-
* - Close BlockSettings when appropriate
|
|
72
|
-
* - Move toolbar when clicking in redactor after closing settings
|
|
73
71
|
* - Clear block selection
|
|
74
72
|
* - Close inline toolbar
|
|
75
73
|
*
|
|
@@ -108,16 +106,6 @@ export const createDocumentClickedHandler = (
|
|
|
108
106
|
Blok.BlockManager.unsetCurrentBlock();
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
const shouldCloseBlockSettings = Blok.BlockSettings.opened && !context.doNotProcess;
|
|
112
|
-
if (shouldCloseBlockSettings) {
|
|
113
|
-
Blok.BlockSettings.close();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (shouldCloseBlockSettings && context.clickedInsideRedactor) {
|
|
117
|
-
const clickedBlock = Blok.BlockManager.getBlockByChildNode(context.target);
|
|
118
|
-
Blok.Toolbar.moveAndOpen(clickedBlock);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
109
|
/**
|
|
122
110
|
* Clear Selection if user clicked somewhere
|
|
123
111
|
* But preserve selection when clicking on block settings toggler or inside block settings
|
|
@@ -189,6 +189,29 @@ export class YjsManager extends Module {
|
|
|
189
189
|
this.undoHistory.redo();
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Check if undo is available.
|
|
194
|
+
* @returns true if undo is available
|
|
195
|
+
*/
|
|
196
|
+
public canUndo(): boolean {
|
|
197
|
+
return this.undoHistory.canUndo();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Check if redo is available.
|
|
202
|
+
* @returns true if redo is available
|
|
203
|
+
*/
|
|
204
|
+
public canRedo(): boolean {
|
|
205
|
+
return this.undoHistory.canRedo();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Clear all history.
|
|
210
|
+
*/
|
|
211
|
+
public clear(): void {
|
|
212
|
+
this.undoHistory.clear();
|
|
213
|
+
}
|
|
214
|
+
|
|
192
215
|
/**
|
|
193
216
|
* Stop capturing changes into current undo group.
|
|
194
217
|
* Call this to force next change into a new undo entry.
|
|
@@ -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
|
*/
|
|
@@ -56,6 +56,22 @@ export const PLACEHOLDER_FOCUS_ONLY_CLASSES: string[] = [
|
|
|
56
56
|
'[&[data-empty=true]:focus]:before:content-[attr(data-blok-placeholder-active)]',
|
|
57
57
|
];
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Placeholder classes that show when the editor is empty (ancestor has data-blok-empty="true").
|
|
61
|
+
* Shows placeholder without requiring focus — used for initial empty-state hint.
|
|
62
|
+
* Uses data-blok-placeholder-active attribute for the placeholder text.
|
|
63
|
+
*/
|
|
64
|
+
export const PLACEHOLDER_EMPTY_EDITOR_CLASSES: string[] = [
|
|
65
|
+
'[[data-blok-empty=true]_&]:empty:before:pointer-events-none',
|
|
66
|
+
'[[data-blok-empty=true]_&]:empty:before:text-gray-text',
|
|
67
|
+
'[[data-blok-empty=true]_&]:empty:before:cursor-text',
|
|
68
|
+
'[[data-blok-empty=true]_&]:empty:before:content-[attr(data-blok-placeholder-active)]',
|
|
69
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:pointer-events-none',
|
|
70
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:text-gray-text',
|
|
71
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:cursor-text',
|
|
72
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:content-[attr(data-blok-placeholder-active)]',
|
|
73
|
+
];
|
|
74
|
+
|
|
59
75
|
/**
|
|
60
76
|
* Check if an element's content is empty
|
|
61
77
|
*
|