@jackuait/blok 0.6.0-beta.9 → 0.7.0-beta.1
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-Bn6Q_o8h.mjs → blok-ob9Fwr1L.mjs} +3414 -2975
- package/dist/chunks/i18next-B47TKgbU.mjs +1303 -0
- package/dist/chunks/{i18next-loader-DjR4d8M7.mjs → i18next-loader-Bu3vFvye.mjs} +2 -2
- package/dist/chunks/{index-oe38cp86.mjs → index-CZmRzRIX.mjs} +12 -12
- package/dist/chunks/{inline-tool-convert-SRTkyaZn.mjs → inline-tool-convert-CvFW2iie.mjs} +1579 -961
- package/dist/chunks/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
- package/dist/chunks/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
- package/dist/{messages-DnXLrlHh.mjs → chunks/messages-4v4MuVEc.mjs} +6 -0
- package/dist/chunks/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
- package/dist/chunks/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
- package/dist/chunks/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
- package/dist/{messages-uKX8WBaD.mjs → chunks/messages-96kNZDll.mjs} +6 -0
- package/dist/chunks/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
- package/dist/{messages-DBn76jVV.mjs → chunks/messages-B217znr-.mjs} +8 -2
- package/dist/{messages-DT4dP5uK.mjs → chunks/messages-B8WNljW3.mjs} +6 -0
- package/dist/chunks/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
- package/dist/{messages-CZygwLwM.mjs → chunks/messages-BI43k_BD.mjs} +6 -0
- package/dist/{messages-CzTufCHu.mjs → chunks/messages-BJ6zrz2j.mjs} +6 -0
- package/dist/{messages-BoJc_p1r.mjs → chunks/messages-BUl_Rcnj.mjs} +6 -0
- package/dist/chunks/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
- package/dist/{messages-C2htQ_3F.mjs → chunks/messages-BcpCubnC.mjs} +6 -0
- package/dist/{messages-D5C3J9qr.mjs → chunks/messages-Bm-E4iRC.mjs} +6 -0
- package/dist/chunks/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
- package/dist/chunks/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
- package/dist/chunks/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
- package/dist/{messages-Dz9L52ol.mjs → chunks/messages-CRJ_mchV.mjs} +6 -0
- package/dist/chunks/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
- package/dist/chunks/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
- package/dist/{messages-R3hUSvr3.mjs → chunks/messages-CfiyT2Wi.mjs} +6 -0
- package/dist/{messages-CJdUsQ-c.mjs → chunks/messages-CgTq3QhU.mjs} +6 -0
- package/dist/chunks/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
- package/dist/{messages-Q7AO_FLv.mjs → chunks/messages-Cjjo7yHR.mjs} +6 -0
- package/dist/{messages-C99mq906.mjs → chunks/messages-Cl6ayUaq.mjs} +6 -0
- package/dist/chunks/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
- package/dist/chunks/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
- package/dist/chunks/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
- package/dist/{messages-BWF-zUpY.mjs → chunks/messages-CrCYPCk3.mjs} +6 -0
- package/dist/{messages-D-ZtY5v0.mjs → chunks/messages-Cs8zmZ3L.mjs} +6 -0
- package/dist/{messages-DprmQg6V.mjs → chunks/messages-CzK0LEhb.mjs} +6 -0
- package/dist/chunks/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
- package/dist/chunks/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
- package/dist/chunks/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
- package/dist/{messages-kep5wtm4.mjs → chunks/messages-D4qqwVgQ.mjs} +6 -0
- package/dist/chunks/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
- package/dist/{messages-CY8_RyFE.mjs → chunks/messages-D7u2bmP2.mjs} +6 -0
- package/dist/chunks/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
- package/dist/{messages-DLfR5bMd.mjs → chunks/messages-D9ndgBnU.mjs} +6 -0
- package/dist/{messages-CVw84KdI.mjs → chunks/messages-DDTQgImT.mjs} +6 -0
- package/dist/{messages-_ErNTNhk.mjs → chunks/messages-DH_jBeED.mjs} +6 -0
- package/dist/chunks/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
- package/dist/chunks/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
- package/dist/chunks/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
- package/dist/chunks/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
- package/dist/chunks/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
- package/dist/chunks/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
- package/dist/{messages-Z9nEU2xK.mjs → chunks/messages-DviiFSv2.mjs} +6 -0
- package/dist/chunks/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
- package/dist/{messages-w7v1GNaE.mjs → chunks/messages-Dzzn6XoD.mjs} +6 -0
- package/dist/{messages-CqWJcCbY.mjs → chunks/messages-GSByFygY.mjs} +6 -0
- package/dist/chunks/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
- package/dist/chunks/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
- package/dist/{messages-BU2nlrLK.mjs → chunks/messages-RonBBCnh.mjs} +6 -0
- package/dist/{messages-Bmu_S7GM.mjs → chunks/messages-VDriF5Qy.mjs} +6 -0
- package/dist/{messages-CLhcMlTc.mjs → chunks/messages-ZjUAIWb1.mjs} +6 -0
- package/dist/{messages-9SihnaXQ.mjs → chunks/messages-b1EdvUm0.mjs} +6 -0
- package/dist/{messages-DvFLX36Q.mjs → chunks/messages-begYOTgC.mjs} +6 -0
- package/dist/{messages-BMv4xwIr.mjs → chunks/messages-jrncnb-H.mjs} +6 -0
- package/dist/{messages-D5iv1Kox.mjs → chunks/messages-nefz1S71.mjs} +6 -0
- package/dist/{messages-CQwpzUFp.mjs → chunks/messages-ucTVgS5G.mjs} +6 -0
- package/dist/chunks/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
- package/dist/{messages-C9eaarcK.mjs → chunks/messages-wmi-iFkH.mjs} +6 -0
- package/dist/chunks/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
- package/dist/full.mjs +30 -27
- package/dist/locales.mjs +90 -84
- package/dist/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
- package/dist/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
- package/dist/{chunks/messages-DnXLrlHh.mjs → messages-4v4MuVEc.mjs} +6 -0
- package/dist/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
- package/dist/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
- package/dist/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
- package/dist/{chunks/messages-uKX8WBaD.mjs → messages-96kNZDll.mjs} +6 -0
- package/dist/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
- package/dist/{chunks/messages-DBn76jVV.mjs → messages-B217znr-.mjs} +8 -2
- package/dist/{chunks/messages-DT4dP5uK.mjs → messages-B8WNljW3.mjs} +6 -0
- package/dist/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
- package/dist/{chunks/messages-CZygwLwM.mjs → messages-BI43k_BD.mjs} +6 -0
- package/dist/{chunks/messages-CzTufCHu.mjs → messages-BJ6zrz2j.mjs} +6 -0
- package/dist/{chunks/messages-BoJc_p1r.mjs → messages-BUl_Rcnj.mjs} +6 -0
- package/dist/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
- package/dist/{chunks/messages-C2htQ_3F.mjs → messages-BcpCubnC.mjs} +6 -0
- package/dist/{chunks/messages-D5C3J9qr.mjs → messages-Bm-E4iRC.mjs} +6 -0
- package/dist/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
- package/dist/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
- package/dist/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
- package/dist/{chunks/messages-Dz9L52ol.mjs → messages-CRJ_mchV.mjs} +6 -0
- package/dist/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
- package/dist/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
- package/dist/{chunks/messages-R3hUSvr3.mjs → messages-CfiyT2Wi.mjs} +6 -0
- package/dist/{chunks/messages-CJdUsQ-c.mjs → messages-CgTq3QhU.mjs} +6 -0
- package/dist/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
- package/dist/{chunks/messages-Q7AO_FLv.mjs → messages-Cjjo7yHR.mjs} +6 -0
- package/dist/{chunks/messages-C99mq906.mjs → messages-Cl6ayUaq.mjs} +6 -0
- package/dist/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
- package/dist/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
- package/dist/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
- package/dist/{chunks/messages-BWF-zUpY.mjs → messages-CrCYPCk3.mjs} +6 -0
- package/dist/{chunks/messages-D-ZtY5v0.mjs → messages-Cs8zmZ3L.mjs} +6 -0
- package/dist/{chunks/messages-DprmQg6V.mjs → messages-CzK0LEhb.mjs} +6 -0
- package/dist/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
- package/dist/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
- package/dist/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
- package/dist/{chunks/messages-kep5wtm4.mjs → messages-D4qqwVgQ.mjs} +6 -0
- package/dist/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
- package/dist/{chunks/messages-CY8_RyFE.mjs → messages-D7u2bmP2.mjs} +6 -0
- package/dist/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
- package/dist/{chunks/messages-DLfR5bMd.mjs → messages-D9ndgBnU.mjs} +6 -0
- package/dist/{chunks/messages-CVw84KdI.mjs → messages-DDTQgImT.mjs} +6 -0
- package/dist/{chunks/messages-_ErNTNhk.mjs → messages-DH_jBeED.mjs} +6 -0
- package/dist/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
- package/dist/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
- package/dist/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
- package/dist/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
- package/dist/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
- package/dist/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
- package/dist/{chunks/messages-Z9nEU2xK.mjs → messages-DviiFSv2.mjs} +6 -0
- package/dist/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
- package/dist/{chunks/messages-w7v1GNaE.mjs → messages-Dzzn6XoD.mjs} +6 -0
- package/dist/{chunks/messages-CqWJcCbY.mjs → messages-GSByFygY.mjs} +6 -0
- package/dist/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
- package/dist/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
- package/dist/{chunks/messages-BU2nlrLK.mjs → messages-RonBBCnh.mjs} +6 -0
- package/dist/{chunks/messages-Bmu_S7GM.mjs → messages-VDriF5Qy.mjs} +6 -0
- package/dist/{chunks/messages-CLhcMlTc.mjs → messages-ZjUAIWb1.mjs} +6 -0
- package/dist/{chunks/messages-9SihnaXQ.mjs → messages-b1EdvUm0.mjs} +6 -0
- package/dist/{chunks/messages-DvFLX36Q.mjs → messages-begYOTgC.mjs} +6 -0
- package/dist/{chunks/messages-BMv4xwIr.mjs → messages-jrncnb-H.mjs} +6 -0
- package/dist/{chunks/messages-D5iv1Kox.mjs → messages-nefz1S71.mjs} +6 -0
- package/dist/{chunks/messages-CQwpzUFp.mjs → messages-ucTVgS5G.mjs} +6 -0
- package/dist/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
- package/dist/{chunks/messages-C9eaarcK.mjs → messages-wmi-iFkH.mjs} +6 -0
- package/dist/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
- package/dist/tools.mjs +3537 -1710
- package/dist/vendor.LICENSE.txt +109 -109
- package/package.json +43 -57
- package/src/blok.ts +12 -0
- package/src/components/__module.ts +21 -0
- package/src/components/block/api.ts +17 -0
- package/src/components/block/style-manager.ts +6 -2
- package/src/components/block/tool-renderer.ts +33 -30
- package/src/components/blocks.ts +132 -15
- package/src/components/constants/data-attributes.ts +7 -0
- package/src/components/i18n/locales/am/messages.json +6 -0
- package/src/components/i18n/locales/ar/messages.json +6 -0
- package/src/components/i18n/locales/az/messages.json +6 -0
- package/src/components/i18n/locales/bg/messages.json +6 -0
- package/src/components/i18n/locales/bn/messages.json +6 -0
- package/src/components/i18n/locales/bs/messages.json +6 -0
- package/src/components/i18n/locales/cs/messages.json +6 -0
- package/src/components/i18n/locales/da/messages.json +6 -0
- package/src/components/i18n/locales/de/messages.json +6 -0
- package/src/components/i18n/locales/dv/messages.json +6 -0
- package/src/components/i18n/locales/el/messages.json +6 -0
- package/src/components/i18n/locales/en/messages.json +6 -0
- package/src/components/i18n/locales/es/messages.json +6 -0
- package/src/components/i18n/locales/et/messages.json +6 -0
- package/src/components/i18n/locales/fa/messages.json +6 -0
- package/src/components/i18n/locales/fi/messages.json +6 -0
- package/src/components/i18n/locales/fil/messages.json +6 -0
- package/src/components/i18n/locales/fr/messages.json +6 -0
- package/src/components/i18n/locales/gu/messages.json +6 -0
- package/src/components/i18n/locales/he/messages.json +6 -0
- package/src/components/i18n/locales/hi/messages.json +6 -0
- package/src/components/i18n/locales/hr/messages.json +6 -0
- package/src/components/i18n/locales/hu/messages.json +6 -0
- package/src/components/i18n/locales/hy/messages.json +6 -0
- package/src/components/i18n/locales/id/messages.json +6 -0
- package/src/components/i18n/locales/it/messages.json +6 -0
- package/src/components/i18n/locales/ja/messages.json +6 -0
- package/src/components/i18n/locales/ka/messages.json +6 -0
- package/src/components/i18n/locales/km/messages.json +6 -0
- package/src/components/i18n/locales/kn/messages.json +6 -0
- package/src/components/i18n/locales/ko/messages.json +6 -0
- package/src/components/i18n/locales/ku/messages.json +6 -0
- package/src/components/i18n/locales/lo/messages.json +6 -0
- package/src/components/i18n/locales/lt/messages.json +6 -0
- package/src/components/i18n/locales/lv/messages.json +6 -0
- package/src/components/i18n/locales/mk/messages.json +6 -0
- package/src/components/i18n/locales/ml/messages.json +6 -0
- package/src/components/i18n/locales/mn/messages.json +6 -0
- package/src/components/i18n/locales/mr/messages.json +6 -0
- package/src/components/i18n/locales/ms/messages.json +6 -0
- package/src/components/i18n/locales/my/messages.json +6 -0
- package/src/components/i18n/locales/ne/messages.json +6 -0
- package/src/components/i18n/locales/nl/messages.json +6 -0
- package/src/components/i18n/locales/no/messages.json +6 -0
- package/src/components/i18n/locales/pa/messages.json +6 -0
- package/src/components/i18n/locales/pl/messages.json +6 -0
- package/src/components/i18n/locales/ps/messages.json +6 -0
- package/src/components/i18n/locales/pt/messages.json +6 -0
- package/src/components/i18n/locales/ro/messages.json +6 -0
- package/src/components/i18n/locales/ru/messages.json +6 -0
- package/src/components/i18n/locales/sd/messages.json +6 -0
- package/src/components/i18n/locales/si/messages.json +6 -0
- package/src/components/i18n/locales/sk/messages.json +6 -0
- package/src/components/i18n/locales/sl/messages.json +6 -0
- package/src/components/i18n/locales/sq/messages.json +6 -0
- package/src/components/i18n/locales/sr/messages.json +6 -0
- package/src/components/i18n/locales/sv/messages.json +6 -0
- package/src/components/i18n/locales/sw/messages.json +6 -0
- package/src/components/i18n/locales/ta/messages.json +6 -0
- package/src/components/i18n/locales/te/messages.json +6 -0
- package/src/components/i18n/locales/th/messages.json +6 -0
- package/src/components/i18n/locales/tr/messages.json +6 -0
- package/src/components/i18n/locales/ug/messages.json +6 -0
- package/src/components/i18n/locales/uk/messages.json +6 -0
- package/src/components/i18n/locales/ur/messages.json +6 -0
- package/src/components/i18n/locales/vi/messages.json +6 -0
- package/src/components/i18n/locales/yi/messages.json +6 -0
- package/src/components/i18n/locales/zh/messages.json +6 -0
- package/src/components/icons/index.ts +61 -7
- package/src/components/inline-tools/inline-tool-link.ts +1 -1
- package/src/components/inline-tools/inline-tool-marker.ts +737 -0
- package/src/components/inline-tools/utils/formatting-range-utils.ts +6 -3
- package/src/components/inline-tools/utils/marker-dom-utils.ts +17 -0
- package/src/components/modules/api/blocks.ts +34 -9
- package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +75 -29
- package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +54 -2
- package/src/components/modules/blockEvents/constants.ts +12 -0
- package/src/components/modules/blockEvents/index.ts +13 -5
- package/src/components/modules/blockManager/blockManager.ts +81 -2
- package/src/components/modules/blockManager/hierarchy.ts +20 -2
- package/src/components/modules/blockManager/operations.ts +70 -35
- package/src/components/modules/blockManager/repository.ts +22 -0
- package/src/components/modules/blockManager/types.ts +3 -1
- package/src/components/modules/blockManager/yjs-sync.ts +173 -39
- package/src/components/modules/blockSelection.ts +3 -0
- package/src/components/modules/crossBlockSelection.ts +11 -3
- package/src/components/modules/drag/preview/DragPreview.ts +10 -2
- package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
- package/src/components/modules/drag/utils/drag.constants.ts +1 -1
- package/src/components/modules/normalizeInlineImages.ts +263 -0
- package/src/components/modules/paste/google-docs-preprocessor.ts +197 -0
- package/src/components/modules/paste/handlers/base.ts +43 -2
- package/src/components/modules/paste/handlers/html-handler.ts +1 -1
- package/src/components/modules/paste/handlers/index.ts +1 -0
- package/src/components/modules/paste/handlers/table-cells-handler.ts +104 -0
- package/src/components/modules/paste/index.ts +20 -3
- package/src/components/modules/readonly.ts +8 -2
- package/src/components/modules/rectangleSelection.ts +5 -2
- package/src/components/modules/renderer.ts +35 -0
- package/src/components/modules/saver.ts +52 -2
- package/src/components/modules/toolbar/blockSettings.ts +52 -44
- package/src/components/modules/toolbar/index.ts +124 -17
- package/src/components/modules/toolbar/inline/index.ts +4 -4
- package/src/components/modules/toolbar/plus-button.ts +3 -3
- package/src/components/modules/toolbar/settings-toggler.ts +3 -3
- package/src/components/modules/toolbar/styles.ts +7 -7
- package/src/components/modules/ui.ts +6 -6
- package/src/components/modules/uiControllers/controllers/blockHover.ts +16 -2
- package/src/components/modules/uiControllers/handlers/touch.ts +83 -10
- package/src/components/modules/yjs/block-observer.ts +9 -3
- package/src/components/modules/yjs/document-store.ts +10 -7
- package/src/components/modules/yjs/types.ts +8 -6
- package/src/components/modules/yjs/undo-history.ts +90 -11
- package/src/components/selection/fake-background/shadows.ts +1 -1
- package/src/components/shared/color-picker.ts +211 -0
- package/src/components/shared/color-presets.ts +25 -0
- package/src/components/ui/toolbox.ts +27 -11
- package/src/components/utils/color-mapping.ts +241 -0
- package/src/components/utils/notifier/draw.ts +9 -9
- package/src/components/utils/placeholder.ts +24 -8
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +3 -3
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +15 -12
- package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
- package/src/components/utils/popover/popover-abstract.ts +30 -5
- package/src/components/utils/popover/popover-desktop.ts +26 -3
- package/src/components/utils/popover/popover-inline.ts +14 -1
- package/src/components/utils/popover/popover-mobile.ts +4 -4
- package/src/components/utils/popover/popover.const.ts +3 -3
- package/src/components/utils/sanitizer.ts +24 -3
- package/src/components/utils/tw.ts +17 -5
- package/src/full.ts +4 -0
- package/src/stories/Header.stories.ts +106 -0
- package/src/stories/MarkerColors.stories.ts +730 -0
- package/src/stories/Placeholder.stories.ts +7 -2
- package/src/stories/Popover.stories.ts +1 -3
- package/src/stories/Table.stories.ts +1662 -0
- package/src/stories/helpers.ts +2 -0
- package/src/styles/main.css +217 -39
- package/src/tools/header/index.ts +204 -26
- package/src/tools/index.ts +5 -1
- package/src/tools/list/caret-manager.ts +28 -10
- package/src/tools/list/constants.ts +2 -2
- package/src/tools/list/dom-builder.ts +3 -3
- package/src/tools/list/static-configs.ts +0 -1
- package/src/tools/paragraph/index.ts +9 -5
- package/src/tools/table/core/table-commands.ts +99 -0
- package/src/tools/table/core/table-controller.ts +231 -0
- package/src/tools/table/core/table-events.ts +102 -0
- package/src/tools/table/index.ts +1070 -174
- package/src/tools/table/ownership/table-event-broker.ts +74 -0
- package/src/tools/table/ownership/table-ownership-registry.ts +126 -0
- package/src/tools/table/table-add-controls.ts +85 -15
- package/src/tools/table/table-cell-blocks.ts +336 -38
- package/src/tools/table/table-cell-clipboard.ts +415 -0
- package/src/tools/table/table-cell-color-picker.ts +34 -0
- package/src/tools/table/table-cell-selection.ts +264 -15
- package/src/tools/table/table-core.ts +3 -42
- package/src/tools/table/table-heading-toggle.ts +2 -2
- package/src/tools/table/table-model.ts +623 -0
- package/src/tools/table/table-operations.ts +59 -78
- package/src/tools/table/table-resize.ts +15 -11
- package/src/tools/table/table-restrictions.ts +69 -3
- package/src/tools/table/table-row-col-action-handler.ts +22 -7
- package/src/tools/table/table-row-col-controls.ts +129 -12
- package/src/tools/table/table-row-col-drag.ts +14 -0
- package/src/tools/table/table-scroll-haze.ts +152 -0
- package/src/tools/table/types.ts +22 -1
- package/src/tools/table/view/table-cell-blocks-adapter.ts +47 -0
- package/src/tools/toggle/block-operations.ts +110 -0
- package/src/tools/toggle/constants.ts +49 -0
- package/src/tools/toggle/dom-builder.ts +125 -0
- package/src/tools/toggle/index.ts +280 -0
- package/src/tools/toggle/toggle-keyboard.ts +139 -0
- package/src/tools/toggle/toggle-lifecycle.ts +80 -0
- package/src/tools/toggle/toggle-shortcuts.ts +107 -0
- package/src/tools/toggle/types.ts +21 -0
- package/src/variants/blok-minimum.ts +13 -0
- package/types/api/block.d.ts +13 -0
- package/types/api/blocks.d.ts +16 -0
- package/types/full.d.ts +2 -0
- package/types/tools/table.d.ts +2 -0
- package/types/tools-entry.d.ts +2 -1
- package/dist/chunks/i18next-CugVlwWp.mjs +0 -1292
- package/src/tools/table/data-normalizer.ts +0 -32
|
@@ -222,11 +222,23 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
224
|
* Set current block to cover the case when the Toolbar showed near hovered Block but caret is set to another Block.
|
|
225
|
-
* Skip this when
|
|
226
|
-
*
|
|
225
|
+
* Skip this when:
|
|
226
|
+
* - the hovered block was resolved from a table cell
|
|
227
|
+
* - the current block's holder is nested inside a table cell container
|
|
228
|
+
* (e.g. "/" was typed in a cell while the toolbar was already open from hover,
|
|
229
|
+
* so hoveredBlockIsFromTableCell may be stale/false from the hover resolution)
|
|
230
|
+
*
|
|
231
|
+
* In both cases, overriding currentBlock with the resolved table block
|
|
232
|
+
* would lose the cell-paragraph context the toolbox needs to hide restricted tools.
|
|
227
233
|
*/
|
|
228
234
|
if (this.hoveredBlock && !this.hoveredBlockIsFromTableCell) {
|
|
229
|
-
this.Blok.BlockManager.currentBlock
|
|
235
|
+
const currentBlock = this.Blok.BlockManager.currentBlock;
|
|
236
|
+
const isCurrentBlockInsideTableCell = currentBlock !== undefined
|
|
237
|
+
&& currentBlock.holder.closest('[data-blok-table-cell-blocks]') !== null;
|
|
238
|
+
|
|
239
|
+
if (!isCurrentBlockInsideTableCell) {
|
|
240
|
+
this.Blok.BlockManager.currentBlock = this.hoveredBlock;
|
|
241
|
+
}
|
|
230
242
|
}
|
|
231
243
|
|
|
232
244
|
this.toolboxInstance.open();
|
|
@@ -336,11 +348,30 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
336
348
|
}
|
|
337
349
|
|
|
338
350
|
/**
|
|
339
|
-
* Track whether the
|
|
340
|
-
*
|
|
341
|
-
*
|
|
351
|
+
* Track whether the hover originated from inside a table cell.
|
|
352
|
+
*
|
|
353
|
+
* Two scenarios:
|
|
354
|
+
* 1. Called with an explicit `target` (via BlockHovered): blockHover.ts resolves
|
|
355
|
+
* cell paragraphs up to the TABLE block before emitting the event, so
|
|
356
|
+
* `unresolvedBlock` is always the TABLE block — its holder is at the top level.
|
|
357
|
+
* Use the raw `target` element to detect if the pointer is inside a cell.
|
|
358
|
+
* 2. Called without args (from activateToolbox / slash menu): `unresolvedBlock`
|
|
359
|
+
* falls back to `BlockManager.currentBlock`, which IS the cell-paragraph.
|
|
360
|
+
* Check the block's holder directly.
|
|
361
|
+
*
|
|
362
|
+
* When this flag is true, the toolbox.open() getter preserves the cell-paragraph
|
|
363
|
+
* as currentBlock so that restricted tools (table, header) can be hidden.
|
|
364
|
+
*
|
|
365
|
+
* NOTE: This flag is NOT used for plus button / settings toggler visibility.
|
|
366
|
+
* Those are handled separately by the focusin listener (tableCellFocusHandler)
|
|
367
|
+
* which detects when the user actually clicks/focuses inside a cell.
|
|
342
368
|
*/
|
|
343
|
-
|
|
369
|
+
const targetIsInsideCell = target instanceof Element
|
|
370
|
+
&& target.closest('[data-blok-table-cell-blocks]') !== null;
|
|
371
|
+
const blockIsInsideCell =
|
|
372
|
+
unresolvedBlock.holder.closest('[data-blok-table-cell-blocks]') !== null;
|
|
373
|
+
|
|
374
|
+
this.hoveredBlockIsFromTableCell = targetIsInsideCell || blockIsInsideCell;
|
|
344
375
|
|
|
345
376
|
const targetBlock = this.resolveTableCellBlock(unresolvedBlock);
|
|
346
377
|
|
|
@@ -362,11 +393,17 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
362
393
|
}
|
|
363
394
|
|
|
364
395
|
/**
|
|
365
|
-
* Suppress toolbar buttons when the
|
|
396
|
+
* Suppress toolbar buttons when the focused element is inside a table cell.
|
|
366
397
|
* The toolbar still positions itself for toolbox/slash-search purposes,
|
|
367
|
-
* but plus button and settings toggler remain hidden.
|
|
398
|
+
* but plus button and settings toggler remain hidden while a cell has focus.
|
|
399
|
+
*
|
|
400
|
+
* Note: we check focus (activeElement) not hover. On hover alone, the plus
|
|
401
|
+
* button should remain visible so the user can click it to add blocks
|
|
402
|
+
* below the table. Only when the user actually clicks/focuses inside a cell
|
|
403
|
+
* should the buttons be suppressed.
|
|
368
404
|
*/
|
|
369
|
-
const
|
|
405
|
+
const focusIsInsideCell = this.isFocusInsideTableCell();
|
|
406
|
+
const displayValue = focusIsInsideCell ? 'none' : '';
|
|
370
407
|
|
|
371
408
|
plusButton.style.display = displayValue;
|
|
372
409
|
|
|
@@ -588,6 +625,16 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
588
625
|
this.settingsTogglerHandler.skipNextToggle();
|
|
589
626
|
}
|
|
590
627
|
|
|
628
|
+
/**
|
|
629
|
+
* Hides the block actions (plus button and settings toggler) without
|
|
630
|
+
* closing the entire toolbar or setting explicitlyClosed.
|
|
631
|
+
* Used when the toolbar should remain positioned but its action buttons
|
|
632
|
+
* should temporarily step aside (e.g., during typing or inline toolbar use).
|
|
633
|
+
*/
|
|
634
|
+
public hideBlockActions(): void {
|
|
635
|
+
this.blockActions.hide();
|
|
636
|
+
}
|
|
637
|
+
|
|
591
638
|
/**
|
|
592
639
|
* Resets the explicitlyClosed flag to allow the toolbar to reopen on hover.
|
|
593
640
|
* Called when drag is cancelled to re-enable hover-based toolbar opening.
|
|
@@ -596,6 +643,48 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
596
643
|
this.explicitlyClosed = false;
|
|
597
644
|
}
|
|
598
645
|
|
|
646
|
+
/**
|
|
647
|
+
* Checks whether the currently focused element (document.activeElement) is
|
|
648
|
+
* inside a table cell container.
|
|
649
|
+
*
|
|
650
|
+
* Used to decide whether the plus button and settings toggler should be hidden.
|
|
651
|
+
* Focus-based check distinguishes click (buttons hidden) from hover (buttons visible).
|
|
652
|
+
*/
|
|
653
|
+
private isFocusInsideTableCell(): boolean {
|
|
654
|
+
const active = document.activeElement;
|
|
655
|
+
|
|
656
|
+
if (!active) {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return active.closest('[data-blok-table-cell-blocks]') !== null;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Updates toolbar button visibility based on whether a table cell has focus.
|
|
665
|
+
* Hides plus button and settings toggler when focus is inside a cell;
|
|
666
|
+
* restores them when focus moves to a regular block.
|
|
667
|
+
*
|
|
668
|
+
* Called from the focusin listener so button state is updated immediately
|
|
669
|
+
* on click, without waiting for the next hover/moveAndOpen cycle.
|
|
670
|
+
*/
|
|
671
|
+
private updateToolbarButtonsForTableCellFocus(): void {
|
|
672
|
+
const { plusButton, settingsToggler } = this.nodes;
|
|
673
|
+
|
|
674
|
+
if (!plusButton) {
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
const focusIsInsideCell = this.isFocusInsideTableCell();
|
|
679
|
+
const displayValue = focusIsInsideCell ? 'none' : '';
|
|
680
|
+
|
|
681
|
+
plusButton.style.display = displayValue;
|
|
682
|
+
|
|
683
|
+
if (settingsToggler) {
|
|
684
|
+
settingsToggler.style.display = displayValue;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
599
688
|
/**
|
|
600
689
|
* If the block is inside a table cell, resolve to the parent table block.
|
|
601
690
|
* This ensures the toolbar shows for the table when clicking/focusing inside cells.
|
|
@@ -680,12 +769,12 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
680
769
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- CSS getter now returns Tailwind classes
|
|
681
770
|
this.CSS.actions,
|
|
682
771
|
// Narrow mode positioning on non-mobile screens
|
|
683
|
-
'not-mobile:group-data-[blok-narrow=true]:right-[calc(-1*
|
|
772
|
+
'not-mobile:group-data-[blok-narrow=true]:right-[calc(-1*(var(--spacing-narrow-mode-right-padding))-5px)]',
|
|
684
773
|
// RTL narrow mode: use left positioning instead
|
|
685
|
-
'not-mobile:group-data-[blok-
|
|
686
|
-
'not-mobile:group-data-[blok-
|
|
774
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:right-auto',
|
|
775
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:left-[calc(-1*(var(--spacing-narrow-mode-right-padding))-5px)]',
|
|
687
776
|
// RTL narrow mode additional left offset
|
|
688
|
-
'not-mobile:group-data-[blok-
|
|
777
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:left-[-5px]',
|
|
689
778
|
]);
|
|
690
779
|
|
|
691
780
|
this.nodes.content = content;
|
|
@@ -845,6 +934,18 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
845
934
|
this.readOnlyMutableListeners.on(settingsToggler, 'mousedown', this.settingsTogglerHandler.createMousedownHandler(), true);
|
|
846
935
|
}
|
|
847
936
|
|
|
937
|
+
/**
|
|
938
|
+
* Listen for focus changes inside the editor.
|
|
939
|
+
* When the user clicks/tabs into a table cell, hide the plus button and
|
|
940
|
+
* settings toggler. When focus moves to a regular block, restore them.
|
|
941
|
+
*
|
|
942
|
+
* This runs on every focusin event (not throttled) to ensure buttons
|
|
943
|
+
* update immediately on click — no 300ms delay.
|
|
944
|
+
*/
|
|
945
|
+
this.readOnlyMutableListeners.on(this.Blok.UI.nodes.wrapper, 'focusin', () => {
|
|
946
|
+
this.updateToolbarButtonsForTableCellFocus();
|
|
947
|
+
});
|
|
948
|
+
|
|
848
949
|
/**
|
|
849
950
|
* Subscribe to the 'block-hovered' event if current view is not mobile
|
|
850
951
|
* @see https://github.com/codex-team/editor.js/issues/1972
|
|
@@ -876,11 +977,17 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
876
977
|
}
|
|
877
978
|
|
|
878
979
|
/**
|
|
879
|
-
* Do not move toolbar if it was explicitly closed
|
|
880
|
-
*
|
|
980
|
+
* Do not move toolbar if it was explicitly closed and the user is still
|
|
981
|
+
* hovering the same block. When the user hovers a DIFFERENT block
|
|
982
|
+
* (or hoveredBlock is null after close()), reset the flag and allow
|
|
983
|
+
* the toolbar to reopen — this is an intentional user action.
|
|
881
984
|
*/
|
|
882
985
|
if (this.explicitlyClosed) {
|
|
883
|
-
|
|
986
|
+
if (this.hoveredBlock !== null && this.hoveredBlock === hoveredBlock) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
this.explicitlyClosed = false;
|
|
884
991
|
}
|
|
885
992
|
|
|
886
993
|
/**
|
|
@@ -188,7 +188,7 @@ export class InlineToolbar extends Module<InlineToolbarNodes> {
|
|
|
188
188
|
await this.openingPromise;
|
|
189
189
|
this.openingPromise = null;
|
|
190
190
|
|
|
191
|
-
this.Blok.Toolbar.
|
|
191
|
+
this.Blok.Toolbar.hideBlockActions();
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
/**
|
|
@@ -266,10 +266,10 @@ export class InlineToolbar extends Module<InlineToolbarNodes> {
|
|
|
266
266
|
*/
|
|
267
267
|
private make(): void {
|
|
268
268
|
this.nodes.wrapper = $.make('div', twMerge(
|
|
269
|
-
'absolute top-0 left-0 z-
|
|
270
|
-
'transition-opacity duration-
|
|
269
|
+
'absolute top-0 left-0 z-3 opacity-100 visible',
|
|
270
|
+
'transition-opacity duration-250 ease-out',
|
|
271
271
|
'will-change-[opacity,left,top]',
|
|
272
|
-
'[
|
|
272
|
+
'**:[[hidden]]:hidden!'
|
|
273
273
|
));
|
|
274
274
|
this.nodes.wrapper.setAttribute(DATA_ATTR.interface, INLINE_TOOLBAR_INTERFACE_VALUE);
|
|
275
275
|
this.nodes.wrapper.setAttribute('data-blok-testid', 'inline-toolbar');
|
|
@@ -99,14 +99,14 @@ export class PlusButtonHandler {
|
|
|
99
99
|
// Keep hover background when toolbox is open
|
|
100
100
|
'group-data-[blok-toolbox-opened=true]:bg-bg-light',
|
|
101
101
|
// Mobile styles (static positioning with overlay-pane appearance)
|
|
102
|
-
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-
|
|
102
|
+
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-2',
|
|
103
103
|
'mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile',
|
|
104
104
|
// RTL styles
|
|
105
|
-
'group-data-[blok-rtl=true]:right-[calc(-1*
|
|
105
|
+
'group-data-[blok-rtl=true]:right-[calc(-1*(var(--spacing-toolbox-btn)))] group-data-[blok-rtl=true]:left-auto',
|
|
106
106
|
// Narrow mode (not-mobile)
|
|
107
107
|
'not-mobile:group-data-[blok-narrow=true]:left-[5px]',
|
|
108
108
|
// Narrow mode RTL (not-mobile)
|
|
109
|
-
'not-mobile:group-data-[blok-
|
|
109
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:left-0 not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:right-[5px]'
|
|
110
110
|
),
|
|
111
111
|
], {
|
|
112
112
|
innerHTML: IconPlus,
|
|
@@ -121,12 +121,12 @@ export class SettingsTogglerHandler {
|
|
|
121
121
|
// Hover (can-hover)
|
|
122
122
|
'can-hover:hover:bg-bg-light can-hover:hover:cursor-grab',
|
|
123
123
|
// When toolbox is opened, use pointer cursor on hover
|
|
124
|
-
'group-data-[blok-toolbox-opened=true]:
|
|
124
|
+
'can-hover:hover:group-data-[blok-toolbox-opened=true]:cursor-pointer',
|
|
125
125
|
// When block settings is opened, show hover background and pointer cursor
|
|
126
126
|
'group-data-[blok-block-settings-opened=true]:bg-bg-light',
|
|
127
|
-
'group-data-[blok-block-settings-opened=true]:
|
|
127
|
+
'can-hover:hover:group-data-[blok-block-settings-opened=true]:cursor-pointer',
|
|
128
128
|
// Mobile styles (static positioning with overlay-pane appearance)
|
|
129
|
-
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-
|
|
129
|
+
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-2',
|
|
130
130
|
'mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile'
|
|
131
131
|
),
|
|
132
132
|
'group-data-[blok-dragging=true]:cursor-grabbing',
|
|
@@ -24,7 +24,7 @@ export const getToolbarStyles = (): { [name: string]: string } => {
|
|
|
24
24
|
// Mobile styles
|
|
25
25
|
'mobile:right-auto',
|
|
26
26
|
// RTL styles
|
|
27
|
-
'group-data-[blok-rtl=true]:right-auto group-data-[blok-rtl=true]:left-[calc(-1*
|
|
27
|
+
'group-data-[blok-rtl=true]:right-auto group-data-[blok-rtl=true]:left-[calc(-1*(var(--spacing-toolbox-btn)))]',
|
|
28
28
|
'mobile:group-data-[blok-rtl=true]:ml-0 mobile:group-data-[blok-rtl=true]:mr-auto mobile:group-data-[blok-rtl=true]:pr-0 mobile:group-data-[blok-rtl=true]:pl-[10px]'
|
|
29
29
|
),
|
|
30
30
|
actionsOpened: 'opacity-100',
|
|
@@ -40,14 +40,14 @@ export const getToolbarStyles = (): { [name: string]: string } => {
|
|
|
40
40
|
// Keep hover background when toolbox is opened
|
|
41
41
|
'group-data-[blok-toolbox-opened=true]:bg-bg-light',
|
|
42
42
|
// Mobile styles (static positioning with overlay-pane appearance)
|
|
43
|
-
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-
|
|
43
|
+
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-2',
|
|
44
44
|
'mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile',
|
|
45
45
|
// RTL styles
|
|
46
|
-
'group-data-[blok-rtl=true]:right-[calc(-1*
|
|
46
|
+
'group-data-[blok-rtl=true]:right-[calc(-1*(var(--spacing-toolbox-btn)))] group-data-[blok-rtl=true]:left-auto',
|
|
47
47
|
// Narrow mode (not-mobile)
|
|
48
48
|
'not-mobile:group-data-[blok-narrow=true]:left-[5px]',
|
|
49
49
|
// Narrow mode RTL (not-mobile)
|
|
50
|
-
'not-mobile:group-data-[blok-
|
|
50
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:left-0 not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:right-[5px]'
|
|
51
51
|
),
|
|
52
52
|
plusButtonShortcutKey: 'text-white',
|
|
53
53
|
/**
|
|
@@ -64,12 +64,12 @@ export const getToolbarStyles = (): { [name: string]: string } => {
|
|
|
64
64
|
// Hover (can-hover)
|
|
65
65
|
'can-hover:hover:bg-bg-light can-hover:hover:cursor-grab',
|
|
66
66
|
// When toolbox is opened, use pointer cursor on hover
|
|
67
|
-
'group-data-[blok-toolbox-opened=true]:
|
|
67
|
+
'can-hover:hover:group-data-[blok-toolbox-opened=true]:cursor-pointer',
|
|
68
68
|
// When block settings is opened, show hover background and pointer cursor
|
|
69
69
|
'group-data-[blok-block-settings-opened=true]:bg-bg-light',
|
|
70
|
-
'group-data-[blok-block-settings-opened=true]:
|
|
70
|
+
'can-hover:hover:group-data-[blok-block-settings-opened=true]:cursor-pointer',
|
|
71
71
|
// Mobile styles (static positioning with overlay-pane appearance)
|
|
72
|
-
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-
|
|
72
|
+
'mobile:bg-white mobile:border mobile:border-[#e8e8eb] mobile:shadow-overlay-pane mobile:rounded-[6px] mobile:z-2',
|
|
73
73
|
'mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile',
|
|
74
74
|
// Not-mobile styles
|
|
75
75
|
'not-mobile:w-6'
|
|
@@ -414,15 +414,15 @@ export class UI extends Module<UINodes> {
|
|
|
414
414
|
'group',
|
|
415
415
|
'relative',
|
|
416
416
|
'box-border',
|
|
417
|
-
'z-
|
|
418
|
-
'
|
|
417
|
+
'z-1',
|
|
418
|
+
'data-[blok-dragging=true]:cursor-grabbing',
|
|
419
419
|
// SVG defaults
|
|
420
420
|
'[&_svg]:max-h-full',
|
|
421
421
|
'[&_path]:stroke-current',
|
|
422
422
|
// Native selection color
|
|
423
423
|
'[&_::selection]:bg-selection-inline',
|
|
424
424
|
// Hide placeholder when toolbox is opened
|
|
425
|
-
'[&[data-blok-toolbox-opened=true]_[contentEditable=true][data-blok-placeholder]:focus]:before
|
|
425
|
+
'[&[data-blok-toolbox-opened=true]_[contentEditable=true][data-blok-placeholder]:focus]:before:opacity-0!',
|
|
426
426
|
...(this.isRtl ? [ '[direction:rtl]' ] : []),
|
|
427
427
|
]);
|
|
428
428
|
this.nodes.wrapper.setAttribute(DATA_ATTR.interface, BLOK_INTERFACE_VALUE);
|
|
@@ -433,10 +433,10 @@ export class UI extends Module<UINodes> {
|
|
|
433
433
|
}
|
|
434
434
|
this.nodes.redactor = $.make('div', [
|
|
435
435
|
// Narrow mode: add right margin on non-mobile screens
|
|
436
|
-
'not-mobile:group-data-[blok-narrow=true]:mr-
|
|
436
|
+
'not-mobile:group-data-[blok-narrow=true]:mr-(--spacing-narrow-mode-right-padding)',
|
|
437
437
|
// RTL narrow mode: add left margin instead
|
|
438
|
-
'not-mobile:group-data-[blok-
|
|
439
|
-
'not-mobile:group-data-[blok-
|
|
438
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:ml-(--spacing-narrow-mode-right-padding)',
|
|
439
|
+
'not-mobile:group-data-[blok-rtl=true]:group-data-[blok-narrow=true]:mr-0',
|
|
440
440
|
// Firefox empty contenteditable fix
|
|
441
441
|
'[&_[contenteditable]:empty]:after:content-["\\feff_"]',
|
|
442
442
|
]);
|
|
@@ -157,13 +157,27 @@ export class BlockHoverController extends Controller {
|
|
|
157
157
|
return null;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Filter out blocks whose holders are inside a table cell container.
|
|
162
|
+
* Cell blocks should not participate in nearest-block detection —
|
|
163
|
+
* the parent table block should be found instead.
|
|
164
|
+
* This matches the direct-hit path which also resolves cell blocks to their parent table block.
|
|
165
|
+
*/
|
|
166
|
+
const topLevelBlocks = blocks.filter(block =>
|
|
167
|
+
block.holder.closest('[data-blok-table-cell-blocks]') === null
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
if (topLevelBlocks.length === 0) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const result = topLevelBlocks.reduce<{ block: Block; distance: number }>((nearest, block) => {
|
|
161
175
|
const rect = block.holder.getBoundingClientRect();
|
|
162
176
|
const centerY = (rect.top + rect.bottom) / 2;
|
|
163
177
|
const distance = Math.abs(clientY - centerY);
|
|
164
178
|
|
|
165
179
|
return distance < nearest.distance ? { block, distance } : nearest;
|
|
166
|
-
}, { block:
|
|
180
|
+
}, { block: topLevelBlocks[0], distance: Infinity });
|
|
167
181
|
|
|
168
182
|
return result.block;
|
|
169
183
|
}
|
|
@@ -35,15 +35,34 @@ export const createRedactorTouchHandler = (
|
|
|
35
35
|
/**
|
|
36
36
|
* Select clicked Block as Current
|
|
37
37
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
const block = deps.Blok.BlockManager.setCurrentBlockByChildNode(clickedNode);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* If clicked outside first-level Blocks and it is not RectSelection, set Caret to the last empty Block
|
|
42
|
+
*/
|
|
43
|
+
if (!block && !deps.Blok.RectangleSelection.isRectActivated()) {
|
|
44
|
+
deps.Blok.Caret.setToTheLastBlock();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* If the click landed below the last block's content area (in the holder padding zone),
|
|
49
|
+
* create/focus a new paragraph instead of keeping the block selected.
|
|
50
|
+
*/
|
|
51
|
+
const isBelowLastBlock = block !== undefined
|
|
52
|
+
&& block === deps.Blok.BlockManager.lastBlock
|
|
53
|
+
&& isClickBelowLastBlockContent(block.holder, event);
|
|
54
|
+
|
|
55
|
+
if (isBelowLastBlock && !deps.Blok.ReadOnly.isEnabled) {
|
|
56
|
+
deps.Blok.Caret.setToTheLastBlock();
|
|
57
|
+
deps.Blok.Toolbar.moveAndOpen(deps.Blok.BlockManager.lastBlock);
|
|
58
|
+
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isBelowLastBlock) {
|
|
63
|
+
deps.Blok.Caret.setToTheLastBlock();
|
|
64
|
+
|
|
65
|
+
return;
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
/**
|
|
@@ -51,7 +70,19 @@ export const createRedactorTouchHandler = (
|
|
|
51
70
|
* (used for showing Block Settings toggler after opening and closing Inline Toolbar)
|
|
52
71
|
*/
|
|
53
72
|
if (!deps.Blok.ReadOnly.isEnabled && !deps.Blok.Toolbar.contains(initialTarget)) {
|
|
54
|
-
|
|
73
|
+
/**
|
|
74
|
+
* When the clicked node is inside a table cell, resolve to the parent table block
|
|
75
|
+
* so moveAndOpen receives the table block (not undefined / the inner cell paragraph).
|
|
76
|
+
* Without this, moveAndOpen falls back to currentBlock (the cell paragraph), detects
|
|
77
|
+
* it's inside a table cell, and hides the plus button and settings toggler.
|
|
78
|
+
*/
|
|
79
|
+
const tableCellContainer = clickedNode.closest?.('[data-blok-table-cell-blocks]');
|
|
80
|
+
const tableBlockWrapper = tableCellContainer?.closest('[data-blok-testid="block-wrapper"]');
|
|
81
|
+
const resolvedBlock = tableBlockWrapper
|
|
82
|
+
? deps.Blok.BlockManager.getBlockByChildNode(tableBlockWrapper)
|
|
83
|
+
: undefined;
|
|
84
|
+
|
|
85
|
+
deps.Blok.Toolbar.moveAndOpen(resolvedBlock, clickedNode);
|
|
55
86
|
}
|
|
56
87
|
};
|
|
57
88
|
}
|
|
@@ -93,3 +124,45 @@ export const getClickedNode = (
|
|
|
93
124
|
|
|
94
125
|
return initialTarget;
|
|
95
126
|
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Extracts the clientY coordinate from a mouse or touch event
|
|
130
|
+
*
|
|
131
|
+
* @param event - The event to extract clientY from
|
|
132
|
+
* @returns The clientY value, or null if not available
|
|
133
|
+
*/
|
|
134
|
+
const getClientY = (event: Event): number | null => {
|
|
135
|
+
if (event instanceof MouseEvent) {
|
|
136
|
+
return event.clientY;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (event instanceof TouchEvent && event.touches.length > 0) {
|
|
140
|
+
return event.touches[0].clientY;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks whether a click event landed below a block's content area.
|
|
148
|
+
* Used to detect clicks in the holder padding zone below the last block.
|
|
149
|
+
*
|
|
150
|
+
* @param blockHolder - The block's holder element
|
|
151
|
+
* @param event - The mouse or touch event
|
|
152
|
+
* @returns True if the click was below the block content's bottom edge
|
|
153
|
+
*/
|
|
154
|
+
const isClickBelowLastBlockContent = (
|
|
155
|
+
blockHolder: HTMLElement,
|
|
156
|
+
event: Event
|
|
157
|
+
): boolean => {
|
|
158
|
+
const clientY = getClientY(event);
|
|
159
|
+
|
|
160
|
+
if (clientY === null) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const contentEl = blockHolder.querySelector('[data-blok-element-content]');
|
|
165
|
+
const contentRect = contentEl?.getBoundingClientRect();
|
|
166
|
+
|
|
167
|
+
return contentRect !== undefined && clientY > contentRect.bottom;
|
|
168
|
+
};
|
|
@@ -169,9 +169,15 @@ export class BlockObserver {
|
|
|
169
169
|
this.emitChange({ type: 'move', blockId, origin });
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// Emit pure adds
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
// Emit pure adds — batch when there are multiple so that parent and
|
|
173
|
+
// child blocks can be registered in BlockManager before any lifecycle
|
|
174
|
+
// hooks (like Table.rendered → initializeCells) fire.
|
|
175
|
+
if (pureAdds.length === 1) {
|
|
176
|
+
this.emitChange({ type: 'add', blockId: pureAdds[0], origin });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (pureAdds.length > 1) {
|
|
180
|
+
this.emitChange({ type: 'batch-add', blockIds: pureAdds, origin });
|
|
175
181
|
}
|
|
176
182
|
|
|
177
183
|
// Emit pure removes
|
|
@@ -2,6 +2,7 @@ import * as Y from 'yjs';
|
|
|
2
2
|
|
|
3
3
|
import type { YBlockSerializer, YjsOutputBlockData } from './serializer';
|
|
4
4
|
import type { TransactionOrigin } from './types';
|
|
5
|
+
import { equals } from '../../utils/object';
|
|
5
6
|
|
|
6
7
|
// Re-export YjsOutputBlockData as DocumentStoreBlockData for consistency
|
|
7
8
|
type DocumentStoreBlockData = YjsOutputBlockData;
|
|
@@ -67,7 +68,7 @@ export class DocumentStore {
|
|
|
67
68
|
const yblock = this.serializer.outputDataToYBlock(blockData);
|
|
68
69
|
|
|
69
70
|
this.transact(() => {
|
|
70
|
-
const insertIndex = index ?? this.yblocks.length;
|
|
71
|
+
const insertIndex = Math.max(0, Math.min(index ?? this.yblocks.length, this.yblocks.length));
|
|
71
72
|
this.yblocks.insert(insertIndex, [yblock]);
|
|
72
73
|
}, 'local');
|
|
73
74
|
|
|
@@ -121,10 +122,11 @@ export class DocumentStore {
|
|
|
121
122
|
|
|
122
123
|
this.yblocks.delete(fromIndex, 1);
|
|
123
124
|
|
|
124
|
-
// toIndex
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
125
|
+
// Clamp toIndex to valid range after deletion shortened the array.
|
|
126
|
+
// An out-of-bounds toIndex means the caller had stale state — clamp
|
|
127
|
+
// to array bounds rather than letting Yjs throw "Length exceeded!".
|
|
128
|
+
const clampedToIndex = Math.max(0, Math.min(toIndex, this.yblocks.length));
|
|
129
|
+
this.yblocks.insert(clampedToIndex, [this.serializer.outputDataToYBlock(blockData)]);
|
|
128
130
|
}, transactionOrigin);
|
|
129
131
|
}
|
|
130
132
|
|
|
@@ -161,8 +163,9 @@ export class DocumentStore {
|
|
|
161
163
|
|
|
162
164
|
// Skip if value hasn't changed - this prevents creating unnecessary undo entries
|
|
163
165
|
// when block data is synced after mutations that don't actually change data
|
|
164
|
-
// (e.g., marker updates in list items during undo/redo
|
|
165
|
-
|
|
166
|
+
// (e.g., marker updates in list items during undo/redo, or table content
|
|
167
|
+
// arrays that are reference-different but structurally identical)
|
|
168
|
+
if (equals(currentValue, value)) {
|
|
166
169
|
return;
|
|
167
170
|
}
|
|
168
171
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Event emitted when blocks change
|
|
2
|
+
* Event emitted when blocks change.
|
|
3
|
+
*
|
|
4
|
+
* Most events carry a single `blockId`. The `batch-add` type carries
|
|
5
|
+
* multiple IDs so that parent and child blocks can be created together
|
|
6
|
+
* before any lifecycle hooks fire.
|
|
3
7
|
*/
|
|
4
|
-
export
|
|
5
|
-
type: 'add' | 'remove' | 'update' | 'move';
|
|
6
|
-
|
|
7
|
-
origin: TransactionOrigin;
|
|
8
|
-
}
|
|
8
|
+
export type BlockChangeEvent =
|
|
9
|
+
| { type: 'add' | 'remove' | 'update' | 'move'; blockId: string; origin: TransactionOrigin }
|
|
10
|
+
| { type: 'batch-add'; blockIds: string[]; origin: TransactionOrigin };
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Transaction origin types.
|