@jackuait/blok 0.6.0-beta.9 → 0.6.0
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-BAh1rvUC.mjs} +3410 -2927
- package/dist/chunks/i18next-B47TKgbU.mjs +1303 -0
- package/dist/chunks/{i18next-loader-DjR4d8M7.mjs → i18next-loader-CHtGO6IK.mjs} +2 -2
- package/dist/chunks/{index-oe38cp86.mjs → index-DBWWKrDe.mjs} +12 -12
- package/dist/chunks/{inline-tool-convert-SRTkyaZn.mjs → inline-tool-convert-DduRc0fF.mjs} +1467 -951
- 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 +2 -2
- 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 +3190 -1690
- 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/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 +17 -0
- 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/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 +19 -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 +2 -2
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +14 -12
- package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
- package/src/components/utils/popover/popover-abstract.ts +27 -3
- 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 +2 -2
- package/src/components/utils/sanitizer.ts +24 -3
- package/src/components/utils/tw.ts +17 -5
- package/src/stories/Header.stories.ts +106 -0
- package/src/stories/MarkerColors.stories.ts +730 -0
- package/src/stories/Popover.stories.ts +1 -3
- package/src/stories/Table.stories.ts +1662 -0
- package/src/styles/main.css +207 -37
- package/src/tools/header/index.ts +1 -1
- package/src/tools/index.ts +3 -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/variants/blok-minimum.ts +13 -0
- package/types/api/block.d.ts +13 -0
- package/types/api/blocks.d.ts +16 -0
- package/types/tools/table.d.ts +2 -0
- package/dist/chunks/i18next-CugVlwWp.mjs +0 -1292
- package/src/tools/table/data-normalizer.ts +0 -32
|
@@ -163,18 +163,19 @@ export const syncColWidthsAfterDeleteColumn = (colWidths: number[] | undefined,
|
|
|
163
163
|
export const computeInsertColumnWidths = (
|
|
164
164
|
gridEl: HTMLElement,
|
|
165
165
|
index: number,
|
|
166
|
-
|
|
166
|
+
colWidths: number[] | undefined,
|
|
167
|
+
initialColWidth: number | undefined,
|
|
167
168
|
grid: TableGrid,
|
|
168
169
|
): number[] => {
|
|
169
|
-
const
|
|
170
|
+
const widths = colWidths ?? readPixelWidths(gridEl);
|
|
170
171
|
|
|
171
|
-
const halfWidth =
|
|
172
|
-
? Math.round((
|
|
173
|
-
: computeHalfAvgWidth(
|
|
172
|
+
const halfWidth = initialColWidth !== undefined
|
|
173
|
+
? Math.round((initialColWidth / 2) * 100) / 100
|
|
174
|
+
: computeHalfAvgWidth(widths);
|
|
174
175
|
|
|
175
|
-
grid.addColumn(gridEl, index,
|
|
176
|
+
grid.addColumn(gridEl, index, widths, halfWidth);
|
|
176
177
|
|
|
177
|
-
const newWidths = [...
|
|
178
|
+
const newWidths = [...widths];
|
|
178
179
|
|
|
179
180
|
newWidths.splice(index, 0, halfWidth);
|
|
180
181
|
|
|
@@ -230,53 +231,6 @@ export const getBlockIdsInColumn = (element: HTMLElement | null, cellBlocks: Tab
|
|
|
230
231
|
return cellBlocks?.getBlockIdsFromCells(cellsInColumn) ?? [];
|
|
231
232
|
};
|
|
232
233
|
|
|
233
|
-
// ─── Row/column deletion with block cleanup ─────────────────────────
|
|
234
|
-
|
|
235
|
-
export const deleteRowWithBlockCleanup = (
|
|
236
|
-
gridEl: HTMLElement,
|
|
237
|
-
rowIndex: number,
|
|
238
|
-
grid: TableGrid,
|
|
239
|
-
cellBlocks: TableCellBlocks | null,
|
|
240
|
-
): void => {
|
|
241
|
-
const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
|
|
242
|
-
const row = rows[rowIndex];
|
|
243
|
-
|
|
244
|
-
if (row && cellBlocks) {
|
|
245
|
-
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
246
|
-
|
|
247
|
-
cellBlocks.deleteBlocks(cellBlocks.getBlockIdsFromCells(cells));
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
grid.deleteRow(gridEl, rowIndex);
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
export const deleteColumnWithBlockCleanup = (
|
|
254
|
-
gridEl: HTMLElement,
|
|
255
|
-
colIndex: number,
|
|
256
|
-
colWidths: number[] | undefined,
|
|
257
|
-
grid: TableGrid,
|
|
258
|
-
cellBlocks: TableCellBlocks | null,
|
|
259
|
-
): number[] | undefined => {
|
|
260
|
-
if (cellBlocks) {
|
|
261
|
-
const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
|
|
262
|
-
const cellsInColumn: Element[] = [];
|
|
263
|
-
|
|
264
|
-
rows.forEach(row => {
|
|
265
|
-
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
266
|
-
|
|
267
|
-
if (colIndex < cells.length) {
|
|
268
|
-
cellsInColumn.push(cells[colIndex]);
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
cellBlocks.deleteBlocks(cellBlocks.getBlockIdsFromCells(cellsInColumn));
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
grid.deleteColumn(gridEl, colIndex);
|
|
276
|
-
|
|
277
|
-
return syncColWidthsAfterDeleteColumn(colWidths, colIndex);
|
|
278
|
-
};
|
|
279
|
-
|
|
280
234
|
// ─── Populate new cells ─────────────────────────────────────────────
|
|
281
235
|
|
|
282
236
|
export const populateNewCells = (gridEl: HTMLElement, cellBlocks: TableCellBlocks | null): void => {
|
|
@@ -293,6 +247,7 @@ export const mountCellBlocksReadOnly = (
|
|
|
293
247
|
gridEl: HTMLElement,
|
|
294
248
|
content: LegacyCellContent[][],
|
|
295
249
|
api: API,
|
|
250
|
+
_tableBlockId: string,
|
|
296
251
|
): void => {
|
|
297
252
|
const rowElements = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
|
|
298
253
|
|
|
@@ -326,21 +281,18 @@ export const mountCellBlocksReadOnly = (
|
|
|
326
281
|
}
|
|
327
282
|
|
|
328
283
|
if (!isCellWithBlocks(cellContent)) {
|
|
329
|
-
//
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
'paragraph',
|
|
333
|
-
{ text: legacyText },
|
|
334
|
-
{},
|
|
335
|
-
undefined,
|
|
336
|
-
true
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
insertedBlock?.holder && container.appendChild(insertedBlock.holder);
|
|
284
|
+
// Read-only render path must not mutate block state.
|
|
285
|
+
// Render legacy content (plain string) in-place.
|
|
286
|
+
container.textContent = cellContent;
|
|
340
287
|
|
|
341
288
|
return;
|
|
342
289
|
}
|
|
343
290
|
|
|
291
|
+
// If this container previously rendered legacy text, clear it before mounting holders.
|
|
292
|
+
if (!hasExistingBlocks && (container.textContent ?? '').length > 0) {
|
|
293
|
+
container.textContent = '';
|
|
294
|
+
}
|
|
295
|
+
|
|
344
296
|
for (const blockId of cellContent.blocks) {
|
|
345
297
|
const index = api.blocks.getBlockIndex(blockId);
|
|
346
298
|
|
|
@@ -356,6 +308,15 @@ export const mountCellBlocksReadOnly = (
|
|
|
356
308
|
|
|
357
309
|
container.appendChild(block.holder);
|
|
358
310
|
}
|
|
311
|
+
|
|
312
|
+
// Strip placeholder attributes so paragraphs inside table cells
|
|
313
|
+
// don't show standalone-paragraph placeholders in readonly mode.
|
|
314
|
+
container.querySelectorAll<HTMLElement>('[data-blok-placeholder-active]').forEach(el => {
|
|
315
|
+
el.removeAttribute('data-blok-placeholder-active');
|
|
316
|
+
});
|
|
317
|
+
container.querySelectorAll<HTMLElement>('[data-placeholder]').forEach(el => {
|
|
318
|
+
el.removeAttribute('data-placeholder');
|
|
319
|
+
});
|
|
359
320
|
});
|
|
360
321
|
});
|
|
361
322
|
};
|
|
@@ -414,7 +375,7 @@ export const setupKeyboardNavigation = (
|
|
|
414
375
|
});
|
|
415
376
|
};
|
|
416
377
|
|
|
417
|
-
export const SCROLL_OVERFLOW_CLASSES = ['overflow-x-auto', '
|
|
378
|
+
export const SCROLL_OVERFLOW_CLASSES = ['overflow-x-auto', 'overflow-y-hidden'];
|
|
418
379
|
|
|
419
380
|
export const enableScrollOverflow = (element: HTMLDivElement | null): void => {
|
|
420
381
|
element?.classList.add(...SCROLL_OVERFLOW_CLASSES);
|
|
@@ -422,13 +383,7 @@ export const enableScrollOverflow = (element: HTMLDivElement | null): void => {
|
|
|
422
383
|
|
|
423
384
|
// ─── Heading styles ─────────────────────────────────────────────────
|
|
424
385
|
|
|
425
|
-
export const updateHeadingStyles = (
|
|
426
|
-
if (!element) {
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
const gridEl = element.firstElementChild as HTMLElement;
|
|
431
|
-
|
|
386
|
+
export const updateHeadingStyles = (gridEl: HTMLElement | null, withHeadings: boolean): void => {
|
|
432
387
|
if (!gridEl) {
|
|
433
388
|
return;
|
|
434
389
|
}
|
|
@@ -444,13 +399,39 @@ export const updateHeadingStyles = (element: HTMLDivElement | null, withHeadings
|
|
|
444
399
|
}
|
|
445
400
|
};
|
|
446
401
|
|
|
447
|
-
export const
|
|
448
|
-
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
402
|
+
export const applyCellColors = (gridEl: HTMLElement, content: LegacyCellContent[][]): void => {
|
|
403
|
+
const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
|
|
451
404
|
|
|
452
|
-
|
|
405
|
+
content.forEach((rowContent, r) => {
|
|
406
|
+
if (r >= rows.length) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const cells = rows[r].querySelectorAll(`[${CELL_ATTR}]`);
|
|
411
|
+
|
|
412
|
+
rowContent.forEach((cellContent, c) => {
|
|
413
|
+
if (c >= cells.length) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const el = cells[c] as HTMLElement;
|
|
418
|
+
|
|
419
|
+
if (isCellWithBlocks(cellContent) && cellContent.color) {
|
|
420
|
+
el.style.backgroundColor = cellContent.color;
|
|
421
|
+
} else {
|
|
422
|
+
el.style.backgroundColor = '';
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (isCellWithBlocks(cellContent) && cellContent.textColor) {
|
|
426
|
+
el.style.color = cellContent.textColor;
|
|
427
|
+
} else {
|
|
428
|
+
el.style.color = '';
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
};
|
|
453
433
|
|
|
434
|
+
export const updateHeadingColumnStyles = (gridEl: HTMLElement | null, withHeadingColumn: boolean): void => {
|
|
454
435
|
if (!gridEl) {
|
|
455
436
|
return;
|
|
456
437
|
}
|
|
@@ -23,6 +23,7 @@ export class TableResize {
|
|
|
23
23
|
private dragStartX = 0;
|
|
24
24
|
private dragColIndex = -1;
|
|
25
25
|
private startColWidth = 0;
|
|
26
|
+
private dragRowCells: HTMLElement[][] | null = null;
|
|
26
27
|
private handles: HTMLElement[] = [];
|
|
27
28
|
private needsInitialApply: boolean;
|
|
28
29
|
|
|
@@ -73,6 +74,7 @@ export class TableResize {
|
|
|
73
74
|
this.gridEl.removeEventListener('pointerdown', this.boundPointerDown);
|
|
74
75
|
document.removeEventListener('pointermove', this.boundPointerMove);
|
|
75
76
|
document.removeEventListener('pointerup', this.boundPointerUp);
|
|
77
|
+
this.dragRowCells = null;
|
|
76
78
|
|
|
77
79
|
this.handles.forEach(handle => handle.remove());
|
|
78
80
|
this.handles = [];
|
|
@@ -168,6 +170,7 @@ export class TableResize {
|
|
|
168
170
|
this.isDragging = true;
|
|
169
171
|
this.dragStartX = e.clientX;
|
|
170
172
|
this.startColWidth = this.colWidths[this.dragColIndex];
|
|
173
|
+
this.dragRowCells = this.resolveRowCells();
|
|
171
174
|
|
|
172
175
|
this.onDragStart?.();
|
|
173
176
|
this.gridEl.style.userSelect = 'none';
|
|
@@ -192,7 +195,7 @@ export class TableResize {
|
|
|
192
195
|
const newWidth = Math.max(MIN_COL_WIDTH, rawWidth);
|
|
193
196
|
|
|
194
197
|
this.colWidths[this.dragColIndex] = newWidth;
|
|
195
|
-
this.applyWidths();
|
|
198
|
+
this.applyWidths(this.dragRowCells ?? undefined);
|
|
196
199
|
this.updateHandlePositions();
|
|
197
200
|
this.onDrag?.();
|
|
198
201
|
}
|
|
@@ -213,25 +216,26 @@ export class TableResize {
|
|
|
213
216
|
|
|
214
217
|
document.removeEventListener('pointermove', this.boundPointerMove);
|
|
215
218
|
document.removeEventListener('pointerup', this.boundPointerUp);
|
|
219
|
+
this.dragRowCells = null;
|
|
216
220
|
|
|
217
221
|
this.onChange([...this.colWidths]);
|
|
218
222
|
}
|
|
219
223
|
|
|
220
|
-
private
|
|
221
|
-
const
|
|
224
|
+
private resolveRowCells(): HTMLElement[][] {
|
|
225
|
+
const rows = this.gridEl.querySelectorAll<HTMLElement>(`[${ROW_ATTR}]`);
|
|
222
226
|
|
|
223
|
-
|
|
227
|
+
return Array.from(rows, row => Array.from(row.querySelectorAll<HTMLElement>(`[${CELL_ATTR}]`)));
|
|
228
|
+
}
|
|
224
229
|
|
|
225
|
-
|
|
230
|
+
private applyWidths(rowCells: HTMLElement[][] = this.resolveRowCells()): void {
|
|
231
|
+
const totalWidth = this.colWidths.reduce((sum, w) => sum + w, 0);
|
|
226
232
|
|
|
227
|
-
|
|
228
|
-
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
233
|
+
this.gridEl.style.width = `${totalWidth + BORDER_WIDTH}px`;
|
|
229
234
|
|
|
230
|
-
|
|
235
|
+
rowCells.forEach(cells => {
|
|
236
|
+
cells.forEach((cellEl, i) => {
|
|
231
237
|
if (i < this.colWidths.length) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
cellEl.style.width = `${this.colWidths[i]}px`;
|
|
238
|
+
cellEl.style.setProperty('width', `${this.colWidths[i]}px`);
|
|
235
239
|
}
|
|
236
240
|
});
|
|
237
241
|
});
|
|
@@ -2,10 +2,75 @@ import type { API } from '../../../types';
|
|
|
2
2
|
import type { Block } from '../../components/block';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Default block tools that are always restricted from being inserted into table cells.
|
|
6
6
|
* These tools create semantic or structural issues when nested in table cells.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
const DEFAULT_RESTRICTED_TOOLS = ['header', 'table'];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Additional restricted tools registered via table tool config.
|
|
12
|
+
* Users can extend the default list by setting `restrictedTools` in the table tool config.
|
|
13
|
+
*/
|
|
14
|
+
const additionalRestrictedTools = new Map<string, number>();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Register additional tools as restricted in table cells.
|
|
18
|
+
* Called by the Table tool constructor when `restrictedTools` is set in the config.
|
|
19
|
+
*
|
|
20
|
+
* @param tools - Tool names to add to the restricted list
|
|
21
|
+
* @returns Cleanup function to unregister these tools when the owner is destroyed
|
|
22
|
+
*/
|
|
23
|
+
export const registerAdditionalRestrictedTools = (tools: string[]): (() => void) => {
|
|
24
|
+
const uniqueTools = [...new Set(tools)];
|
|
25
|
+
|
|
26
|
+
for (const tool of uniqueTools) {
|
|
27
|
+
const currentCount = additionalRestrictedTools.get(tool) ?? 0;
|
|
28
|
+
|
|
29
|
+
additionalRestrictedTools.set(tool, currentCount + 1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const state = { cleanedUp: false };
|
|
33
|
+
|
|
34
|
+
return (): void => {
|
|
35
|
+
if (state.cleanedUp) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
state.cleanedUp = true;
|
|
40
|
+
|
|
41
|
+
for (const tool of uniqueTools) {
|
|
42
|
+
const currentCount = additionalRestrictedTools.get(tool);
|
|
43
|
+
|
|
44
|
+
if (currentCount === undefined) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (currentCount <= 1) {
|
|
49
|
+
additionalRestrictedTools.delete(tool);
|
|
50
|
+
} else {
|
|
51
|
+
additionalRestrictedTools.set(tool, currentCount - 1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Clear all additional restricted tools.
|
|
59
|
+
* Useful for cleanup when the editor is destroyed or in tests.
|
|
60
|
+
*/
|
|
61
|
+
export const clearAdditionalRestrictedTools = (): void => {
|
|
62
|
+
additionalRestrictedTools.clear();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Returns all restricted tool names (default + additional registered via config).
|
|
67
|
+
* Used by the toolbox to hide restricted tools when inside table cells.
|
|
68
|
+
*
|
|
69
|
+
* @returns Array of all restricted tool names
|
|
70
|
+
*/
|
|
71
|
+
export const getRestrictedTools = (): string[] => {
|
|
72
|
+
return [...DEFAULT_RESTRICTED_TOOLS, ...additionalRestrictedTools.keys()];
|
|
73
|
+
};
|
|
9
74
|
|
|
10
75
|
/**
|
|
11
76
|
* Check if a block or element is inside a table cell.
|
|
@@ -26,12 +91,13 @@ export const isInsideTableCell = (block: Block | HTMLElement | null | undefined)
|
|
|
26
91
|
|
|
27
92
|
/**
|
|
28
93
|
* Check if a tool name is restricted inside table cells.
|
|
94
|
+
* Checks both the default restricted list and any additional tools registered via config.
|
|
29
95
|
*
|
|
30
96
|
* @param toolName - Name of the block tool to check
|
|
31
97
|
* @returns true if the tool is restricted in table cells, false otherwise
|
|
32
98
|
*/
|
|
33
99
|
export const isRestrictedInTableCell = (toolName: string): boolean => {
|
|
34
|
-
return
|
|
100
|
+
return DEFAULT_RESTRICTED_TOOLS.includes(toolName) || additionalRestrictedTools.has(toolName);
|
|
35
101
|
};
|
|
36
102
|
|
|
37
103
|
/**
|
|
@@ -3,24 +3,34 @@ import type { TableGrid } from './table-core';
|
|
|
3
3
|
import {
|
|
4
4
|
applyPixelWidths,
|
|
5
5
|
computeInsertColumnWidths,
|
|
6
|
-
deleteColumnWithBlockCleanup,
|
|
7
|
-
deleteRowWithBlockCleanup,
|
|
8
6
|
populateNewCells,
|
|
9
7
|
redistributePercentWidths,
|
|
8
|
+
syncColWidthsAfterDeleteColumn,
|
|
10
9
|
syncColWidthsAfterMove,
|
|
11
10
|
} from './table-operations';
|
|
12
11
|
import type { RowColAction } from './table-row-col-controls';
|
|
13
|
-
import type { TableData } from './types';
|
|
14
12
|
|
|
15
13
|
/**
|
|
16
14
|
* Describes which row or column to highlight after an action completes.
|
|
17
15
|
*/
|
|
18
16
|
export type PendingHighlight = { type: 'row' | 'col'; index: number };
|
|
19
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Minimal metadata the action handler needs.
|
|
20
|
+
* Decoupled from TableData so callers can pass model-derived primitives.
|
|
21
|
+
*/
|
|
22
|
+
export interface ActionData {
|
|
23
|
+
colWidths?: number[];
|
|
24
|
+
withHeadings: boolean;
|
|
25
|
+
withHeadingColumn: boolean;
|
|
26
|
+
initialColWidth?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
interface ActionContext {
|
|
21
30
|
grid: TableGrid;
|
|
22
|
-
data:
|
|
31
|
+
data: ActionData;
|
|
23
32
|
cellBlocks: TableCellBlocks | null;
|
|
33
|
+
blocksToDelete?: string[];
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
interface ActionResult {
|
|
@@ -53,7 +63,7 @@ const handleInsertCol = (
|
|
|
53
63
|
index: number,
|
|
54
64
|
ctx: ActionContext,
|
|
55
65
|
): ActionResult => {
|
|
56
|
-
const colWidths = computeInsertColumnWidths(gridEl, index, ctx.data, ctx.grid);
|
|
66
|
+
const colWidths = computeInsertColumnWidths(gridEl, index, ctx.data.colWidths, ctx.data.initialColWidth, ctx.grid);
|
|
57
67
|
|
|
58
68
|
populateNewCells(gridEl, ctx.cellBlocks);
|
|
59
69
|
|
|
@@ -105,7 +115,9 @@ const handleDeleteRow = (
|
|
|
105
115
|
index: number,
|
|
106
116
|
ctx: ActionContext,
|
|
107
117
|
): ActionResult => {
|
|
108
|
-
|
|
118
|
+
ctx.cellBlocks?.deleteBlocks(ctx.blocksToDelete ?? []);
|
|
119
|
+
ctx.grid.deleteRow(gridEl, index);
|
|
120
|
+
|
|
109
121
|
const newRowCount = ctx.grid.getRowCount(gridEl);
|
|
110
122
|
const neighborRow = index < newRowCount ? index : index - 1;
|
|
111
123
|
|
|
@@ -123,7 +135,10 @@ const handleDeleteCol = (
|
|
|
123
135
|
index: number,
|
|
124
136
|
ctx: ActionContext,
|
|
125
137
|
): ActionResult => {
|
|
126
|
-
|
|
138
|
+
ctx.cellBlocks?.deleteBlocks(ctx.blocksToDelete ?? []);
|
|
139
|
+
ctx.grid.deleteColumn(gridEl, index);
|
|
140
|
+
|
|
141
|
+
const colWidths = syncColWidthsAfterDeleteColumn(ctx.data.colWidths, index);
|
|
127
142
|
|
|
128
143
|
if (colWidths) {
|
|
129
144
|
applyPixelWidths(gridEl, colWidths);
|
|
@@ -33,6 +33,8 @@ export type RowColAction =
|
|
|
33
33
|
|
|
34
34
|
export interface TableRowColControlsOptions {
|
|
35
35
|
grid: HTMLElement;
|
|
36
|
+
overlay?: HTMLElement;
|
|
37
|
+
scrollContainer?: HTMLElement;
|
|
36
38
|
getColumnCount: () => number;
|
|
37
39
|
getRowCount: () => number;
|
|
38
40
|
isHeadingRow: () => boolean;
|
|
@@ -46,8 +48,8 @@ export interface TableRowColControlsOptions {
|
|
|
46
48
|
|
|
47
49
|
const GRIP_CAPSULE_CLASSES = [
|
|
48
50
|
'absolute',
|
|
49
|
-
'z-
|
|
50
|
-
'rounded',
|
|
51
|
+
'z-3',
|
|
52
|
+
'rounded-sm',
|
|
51
53
|
'cursor-grab',
|
|
52
54
|
'select-none',
|
|
53
55
|
'transition-[opacity,background-color,width,height]',
|
|
@@ -83,6 +85,8 @@ const GRIP_ACTIVE_CLASSES = [
|
|
|
83
85
|
*/
|
|
84
86
|
export class TableRowColControls {
|
|
85
87
|
private grid: HTMLElement;
|
|
88
|
+
private overlay: HTMLElement | undefined;
|
|
89
|
+
private scrollContainer: HTMLElement | undefined;
|
|
86
90
|
private getColumnCount: () => number;
|
|
87
91
|
private getRowCount: () => number;
|
|
88
92
|
private isHeadingRow: () => boolean;
|
|
@@ -108,9 +112,12 @@ export class TableRowColControls {
|
|
|
108
112
|
private boundMouseOver: (e: MouseEvent) => void;
|
|
109
113
|
private boundMouseLeave: (e: MouseEvent) => void;
|
|
110
114
|
private boundPointerDown: (e: PointerEvent) => void;
|
|
115
|
+
private boundScrollHandler: (() => void) | null = null;
|
|
111
116
|
|
|
112
117
|
constructor(options: TableRowColControlsOptions) {
|
|
113
118
|
this.grid = options.grid;
|
|
119
|
+
this.overlay = options.overlay;
|
|
120
|
+
this.scrollContainer = options.scrollContainer;
|
|
114
121
|
this.getColumnCount = options.getColumnCount;
|
|
115
122
|
this.getRowCount = options.getRowCount;
|
|
116
123
|
this.isHeadingRow = options.isHeadingRow;
|
|
@@ -141,11 +148,39 @@ export class TableRowColControls {
|
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
/**
|
|
144
|
-
* Recreate grips after structural changes (row/column add/delete/move)
|
|
151
|
+
* Recreate grips after structural changes (row/column add/delete/move).
|
|
152
|
+
* Preserves the active grip state when a popover is open so the grip
|
|
153
|
+
* remains visible after being recreated.
|
|
145
154
|
*/
|
|
146
155
|
public refresh(): void {
|
|
156
|
+
const popoverGripInfo = this.popoverState.grip
|
|
157
|
+
? this.detectGripType(this.popoverState.grip)
|
|
158
|
+
: null;
|
|
159
|
+
|
|
147
160
|
this.destroyGrips();
|
|
148
161
|
this.createGrips();
|
|
162
|
+
|
|
163
|
+
if (!popoverGripInfo) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const newGrip = popoverGripInfo.type === 'col'
|
|
168
|
+
? this.colGrips[popoverGripInfo.index]
|
|
169
|
+
: this.rowGrips[popoverGripInfo.index];
|
|
170
|
+
|
|
171
|
+
if (!newGrip) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
this.popoverState.grip = newGrip;
|
|
176
|
+
this.hideAllGripsExcept(newGrip);
|
|
177
|
+
this.applyActiveClasses(newGrip);
|
|
178
|
+
|
|
179
|
+
if (popoverGripInfo.type === 'col') {
|
|
180
|
+
newGrip.style.height = `${GRIP_HOVER_SIZE}px`;
|
|
181
|
+
} else {
|
|
182
|
+
newGrip.style.width = `${GRIP_HOVER_SIZE}px`;
|
|
183
|
+
}
|
|
149
184
|
}
|
|
150
185
|
|
|
151
186
|
/**
|
|
@@ -162,6 +197,7 @@ export class TableRowColControls {
|
|
|
162
197
|
}
|
|
163
198
|
|
|
164
199
|
this.unlockGrip();
|
|
200
|
+
this.clearHideTimeout();
|
|
165
201
|
this.hideAllGripsExcept(grip);
|
|
166
202
|
this.applyActiveClasses(grip);
|
|
167
203
|
|
|
@@ -173,18 +209,32 @@ export class TableRowColControls {
|
|
|
173
209
|
|
|
174
210
|
this.lockedGrip = grip;
|
|
175
211
|
|
|
176
|
-
|
|
177
|
-
document.addEventListener('pointerdown', this.boundUnlockGrip);
|
|
178
|
-
});
|
|
212
|
+
document.addEventListener('pointerdown', this.boundUnlockGrip);
|
|
179
213
|
}
|
|
180
214
|
|
|
181
|
-
private handleUnlockGrip(): void {
|
|
215
|
+
private handleUnlockGrip(e: PointerEvent): void {
|
|
182
216
|
document.removeEventListener('pointerdown', this.boundUnlockGrip);
|
|
183
217
|
|
|
184
218
|
if (this.lockedGrip) {
|
|
185
219
|
this.applyIdleClasses(this.lockedGrip);
|
|
186
220
|
this.lockedGrip = null;
|
|
187
221
|
}
|
|
222
|
+
|
|
223
|
+
// Re-evaluate grip visibility: the preceding mouseover was blocked
|
|
224
|
+
// by isGripInteractionLocked(). Check if pointer is over a table cell.
|
|
225
|
+
const target = e.target instanceof HTMLElement ? e.target : null;
|
|
226
|
+
const cell = target?.closest<HTMLElement>(`[${CELL_ATTR}]`);
|
|
227
|
+
|
|
228
|
+
if (cell) {
|
|
229
|
+
const position = this.getCellPosition(cell);
|
|
230
|
+
|
|
231
|
+
if (position) {
|
|
232
|
+
this.clearHideTimeout();
|
|
233
|
+
this.showColGrip(position.col);
|
|
234
|
+
this.showRowGrip(position.row);
|
|
235
|
+
this.isInsideTable = true;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
188
238
|
}
|
|
189
239
|
|
|
190
240
|
private unlockGrip(): void {
|
|
@@ -192,6 +242,37 @@ export class TableRowColControls {
|
|
|
192
242
|
this.lockedGrip = null;
|
|
193
243
|
}
|
|
194
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Return the indices of the currently visible grips, or null if none are active.
|
|
247
|
+
*/
|
|
248
|
+
public getVisibleGripIndices(): { col: number; row: number } | null {
|
|
249
|
+
if (this.activeColGripIndex < 0 && this.activeRowGripIndex < 0) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return { col: this.activeColGripIndex, row: this.activeRowGripIndex };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Programmatically restore grip visibility (e.g. after a DOM rebuild during undo).
|
|
258
|
+
*/
|
|
259
|
+
public restoreVisibleGrips(col: number, row: number): void {
|
|
260
|
+
// Set isInsideTable BEFORE showing grips so applyVisibleClasses()
|
|
261
|
+
// skips the CSS opacity transition (no flash).
|
|
262
|
+
this.isInsideTable = col >= 0 || row >= 0;
|
|
263
|
+
|
|
264
|
+
if (col >= 0) {
|
|
265
|
+
this.showColGrip(col);
|
|
266
|
+
}
|
|
267
|
+
if (row >= 0) {
|
|
268
|
+
this.showRowGrip(row);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
public get isPopoverOpen(): boolean {
|
|
273
|
+
return this.popoverState.popover !== null;
|
|
274
|
+
}
|
|
275
|
+
|
|
195
276
|
public destroy(): void {
|
|
196
277
|
this.destroyPopover();
|
|
197
278
|
this.unlockGrip();
|
|
@@ -205,28 +286,45 @@ export class TableRowColControls {
|
|
|
205
286
|
private createGrips(): void {
|
|
206
287
|
const colCount = this.getColumnCount();
|
|
207
288
|
const rowCount = this.getRowCount();
|
|
289
|
+
const gripContainer = this.overlay ?? this.grid;
|
|
208
290
|
|
|
209
291
|
Array.from({ length: colCount }).forEach((_, i) => {
|
|
210
292
|
const grip = this.createGripElement('col', i);
|
|
211
293
|
|
|
212
294
|
this.colGrips.push(grip);
|
|
213
|
-
|
|
295
|
+
gripContainer.appendChild(grip);
|
|
214
296
|
});
|
|
215
297
|
|
|
216
298
|
Array.from({ length: rowCount }).forEach((_, i) => {
|
|
217
299
|
const grip = this.createGripElement('row', i);
|
|
218
300
|
|
|
219
301
|
this.rowGrips.push(grip);
|
|
220
|
-
|
|
302
|
+
gripContainer.appendChild(grip);
|
|
221
303
|
});
|
|
222
304
|
|
|
223
305
|
this.positionGrips();
|
|
224
306
|
this.observeRowHeights();
|
|
307
|
+
this.attachScrollListener();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private attachScrollListener(): void {
|
|
311
|
+
if (this.overlay && this.scrollContainer) {
|
|
312
|
+
this.boundScrollHandler = () => this.positionGrips();
|
|
313
|
+
this.scrollContainer.addEventListener('scroll', this.boundScrollHandler);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private detachScrollListener(): void {
|
|
318
|
+
if (this.boundScrollHandler && this.scrollContainer) {
|
|
319
|
+
this.scrollContainer.removeEventListener('scroll', this.boundScrollHandler);
|
|
320
|
+
this.boundScrollHandler = null;
|
|
321
|
+
}
|
|
225
322
|
}
|
|
226
323
|
|
|
227
324
|
private destroyGrips(): void {
|
|
228
325
|
this.rowResizeObserver?.disconnect();
|
|
229
326
|
this.rowResizeObserver = null;
|
|
327
|
+
this.detachScrollListener();
|
|
230
328
|
this.colGrips.forEach(g => g.remove());
|
|
231
329
|
this.rowGrips.forEach(g => g.remove());
|
|
232
330
|
this.colGrips = [];
|
|
@@ -257,13 +355,20 @@ export class TableRowColControls {
|
|
|
257
355
|
|
|
258
356
|
grip.addEventListener('pointerdown', this.boundPointerDown);
|
|
259
357
|
grip.addEventListener('mouseenter', () => {
|
|
358
|
+
if (this.overlay) {
|
|
359
|
+
this.clearHideTimeout();
|
|
360
|
+
}
|
|
260
361
|
if (!this.isGripInteractionLocked()) {
|
|
261
362
|
expandGrip(grip, type);
|
|
262
363
|
}
|
|
263
364
|
});
|
|
264
365
|
grip.addEventListener('mouseleave', () => {
|
|
265
|
-
if (
|
|
266
|
-
|
|
366
|
+
if (this.isGripInteractionLocked()) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
collapseGrip(grip, type, pillSize);
|
|
370
|
+
if (this.overlay) {
|
|
371
|
+
this.scheduleHideAll();
|
|
267
372
|
}
|
|
268
373
|
});
|
|
269
374
|
|
|
@@ -283,6 +388,12 @@ export class TableRowColControls {
|
|
|
283
388
|
}
|
|
284
389
|
|
|
285
390
|
const edges = getCumulativeColEdges(this.grid);
|
|
391
|
+
const scrollLeft = this.overlay && this.scrollContainer
|
|
392
|
+
? this.scrollContainer.scrollLeft
|
|
393
|
+
: 0;
|
|
394
|
+
const containerWidth = this.overlay && this.scrollContainer
|
|
395
|
+
? this.scrollContainer.clientWidth
|
|
396
|
+
: Infinity;
|
|
286
397
|
|
|
287
398
|
this.colGrips.forEach((grip, i) => {
|
|
288
399
|
if (i + 1 >= edges.length) {
|
|
@@ -290,10 +401,16 @@ export class TableRowColControls {
|
|
|
290
401
|
}
|
|
291
402
|
|
|
292
403
|
const centerX = (edges[i] + edges[i + 1]) / 2;
|
|
404
|
+
const adjustedX = centerX - scrollLeft;
|
|
293
405
|
const style = grip.style;
|
|
294
406
|
|
|
295
407
|
style.top = `${-BORDER_WIDTH / 2}px`;
|
|
296
|
-
style.left = `${
|
|
408
|
+
style.left = `${adjustedX}px`;
|
|
409
|
+
|
|
410
|
+
// Hide grips scrolled out of the visible area
|
|
411
|
+
if (this.overlay) {
|
|
412
|
+
style.visibility = (adjustedX < 0 || adjustedX > containerWidth) ? 'hidden' : '';
|
|
413
|
+
}
|
|
297
414
|
});
|
|
298
415
|
|
|
299
416
|
this.rowGrips.forEach((grip, i) => {
|