@jackuait/blok 0.6.0-beta.4 → 0.6.0-beta.6
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-DK-97ZTf.mjs → blok-BOtlKwVO.mjs} +1486 -1354
- package/dist/chunks/{i18next-loader-CRollibS.mjs → i18next-loader-CJNShSyT.mjs} +1 -1
- package/dist/chunks/{index-jgHmMDND.mjs → index-BUAPAChM.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-BIwvipPw.mjs → inline-tool-convert-UoYdJJic.mjs} +88 -73
- 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 +929 -779
- 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/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/modules/api/blocks.ts +17 -2
- package/src/components/modules/api/history.ts +64 -0
- package/src/components/modules/api/index.ts +1 -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/yjs-sync.ts +12 -2
- package/src/components/modules/index.ts +3 -0
- package/src/components/modules/readonly.ts +11 -0
- package/src/components/modules/toolbar/index.ts +29 -7
- package/src/components/modules/ui.ts +46 -68
- package/src/components/modules/uiControllers/controllers/blockHover.ts +40 -61
- package/src/components/modules/yjs/index.ts +23 -0
- package/src/components/ui/toolbox.ts +41 -6
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +3 -1
- package/src/components/utils/popover/popover-desktop.ts +27 -8
- package/src/tools/table/index.ts +87 -70
- package/src/tools/table/table-add-controls.ts +33 -7
- package/src/tools/table/table-cell-blocks.ts +77 -5
- package/src/tools/table/table-cell-selection.ts +70 -46
- package/src/tools/table/table-core.ts +20 -15
- package/src/tools/table/table-grip-visuals.ts +4 -4
- package/src/tools/table/table-operations.ts +22 -12
- 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 +91 -182
- 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 +2 -0
- package/src/types-internal/blok-modules.d.ts +2 -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 +3 -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,3 +1,4 @@
|
|
|
1
|
+
import type { I18n } from '../../../types/api';
|
|
1
2
|
import { IconCross } from '../../components/icons';
|
|
2
3
|
import { PopoverDesktop } from '../../components/utils/popover';
|
|
3
4
|
import { twMerge } from '../../components/utils/tw';
|
|
@@ -56,6 +57,7 @@ interface CellSelectionOptions {
|
|
|
56
57
|
rectangleSelection?: { cancelActiveSelection: () => void };
|
|
57
58
|
onSelectionActiveChange?: (hasSelection: boolean) => void;
|
|
58
59
|
onClearContent?: (cells: HTMLElement[]) => void;
|
|
60
|
+
i18n: I18n;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export class TableCellSelection {
|
|
@@ -63,6 +65,7 @@ export class TableCellSelection {
|
|
|
63
65
|
private rectangleSelection?: { cancelActiveSelection: () => void };
|
|
64
66
|
private onSelectionActiveChange: ((hasSelection: boolean) => void) | undefined;
|
|
65
67
|
private onClearContent: ((cells: HTMLElement[]) => void) | undefined;
|
|
68
|
+
private i18n: I18n;
|
|
66
69
|
private anchorCell: CellCoord | null = null;
|
|
67
70
|
private extentCell: CellCoord | null = null;
|
|
68
71
|
private isSelecting = false;
|
|
@@ -77,12 +80,14 @@ export class TableCellSelection {
|
|
|
77
80
|
private boundPointerUp: () => void;
|
|
78
81
|
private boundClearSelection: (e: PointerEvent) => void;
|
|
79
82
|
private boundCancelRectangle: (e: MouseEvent) => void;
|
|
83
|
+
private boundKeyDown: (e: KeyboardEvent) => void;
|
|
80
84
|
|
|
81
85
|
constructor(options: CellSelectionOptions) {
|
|
82
86
|
this.grid = options.grid;
|
|
83
87
|
this.rectangleSelection = options.rectangleSelection;
|
|
84
88
|
this.onSelectionActiveChange = options.onSelectionActiveChange;
|
|
85
89
|
this.onClearContent = options.onClearContent;
|
|
90
|
+
this.i18n = options.i18n;
|
|
86
91
|
this.grid.style.position = 'relative';
|
|
87
92
|
|
|
88
93
|
this.boundPointerDown = this.handlePointerDown.bind(this);
|
|
@@ -90,8 +95,10 @@ export class TableCellSelection {
|
|
|
90
95
|
this.boundPointerUp = this.handlePointerUp.bind(this);
|
|
91
96
|
this.boundClearSelection = this.handleClearSelection.bind(this);
|
|
92
97
|
this.boundCancelRectangle = this.handleCancelRectangle.bind(this);
|
|
98
|
+
this.boundKeyDown = this.handleKeyDown.bind(this);
|
|
93
99
|
|
|
94
100
|
this.grid.addEventListener('pointerdown', this.boundPointerDown);
|
|
101
|
+
document.addEventListener('keydown', this.boundKeyDown);
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
public destroy(): void {
|
|
@@ -102,6 +109,7 @@ export class TableCellSelection {
|
|
|
102
109
|
document.removeEventListener('pointerup', this.boundPointerUp);
|
|
103
110
|
document.removeEventListener('pointerdown', this.boundClearSelection);
|
|
104
111
|
document.removeEventListener('mousemove', this.boundCancelRectangle, true);
|
|
112
|
+
document.removeEventListener('keydown', this.boundKeyDown);
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
/**
|
|
@@ -276,6 +284,25 @@ export class TableCellSelection {
|
|
|
276
284
|
this.clearSelection();
|
|
277
285
|
}
|
|
278
286
|
|
|
287
|
+
private handleKeyDown(e: KeyboardEvent): void {
|
|
288
|
+
// Only trigger when selection is active
|
|
289
|
+
if (!this.hasSelection) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Check for Delete or Backspace
|
|
294
|
+
if (e.key !== 'Delete' && e.key !== 'Backspace') {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Prevent default behavior
|
|
299
|
+
e.preventDefault();
|
|
300
|
+
|
|
301
|
+
// Clear content and dismiss selection
|
|
302
|
+
this.onClearContent?.([...this.selectedCells]);
|
|
303
|
+
this.clearSelection();
|
|
304
|
+
}
|
|
305
|
+
|
|
279
306
|
private clearSelection(): void {
|
|
280
307
|
const hadSelection = this.hasSelection;
|
|
281
308
|
|
|
@@ -348,26 +375,10 @@ export class TableCellSelection {
|
|
|
348
375
|
const rows = this.grid.querySelectorAll(`[${ROW_ATTR}]`);
|
|
349
376
|
|
|
350
377
|
// Mark selected cells
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
359
|
-
|
|
360
|
-
for (let c = minCol; c <= maxCol; c++) {
|
|
361
|
-
const cell = cells[c] as HTMLElement | undefined;
|
|
362
|
-
|
|
363
|
-
if (!cell) {
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
cell.setAttribute(SELECTED_ATTR, '');
|
|
368
|
-
this.selectedCells.push(cell);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
378
|
+
this.selectedCells = this.collectCellsInRange(rows, minRow, maxRow, minCol, maxCol);
|
|
379
|
+
this.selectedCells.forEach(cell => {
|
|
380
|
+
cell.setAttribute(SELECTED_ATTR, '');
|
|
381
|
+
});
|
|
371
382
|
|
|
372
383
|
// Calculate overlay position from bounding rects of corner cells
|
|
373
384
|
const firstCell = rows[minRow]?.querySelectorAll(`[${CELL_ATTR}]`)[minCol] as HTMLElement | undefined;
|
|
@@ -388,16 +399,14 @@ export class TableCellSelection {
|
|
|
388
399
|
const borderTop = parseFloat(gridStyle.borderTopWidth) || 0;
|
|
389
400
|
const borderLeft = parseFloat(gridStyle.borderLeftWidth) || 0;
|
|
390
401
|
|
|
391
|
-
let top = firstRect.top - gridRect.top - borderTop;
|
|
392
|
-
let left = firstRect.left - gridRect.left - borderLeft;
|
|
393
402
|
const width = lastRect.right - firstRect.left + 1;
|
|
394
403
|
const height = lastRect.bottom - firstRect.top + 1;
|
|
395
404
|
|
|
396
405
|
// Extend overlay 1px outward to cover adjacent borders:
|
|
397
406
|
// grid border-top/border-left at row 0/col 0, or the previous
|
|
398
407
|
// row's border-bottom / previous column's border-right otherwise.
|
|
399
|
-
top
|
|
400
|
-
left
|
|
408
|
+
const top = firstRect.top - gridRect.top - borderTop - 1;
|
|
409
|
+
const left = firstRect.left - gridRect.left - borderLeft - 1;
|
|
401
410
|
|
|
402
411
|
// Create overlay once, reuse on subsequent paints
|
|
403
412
|
if (!this.overlay) {
|
|
@@ -476,7 +485,7 @@ export class TableCellSelection {
|
|
|
476
485
|
const items: PopoverItemParams[] = [
|
|
477
486
|
{
|
|
478
487
|
icon: IconCross,
|
|
479
|
-
title: '
|
|
488
|
+
title: this.i18n.t('tools.table.clearSelection'),
|
|
480
489
|
closeOnActivate: true,
|
|
481
490
|
onActivate: (): void => {
|
|
482
491
|
this.onClearContent?.([...this.selectedCells]);
|
|
@@ -592,27 +601,8 @@ export class TableCellSelection {
|
|
|
592
601
|
return;
|
|
593
602
|
}
|
|
594
603
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
if (e.clientY < gridRect.top) {
|
|
599
|
-
row = 0;
|
|
600
|
-
} else if (e.clientY > gridRect.bottom) {
|
|
601
|
-
row = rowCount - 1;
|
|
602
|
-
} else {
|
|
603
|
-
row = this.extentCell?.row ?? this.anchorCell.row;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// Clamp col
|
|
607
|
-
let col: number;
|
|
608
|
-
|
|
609
|
-
if (e.clientX < gridRect.left) {
|
|
610
|
-
col = 0;
|
|
611
|
-
} else if (e.clientX > gridRect.right) {
|
|
612
|
-
col = colCount - 1;
|
|
613
|
-
} else {
|
|
614
|
-
col = this.extentCell?.col ?? this.anchorCell.col;
|
|
615
|
-
}
|
|
604
|
+
const row = this.clampAxis(e.clientY, gridRect.top, gridRect.bottom, rowCount, this.extentCell?.row ?? this.anchorCell.row);
|
|
605
|
+
const col = this.clampAxis(e.clientX, gridRect.left, gridRect.right, colCount, this.extentCell?.col ?? this.anchorCell.col);
|
|
616
606
|
|
|
617
607
|
const clamped = { row, col };
|
|
618
608
|
|
|
@@ -621,4 +611,38 @@ export class TableCellSelection {
|
|
|
621
611
|
this.paintSelection();
|
|
622
612
|
}
|
|
623
613
|
}
|
|
614
|
+
|
|
615
|
+
private collectCellsInRange(
|
|
616
|
+
rows: NodeListOf<Element>,
|
|
617
|
+
minRow: number,
|
|
618
|
+
maxRow: number,
|
|
619
|
+
minCol: number,
|
|
620
|
+
maxCol: number,
|
|
621
|
+
): HTMLElement[] {
|
|
622
|
+
return Array.from(rows)
|
|
623
|
+
.slice(minRow, maxRow + 1)
|
|
624
|
+
.flatMap(row => {
|
|
625
|
+
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
626
|
+
|
|
627
|
+
return Array.from(cells)
|
|
628
|
+
.slice(minCol, maxCol + 1)
|
|
629
|
+
.filter((cell): cell is HTMLElement => cell instanceof HTMLElement);
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Clamp a pointer coordinate to an axis range, returning the edge index
|
|
635
|
+
* when outside or the fallback when inside.
|
|
636
|
+
*/
|
|
637
|
+
private clampAxis(pointer: number, min: number, max: number, count: number, fallback: number): number {
|
|
638
|
+
if (pointer < min) {
|
|
639
|
+
return 0;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (pointer > max) {
|
|
643
|
+
return count - 1;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return fallback;
|
|
647
|
+
}
|
|
624
648
|
}
|
|
@@ -20,6 +20,7 @@ const CELL_CLASSES = [
|
|
|
20
20
|
'outline-none',
|
|
21
21
|
'leading-normal',
|
|
22
22
|
'text-sm',
|
|
23
|
+
'cursor-text',
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -131,7 +132,7 @@ export class TableGrid {
|
|
|
131
132
|
* those widths and the new column is added in px mode. This prevents
|
|
132
133
|
* existing columns from shrinking when the table is in percent mode.
|
|
133
134
|
*/
|
|
134
|
-
public addColumn(table: HTMLElement, index?: number, colWidths?: number[]): boolean {
|
|
135
|
+
public addColumn(table: HTMLElement, index?: number, colWidths?: number[], newColWidth?: number): boolean {
|
|
135
136
|
const rows = table.querySelectorAll(`[${ROW_ATTR}]`);
|
|
136
137
|
const oldColCount = this.getColumnCount(table);
|
|
137
138
|
const hasValidColWidths = colWidths !== undefined && colWidths.length === oldColCount;
|
|
@@ -142,7 +143,7 @@ export class TableGrid {
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
if (usePx) {
|
|
145
|
-
this.addColumnPx(rows, oldColCount, index);
|
|
146
|
+
this.addColumnPx(rows, oldColCount, index, newColWidth);
|
|
146
147
|
|
|
147
148
|
return true;
|
|
148
149
|
}
|
|
@@ -170,24 +171,15 @@ export class TableGrid {
|
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
/**
|
|
173
|
-
* Add column in px mode: keep existing widths, add new column at half the average
|
|
174
|
+
* Add column in px mode: keep existing widths, add new column at given width or half the average
|
|
174
175
|
*/
|
|
175
|
-
private addColumnPx(rows: NodeListOf<Element>, oldColCount: number, index?: number): void {
|
|
176
|
-
const
|
|
177
|
-
const firstRowCells = firstRow?.querySelectorAll(`[${CELL_ATTR}]`);
|
|
178
|
-
const totalWidth = Array.from(firstRowCells ?? []).reduce(
|
|
179
|
-
(sum, node) => sum + (parseFloat((node as HTMLElement).style.width) || 0),
|
|
180
|
-
0
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
const newColWidth = oldColCount > 0
|
|
184
|
-
? Math.round((totalWidth / oldColCount / 2) * 100) / 100
|
|
185
|
-
: 0;
|
|
176
|
+
private addColumnPx(rows: NodeListOf<Element>, oldColCount: number, index?: number, newColWidth?: number): void {
|
|
177
|
+
const computedWidth = newColWidth ?? this.computeHalfAvgPxWidth(rows, oldColCount);
|
|
186
178
|
|
|
187
179
|
rows.forEach(row => {
|
|
188
180
|
const cells = row.querySelectorAll(`[${CELL_ATTR}]`);
|
|
189
181
|
const isAppend = index === undefined || index >= cells.length;
|
|
190
|
-
const cell = this.createCell(`${
|
|
182
|
+
const cell = this.createCell(`${computedWidth}px`);
|
|
191
183
|
|
|
192
184
|
if (!isAppend) {
|
|
193
185
|
row.insertBefore(cell, cells[index]);
|
|
@@ -199,6 +191,19 @@ export class TableGrid {
|
|
|
199
191
|
});
|
|
200
192
|
}
|
|
201
193
|
|
|
194
|
+
private computeHalfAvgPxWidth(rows: NodeListOf<Element>, oldColCount: number): number {
|
|
195
|
+
const firstRow = rows[0];
|
|
196
|
+
const firstRowCells = firstRow?.querySelectorAll(`[${CELL_ATTR}]`);
|
|
197
|
+
const totalWidth = Array.from(firstRowCells ?? []).reduce(
|
|
198
|
+
(sum, node) => sum + (parseFloat((node as HTMLElement).style.width) || 0),
|
|
199
|
+
0
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
return oldColCount > 0
|
|
203
|
+
? Math.round((totalWidth / oldColCount / 2) * 100) / 100
|
|
204
|
+
: 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
202
207
|
/**
|
|
203
208
|
* Add column in % mode: shrink existing columns slightly and add new column at half the average width
|
|
204
209
|
*/
|
|
@@ -57,9 +57,9 @@ export const createGripDotsSvg = (orientation: 'horizontal' | 'vertical'): SVGEl
|
|
|
57
57
|
*/
|
|
58
58
|
export const expandGrip = (grip: HTMLElement, type: 'col' | 'row'): void => {
|
|
59
59
|
if (type === 'col') {
|
|
60
|
-
grip.style
|
|
60
|
+
Object.assign(grip.style, { height: `${GRIP_HOVER_SIZE}px` });
|
|
61
61
|
} else {
|
|
62
|
-
grip.style
|
|
62
|
+
Object.assign(grip.style, { width: `${GRIP_HOVER_SIZE}px` });
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
grip.classList.add('bg-gray-200');
|
|
@@ -79,9 +79,9 @@ export const expandGrip = (grip: HTMLElement, type: 'col' | 'row'): void => {
|
|
|
79
79
|
*/
|
|
80
80
|
export const collapseGrip = (grip: HTMLElement, type: 'col' | 'row', pillSize: number): void => {
|
|
81
81
|
if (type === 'col') {
|
|
82
|
-
grip.style
|
|
82
|
+
Object.assign(grip.style, { height: `${pillSize}px` });
|
|
83
83
|
} else {
|
|
84
|
-
grip.style
|
|
84
|
+
Object.assign(grip.style, { width: `${pillSize}px` });
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
grip.classList.remove('bg-gray-200');
|
|
@@ -168,14 +168,15 @@ export const computeInsertColumnWidths = (
|
|
|
168
168
|
): number[] => {
|
|
169
169
|
const colWidths = data.colWidths ?? readPixelWidths(gridEl);
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
const halfWidth = data.initialColWidth !== undefined
|
|
172
|
+
? Math.round((data.initialColWidth / 2) * 100) / 100
|
|
173
|
+
: computeHalfAvgWidth(colWidths);
|
|
174
|
+
|
|
175
|
+
grid.addColumn(gridEl, index, colWidths, halfWidth);
|
|
172
176
|
|
|
173
|
-
const halfAvgWidth = Math.round(
|
|
174
|
-
(colWidths.reduce((sum, w) => sum + w, 0) / colWidths.length / 2) * 100
|
|
175
|
-
) / 100;
|
|
176
177
|
const newWidths = [...colWidths];
|
|
177
178
|
|
|
178
|
-
newWidths.splice(index, 0,
|
|
179
|
+
newWidths.splice(index, 0, halfWidth);
|
|
179
180
|
|
|
180
181
|
return newWidths;
|
|
181
182
|
};
|
|
@@ -185,6 +186,14 @@ export const computeHalfAvgWidth = (colWidths: number[]): number =>
|
|
|
185
186
|
(colWidths.reduce((sum, w) => sum + w, 0) / colWidths.length / 2) * 100
|
|
186
187
|
) / 100;
|
|
187
188
|
|
|
189
|
+
export const computeInitialColWidth = (colWidths: number[]): number => {
|
|
190
|
+
if (colWidths.length === 0) {
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return Math.round((colWidths.reduce((sum, w) => sum + w, 0) / colWidths.length) * 100) / 100;
|
|
195
|
+
};
|
|
196
|
+
|
|
188
197
|
// ─── Block IDs from cells ───────────────────────────────────────────
|
|
189
198
|
|
|
190
199
|
export const getBlockIdsInRow = (element: HTMLElement | null, cellBlocks: TableCellBlocks | null, rowIndex: number): string[] => {
|
|
@@ -309,15 +318,15 @@ export const mountCellBlocksReadOnly = (
|
|
|
309
318
|
return;
|
|
310
319
|
}
|
|
311
320
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
// Check if container already has blocks to ensure idempotency
|
|
315
|
-
const existingBlocks = container.querySelectorAll('[data-blok-id]');
|
|
321
|
+
// Skip legacy cells that already have blocks (idempotency guard)
|
|
322
|
+
const hasExistingBlocks = container.querySelectorAll('[data-blok-id]').length > 0;
|
|
316
323
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
324
|
+
if (!isCellWithBlocks(cellContent) && hasExistingBlocks) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
320
327
|
|
|
328
|
+
if (!isCellWithBlocks(cellContent)) {
|
|
329
|
+
// Handle legacy string content by creating a paragraph block
|
|
321
330
|
const legacyText = typeof cellContent === 'string' ? cellContent : '';
|
|
322
331
|
const insertedBlock = api.blocks.insert(
|
|
323
332
|
'paragraph',
|
|
@@ -379,6 +388,7 @@ export const normalizeTableData = (
|
|
|
379
388
|
stretched: tableData.stretched ?? config.stretched ?? false,
|
|
380
389
|
content: tableData.content ?? [],
|
|
381
390
|
colWidths: validWidths,
|
|
391
|
+
initialColWidth: tableData.initialColWidth,
|
|
382
392
|
};
|
|
383
393
|
};
|
|
384
394
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { API } from '../../../types';
|
|
2
|
+
import type { Block } from '../../components/block';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* List of block tools that are restricted from being inserted into table cells.
|
|
6
|
+
* These tools create semantic or structural issues when nested in table cells.
|
|
7
|
+
*/
|
|
8
|
+
export const RESTRICTED_TOOLS = ['header', 'table'];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Check if a block or element is inside a table cell.
|
|
12
|
+
* Uses the data-blok-table-cell-blocks attribute to detect cell containers.
|
|
13
|
+
*
|
|
14
|
+
* @param block - Block instance or HTMLElement to check
|
|
15
|
+
* @returns true if inside a table cell, false otherwise
|
|
16
|
+
*/
|
|
17
|
+
export const isInsideTableCell = (block: Block | HTMLElement | null | undefined): boolean => {
|
|
18
|
+
if (!block) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const element = block instanceof HTMLElement ? block : block.holder;
|
|
23
|
+
|
|
24
|
+
return element.closest('[data-blok-table-cell-blocks]') !== null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Check if a tool name is restricted inside table cells.
|
|
29
|
+
*
|
|
30
|
+
* @param toolName - Name of the block tool to check
|
|
31
|
+
* @returns true if the tool is restricted in table cells, false otherwise
|
|
32
|
+
*/
|
|
33
|
+
export const isRestrictedInTableCell = (toolName: string): boolean => {
|
|
34
|
+
return RESTRICTED_TOOLS.includes(toolName);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert a restricted block to a paragraph block, preserving text content.
|
|
39
|
+
* Replaces the original block in place.
|
|
40
|
+
*
|
|
41
|
+
* @param block - The block to convert
|
|
42
|
+
* @param api - Blok API instance
|
|
43
|
+
* @returns The newly created paragraph block
|
|
44
|
+
* @throws Error if block index cannot be found
|
|
45
|
+
*/
|
|
46
|
+
export const convertToParagraph = (block: Block, api: API): Block => {
|
|
47
|
+
const text = block.holder.textContent || '';
|
|
48
|
+
const blockIndex = api.blocks.getBlockIndex(block.id);
|
|
49
|
+
|
|
50
|
+
if (blockIndex === undefined) {
|
|
51
|
+
throw new Error('Block index not found');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Replace with paragraph, preserving text
|
|
55
|
+
return api.blocks.insert(
|
|
56
|
+
'paragraph',
|
|
57
|
+
{ text },
|
|
58
|
+
{},
|
|
59
|
+
blockIndex,
|
|
60
|
+
false, // don't focus
|
|
61
|
+
true, // replace existing
|
|
62
|
+
block.id
|
|
63
|
+
) as unknown as Block;
|
|
64
|
+
};
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import type { TableCellBlocks } from './table-cell-blocks';
|
|
2
|
+
import type { TableGrid } from './table-core';
|
|
3
|
+
import {
|
|
4
|
+
applyPixelWidths,
|
|
5
|
+
computeInsertColumnWidths,
|
|
6
|
+
deleteColumnWithBlockCleanup,
|
|
7
|
+
deleteRowWithBlockCleanup,
|
|
8
|
+
populateNewCells,
|
|
9
|
+
redistributePercentWidths,
|
|
10
|
+
syncColWidthsAfterMove,
|
|
11
|
+
} from './table-operations';
|
|
12
|
+
import type { RowColAction } from './table-row-col-controls';
|
|
13
|
+
import type { TableData } from './types';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Describes which row or column to highlight after an action completes.
|
|
17
|
+
*/
|
|
18
|
+
export type PendingHighlight = { type: 'row' | 'col'; index: number };
|
|
19
|
+
|
|
20
|
+
interface ActionContext {
|
|
21
|
+
grid: TableGrid;
|
|
22
|
+
data: TableData;
|
|
23
|
+
cellBlocks: TableCellBlocks | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ActionResult {
|
|
27
|
+
pendingHighlight: PendingHighlight | null;
|
|
28
|
+
moveSelection: { type: 'row' | 'col'; index: number } | null;
|
|
29
|
+
colWidths: number[] | undefined;
|
|
30
|
+
withHeadings: boolean;
|
|
31
|
+
withHeadingColumn: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const handleInsertRow = (
|
|
35
|
+
gridEl: HTMLElement,
|
|
36
|
+
index: number,
|
|
37
|
+
ctx: ActionContext,
|
|
38
|
+
): ActionResult => {
|
|
39
|
+
ctx.grid.addRow(gridEl, index);
|
|
40
|
+
populateNewCells(gridEl, ctx.cellBlocks);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
pendingHighlight: { type: 'row', index },
|
|
44
|
+
moveSelection: null,
|
|
45
|
+
colWidths: ctx.data.colWidths,
|
|
46
|
+
withHeadings: ctx.data.withHeadings,
|
|
47
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handleInsertCol = (
|
|
52
|
+
gridEl: HTMLElement,
|
|
53
|
+
index: number,
|
|
54
|
+
ctx: ActionContext,
|
|
55
|
+
): ActionResult => {
|
|
56
|
+
const colWidths = computeInsertColumnWidths(gridEl, index, ctx.data, ctx.grid);
|
|
57
|
+
|
|
58
|
+
populateNewCells(gridEl, ctx.cellBlocks);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
pendingHighlight: { type: 'col', index },
|
|
62
|
+
moveSelection: null,
|
|
63
|
+
colWidths,
|
|
64
|
+
withHeadings: ctx.data.withHeadings,
|
|
65
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const handleMoveRow = (
|
|
70
|
+
gridEl: HTMLElement,
|
|
71
|
+
fromIndex: number,
|
|
72
|
+
toIndex: number,
|
|
73
|
+
ctx: ActionContext,
|
|
74
|
+
): ActionResult => {
|
|
75
|
+
ctx.grid.moveRow(gridEl, fromIndex, toIndex);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
pendingHighlight: null,
|
|
79
|
+
moveSelection: { type: 'row', index: toIndex },
|
|
80
|
+
colWidths: ctx.data.colWidths,
|
|
81
|
+
withHeadings: ctx.data.withHeadings,
|
|
82
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const handleMoveCol = (
|
|
87
|
+
gridEl: HTMLElement,
|
|
88
|
+
fromIndex: number,
|
|
89
|
+
toIndex: number,
|
|
90
|
+
ctx: ActionContext,
|
|
91
|
+
): ActionResult => {
|
|
92
|
+
ctx.grid.moveColumn(gridEl, fromIndex, toIndex);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
pendingHighlight: null,
|
|
96
|
+
moveSelection: { type: 'col', index: toIndex },
|
|
97
|
+
colWidths: syncColWidthsAfterMove(ctx.data.colWidths, fromIndex, toIndex),
|
|
98
|
+
withHeadings: ctx.data.withHeadings,
|
|
99
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const handleDeleteRow = (
|
|
104
|
+
gridEl: HTMLElement,
|
|
105
|
+
index: number,
|
|
106
|
+
ctx: ActionContext,
|
|
107
|
+
): ActionResult => {
|
|
108
|
+
deleteRowWithBlockCleanup(gridEl, index, ctx.grid, ctx.cellBlocks);
|
|
109
|
+
const newRowCount = ctx.grid.getRowCount(gridEl);
|
|
110
|
+
const neighborRow = index < newRowCount ? index : index - 1;
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
pendingHighlight: { type: 'row', index: neighborRow },
|
|
114
|
+
moveSelection: null,
|
|
115
|
+
colWidths: ctx.data.colWidths,
|
|
116
|
+
withHeadings: ctx.data.withHeadings,
|
|
117
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const handleDeleteCol = (
|
|
122
|
+
gridEl: HTMLElement,
|
|
123
|
+
index: number,
|
|
124
|
+
ctx: ActionContext,
|
|
125
|
+
): ActionResult => {
|
|
126
|
+
const colWidths = deleteColumnWithBlockCleanup(gridEl, index, ctx.data.colWidths, ctx.grid, ctx.cellBlocks);
|
|
127
|
+
|
|
128
|
+
if (colWidths) {
|
|
129
|
+
applyPixelWidths(gridEl, colWidths);
|
|
130
|
+
} else {
|
|
131
|
+
redistributePercentWidths(gridEl);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const newColCount = ctx.grid.getColumnCount(gridEl);
|
|
135
|
+
const neighborCol = index < newColCount ? index : index - 1;
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
pendingHighlight: { type: 'col', index: neighborCol },
|
|
139
|
+
moveSelection: null,
|
|
140
|
+
colWidths,
|
|
141
|
+
withHeadings: ctx.data.withHeadings,
|
|
142
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Execute a row/column action on the table grid.
|
|
148
|
+
* Returns the updated colWidths, withHeadings, withHeadingColumn values
|
|
149
|
+
* along with pendingHighlight and moveSelection for the caller to apply.
|
|
150
|
+
*/
|
|
151
|
+
export const executeRowColAction = (
|
|
152
|
+
gridEl: HTMLElement,
|
|
153
|
+
action: RowColAction,
|
|
154
|
+
ctx: ActionContext,
|
|
155
|
+
): ActionResult => {
|
|
156
|
+
switch (action.type) {
|
|
157
|
+
case 'insert-row-above':
|
|
158
|
+
return handleInsertRow(gridEl, action.index, ctx);
|
|
159
|
+
case 'insert-row-below':
|
|
160
|
+
return handleInsertRow(gridEl, action.index + 1, ctx);
|
|
161
|
+
case 'insert-col-left':
|
|
162
|
+
return handleInsertCol(gridEl, action.index, ctx);
|
|
163
|
+
case 'insert-col-right':
|
|
164
|
+
return handleInsertCol(gridEl, action.index + 1, ctx);
|
|
165
|
+
case 'move-row':
|
|
166
|
+
return handleMoveRow(gridEl, action.fromIndex, action.toIndex, ctx);
|
|
167
|
+
case 'move-col':
|
|
168
|
+
return handleMoveCol(gridEl, action.fromIndex, action.toIndex, ctx);
|
|
169
|
+
case 'delete-row':
|
|
170
|
+
return handleDeleteRow(gridEl, action.index, ctx);
|
|
171
|
+
case 'delete-col':
|
|
172
|
+
return handleDeleteCol(gridEl, action.index, ctx);
|
|
173
|
+
case 'toggle-heading':
|
|
174
|
+
return {
|
|
175
|
+
pendingHighlight: { type: 'row', index: 0 },
|
|
176
|
+
moveSelection: null,
|
|
177
|
+
colWidths: ctx.data.colWidths,
|
|
178
|
+
withHeadings: !ctx.data.withHeadings,
|
|
179
|
+
withHeadingColumn: ctx.data.withHeadingColumn,
|
|
180
|
+
};
|
|
181
|
+
case 'toggle-heading-column':
|
|
182
|
+
return {
|
|
183
|
+
pendingHighlight: { type: 'col', index: 0 },
|
|
184
|
+
moveSelection: null,
|
|
185
|
+
colWidths: ctx.data.colWidths,
|
|
186
|
+
withHeadings: ctx.data.withHeadings,
|
|
187
|
+
withHeadingColumn: !ctx.data.withHeadingColumn,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
};
|