@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
|
@@ -1,59 +1,118 @@
|
|
|
1
|
+
import type { I18n } from '../../../types/api';
|
|
2
|
+
import { IconPlus } from '../../components/icons';
|
|
3
|
+
import { createTooltipContent } from '../../components/modules/toolbar/tooltip';
|
|
4
|
+
import { hide as hideTooltip, onHover } from '../../components/utils/tooltip';
|
|
1
5
|
import { twMerge } from '../../components/utils/tw';
|
|
2
6
|
|
|
3
7
|
const ADD_ROW_ATTR = 'data-blok-table-add-row';
|
|
4
8
|
const ADD_COL_ATTR = 'data-blok-table-add-col';
|
|
5
9
|
const HIDE_DELAY_MS = 150;
|
|
10
|
+
const DRAG_THRESHOLD = 5;
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* How close (px) the cursor must be to a grid edge for
|
|
14
|
+
* the corresponding add button to appear.
|
|
15
|
+
*/
|
|
16
|
+
const PROXIMITY_PX = 40;
|
|
17
|
+
|
|
18
|
+
const HIT_AREA_CLASSES = [
|
|
8
19
|
'flex',
|
|
9
20
|
'items-center',
|
|
10
21
|
'justify-center',
|
|
11
|
-
'cursor-pointer',
|
|
12
|
-
'border',
|
|
13
|
-
'border-gray-300',
|
|
14
|
-
'rounded-full',
|
|
15
|
-
'hover:bg-gray-50',
|
|
16
22
|
'transition-opacity',
|
|
17
23
|
'duration-150',
|
|
18
24
|
];
|
|
19
25
|
|
|
20
|
-
const
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
26
|
+
const VISUAL_CLASSES = [
|
|
27
|
+
'flex',
|
|
28
|
+
'items-center',
|
|
29
|
+
'justify-center',
|
|
30
|
+
'border',
|
|
31
|
+
'border-gray-300',
|
|
32
|
+
'rounded-full',
|
|
33
|
+
'group-hover/add:bg-gray-50',
|
|
25
34
|
];
|
|
26
35
|
|
|
36
|
+
const ICON_SIZE = '12';
|
|
37
|
+
|
|
38
|
+
interface DragState {
|
|
39
|
+
axis: 'row' | 'col';
|
|
40
|
+
startPos: number;
|
|
41
|
+
unitSize: number;
|
|
42
|
+
addedCount: number;
|
|
43
|
+
pointerId: number;
|
|
44
|
+
didDrag: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
27
47
|
interface TableAddControlsOptions {
|
|
28
48
|
wrapper: HTMLElement;
|
|
29
49
|
grid: HTMLElement;
|
|
50
|
+
i18n: I18n;
|
|
30
51
|
onAddRow: () => void;
|
|
31
52
|
onAddColumn: () => void;
|
|
53
|
+
onDragStart: () => void;
|
|
54
|
+
onDragAddRow: () => void;
|
|
55
|
+
onDragRemoveRow: () => void;
|
|
56
|
+
onDragAddCol: () => void;
|
|
57
|
+
onDragRemoveCol: () => void;
|
|
58
|
+
onDragEnd: () => void;
|
|
59
|
+
/** Returns the pixel width of a newly added column, used as the drag unit size. */
|
|
60
|
+
getNewColumnWidth?: () => number;
|
|
32
61
|
}
|
|
33
62
|
|
|
34
63
|
/**
|
|
35
64
|
* Manages hover-to-reveal "+" buttons for adding rows and columns to the table.
|
|
65
|
+
* Buttons only appear when the cursor is near the relevant edge of the grid.
|
|
66
|
+
* Supports both click (add one) and drag (add multiple) interactions.
|
|
36
67
|
*/
|
|
37
68
|
export class TableAddControls {
|
|
38
69
|
private wrapper: HTMLElement;
|
|
39
70
|
private grid: HTMLElement;
|
|
71
|
+
private i18n: I18n;
|
|
40
72
|
private addRowBtn: HTMLElement;
|
|
41
73
|
private addColBtn: HTMLElement;
|
|
42
|
-
private
|
|
74
|
+
private rowHideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
75
|
+
private colHideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
76
|
+
private rowVisible = false;
|
|
77
|
+
private colVisible = false;
|
|
78
|
+
private dragState: DragState | null = null;
|
|
43
79
|
|
|
44
|
-
private
|
|
80
|
+
private boundMouseMove: (e: MouseEvent) => void;
|
|
45
81
|
private boundMouseLeave: () => void;
|
|
46
82
|
private boundAddRowClick: () => void;
|
|
47
83
|
private boundAddColClick: () => void;
|
|
84
|
+
private onDragStart: () => void;
|
|
85
|
+
private onDragAddRow: () => void;
|
|
86
|
+
private onDragRemoveRow: () => void;
|
|
87
|
+
private onDragAddCol: () => void;
|
|
88
|
+
private onDragRemoveCol: () => void;
|
|
89
|
+
private onDragEnd: () => void;
|
|
90
|
+
private boundPointerMove: (e: PointerEvent) => void;
|
|
91
|
+
private boundPointerUp: (e: PointerEvent) => void;
|
|
92
|
+
private boundRowPointerDown: (e: PointerEvent) => void;
|
|
93
|
+
private boundColPointerDown: (e: PointerEvent) => void;
|
|
94
|
+
private getNewColumnWidth: (() => number) | undefined;
|
|
48
95
|
|
|
49
96
|
constructor(options: TableAddControlsOptions) {
|
|
50
97
|
this.wrapper = options.wrapper;
|
|
51
98
|
this.grid = options.grid;
|
|
99
|
+
this.i18n = options.i18n;
|
|
52
100
|
|
|
53
101
|
this.boundAddRowClick = options.onAddRow;
|
|
54
102
|
this.boundAddColClick = options.onAddColumn;
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
103
|
+
this.onDragStart = options.onDragStart;
|
|
104
|
+
this.onDragAddRow = options.onDragAddRow;
|
|
105
|
+
this.onDragRemoveRow = options.onDragRemoveRow;
|
|
106
|
+
this.onDragAddCol = options.onDragAddCol;
|
|
107
|
+
this.onDragRemoveCol = options.onDragRemoveCol;
|
|
108
|
+
this.onDragEnd = options.onDragEnd;
|
|
109
|
+
this.getNewColumnWidth = options.getNewColumnWidth;
|
|
110
|
+
this.boundMouseMove = this.handleMouseMove.bind(this);
|
|
111
|
+
this.boundMouseLeave = this.handleMouseLeave.bind(this);
|
|
112
|
+
this.boundPointerMove = this.handlePointerMove.bind(this);
|
|
113
|
+
this.boundPointerUp = this.handlePointerUp.bind(this);
|
|
114
|
+
this.boundRowPointerDown = (e: PointerEvent): void => this.handlePointerDown('row', e);
|
|
115
|
+
this.boundColPointerDown = (e: PointerEvent): void => this.handlePointerDown('col', e);
|
|
57
116
|
|
|
58
117
|
this.addRowBtn = this.createAddRowButton();
|
|
59
118
|
this.addColBtn = this.createAddColumnButton();
|
|
@@ -62,11 +121,12 @@ export class TableAddControls {
|
|
|
62
121
|
this.grid.appendChild(this.addColBtn);
|
|
63
122
|
this.syncRowButtonWidth();
|
|
64
123
|
|
|
65
|
-
this.wrapper.addEventListener('
|
|
124
|
+
this.wrapper.addEventListener('mousemove', this.boundMouseMove);
|
|
66
125
|
this.wrapper.addEventListener('mouseleave', this.boundMouseLeave);
|
|
67
126
|
|
|
68
|
-
this.addRowBtn.addEventListener('
|
|
69
|
-
this.addColBtn.addEventListener('
|
|
127
|
+
this.addRowBtn.addEventListener('pointerdown', this.boundRowPointerDown);
|
|
128
|
+
this.addColBtn.addEventListener('pointerdown', this.boundColPointerDown);
|
|
129
|
+
|
|
70
130
|
}
|
|
71
131
|
|
|
72
132
|
/**
|
|
@@ -83,55 +143,279 @@ export class TableAddControls {
|
|
|
83
143
|
: '100%';
|
|
84
144
|
}
|
|
85
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Toggle display of both add buttons.
|
|
148
|
+
* Used to hide controls during row/column drag operations.
|
|
149
|
+
*/
|
|
150
|
+
public setDisplay(visible: boolean): void {
|
|
151
|
+
const display = visible ? '' : 'none';
|
|
152
|
+
|
|
153
|
+
this.addRowBtn.style.display = display;
|
|
154
|
+
this.addColBtn.style.display = display;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Toggle interactivity of both add buttons without removing them from the DOM.
|
|
159
|
+
* Disables pointer events and hover effects during cell selection.
|
|
160
|
+
*/
|
|
161
|
+
public setInteractive(interactive: boolean): void {
|
|
162
|
+
if (!interactive) {
|
|
163
|
+
this.addRowBtn.style.pointerEvents = 'none';
|
|
164
|
+
this.addColBtn.style.pointerEvents = 'none';
|
|
165
|
+
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.addRowBtn.style.pointerEvents = this.rowVisible ? '' : 'none';
|
|
170
|
+
this.addColBtn.style.pointerEvents = this.colVisible ? '' : 'none';
|
|
171
|
+
}
|
|
172
|
+
|
|
86
173
|
public destroy(): void {
|
|
87
|
-
this.wrapper.removeEventListener('
|
|
174
|
+
this.wrapper.removeEventListener('mousemove', this.boundMouseMove);
|
|
88
175
|
this.wrapper.removeEventListener('mouseleave', this.boundMouseLeave);
|
|
89
|
-
this.addRowBtn.removeEventListener('
|
|
90
|
-
this.addColBtn.removeEventListener('
|
|
176
|
+
this.addRowBtn.removeEventListener('pointerdown', this.boundRowPointerDown);
|
|
177
|
+
this.addColBtn.removeEventListener('pointerdown', this.boundColPointerDown);
|
|
178
|
+
|
|
179
|
+
if (this.dragState) {
|
|
180
|
+
const target = this.dragState.axis === 'row' ? this.addRowBtn : this.addColBtn;
|
|
91
181
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
182
|
+
target.removeEventListener('pointermove', this.boundPointerMove);
|
|
183
|
+
target.removeEventListener('pointerup', this.boundPointerUp);
|
|
184
|
+
document.body.style.cursor = '';
|
|
185
|
+
this.dragState = null;
|
|
95
186
|
}
|
|
96
187
|
|
|
188
|
+
this.clearRowTimeout();
|
|
189
|
+
this.clearColTimeout();
|
|
190
|
+
|
|
97
191
|
this.addRowBtn.remove();
|
|
98
192
|
this.addColBtn.remove();
|
|
99
193
|
}
|
|
100
194
|
|
|
101
|
-
private
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
195
|
+
private handlePointerDown(axis: 'row' | 'col', e: PointerEvent): void {
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
|
|
198
|
+
const target = axis === 'row' ? this.addRowBtn : this.addColBtn;
|
|
199
|
+
|
|
200
|
+
target.setPointerCapture(e.pointerId);
|
|
201
|
+
|
|
202
|
+
const unitSize = this.measureUnitSize(axis);
|
|
203
|
+
|
|
204
|
+
this.dragState = {
|
|
205
|
+
axis,
|
|
206
|
+
startPos: axis === 'row' ? e.clientY : e.clientX,
|
|
207
|
+
unitSize,
|
|
208
|
+
addedCount: 0,
|
|
209
|
+
pointerId: e.pointerId,
|
|
210
|
+
didDrag: false,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
target.addEventListener('pointermove', this.boundPointerMove);
|
|
214
|
+
target.addEventListener('pointerup', this.boundPointerUp);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private handlePointerMove(e: PointerEvent): void {
|
|
218
|
+
if (!this.dragState) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const { axis, startPos, unitSize } = this.dragState;
|
|
223
|
+
const currentPos = axis === 'row' ? e.clientY : e.clientX;
|
|
224
|
+
const delta = currentPos - startPos;
|
|
225
|
+
const targetCount = Math.floor(delta / unitSize);
|
|
226
|
+
|
|
227
|
+
while (this.dragState.addedCount < targetCount) {
|
|
228
|
+
if (axis === 'row') {
|
|
229
|
+
this.onDragAddRow();
|
|
230
|
+
} else {
|
|
231
|
+
this.onDragAddCol();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
this.dragState.addedCount++;
|
|
105
235
|
}
|
|
106
236
|
|
|
107
|
-
this.
|
|
108
|
-
|
|
237
|
+
while (this.dragState.addedCount > targetCount) {
|
|
238
|
+
if (axis === 'row') {
|
|
239
|
+
this.onDragRemoveRow();
|
|
240
|
+
} else {
|
|
241
|
+
this.onDragRemoveCol();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
this.dragState.addedCount--;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (Math.abs(delta) > DRAG_THRESHOLD && !this.dragState.didDrag) {
|
|
248
|
+
this.dragState.didDrag = true;
|
|
249
|
+
document.body.style.cursor = axis === 'row' ? 'row-resize' : 'col-resize';
|
|
250
|
+
hideTooltip();
|
|
251
|
+
this.onDragStart();
|
|
252
|
+
}
|
|
109
253
|
}
|
|
110
254
|
|
|
111
|
-
private
|
|
112
|
-
this.
|
|
255
|
+
private handlePointerUp(_e: PointerEvent): void {
|
|
256
|
+
if (!this.dragState) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const { axis, pointerId, didDrag } = this.dragState;
|
|
261
|
+
|
|
262
|
+
const target = axis === 'row' ? this.addRowBtn : this.addColBtn;
|
|
263
|
+
|
|
264
|
+
target.releasePointerCapture(pointerId);
|
|
265
|
+
target.removeEventListener('pointermove', this.boundPointerMove);
|
|
266
|
+
target.removeEventListener('pointerup', this.boundPointerUp);
|
|
267
|
+
|
|
268
|
+
document.body.style.cursor = '';
|
|
269
|
+
this.dragState = null;
|
|
270
|
+
|
|
271
|
+
if (!didDrag) {
|
|
272
|
+
const clickHandler = axis === 'row' ? this.boundAddRowClick : this.boundAddColClick;
|
|
273
|
+
|
|
274
|
+
clickHandler();
|
|
275
|
+
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this.onDragEnd();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private measureUnitSize(axis: 'row' | 'col'): number {
|
|
283
|
+
if (axis === 'row') {
|
|
284
|
+
const rows = this.grid.querySelectorAll('[data-blok-table-row]');
|
|
285
|
+
const lastRow = rows[rows.length - 1] as HTMLElement | undefined;
|
|
286
|
+
|
|
287
|
+
return lastRow?.offsetHeight || 30;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (this.getNewColumnWidth) {
|
|
291
|
+
return this.getNewColumnWidth() || 100;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const firstRow = this.grid.querySelector('[data-blok-table-row]');
|
|
295
|
+
|
|
296
|
+
if (!firstRow) {
|
|
297
|
+
return 100;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const cells = firstRow.querySelectorAll('[data-blok-table-cell]');
|
|
301
|
+
const lastCell = cells[cells.length - 1] as HTMLElement | undefined;
|
|
302
|
+
|
|
303
|
+
return lastCell?.offsetWidth || 100;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private handleMouseMove(e: MouseEvent): void {
|
|
307
|
+
const gridRect = this.grid.getBoundingClientRect();
|
|
308
|
+
const distFromBottom = Math.abs(e.clientY - gridRect.bottom);
|
|
309
|
+
const distFromRight = Math.abs(e.clientX - gridRect.right);
|
|
310
|
+
|
|
311
|
+
if (distFromBottom <= PROXIMITY_PX) {
|
|
312
|
+
this.showRow();
|
|
313
|
+
} else {
|
|
314
|
+
this.scheduleHideRow();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (distFromRight <= PROXIMITY_PX) {
|
|
318
|
+
this.showCol();
|
|
319
|
+
} else {
|
|
320
|
+
this.scheduleHideCol();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private handleMouseLeave(): void {
|
|
325
|
+
this.scheduleHideRow();
|
|
326
|
+
this.scheduleHideCol();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private showRow(): void {
|
|
330
|
+
this.clearRowTimeout();
|
|
331
|
+
|
|
332
|
+
if (!this.rowVisible) {
|
|
333
|
+
this.addRowBtn.style.opacity = '1';
|
|
334
|
+
this.addRowBtn.style.pointerEvents = '';
|
|
335
|
+
this.rowVisible = true;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private showCol(): void {
|
|
340
|
+
this.clearColTimeout();
|
|
341
|
+
|
|
342
|
+
if (!this.colVisible) {
|
|
343
|
+
this.addColBtn.style.opacity = '1';
|
|
344
|
+
this.addColBtn.style.pointerEvents = '';
|
|
345
|
+
this.colVisible = true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private scheduleHideRow(): void {
|
|
350
|
+
if (!this.rowVisible || this.rowHideTimeout !== null || this.dragState?.axis === 'row') {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
this.rowHideTimeout = setTimeout(() => {
|
|
113
355
|
this.addRowBtn.style.opacity = '0';
|
|
356
|
+
this.addRowBtn.style.pointerEvents = 'none';
|
|
357
|
+
this.rowVisible = false;
|
|
358
|
+
this.rowHideTimeout = null;
|
|
359
|
+
}, HIDE_DELAY_MS);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private scheduleHideCol(): void {
|
|
363
|
+
if (!this.colVisible || this.colHideTimeout !== null || this.dragState?.axis === 'col') {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
this.colHideTimeout = setTimeout(() => {
|
|
114
368
|
this.addColBtn.style.opacity = '0';
|
|
115
|
-
this.
|
|
369
|
+
this.addColBtn.style.pointerEvents = 'none';
|
|
370
|
+
this.colVisible = false;
|
|
371
|
+
this.colHideTimeout = null;
|
|
116
372
|
}, HIDE_DELAY_MS);
|
|
117
373
|
}
|
|
118
374
|
|
|
375
|
+
private clearRowTimeout(): void {
|
|
376
|
+
if (this.rowHideTimeout !== null) {
|
|
377
|
+
clearTimeout(this.rowHideTimeout);
|
|
378
|
+
this.rowHideTimeout = null;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private clearColTimeout(): void {
|
|
383
|
+
if (this.colHideTimeout !== null) {
|
|
384
|
+
clearTimeout(this.colHideTimeout);
|
|
385
|
+
this.colHideTimeout = null;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
119
389
|
private createAddRowButton(): HTMLElement {
|
|
120
390
|
const btn = document.createElement('div');
|
|
121
391
|
|
|
122
|
-
btn.className = twMerge(
|
|
392
|
+
btn.className = twMerge(HIT_AREA_CLASSES, 'group/add', 'items-start', 'cursor-row-resize');
|
|
123
393
|
btn.setAttribute(ADD_ROW_ATTR, '');
|
|
124
394
|
btn.setAttribute('contenteditable', 'false');
|
|
125
395
|
btn.style.opacity = '0';
|
|
396
|
+
btn.style.pointerEvents = 'none';
|
|
397
|
+
btn.style.position = 'absolute';
|
|
398
|
+
btn.style.left = '0';
|
|
399
|
+
btn.style.bottom = '-36px';
|
|
400
|
+
btn.style.boxSizing = 'content-box';
|
|
126
401
|
btn.style.width = '100%';
|
|
127
|
-
btn.style.height = '
|
|
128
|
-
btn.style.
|
|
402
|
+
btn.style.height = '32px';
|
|
403
|
+
btn.style.padding = '4px 8px 0';
|
|
404
|
+
btn.style.marginLeft = '-8px';
|
|
129
405
|
|
|
130
|
-
const
|
|
406
|
+
const visual = document.createElement('div');
|
|
131
407
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
408
|
+
visual.className = twMerge(VISUAL_CLASSES);
|
|
409
|
+
visual.style.width = '100%';
|
|
410
|
+
visual.style.height = '16px';
|
|
411
|
+
|
|
412
|
+
this.appendIcon(visual);
|
|
413
|
+
btn.appendChild(visual);
|
|
414
|
+
|
|
415
|
+
onHover(btn, createTooltipContent([
|
|
416
|
+
this.i18n.t('tools.table.clickToAddRow'),
|
|
417
|
+
this.i18n.t('tools.table.dragToAddRemoveRows'),
|
|
418
|
+
]), { placement: 'bottom', marginTop: -16 });
|
|
135
419
|
|
|
136
420
|
return btn;
|
|
137
421
|
}
|
|
@@ -139,22 +423,44 @@ export class TableAddControls {
|
|
|
139
423
|
private createAddColumnButton(): HTMLElement {
|
|
140
424
|
const btn = document.createElement('div');
|
|
141
425
|
|
|
142
|
-
btn.className = twMerge(
|
|
426
|
+
btn.className = twMerge(HIT_AREA_CLASSES, 'group/add', 'justify-start', 'cursor-col-resize');
|
|
143
427
|
btn.setAttribute(ADD_COL_ATTR, '');
|
|
144
428
|
btn.setAttribute('contenteditable', 'false');
|
|
145
429
|
btn.style.opacity = '0';
|
|
430
|
+
btn.style.pointerEvents = 'none';
|
|
146
431
|
btn.style.position = 'absolute';
|
|
147
|
-
btn.style.right = '-
|
|
432
|
+
btn.style.right = '-36px';
|
|
148
433
|
btn.style.top = '0px';
|
|
149
434
|
btn.style.bottom = '0px';
|
|
150
|
-
btn.style.width = '
|
|
435
|
+
btn.style.width = '32px';
|
|
436
|
+
|
|
437
|
+
const visual = document.createElement('div');
|
|
151
438
|
|
|
152
|
-
|
|
439
|
+
visual.className = twMerge(VISUAL_CLASSES);
|
|
440
|
+
visual.style.width = '16px';
|
|
441
|
+
visual.style.height = '100%';
|
|
153
442
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
443
|
+
this.appendIcon(visual);
|
|
444
|
+
btn.appendChild(visual);
|
|
445
|
+
|
|
446
|
+
onHover(btn, createTooltipContent([
|
|
447
|
+
this.i18n.t('tools.table.clickToAddColumn'),
|
|
448
|
+
this.i18n.t('tools.table.dragToAddRemoveColumns'),
|
|
449
|
+
]), { placement: 'bottom' });
|
|
157
450
|
|
|
158
451
|
return btn;
|
|
159
452
|
}
|
|
453
|
+
|
|
454
|
+
private appendIcon(parent: HTMLElement): void {
|
|
455
|
+
parent.insertAdjacentHTML('beforeend', IconPlus);
|
|
456
|
+
|
|
457
|
+
const svg = parent.querySelector('svg');
|
|
458
|
+
|
|
459
|
+
if (svg) {
|
|
460
|
+
svg.setAttribute('width', ICON_SIZE);
|
|
461
|
+
svg.setAttribute('height', ICON_SIZE);
|
|
462
|
+
svg.setAttribute('viewBox', '0 0 24 24');
|
|
463
|
+
svg.classList.add('text-gray-500', 'pointer-events-none');
|
|
464
|
+
}
|
|
465
|
+
}
|
|
160
466
|
}
|
|
@@ -45,6 +45,7 @@ interface TableCellBlocksOptions {
|
|
|
45
45
|
export class TableCellBlocks {
|
|
46
46
|
private api: API;
|
|
47
47
|
private gridElement: HTMLElement;
|
|
48
|
+
private tableBlockId: string;
|
|
48
49
|
private _activeCellWithBlocks: CellPosition | null = null;
|
|
49
50
|
private onNavigateToCell?: CellNavigationCallback;
|
|
50
51
|
|
|
@@ -68,9 +69,11 @@ export class TableCellBlocks {
|
|
|
68
69
|
constructor(options: TableCellBlocksOptions) {
|
|
69
70
|
this.api = options.api;
|
|
70
71
|
this.gridElement = options.gridElement;
|
|
72
|
+
this.tableBlockId = options.tableBlockId;
|
|
71
73
|
this.onNavigateToCell = options.onNavigateToCell;
|
|
72
74
|
|
|
73
75
|
this.api.events.on('block changed', this.handleBlockMutation);
|
|
76
|
+
this.gridElement.addEventListener('click', this.handleCellBlankSpaceClick);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
/**
|
|
@@ -228,6 +231,7 @@ export class TableCellBlocks {
|
|
|
228
231
|
* Initialize all cells with blocks.
|
|
229
232
|
* - Empty cells or legacy string cells get a new paragraph block.
|
|
230
233
|
* - Cells that already have block references get those blocks mounted.
|
|
234
|
+
* - If referenced blocks are missing from BlockManager, a fallback paragraph is created.
|
|
231
235
|
*/
|
|
232
236
|
public initializeCells(content: LegacyCellContent[][]): CellContent[][] {
|
|
233
237
|
const rowElements = this.gridElement.querySelectorAll(`[${ROW_ATTR}]`);
|
|
@@ -256,14 +260,18 @@ export class TableCellBlocks {
|
|
|
256
260
|
return;
|
|
257
261
|
}
|
|
258
262
|
|
|
259
|
-
|
|
260
|
-
this.mountBlocksInCell(container, cellContent.blocks)
|
|
261
|
-
|
|
263
|
+
const mountedIds = isCellWithBlocks(cellContent)
|
|
264
|
+
? this.mountBlocksInCell(container, cellContent.blocks)
|
|
265
|
+
: [];
|
|
266
|
+
|
|
267
|
+
if (mountedIds.length > 0) {
|
|
268
|
+
normalizedRow.push({ blocks: mountedIds });
|
|
262
269
|
} else {
|
|
263
270
|
const text = typeof cellContent === 'string' ? cellContent : '';
|
|
264
271
|
const block = this.api.blocks.insert('paragraph', { text }, {}, this.api.blocks.getBlocksCount(), false);
|
|
265
272
|
|
|
266
273
|
container.appendChild(block.holder);
|
|
274
|
+
this.api.blocks.setBlockParent(block.id, this.tableBlockId);
|
|
267
275
|
normalizedRow.push({ blocks: [block.id] });
|
|
268
276
|
}
|
|
269
277
|
|
|
@@ -290,9 +298,12 @@ export class TableCellBlocks {
|
|
|
290
298
|
}
|
|
291
299
|
|
|
292
300
|
/**
|
|
293
|
-
* Mount existing blocks into a cell container by their IDs
|
|
301
|
+
* Mount existing blocks into a cell container by their IDs.
|
|
302
|
+
* Returns the IDs of blocks that were successfully mounted.
|
|
294
303
|
*/
|
|
295
|
-
private mountBlocksInCell(container: HTMLElement, blockIds: string[]):
|
|
304
|
+
private mountBlocksInCell(container: HTMLElement, blockIds: string[]): string[] {
|
|
305
|
+
const mountedIds: string[] = [];
|
|
306
|
+
|
|
296
307
|
for (const blockId of blockIds) {
|
|
297
308
|
const index = this.api.blocks.getBlockIndex(blockId);
|
|
298
309
|
|
|
@@ -307,7 +318,11 @@ export class TableCellBlocks {
|
|
|
307
318
|
}
|
|
308
319
|
|
|
309
320
|
container.appendChild(block.holder);
|
|
321
|
+
this.api.blocks.setBlockParent(blockId, this.tableBlockId);
|
|
322
|
+
mountedIds.push(blockId);
|
|
310
323
|
}
|
|
324
|
+
|
|
325
|
+
return mountedIds;
|
|
311
326
|
}
|
|
312
327
|
|
|
313
328
|
/**
|
|
@@ -333,6 +348,7 @@ export class TableCellBlocks {
|
|
|
333
348
|
}
|
|
334
349
|
|
|
335
350
|
container.appendChild(block.holder);
|
|
351
|
+
this.api.blocks.setBlockParent(blockId, this.tableBlockId);
|
|
336
352
|
this.stripPlaceholders(container);
|
|
337
353
|
}
|
|
338
354
|
|
|
@@ -391,6 +407,7 @@ export class TableCellBlocks {
|
|
|
391
407
|
const block = this.api.blocks.insert('paragraph', { text: '' }, {}, this.api.blocks.getBlocksCount(), true);
|
|
392
408
|
|
|
393
409
|
container.appendChild(block.holder);
|
|
410
|
+
this.api.blocks.setBlockParent(block.id, this.tableBlockId);
|
|
394
411
|
this.stripPlaceholders(container);
|
|
395
412
|
}
|
|
396
413
|
|
|
@@ -454,10 +471,20 @@ export class TableCellBlocks {
|
|
|
454
471
|
}
|
|
455
472
|
|
|
456
473
|
// For non-replace inserts: if the holder is already in a cell (placed
|
|
457
|
-
// by insertToDOM next to an adjacent cell block),
|
|
474
|
+
// by insertToDOM next to an adjacent cell block), just strip placeholders.
|
|
458
475
|
const holder = detail.target.holder;
|
|
476
|
+
const existingContainer = holder.closest<HTMLElement>(`[${CELL_BLOCKS_ATTR}]`);
|
|
477
|
+
|
|
478
|
+
if (existingContainer) {
|
|
479
|
+
this.stripPlaceholders(existingContainer);
|
|
459
480
|
|
|
460
|
-
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Only claim blocks whose holder is inside this table's grid.
|
|
485
|
+
// Blocks placed outside the grid (e.g., via replaceWith during toolbox
|
|
486
|
+
// insertion) should not be pulled into a cell by adjacency.
|
|
487
|
+
if (!this.gridElement.contains(holder)) {
|
|
461
488
|
return;
|
|
462
489
|
}
|
|
463
490
|
|
|
@@ -572,10 +599,71 @@ export class TableCellBlocks {
|
|
|
572
599
|
});
|
|
573
600
|
}
|
|
574
601
|
|
|
602
|
+
/**
|
|
603
|
+
* Delete all blocks managed by this table from the BlockManager.
|
|
604
|
+
* Called before the table block itself is removed to prevent orphaned cell blocks.
|
|
605
|
+
*/
|
|
606
|
+
public deleteAllBlocks(): void {
|
|
607
|
+
const allCells = this.gridElement.querySelectorAll(`[${CELL_ATTR}]`);
|
|
608
|
+
const blockIds = this.getBlockIdsFromCells(allCells);
|
|
609
|
+
|
|
610
|
+
this.deleteBlocks(blockIds);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Handle clicks on blank cell space.
|
|
615
|
+
* When a click lands on the cell or blocks container (not on block content),
|
|
616
|
+
* set the caret to the end of the last block in that cell.
|
|
617
|
+
*/
|
|
618
|
+
private handleCellBlankSpaceClick = (event: Event): void => {
|
|
619
|
+
const target = event.target as HTMLElement | null;
|
|
620
|
+
|
|
621
|
+
if (!target) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const isCell = target.hasAttribute(CELL_ATTR);
|
|
626
|
+
const isBlocksContainer = target.hasAttribute(CELL_BLOCKS_ATTR);
|
|
627
|
+
|
|
628
|
+
if (!isCell && !isBlocksContainer) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const cell = isCell ? target : target.closest<HTMLElement>(`[${CELL_ATTR}]`);
|
|
633
|
+
|
|
634
|
+
if (!cell) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const container = isCell
|
|
639
|
+
? cell.querySelector<HTMLElement>(`[${CELL_BLOCKS_ATTR}]`)
|
|
640
|
+
: target;
|
|
641
|
+
|
|
642
|
+
if (!container) {
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const blockHolders = container.querySelectorAll('[data-blok-id]');
|
|
647
|
+
const lastHolder = blockHolders[blockHolders.length - 1];
|
|
648
|
+
|
|
649
|
+
if (!lastHolder) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
const blockId = lastHolder.getAttribute('data-blok-id');
|
|
654
|
+
|
|
655
|
+
if (!blockId) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
this.api.caret.setToBlock(blockId, 'end');
|
|
660
|
+
};
|
|
661
|
+
|
|
575
662
|
/**
|
|
576
663
|
* Clean up event listeners
|
|
577
664
|
*/
|
|
578
665
|
destroy(): void {
|
|
666
|
+
this.gridElement.removeEventListener('click', this.handleCellBlankSpaceClick);
|
|
579
667
|
this.api.events.off('block changed', this.handleBlockMutation);
|
|
580
668
|
this._activeCellWithBlocks = null;
|
|
581
669
|
this.cellsPendingCheck.clear();
|