@jackuait/blok 0.6.0-beta.0 → 0.6.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -169
- package/bin/blok.mjs +10 -0
- package/dist/blok.mjs +2 -2
- package/dist/chunks/{blok-Bu9S3SsR.mjs → blok-Buf0btS7.mjs} +2267 -2024
- package/dist/chunks/{i18next-loader-CKuXJ0Av.mjs → i18next-loader-CVf_ZfwA.mjs} +1 -1
- package/dist/chunks/{index-jtZaryNw.mjs → index-C6jsfLLp.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-CFjyrH30.mjs → inline-tool-convert-BKKEoOqB.mjs} +710 -570
- package/dist/chunks/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
- package/dist/chunks/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
- package/dist/{messages-LvFKBBPa.mjs → chunks/messages-7W4d0DwD.mjs} +15 -1
- package/dist/{messages-Bn253WWC.mjs → chunks/messages-9SihnaXQ.mjs} +14 -0
- package/dist/{messages-Bf6Y3_GI.mjs → chunks/messages-B1Aww8q7.mjs} +16 -2
- package/dist/{messages-pA5TvcAj.mjs → chunks/messages-BB5z9Uba.mjs} +14 -0
- package/dist/chunks/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
- package/dist/chunks/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
- package/dist/chunks/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
- package/dist/{messages-B5puUm7R.mjs → chunks/messages-BL0tXcDf.mjs} +15 -1
- package/dist/chunks/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
- package/dist/{messages-CyDU5lz9.mjs → chunks/messages-BMv4xwIr.mjs} +16 -2
- package/dist/chunks/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
- package/dist/chunks/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
- package/dist/chunks/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
- package/dist/{messages-CXHd9SUK.mjs → chunks/messages-BYyy6Wqf.mjs} +14 -0
- package/dist/chunks/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
- package/dist/chunks/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
- package/dist/chunks/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
- package/dist/chunks/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
- package/dist/chunks/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
- package/dist/chunks/{messages-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
- package/dist/chunks/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
- package/dist/chunks/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
- package/dist/chunks/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
- package/dist/chunks/messages-CKI54h6O.mjs +62 -0
- package/dist/{messages-CrsJ1TEJ.mjs → chunks/messages-CLhcMlTc.mjs} +15 -1
- package/dist/{messages-CnvW8Slp.mjs → chunks/messages-CMkNSDTo.mjs} +17 -3
- package/dist/{messages-BlpqL8vG.mjs → chunks/messages-CQwpzUFp.mjs} +19 -5
- package/dist/chunks/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
- package/dist/chunks/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
- package/dist/chunks/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
- package/dist/chunks/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
- package/dist/chunks/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
- package/dist/{messages-Dg92dXZ5.mjs → chunks/messages-CvGLfqmV.mjs} +14 -0
- package/dist/{messages-AHESHJm_.mjs → chunks/messages-CzTufCHu.mjs} +14 -0
- package/dist/chunks/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
- package/dist/chunks/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
- package/dist/chunks/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
- package/dist/chunks/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
- package/dist/chunks/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
- package/dist/{messages-zSzDzXej.mjs → chunks/messages-DBRw-7Zc.mjs} +16 -2
- package/dist/chunks/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
- package/dist/chunks/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
- package/dist/{messages-DDLgIPDF.mjs → chunks/messages-DLfR5bMd.mjs} +16 -2
- package/dist/{messages-CbhuIWRJ.mjs → chunks/messages-DT4dP5uK.mjs} +15 -1
- package/dist/chunks/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
- package/dist/{messages-BPqWKx5Z.mjs → chunks/messages-Diu6jAaR.mjs} +17 -3
- package/dist/{messages-BA0rcTCY.mjs → chunks/messages-DnIhyAJk.mjs} +18 -4
- package/dist/chunks/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
- package/dist/chunks/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
- package/dist/{messages-CJoBtXU6.mjs → chunks/messages-DqM1LFg5.mjs} +14 -0
- package/dist/chunks/{messages-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
- package/dist/chunks/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
- package/dist/chunks/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
- package/dist/chunks/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
- package/dist/{messages-DY94ykcE.mjs → chunks/messages-LPVfA-8K.mjs} +14 -0
- package/dist/{messages-Cr-RJ7YB.mjs → chunks/messages-O5tQus_0.mjs} +14 -0
- package/dist/chunks/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
- package/dist/chunks/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
- package/dist/{messages-CUy1vn-b.mjs → chunks/messages-Xq8UmkVs.mjs} +14 -0
- package/dist/chunks/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
- package/dist/chunks/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
- package/dist/chunks/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
- package/dist/chunks/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
- package/dist/chunks/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
- package/dist/chunks/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
- package/dist/cli.mjs +50 -0
- package/dist/full.mjs +15 -15
- package/dist/locales.mjs +102 -88
- package/dist/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
- package/dist/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
- package/dist/{chunks/messages-LvFKBBPa.mjs → messages-7W4d0DwD.mjs} +15 -1
- package/dist/{chunks/messages-Bn253WWC.mjs → messages-9SihnaXQ.mjs} +14 -0
- package/dist/{chunks/messages-Bf6Y3_GI.mjs → messages-B1Aww8q7.mjs} +16 -2
- package/dist/{chunks/messages-pA5TvcAj.mjs → messages-BB5z9Uba.mjs} +14 -0
- package/dist/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
- package/dist/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
- package/dist/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
- package/dist/{chunks/messages-B5puUm7R.mjs → messages-BL0tXcDf.mjs} +15 -1
- package/dist/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
- package/dist/{chunks/messages-CyDU5lz9.mjs → messages-BMv4xwIr.mjs} +16 -2
- package/dist/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
- package/dist/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
- package/dist/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
- package/dist/{chunks/messages-CXHd9SUK.mjs → messages-BYyy6Wqf.mjs} +14 -0
- package/dist/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
- package/dist/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
- package/dist/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
- package/dist/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
- package/dist/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
- package/dist/{messages-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
- package/dist/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
- package/dist/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
- package/dist/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
- package/dist/messages-CKI54h6O.mjs +62 -0
- package/dist/{chunks/messages-CrsJ1TEJ.mjs → messages-CLhcMlTc.mjs} +15 -1
- package/dist/{chunks/messages-CnvW8Slp.mjs → messages-CMkNSDTo.mjs} +17 -3
- package/dist/{chunks/messages-BlpqL8vG.mjs → messages-CQwpzUFp.mjs} +19 -5
- package/dist/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
- package/dist/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
- package/dist/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
- package/dist/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
- package/dist/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
- package/dist/{chunks/messages-Dg92dXZ5.mjs → messages-CvGLfqmV.mjs} +14 -0
- package/dist/{chunks/messages-AHESHJm_.mjs → messages-CzTufCHu.mjs} +14 -0
- package/dist/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
- package/dist/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
- package/dist/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
- package/dist/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
- package/dist/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
- package/dist/{chunks/messages-zSzDzXej.mjs → messages-DBRw-7Zc.mjs} +16 -2
- package/dist/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
- package/dist/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
- package/dist/{chunks/messages-DDLgIPDF.mjs → messages-DLfR5bMd.mjs} +16 -2
- package/dist/{chunks/messages-CbhuIWRJ.mjs → messages-DT4dP5uK.mjs} +15 -1
- package/dist/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
- package/dist/{chunks/messages-BPqWKx5Z.mjs → messages-Diu6jAaR.mjs} +17 -3
- package/dist/{chunks/messages-BA0rcTCY.mjs → messages-DnIhyAJk.mjs} +18 -4
- package/dist/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
- package/dist/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
- package/dist/{chunks/messages-CJoBtXU6.mjs → messages-DqM1LFg5.mjs} +14 -0
- package/dist/{messages-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
- package/dist/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
- package/dist/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
- package/dist/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
- package/dist/{chunks/messages-DY94ykcE.mjs → messages-LPVfA-8K.mjs} +14 -0
- package/dist/{chunks/messages-Cr-RJ7YB.mjs → messages-O5tQus_0.mjs} +14 -0
- package/dist/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
- package/dist/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
- package/dist/{chunks/messages-CUy1vn-b.mjs → messages-Xq8UmkVs.mjs} +14 -0
- package/dist/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
- package/dist/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
- package/dist/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
- package/dist/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
- package/dist/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
- package/dist/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
- package/dist/tools.mjs +2005 -1267
- package/dist/vendor.LICENSE.txt +1 -1
- package/package.json +15 -14
- package/src/cli/commands/migration.ts +16 -0
- package/src/cli/commands/migrationContent.ts +6 -0
- package/src/cli/index.ts +47 -0
- package/src/cli/utils/output.ts +10 -0
- package/src/components/block-tunes/block-tune-delete.ts +3 -2
- package/src/components/blocks.ts +23 -6
- package/src/components/constants/data-attributes.ts +2 -0
- package/src/components/i18n/locales/am/messages.json +15 -1
- package/src/components/i18n/locales/ar/messages.json +14 -0
- package/src/components/i18n/locales/az/messages.json +14 -0
- package/src/components/i18n/locales/bg/messages.json +14 -0
- package/src/components/i18n/locales/bn/messages.json +25 -11
- package/src/components/i18n/locales/bs/messages.json +15 -1
- package/src/components/i18n/locales/cs/messages.json +14 -0
- package/src/components/i18n/locales/da/messages.json +14 -0
- package/src/components/i18n/locales/de/messages.json +14 -0
- package/src/components/i18n/locales/dv/messages.json +15 -1
- package/src/components/i18n/locales/el/messages.json +15 -1
- package/src/components/i18n/locales/en/messages.json +14 -0
- package/src/components/i18n/locales/es/messages.json +14 -0
- package/src/components/i18n/locales/et/messages.json +14 -0
- package/src/components/i18n/locales/fa/messages.json +15 -1
- package/src/components/i18n/locales/fi/messages.json +15 -1
- package/src/components/i18n/locales/fil/messages.json +20 -6
- package/src/components/i18n/locales/fr/messages.json +15 -1
- package/src/components/i18n/locales/gu/messages.json +15 -1
- package/src/components/i18n/locales/he/messages.json +14 -0
- package/src/components/i18n/locales/hi/messages.json +23 -9
- package/src/components/i18n/locales/hr/messages.json +14 -0
- package/src/components/i18n/locales/hu/messages.json +14 -0
- package/src/components/i18n/locales/hy/messages.json +16 -2
- package/src/components/i18n/locales/id/messages.json +19 -5
- package/src/components/i18n/locales/it/messages.json +14 -0
- package/src/components/i18n/locales/ja/messages.json +14 -0
- package/src/components/i18n/locales/ka/messages.json +15 -1
- package/src/components/i18n/locales/km/messages.json +16 -2
- package/src/components/i18n/locales/kn/messages.json +16 -2
- package/src/components/i18n/locales/ko/messages.json +14 -0
- package/src/components/i18n/locales/ku/messages.json +16 -2
- package/src/components/i18n/locales/lo/messages.json +15 -1
- package/src/components/i18n/locales/lt/messages.json +15 -1
- package/src/components/i18n/locales/lv/messages.json +15 -1
- package/src/components/i18n/locales/mk/messages.json +16 -2
- package/src/components/i18n/locales/ml/messages.json +16 -2
- package/src/components/i18n/locales/mn/messages.json +16 -2
- package/src/components/i18n/locales/mr/messages.json +24 -10
- package/src/components/i18n/locales/ms/messages.json +17 -3
- package/src/components/i18n/locales/my/messages.json +16 -2
- package/src/components/i18n/locales/ne/messages.json +24 -10
- package/src/components/i18n/locales/nl/messages.json +15 -1
- package/src/components/i18n/locales/no/messages.json +16 -2
- package/src/components/i18n/locales/pa/messages.json +15 -1
- package/src/components/i18n/locales/pl/messages.json +14 -0
- package/src/components/i18n/locales/ps/messages.json +17 -3
- package/src/components/i18n/locales/pt/messages.json +14 -0
- package/src/components/i18n/locales/ro/messages.json +15 -1
- package/src/components/i18n/locales/ru/messages.json +14 -0
- package/src/components/i18n/locales/sd/messages.json +16 -2
- package/src/components/i18n/locales/si/messages.json +23 -9
- package/src/components/i18n/locales/sk/messages.json +15 -1
- package/src/components/i18n/locales/sl/messages.json +16 -2
- package/src/components/i18n/locales/sq/messages.json +16 -2
- package/src/components/i18n/locales/sr/messages.json +16 -2
- package/src/components/i18n/locales/sv/messages.json +16 -2
- package/src/components/i18n/locales/sw/messages.json +16 -2
- package/src/components/i18n/locales/ta/messages.json +21 -7
- package/src/components/i18n/locales/te/messages.json +40 -26
- package/src/components/i18n/locales/th/messages.json +19 -5
- package/src/components/i18n/locales/tr/messages.json +15 -1
- package/src/components/i18n/locales/ug/messages.json +16 -2
- package/src/components/i18n/locales/uk/messages.json +15 -1
- package/src/components/i18n/locales/ur/messages.json +15 -1
- package/src/components/i18n/locales/vi/messages.json +25 -11
- package/src/components/i18n/locales/yi/messages.json +16 -2
- package/src/components/i18n/locales/zh/messages.json +15 -1
- package/src/components/icons/index.ts +104 -83
- package/src/components/modules/api/blocks.ts +35 -2
- package/src/components/modules/api/history.ts +64 -0
- package/src/components/modules/api/index.ts +2 -0
- package/src/components/modules/api/readonly.ts +11 -1
- package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +12 -1
- package/src/components/modules/blockManager/blockManager.ts +7 -0
- package/src/components/modules/blockManager/operations.ts +3 -2
- package/src/components/modules/blockManager/types.ts +3 -1
- package/src/components/modules/blockManager/yjs-sync.ts +12 -2
- package/src/components/modules/index.ts +3 -0
- package/src/components/modules/normalizeInlineImages.ts +263 -0
- package/src/components/modules/readonly.ts +11 -0
- package/src/components/modules/rectangleSelection.ts +19 -3
- package/src/components/modules/saver.ts +7 -3
- package/src/components/modules/toolbar/blockSettings.ts +3 -3
- package/src/components/modules/toolbar/index.ts +72 -14
- package/src/components/modules/toolbar/plus-button.ts +24 -3
- package/src/components/modules/toolbar/settings-toggler.ts +3 -5
- package/src/components/modules/ui.ts +46 -68
- package/src/components/modules/uiControllers/controllers/blockHover.ts +49 -61
- package/src/components/modules/uiControllers/controllers/keyboard.ts +17 -11
- package/src/components/modules/uiControllers/handlers/click.ts +0 -12
- package/src/components/modules/yjs/index.ts +23 -0
- package/src/components/ui/toolbox.ts +41 -6
- package/src/components/utils/placeholder.ts +16 -0
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -1
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -1
- package/src/components/utils/popover/index.ts +1 -0
- package/src/components/utils/popover/popover-abstract.ts +11 -1
- package/src/components/utils/popover/popover-desktop.ts +27 -8
- package/src/components/utils/popover/popover-registry.ts +188 -0
- package/src/components/utils/sanitizer.ts +23 -2
- package/src/components/utils/tooltip.ts +2 -24
- package/src/styles/main.css +22 -0
- package/src/tools/paragraph/index.ts +12 -4
- package/src/tools/table/data-normalizer.ts +1 -0
- package/src/tools/table/index.ts +283 -346
- package/src/tools/table/table-add-controls.ts +353 -47
- package/src/tools/table/table-cell-blocks.ts +95 -7
- package/src/tools/table/table-cell-selection.ts +648 -0
- package/src/tools/table/table-core.ts +21 -32
- package/src/tools/table/table-grip-visuals.ts +96 -0
- package/src/tools/table/table-heading-toggle.ts +127 -0
- package/src/tools/table/table-operations.ts +475 -0
- package/src/tools/table/table-resize.ts +27 -6
- package/src/tools/table/table-restrictions.ts +64 -0
- package/src/tools/table/table-row-col-action-handler.ts +190 -0
- package/src/tools/table/table-row-col-controls.ts +265 -211
- package/src/tools/table/table-row-col-drag.ts +4 -4
- package/src/tools/table/table-row-col-popover.ts +225 -0
- package/src/tools/table/types.ts +4 -0
- package/src/types-internal/blok-modules.d.ts +2 -0
- package/types/api/blocks.d.ts +8 -0
- package/types/api/history.d.ts +33 -0
- package/types/api/index.d.ts +1 -0
- package/types/api/readonly.d.ts +12 -2
- package/types/index.d.ts +10 -0
- package/types/tools/table.d.ts +67 -0
- package/types/tools-entry.d.ts +4 -0
- package/types/utils/popover/popover-item.d.ts +6 -0
- package/types/utils/popover/popover.d.ts +7 -0
- package/dist/chunks/messages-CySyfkMU.mjs +0 -48
- package/dist/messages-CySyfkMU.mjs +0 -48
package/src/tools/table/index.ts
CHANGED
|
@@ -7,15 +7,37 @@ import type {
|
|
|
7
7
|
ToolboxConfig,
|
|
8
8
|
} from '../../../types';
|
|
9
9
|
import type { ToolSanitizerConfig } from '../../../types/configs/sanitizer-config';
|
|
10
|
-
import type { MenuConfig } from '../../../types/tools/menu-config';
|
|
11
10
|
import { DATA_ATTR } from '../../components/constants';
|
|
12
11
|
import { IconTable } from '../../components/icons';
|
|
13
12
|
import { twMerge } from '../../components/utils/tw';
|
|
14
13
|
|
|
15
14
|
import { TableAddControls } from './table-add-controls';
|
|
16
15
|
import { TableCellBlocks } from './table-cell-blocks';
|
|
17
|
-
import {
|
|
16
|
+
import { TableCellSelection } from './table-cell-selection';
|
|
17
|
+
import { TableGrid } from './table-core';
|
|
18
|
+
import {
|
|
19
|
+
applyPixelWidths,
|
|
20
|
+
computeHalfAvgWidth,
|
|
21
|
+
computeInitialColWidth,
|
|
22
|
+
deleteColumnWithBlockCleanup,
|
|
23
|
+
deleteRowWithBlockCleanup,
|
|
24
|
+
enableScrollOverflow,
|
|
25
|
+
getBlockIdsInColumn,
|
|
26
|
+
getBlockIdsInRow,
|
|
27
|
+
isColumnEmpty,
|
|
28
|
+
isRowEmpty,
|
|
29
|
+
mountCellBlocksReadOnly,
|
|
30
|
+
normalizeTableData,
|
|
31
|
+
populateNewCells,
|
|
32
|
+
readPixelWidths,
|
|
33
|
+
SCROLL_OVERFLOW_CLASSES,
|
|
34
|
+
setupKeyboardNavigation,
|
|
35
|
+
updateHeadingColumnStyles,
|
|
36
|
+
updateHeadingStyles,
|
|
37
|
+
} from './table-operations';
|
|
18
38
|
import { TableResize } from './table-resize';
|
|
39
|
+
import { executeRowColAction } from './table-row-col-action-handler';
|
|
40
|
+
import type { PendingHighlight } from './table-row-col-action-handler';
|
|
19
41
|
import { TableRowColControls } from './table-row-col-controls';
|
|
20
42
|
import type { RowColAction } from './table-row-col-controls';
|
|
21
43
|
import type { TableData, TableConfig } from './types';
|
|
@@ -24,14 +46,12 @@ const DEFAULT_ROWS = 3;
|
|
|
24
46
|
const DEFAULT_COLS = 3;
|
|
25
47
|
|
|
26
48
|
const WRAPPER_CLASSES = [
|
|
27
|
-
'overflow-x-auto',
|
|
28
49
|
'my-2',
|
|
50
|
+
'pr-5',
|
|
29
51
|
];
|
|
30
52
|
|
|
31
53
|
const WRAPPER_EDIT_CLASSES = [
|
|
32
54
|
'relative',
|
|
33
|
-
'pr-9',
|
|
34
|
-
'pb-9',
|
|
35
55
|
];
|
|
36
56
|
|
|
37
57
|
/**
|
|
@@ -48,21 +68,21 @@ export class Table implements BlockTool {
|
|
|
48
68
|
private addControls: TableAddControls | null = null;
|
|
49
69
|
private rowColControls: TableRowColControls | null = null;
|
|
50
70
|
private cellBlocks: TableCellBlocks | null = null;
|
|
71
|
+
private cellSelection: TableCellSelection | null = null;
|
|
51
72
|
private element: HTMLDivElement | null = null;
|
|
52
73
|
private blockId: string | undefined;
|
|
74
|
+
private pendingHighlight: PendingHighlight | null = null;
|
|
75
|
+
private isNewTable = false;
|
|
53
76
|
|
|
54
77
|
constructor({ data, config, api, readOnly, block }: BlockToolConstructorOptions<TableData, TableConfig>) {
|
|
55
78
|
this.api = api;
|
|
56
79
|
this.readOnly = readOnly;
|
|
57
80
|
this.config = config ?? {};
|
|
58
|
-
this.data =
|
|
81
|
+
this.data = normalizeTableData(data, config ?? {});
|
|
59
82
|
this.grid = new TableGrid({ readOnly });
|
|
60
83
|
this.blockId = block?.id;
|
|
61
84
|
}
|
|
62
85
|
|
|
63
|
-
/**
|
|
64
|
-
* Toolbox configuration
|
|
65
|
-
*/
|
|
66
86
|
public static get toolbox(): ToolboxConfig {
|
|
67
87
|
return {
|
|
68
88
|
icon: IconTable,
|
|
@@ -98,19 +118,18 @@ export class Table implements BlockTool {
|
|
|
98
118
|
};
|
|
99
119
|
}
|
|
100
120
|
|
|
101
|
-
/**
|
|
102
|
-
* Render the table
|
|
103
|
-
*/
|
|
104
121
|
public render(): HTMLDivElement {
|
|
105
122
|
const wrapper = document.createElement('div');
|
|
106
123
|
|
|
107
|
-
wrapper.className = twMerge(WRAPPER_CLASSES, !this.readOnly && WRAPPER_EDIT_CLASSES);
|
|
124
|
+
wrapper.className = twMerge(WRAPPER_CLASSES, !this.readOnly && WRAPPER_EDIT_CLASSES, this.data.colWidths && SCROLL_OVERFLOW_CLASSES);
|
|
108
125
|
wrapper.setAttribute(DATA_ATTR.tool, 'table');
|
|
109
126
|
|
|
110
127
|
if (this.readOnly) {
|
|
111
128
|
wrapper.setAttribute('data-blok-table-readonly', '');
|
|
112
129
|
}
|
|
113
130
|
|
|
131
|
+
this.isNewTable = this.data.content.length === 0;
|
|
132
|
+
|
|
114
133
|
const rows = this.data.content.length || this.config.rows || DEFAULT_ROWS;
|
|
115
134
|
const cols = this.data.content[0]?.length || this.config.cols || DEFAULT_COLS;
|
|
116
135
|
|
|
@@ -121,30 +140,30 @@ export class Table implements BlockTool {
|
|
|
121
140
|
}
|
|
122
141
|
|
|
123
142
|
if (this.data.colWidths) {
|
|
124
|
-
|
|
143
|
+
applyPixelWidths(gridEl, this.data.colWidths);
|
|
125
144
|
}
|
|
126
145
|
|
|
127
146
|
wrapper.appendChild(gridEl);
|
|
128
147
|
this.element = wrapper;
|
|
129
148
|
|
|
130
149
|
if (this.data.withHeadings) {
|
|
131
|
-
this.
|
|
150
|
+
updateHeadingStyles(this.element, this.data.withHeadings);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.data.withHeadingColumn) {
|
|
154
|
+
updateHeadingColumnStyles(this.element, this.data.withHeadingColumn);
|
|
132
155
|
}
|
|
133
156
|
|
|
134
157
|
if (!this.readOnly) {
|
|
135
|
-
this.setupKeyboardNavigation(gridEl);
|
|
136
158
|
this.initCellBlocks(gridEl);
|
|
159
|
+
setupKeyboardNavigation(gridEl, this.cellBlocks);
|
|
137
160
|
}
|
|
138
161
|
|
|
139
162
|
return wrapper;
|
|
140
163
|
}
|
|
141
164
|
|
|
142
|
-
/**
|
|
143
|
-
* Called after block element is added to the DOM.
|
|
144
|
-
* Initializes resize handles now that pixel widths can be measured.
|
|
145
|
-
*/
|
|
146
165
|
public rendered(): void {
|
|
147
|
-
if (
|
|
166
|
+
if (!this.element) {
|
|
148
167
|
return;
|
|
149
168
|
}
|
|
150
169
|
|
|
@@ -154,62 +173,59 @@ export class Table implements BlockTool {
|
|
|
154
173
|
return;
|
|
155
174
|
}
|
|
156
175
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
176
|
+
if (this.readOnly) {
|
|
177
|
+
mountCellBlocksReadOnly(gridEl, this.data.content, this.api);
|
|
178
|
+
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
161
182
|
this.data.content = this.cellBlocks?.initializeCells(this.data.content) ?? this.data.content;
|
|
162
183
|
|
|
184
|
+
if (this.isNewTable) {
|
|
185
|
+
populateNewCells(gridEl, this.cellBlocks);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (this.data.initialColWidth === undefined) {
|
|
189
|
+
const widths = this.data.colWidths ?? readPixelWidths(gridEl);
|
|
190
|
+
|
|
191
|
+
this.data.initialColWidth = widths.length > 0
|
|
192
|
+
? computeInitialColWidth(widths)
|
|
193
|
+
: undefined;
|
|
194
|
+
}
|
|
195
|
+
|
|
163
196
|
this.initResize(gridEl);
|
|
164
197
|
this.initAddControls(gridEl);
|
|
165
198
|
this.initRowColControls(gridEl);
|
|
199
|
+
this.initCellSelection(gridEl);
|
|
200
|
+
|
|
201
|
+
if (this.isNewTable) {
|
|
202
|
+
const firstEditable = gridEl.querySelector<HTMLElement>('[contenteditable="true"]');
|
|
203
|
+
|
|
204
|
+
firstEditable?.focus();
|
|
205
|
+
}
|
|
166
206
|
}
|
|
167
207
|
|
|
168
|
-
/**
|
|
169
|
-
* Extract data from the rendered table
|
|
170
|
-
*/
|
|
171
208
|
public save(blockContent: HTMLElement): TableData {
|
|
172
209
|
const gridEl = blockContent.firstElementChild as HTMLElement;
|
|
173
210
|
const colWidths = this.data.colWidths;
|
|
211
|
+
const content = this.readOnly
|
|
212
|
+
? this.data.content
|
|
213
|
+
: this.grid.getData(gridEl);
|
|
174
214
|
|
|
175
215
|
return {
|
|
176
216
|
withHeadings: this.data.withHeadings,
|
|
217
|
+
withHeadingColumn: this.data.withHeadingColumn,
|
|
177
218
|
stretched: this.data.stretched,
|
|
178
|
-
content
|
|
219
|
+
content,
|
|
179
220
|
...(colWidths ? { colWidths } : {}),
|
|
221
|
+
...(this.data.initialColWidth !== undefined ? { initialColWidth: this.data.initialColWidth } : {}),
|
|
180
222
|
};
|
|
181
223
|
}
|
|
182
224
|
|
|
183
|
-
/**
|
|
184
|
-
* Validate saved data
|
|
185
|
-
*/
|
|
186
225
|
public validate(savedData: TableData): boolean {
|
|
187
226
|
return savedData.content.length > 0;
|
|
188
227
|
}
|
|
189
228
|
|
|
190
|
-
/**
|
|
191
|
-
* Render block settings
|
|
192
|
-
*/
|
|
193
|
-
public renderSettings(): MenuConfig {
|
|
194
|
-
return [
|
|
195
|
-
{
|
|
196
|
-
icon: IconTable,
|
|
197
|
-
title: this.api.i18n.t(this.data.withHeadings
|
|
198
|
-
? 'tools.table.withoutHeadings'
|
|
199
|
-
: 'tools.table.withHeadings'),
|
|
200
|
-
onActivate: (): void => {
|
|
201
|
-
this.data.withHeadings = !this.data.withHeadings;
|
|
202
|
-
this.updateHeadingStyles();
|
|
203
|
-
},
|
|
204
|
-
closeOnActivate: true,
|
|
205
|
-
isActive: this.data.withHeadings,
|
|
206
|
-
},
|
|
207
|
-
];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Handle paste of HTML table
|
|
212
|
-
*/
|
|
213
229
|
public onPaste(event: HTMLPasteEvent): void {
|
|
214
230
|
const content = event.detail.data;
|
|
215
231
|
const rows = content.querySelectorAll('tr');
|
|
@@ -228,18 +244,17 @@ export class Table implements BlockTool {
|
|
|
228
244
|
}
|
|
229
245
|
});
|
|
230
246
|
|
|
231
|
-
// Detect headings from thead or th elements in first row
|
|
232
247
|
const hasTheadHeadings = content.querySelector('thead') !== null;
|
|
233
248
|
const hasThHeadings = rows[0]?.querySelector('th') !== null;
|
|
234
249
|
const withHeadings = hasTheadHeadings || hasThHeadings;
|
|
235
250
|
|
|
236
251
|
this.data = {
|
|
237
252
|
withHeadings,
|
|
253
|
+
withHeadingColumn: this.data.withHeadingColumn,
|
|
238
254
|
stretched: this.data.stretched,
|
|
239
255
|
content: tableContent,
|
|
240
256
|
};
|
|
241
257
|
|
|
242
|
-
// Re-render with new data
|
|
243
258
|
if (!this.element?.parentNode) {
|
|
244
259
|
return;
|
|
245
260
|
}
|
|
@@ -258,10 +273,9 @@ export class Table implements BlockTool {
|
|
|
258
273
|
}
|
|
259
274
|
}
|
|
260
275
|
|
|
261
|
-
/**
|
|
262
|
-
* Clean up
|
|
263
|
-
*/
|
|
264
276
|
public destroy(): void {
|
|
277
|
+
this.cellBlocks?.deleteAllBlocks();
|
|
278
|
+
|
|
265
279
|
this.resize?.destroy();
|
|
266
280
|
this.resize = null;
|
|
267
281
|
this.addControls?.destroy();
|
|
@@ -270,55 +284,33 @@ export class Table implements BlockTool {
|
|
|
270
284
|
this.rowColControls = null;
|
|
271
285
|
this.cellBlocks?.destroy();
|
|
272
286
|
this.cellBlocks = null;
|
|
287
|
+
this.cellSelection?.destroy();
|
|
288
|
+
this.cellSelection = null;
|
|
273
289
|
this.element = null;
|
|
274
290
|
}
|
|
275
291
|
|
|
276
|
-
|
|
277
|
-
const
|
|
292
|
+
public deleteRowWithCleanup(rowIndex: number): void {
|
|
293
|
+
const gridEl = this.element?.firstElementChild as HTMLElement | undefined;
|
|
278
294
|
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
withHeadings: this.config.withHeadings ?? false,
|
|
282
|
-
stretched: this.config.stretched ?? false,
|
|
283
|
-
content: [],
|
|
284
|
-
};
|
|
295
|
+
if (gridEl) {
|
|
296
|
+
deleteRowWithBlockCleanup(gridEl, rowIndex, this.grid, this.cellBlocks);
|
|
285
297
|
}
|
|
286
|
-
|
|
287
|
-
const tableData = data as TableData;
|
|
288
|
-
const cols = tableData.content?.[0]?.length;
|
|
289
|
-
const colWidths = tableData.colWidths;
|
|
290
|
-
const validWidths = colWidths && cols && colWidths.length === cols ? colWidths : undefined;
|
|
291
|
-
|
|
292
|
-
return {
|
|
293
|
-
withHeadings: tableData.withHeadings ?? this.config.withHeadings ?? false,
|
|
294
|
-
stretched: tableData.stretched ?? this.config.stretched ?? false,
|
|
295
|
-
content: tableData.content ?? [],
|
|
296
|
-
colWidths: validWidths,
|
|
297
|
-
};
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const gridEl = this.element.firstElementChild as HTMLElement;
|
|
300
|
+
public deleteColumnWithCleanup(colIndex: number): void {
|
|
301
|
+
const gridEl = this.element?.firstElementChild as HTMLElement | undefined;
|
|
306
302
|
|
|
307
|
-
if (
|
|
308
|
-
|
|
303
|
+
if (gridEl) {
|
|
304
|
+
this.data.colWidths = deleteColumnWithBlockCleanup(gridEl, colIndex, this.data.colWidths, this.grid, this.cellBlocks);
|
|
309
305
|
}
|
|
306
|
+
}
|
|
310
307
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
308
|
+
public getBlockIdsInRow(rowIndex: number): string[] {
|
|
309
|
+
return getBlockIdsInRow(this.element, this.cellBlocks, rowIndex);
|
|
310
|
+
}
|
|
316
311
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
} else {
|
|
320
|
-
firstRow.removeAttribute('data-blok-table-heading');
|
|
321
|
-
}
|
|
312
|
+
public getBlockIdsInColumn(colIndex: number): string[] {
|
|
313
|
+
return getBlockIdsInColumn(this.element, this.cellBlocks, colIndex);
|
|
322
314
|
}
|
|
323
315
|
|
|
324
316
|
private initAddControls(gridEl: HTMLElement): void {
|
|
@@ -328,24 +320,108 @@ export class Table implements BlockTool {
|
|
|
328
320
|
return;
|
|
329
321
|
}
|
|
330
322
|
|
|
323
|
+
const dragState = { addedCols: 0 };
|
|
324
|
+
|
|
331
325
|
this.addControls = new TableAddControls({
|
|
332
326
|
wrapper: this.element,
|
|
333
327
|
grid: gridEl,
|
|
328
|
+
i18n: this.api.i18n,
|
|
329
|
+
getNewColumnWidth: () => {
|
|
330
|
+
const colWidths = this.data.colWidths ?? readPixelWidths(gridEl);
|
|
331
|
+
|
|
332
|
+
return this.data.initialColWidth !== undefined
|
|
333
|
+
? Math.round((this.data.initialColWidth / 2) * 100) / 100
|
|
334
|
+
: computeHalfAvgWidth(colWidths);
|
|
335
|
+
},
|
|
334
336
|
onAddRow: () => {
|
|
335
337
|
this.grid.addRow(gridEl);
|
|
336
|
-
|
|
338
|
+
populateNewCells(gridEl, this.cellBlocks);
|
|
339
|
+
updateHeadingStyles(this.element, this.data.withHeadings);
|
|
340
|
+
updateHeadingColumnStyles(this.element, this.data.withHeadingColumn);
|
|
341
|
+
this.initResize(gridEl);
|
|
342
|
+
this.addControls?.syncRowButtonWidth();
|
|
343
|
+
this.rowColControls?.refresh();
|
|
337
344
|
},
|
|
338
345
|
onAddColumn: () => {
|
|
339
|
-
const colWidths = this.data.colWidths ??
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
this.grid.addColumn(gridEl, undefined, colWidths);
|
|
345
|
-
this.data.colWidths = [...colWidths,
|
|
346
|
-
|
|
346
|
+
const colWidths = this.data.colWidths ?? readPixelWidths(gridEl);
|
|
347
|
+
const halfWidth = this.data.initialColWidth !== undefined
|
|
348
|
+
? Math.round((this.data.initialColWidth / 2) * 100) / 100
|
|
349
|
+
: computeHalfAvgWidth(colWidths);
|
|
350
|
+
|
|
351
|
+
this.grid.addColumn(gridEl, undefined, colWidths, halfWidth);
|
|
352
|
+
this.data.colWidths = [...colWidths, halfWidth];
|
|
353
|
+
populateNewCells(gridEl, this.cellBlocks);
|
|
354
|
+
updateHeadingColumnStyles(this.element, this.data.withHeadingColumn);
|
|
347
355
|
this.initResize(gridEl);
|
|
348
356
|
this.addControls?.syncRowButtonWidth();
|
|
357
|
+
this.rowColControls?.refresh();
|
|
358
|
+
},
|
|
359
|
+
onDragStart: () => {
|
|
360
|
+
if (this.resize) {
|
|
361
|
+
this.resize.enabled = false;
|
|
362
|
+
}
|
|
363
|
+
this.rowColControls?.hideAllGrips();
|
|
364
|
+
this.rowColControls?.setGripsDisplay(false);
|
|
365
|
+
},
|
|
366
|
+
onDragAddRow: () => {
|
|
367
|
+
this.grid.addRow(gridEl);
|
|
368
|
+
populateNewCells(gridEl, this.cellBlocks);
|
|
369
|
+
updateHeadingStyles(this.element, this.data.withHeadings);
|
|
370
|
+
updateHeadingColumnStyles(this.element, this.data.withHeadingColumn);
|
|
371
|
+
},
|
|
372
|
+
onDragRemoveRow: () => {
|
|
373
|
+
const rowCount = this.grid.getRowCount(gridEl);
|
|
374
|
+
|
|
375
|
+
if (rowCount > 1 && isRowEmpty(gridEl, rowCount - 1)) {
|
|
376
|
+
deleteRowWithBlockCleanup(gridEl, rowCount - 1, this.grid, this.cellBlocks);
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
onDragAddCol: () => {
|
|
380
|
+
const colWidths = this.data.colWidths ?? readPixelWidths(gridEl);
|
|
381
|
+
const halfWidth = this.data.initialColWidth !== undefined
|
|
382
|
+
? Math.round((this.data.initialColWidth / 2) * 100) / 100
|
|
383
|
+
: computeHalfAvgWidth(colWidths);
|
|
384
|
+
|
|
385
|
+
this.grid.addColumn(gridEl, undefined, colWidths, halfWidth);
|
|
386
|
+
this.data.colWidths = [...colWidths, halfWidth];
|
|
387
|
+
applyPixelWidths(gridEl, this.data.colWidths);
|
|
388
|
+
populateNewCells(gridEl, this.cellBlocks);
|
|
389
|
+
updateHeadingColumnStyles(this.element, this.data.withHeadingColumn);
|
|
390
|
+
this.initResize(gridEl);
|
|
391
|
+
|
|
392
|
+
dragState.addedCols++;
|
|
393
|
+
|
|
394
|
+
if (this.element) {
|
|
395
|
+
this.element.scrollLeft = this.element.scrollWidth;
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
onDragRemoveCol: () => {
|
|
399
|
+
const colCount = this.grid.getColumnCount(gridEl);
|
|
400
|
+
|
|
401
|
+
if (colCount <= 1 || !isColumnEmpty(gridEl, colCount - 1)) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
this.data.colWidths = deleteColumnWithBlockCleanup(gridEl, colCount - 1, this.data.colWidths, this.grid, this.cellBlocks);
|
|
406
|
+
|
|
407
|
+
if (this.data.colWidths) {
|
|
408
|
+
applyPixelWidths(gridEl, this.data.colWidths);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
this.initResize(gridEl);
|
|
412
|
+
|
|
413
|
+
dragState.addedCols--;
|
|
414
|
+
},
|
|
415
|
+
onDragEnd: () => {
|
|
416
|
+
this.initResize(gridEl);
|
|
417
|
+
this.addControls?.syncRowButtonWidth();
|
|
418
|
+
this.rowColControls?.refresh();
|
|
419
|
+
|
|
420
|
+
if (this.element) {
|
|
421
|
+
this.element.scrollLeft = dragState.addedCols > 0 ? this.element.scrollWidth : 0;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
dragState.addedCols = 0;
|
|
349
425
|
},
|
|
350
426
|
});
|
|
351
427
|
}
|
|
@@ -362,171 +438,114 @@ export class Table implements BlockTool {
|
|
|
362
438
|
getColumnCount: () => this.grid.getColumnCount(gridEl),
|
|
363
439
|
getRowCount: () => this.grid.getRowCount(gridEl),
|
|
364
440
|
isHeadingRow: () => this.data.withHeadings,
|
|
441
|
+
isHeadingColumn: () => this.data.withHeadingColumn,
|
|
442
|
+
i18n: this.api.i18n,
|
|
365
443
|
onAction: (action: RowColAction) => this.handleRowColAction(gridEl, action),
|
|
366
444
|
onDragStateChange: (isDragging: boolean) => {
|
|
367
|
-
if (
|
|
368
|
-
|
|
445
|
+
if (this.resize) {
|
|
446
|
+
this.resize.enabled = !isDragging;
|
|
369
447
|
}
|
|
370
448
|
|
|
371
|
-
this.
|
|
449
|
+
this.addControls?.setDisplay(!isDragging);
|
|
450
|
+
|
|
451
|
+
if (isDragging) {
|
|
452
|
+
this.api.toolbar.close({ setExplicitlyClosed: false });
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
onGripClick: (type, index) => {
|
|
456
|
+
if (type === 'row') {
|
|
457
|
+
this.cellSelection?.selectRow(index);
|
|
458
|
+
} else {
|
|
459
|
+
this.cellSelection?.selectColumn(index);
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
onGripPopoverClose: () => {
|
|
463
|
+
if (this.pendingHighlight) {
|
|
464
|
+
const { type, index } = this.pendingHighlight;
|
|
465
|
+
|
|
466
|
+
this.pendingHighlight = null;
|
|
467
|
+
|
|
468
|
+
// Lock the grip synchronously so the unlock listener is registered
|
|
469
|
+
// before any external click can race with a deferred RAF
|
|
470
|
+
this.rowColControls?.setActiveGrip(type, index);
|
|
471
|
+
|
|
472
|
+
// Wait for layout so newly inserted cells have dimensions
|
|
473
|
+
requestAnimationFrame(() => {
|
|
474
|
+
if (type === 'row') {
|
|
475
|
+
this.cellSelection?.selectRow(index);
|
|
476
|
+
} else {
|
|
477
|
+
this.cellSelection?.selectColumn(index);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
} else {
|
|
481
|
+
this.cellSelection?.clearActiveSelection();
|
|
482
|
+
}
|
|
372
483
|
},
|
|
373
484
|
});
|
|
374
485
|
}
|
|
375
486
|
|
|
376
487
|
private handleRowColAction(gridEl: HTMLElement, action: RowColAction): void {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
case 'insert-row-below':
|
|
383
|
-
this.grid.addRow(gridEl, action.index + 1);
|
|
384
|
-
this.populateNewCells(gridEl);
|
|
385
|
-
break;
|
|
386
|
-
case 'insert-col-left':
|
|
387
|
-
this.handleInsertColumn(gridEl, action.index);
|
|
388
|
-
this.populateNewCells(gridEl);
|
|
389
|
-
break;
|
|
390
|
-
case 'insert-col-right':
|
|
391
|
-
this.handleInsertColumn(gridEl, action.index + 1);
|
|
392
|
-
this.populateNewCells(gridEl);
|
|
393
|
-
break;
|
|
394
|
-
case 'move-row':
|
|
395
|
-
this.grid.moveRow(gridEl, action.fromIndex, action.toIndex);
|
|
396
|
-
break;
|
|
397
|
-
case 'move-col':
|
|
398
|
-
this.grid.moveColumn(gridEl, action.fromIndex, action.toIndex);
|
|
399
|
-
this.syncColWidthsAfterMove(action.fromIndex, action.toIndex);
|
|
400
|
-
break;
|
|
401
|
-
case 'delete-row':
|
|
402
|
-
this.deleteRowWithBlockCleanup(gridEl, action.index);
|
|
403
|
-
break;
|
|
404
|
-
case 'delete-col':
|
|
405
|
-
this.deleteColumnWithBlockCleanup(gridEl, action.index);
|
|
406
|
-
break;
|
|
407
|
-
case 'toggle-heading':
|
|
408
|
-
this.data.withHeadings = !this.data.withHeadings;
|
|
409
|
-
this.updateHeadingStyles();
|
|
410
|
-
break;
|
|
411
|
-
}
|
|
488
|
+
const result = executeRowColAction(
|
|
489
|
+
gridEl,
|
|
490
|
+
action,
|
|
491
|
+
{ grid: this.grid, data: this.data, cellBlocks: this.cellBlocks },
|
|
492
|
+
);
|
|
412
493
|
|
|
494
|
+
this.data.colWidths = result.colWidths;
|
|
495
|
+
this.data.withHeadings = result.withHeadings;
|
|
496
|
+
this.data.withHeadingColumn = result.withHeadingColumn;
|
|
497
|
+
this.pendingHighlight = result.pendingHighlight;
|
|
498
|
+
|
|
499
|
+
updateHeadingStyles(this.element, this.data.withHeadings);
|
|
500
|
+
updateHeadingColumnStyles(this.element, this.data.withHeadingColumn);
|
|
413
501
|
this.initResize(gridEl);
|
|
414
502
|
this.addControls?.syncRowButtonWidth();
|
|
415
503
|
this.rowColControls?.refresh();
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
private handleInsertColumn(gridEl: HTMLElement, index: number): void {
|
|
419
|
-
const colWidths = this.data.colWidths ?? this.readPixelWidths(gridEl);
|
|
420
|
-
|
|
421
|
-
this.grid.addColumn(gridEl, index, colWidths);
|
|
422
|
-
|
|
423
|
-
const halfAvgWidth = Math.round(
|
|
424
|
-
(colWidths.reduce((sum, w) => sum + w, 0) / colWidths.length / 2) * 100
|
|
425
|
-
) / 100;
|
|
426
|
-
const newWidths = [...colWidths];
|
|
427
504
|
|
|
428
|
-
|
|
429
|
-
this.data.colWidths = newWidths;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
private syncColWidthsAfterMove(fromIndex: number, toIndex: number): void {
|
|
433
|
-
if (!this.data.colWidths) {
|
|
505
|
+
if (!result.moveSelection) {
|
|
434
506
|
return;
|
|
435
507
|
}
|
|
436
508
|
|
|
437
|
-
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
widths.splice(toIndex, 0, moved);
|
|
441
|
-
this.data.colWidths = widths;
|
|
442
|
-
}
|
|
509
|
+
// After move operations, select the moved row/column to show where it landed
|
|
510
|
+
const { type: moveType, index: moveIndex } = result.moveSelection;
|
|
443
511
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
512
|
+
if (moveType === 'row') {
|
|
513
|
+
this.cellSelection?.selectRow(moveIndex);
|
|
514
|
+
} else {
|
|
515
|
+
this.cellSelection?.selectColumn(moveIndex);
|
|
447
516
|
}
|
|
448
517
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
widths.splice(index, 1);
|
|
452
|
-
this.data.colWidths = widths.length > 0 ? widths : undefined;
|
|
518
|
+
this.rowColControls?.setActiveGrip(moveType, moveIndex);
|
|
453
519
|
}
|
|
454
520
|
|
|
455
521
|
private initResize(gridEl: HTMLElement): void {
|
|
456
522
|
this.resize?.destroy();
|
|
457
523
|
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
this.resize = new TableResize(gridEl, widths, (newWidths: number[]) => {
|
|
461
|
-
this.data.colWidths = newWidths;
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
private readPixelWidths(gridEl: HTMLElement): number[] {
|
|
466
|
-
const firstRow = gridEl.querySelector('[data-blok-table-row]');
|
|
524
|
+
const isPercentMode = this.data.colWidths === undefined;
|
|
525
|
+
const widths = this.data.colWidths ?? readPixelWidths(gridEl);
|
|
467
526
|
|
|
468
|
-
if (!
|
|
469
|
-
|
|
527
|
+
if (!isPercentMode) {
|
|
528
|
+
enableScrollOverflow(this.element);
|
|
470
529
|
}
|
|
471
530
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
(
|
|
531
|
+
this.resize = new TableResize(
|
|
532
|
+
gridEl,
|
|
533
|
+
widths,
|
|
534
|
+
(newWidths: number[]) => {
|
|
535
|
+
this.data.colWidths = newWidths;
|
|
536
|
+
enableScrollOverflow(this.element);
|
|
537
|
+
this.rowColControls?.positionGrips();
|
|
538
|
+
},
|
|
539
|
+
() => {
|
|
540
|
+
this.rowColControls?.hideAllGrips();
|
|
541
|
+
},
|
|
542
|
+
() => {
|
|
543
|
+
this.addControls?.syncRowButtonWidth();
|
|
544
|
+
},
|
|
545
|
+
isPercentMode,
|
|
476
546
|
);
|
|
477
547
|
}
|
|
478
548
|
|
|
479
|
-
private applyPixelWidths(grid: HTMLElement, widths: number[]): void {
|
|
480
|
-
const totalWidth = widths.reduce((sum, w) => sum + w, 0);
|
|
481
|
-
const gridStyle: HTMLElement = grid;
|
|
482
|
-
|
|
483
|
-
gridStyle.style.width = `${totalWidth + BORDER_WIDTH}px`;
|
|
484
|
-
|
|
485
|
-
const rowEls = grid.querySelectorAll('[data-blok-table-row]');
|
|
486
|
-
|
|
487
|
-
rowEls.forEach(row => {
|
|
488
|
-
const cells = row.querySelectorAll('[data-blok-table-cell]');
|
|
489
|
-
|
|
490
|
-
cells.forEach((node, i) => {
|
|
491
|
-
if (i < widths.length) {
|
|
492
|
-
const cellEl = node as HTMLElement;
|
|
493
|
-
|
|
494
|
-
cellEl.style.width = `${widths[i]}px`;
|
|
495
|
-
}
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
private setupKeyboardNavigation(gridEl: HTMLElement): void {
|
|
501
|
-
gridEl.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
502
|
-
const target = event.target as HTMLElement;
|
|
503
|
-
const cell = target.closest<HTMLElement>('[data-blok-table-cell]');
|
|
504
|
-
|
|
505
|
-
if (!cell) {
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
const position = this.getCellPosition(gridEl, cell);
|
|
510
|
-
|
|
511
|
-
if (position) {
|
|
512
|
-
this.cellBlocks?.handleKeyDown(event, position);
|
|
513
|
-
}
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Ensure every cell in the grid has at least one block.
|
|
519
|
-
* Called after addRow / addColumn so new empty cells get an initial paragraph.
|
|
520
|
-
* Cells that already contain blocks are left untouched.
|
|
521
|
-
*/
|
|
522
|
-
private populateNewCells(gridEl: HTMLElement): void {
|
|
523
|
-
const cells = gridEl.querySelectorAll(`[${CELL_ATTR}]`);
|
|
524
|
-
|
|
525
|
-
cells.forEach(cell => {
|
|
526
|
-
this.cellBlocks?.ensureCellHasBlock(cell as HTMLElement);
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
|
|
530
549
|
private initCellBlocks(gridEl: HTMLElement): void {
|
|
531
550
|
this.cellBlocks = new TableCellBlocks({
|
|
532
551
|
api: this.api,
|
|
@@ -535,117 +554,35 @@ export class Table implements BlockTool {
|
|
|
535
554
|
});
|
|
536
555
|
}
|
|
537
556
|
|
|
538
|
-
private
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
const rowIndex = rows.findIndex(row => {
|
|
542
|
-
const cells = Array.from(row.querySelectorAll('[data-blok-table-cell]'));
|
|
543
|
-
|
|
544
|
-
return cells.includes(cell);
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
if (rowIndex === -1) {
|
|
548
|
-
return null;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
const cells = Array.from(rows[rowIndex].querySelectorAll('[data-blok-table-cell]'));
|
|
552
|
-
const colIndex = cells.indexOf(cell);
|
|
553
|
-
|
|
554
|
-
return { row: rowIndex, col: colIndex };
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Delete a row and clean up any nested blocks within its cells
|
|
559
|
-
*/
|
|
560
|
-
public deleteRowWithCleanup(rowIndex: number): void {
|
|
561
|
-
const gridEl = this.element?.firstElementChild as HTMLElement | undefined;
|
|
562
|
-
|
|
563
|
-
if (gridEl) {
|
|
564
|
-
this.deleteRowWithBlockCleanup(gridEl, rowIndex);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
/**
|
|
569
|
-
* Delete a column and clean up any nested blocks within its cells
|
|
570
|
-
*/
|
|
571
|
-
public deleteColumnWithCleanup(colIndex: number): void {
|
|
572
|
-
const gridEl = this.element?.firstElementChild as HTMLElement | undefined;
|
|
573
|
-
|
|
574
|
-
if (gridEl) {
|
|
575
|
-
this.deleteColumnWithBlockCleanup(gridEl, colIndex);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
private deleteRowWithBlockCleanup(gridEl: HTMLElement, rowIndex: number): void {
|
|
580
|
-
const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
|
|
581
|
-
const row = rows[rowIndex];
|
|
582
|
-
|
|
583
|
-
if (row && this.cellBlocks) {
|
|
584
|
-
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
585
|
-
|
|
586
|
-
this.cellBlocks.deleteBlocks(this.cellBlocks.getBlockIdsFromCells(cells));
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
this.grid.deleteRow(gridEl, rowIndex);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
private deleteColumnWithBlockCleanup(gridEl: HTMLElement, colIndex: number): void {
|
|
593
|
-
if (this.cellBlocks) {
|
|
594
|
-
const rows = gridEl.querySelectorAll(`[${ROW_ATTR}]`);
|
|
595
|
-
const cellsInColumn: Element[] = [];
|
|
557
|
+
private initCellSelection(gridEl: HTMLElement): void {
|
|
558
|
+
this.cellSelection?.destroy();
|
|
596
559
|
|
|
597
|
-
|
|
598
|
-
|
|
560
|
+
// Get RectangleSelection from API
|
|
561
|
+
const rectangleSelection = this.api.rectangleSelection;
|
|
599
562
|
|
|
600
|
-
|
|
601
|
-
|
|
563
|
+
this.cellSelection = new TableCellSelection({
|
|
564
|
+
grid: gridEl,
|
|
565
|
+
rectangleSelection, // Pass reference
|
|
566
|
+
i18n: this.api.i18n,
|
|
567
|
+
onSelectionActiveChange: (hasSelection) => {
|
|
568
|
+
if (this.resize) {
|
|
569
|
+
this.resize.enabled = !hasSelection;
|
|
602
570
|
}
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
this.cellBlocks.deleteBlocks(this.cellBlocks.getBlockIdsFromCells(cellsInColumn));
|
|
606
|
-
}
|
|
607
571
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
public getBlockIdsInRow(rowIndex: number): string[] {
|
|
616
|
-
if (!this.element) {
|
|
617
|
-
return [];
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
const rows = this.element.querySelectorAll(`[${ROW_ATTR}]`);
|
|
621
|
-
const row = rows[rowIndex];
|
|
622
|
-
|
|
623
|
-
if (!row) {
|
|
624
|
-
return [];
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
return this.cellBlocks?.getBlockIdsFromCells(row.querySelectorAll(`[${CELL_ATTR}]`)) ?? [];
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* Get all block IDs from cells in a specific column
|
|
632
|
-
*/
|
|
633
|
-
public getBlockIdsInColumn(colIndex: number): string[] {
|
|
634
|
-
if (!this.element) {
|
|
635
|
-
return [];
|
|
636
|
-
}
|
|
572
|
+
this.addControls?.setInteractive(!hasSelection);
|
|
573
|
+
this.rowColControls?.setGripsDisplay(!hasSelection);
|
|
574
|
+
},
|
|
575
|
+
onClearContent: (cells) => {
|
|
576
|
+
if (!this.cellBlocks) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
637
579
|
|
|
638
|
-
|
|
639
|
-
const cellsInColumn: Element[] = [];
|
|
580
|
+
const blockIds = this.cellBlocks.getBlockIdsFromCells(cells);
|
|
640
581
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
if (colIndex < cells.length) {
|
|
645
|
-
cellsInColumn.push(cells[colIndex]);
|
|
646
|
-
}
|
|
582
|
+
this.cellBlocks.deleteBlocks(blockIds);
|
|
583
|
+
},
|
|
647
584
|
});
|
|
648
|
-
|
|
649
|
-
return this.cellBlocks?.getBlockIdsFromCells(cellsInColumn) ?? [];
|
|
650
585
|
}
|
|
651
586
|
}
|
|
587
|
+
|
|
588
|
+
export { isInsideTableCell, isRestrictedInTableCell, convertToParagraph } from './table-restrictions';
|