@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,22 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IconInsertAbove,
|
|
3
|
-
IconInsertBelow,
|
|
4
|
-
IconInsertLeft,
|
|
5
|
-
IconInsertRight,
|
|
6
|
-
IconTrash,
|
|
7
|
-
IconHeaderRow,
|
|
8
|
-
IconHeaderColumn,
|
|
9
|
-
} from '../../components/icons';
|
|
10
|
-
import { PopoverDesktop, PopoverItemType } from '../../components/utils/popover';
|
|
1
|
+
import type { I18n } from '../../../types/api';
|
|
11
2
|
import { twMerge } from '../../components/utils/tw';
|
|
12
3
|
|
|
13
4
|
import { BORDER_WIDTH, CELL_ATTR, ROW_ATTR } from './table-core';
|
|
14
5
|
import { collapseGrip, createGripDotsSvg, expandGrip, GRIP_HOVER_SIZE } from './table-grip-visuals';
|
|
15
|
-
import { createHeadingToggle } from './table-heading-toggle';
|
|
16
6
|
import { getCumulativeColEdges, TableRowColDrag } from './table-row-col-drag';
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
import type { PopoverItemParams } from '@/types/utils/popover/popover-item';
|
|
7
|
+
import { createGripPopover } from './table-row-col-popover';
|
|
8
|
+
import type { PopoverState } from './table-row-col-popover';
|
|
20
9
|
|
|
21
10
|
const GRIP_ATTR = 'data-blok-table-grip';
|
|
22
11
|
const GRIP_COL_ATTR = 'data-blok-table-grip-col';
|
|
@@ -52,6 +41,7 @@ export interface TableRowColControlsOptions {
|
|
|
52
41
|
onDragStateChange?: (isDragging: boolean, dragType: 'row' | 'col' | null) => void;
|
|
53
42
|
onGripClick?: (type: 'row' | 'col', index: number) => void;
|
|
54
43
|
onGripPopoverClose?: () => void;
|
|
44
|
+
i18n: I18n;
|
|
55
45
|
}
|
|
56
46
|
|
|
57
47
|
const GRIP_CAPSULE_CLASSES = [
|
|
@@ -100,16 +90,18 @@ export class TableRowColControls {
|
|
|
100
90
|
private onAction: (action: RowColAction) => void;
|
|
101
91
|
private onGripClick: ((type: 'row' | 'col', index: number) => void) | undefined;
|
|
102
92
|
private onGripPopoverClose: (() => void) | undefined;
|
|
93
|
+
private i18n: I18n;
|
|
103
94
|
|
|
104
95
|
private colGrips: HTMLElement[] = [];
|
|
105
96
|
private rowGrips: HTMLElement[] = [];
|
|
106
|
-
private
|
|
107
|
-
private activePopoverGrip: HTMLElement | null = null;
|
|
97
|
+
private popoverState: PopoverState = { popover: null, grip: null };
|
|
108
98
|
private lockedGrip: HTMLElement | null = null;
|
|
109
99
|
private boundUnlockGrip: (e: PointerEvent) => void;
|
|
110
100
|
private hideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
111
101
|
private activeColGripIndex = -1;
|
|
112
102
|
private activeRowGripIndex = -1;
|
|
103
|
+
private isInsideTable = false;
|
|
104
|
+
private rowResizeObserver: ResizeObserver | null = null;
|
|
113
105
|
|
|
114
106
|
private drag: TableRowColDrag;
|
|
115
107
|
|
|
@@ -126,6 +118,7 @@ export class TableRowColControls {
|
|
|
126
118
|
this.onAction = options.onAction;
|
|
127
119
|
this.onGripClick = options.onGripClick;
|
|
128
120
|
this.onGripPopoverClose = options.onGripPopoverClose;
|
|
121
|
+
this.i18n = options.i18n;
|
|
129
122
|
|
|
130
123
|
this.drag = new TableRowColDrag({
|
|
131
124
|
grid: this.grid,
|
|
@@ -228,15 +221,19 @@ export class TableRowColControls {
|
|
|
228
221
|
});
|
|
229
222
|
|
|
230
223
|
this.positionGrips();
|
|
224
|
+
this.observeRowHeights();
|
|
231
225
|
}
|
|
232
226
|
|
|
233
227
|
private destroyGrips(): void {
|
|
228
|
+
this.rowResizeObserver?.disconnect();
|
|
229
|
+
this.rowResizeObserver = null;
|
|
234
230
|
this.colGrips.forEach(g => g.remove());
|
|
235
231
|
this.rowGrips.forEach(g => g.remove());
|
|
236
232
|
this.colGrips = [];
|
|
237
233
|
this.rowGrips = [];
|
|
238
234
|
this.activeColGripIndex = -1;
|
|
239
235
|
this.activeRowGripIndex = -1;
|
|
236
|
+
this.isInsideTable = false;
|
|
240
237
|
}
|
|
241
238
|
|
|
242
239
|
private createGripElement(type: 'row' | 'col', index: number): HTMLElement {
|
|
@@ -313,8 +310,25 @@ export class TableRowColControls {
|
|
|
313
310
|
});
|
|
314
311
|
}
|
|
315
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Set up ResizeObserver to watch for row height changes and reposition grips.
|
|
315
|
+
*/
|
|
316
|
+
private observeRowHeights(): void {
|
|
317
|
+
this.rowResizeObserver?.disconnect();
|
|
318
|
+
|
|
319
|
+
this.rowResizeObserver = new ResizeObserver(() => {
|
|
320
|
+
this.positionGrips();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const rows = this.grid.querySelectorAll(`[${ROW_ATTR}]`);
|
|
324
|
+
|
|
325
|
+
rows.forEach(row => {
|
|
326
|
+
this.rowResizeObserver?.observe(row as HTMLElement);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
316
330
|
private isGripInteractionLocked(): boolean {
|
|
317
|
-
return this.
|
|
331
|
+
return this.popoverState.popover !== null || this.lockedGrip !== null;
|
|
318
332
|
}
|
|
319
333
|
|
|
320
334
|
private handleMouseOver(e: MouseEvent): void {
|
|
@@ -339,6 +353,7 @@ export class TableRowColControls {
|
|
|
339
353
|
|
|
340
354
|
this.showColGrip(position.col);
|
|
341
355
|
this.showRowGrip(position.row);
|
|
356
|
+
this.isInsideTable = true;
|
|
342
357
|
}
|
|
343
358
|
|
|
344
359
|
private handleMouseLeave(): void {
|
|
@@ -385,7 +400,7 @@ export class TableRowColControls {
|
|
|
385
400
|
const el: HTMLElement = grip;
|
|
386
401
|
|
|
387
402
|
// Don't hide the grip that has an active popover
|
|
388
|
-
if (!visible && grip === this.
|
|
403
|
+
if (!visible && grip === this.popoverState.grip) {
|
|
389
404
|
return;
|
|
390
405
|
}
|
|
391
406
|
|
|
@@ -400,6 +415,7 @@ export class TableRowColControls {
|
|
|
400
415
|
this.clearHideTimeout();
|
|
401
416
|
this.hideColGrip();
|
|
402
417
|
this.hideRowGrip();
|
|
418
|
+
this.isInsideTable = false;
|
|
403
419
|
}
|
|
404
420
|
|
|
405
421
|
private showColGrip(index: number): void {
|
|
@@ -440,10 +456,25 @@ export class TableRowColControls {
|
|
|
440
456
|
|
|
441
457
|
private applyVisibleClasses(grip: HTMLElement): void {
|
|
442
458
|
const el = grip;
|
|
459
|
+
const isCol = el.hasAttribute(GRIP_COL_ATTR);
|
|
460
|
+
const type: 'col' | 'row' = isCol ? 'col' : 'row';
|
|
461
|
+
const pillSize = isCol ? COL_PILL_HEIGHT : ROW_PILL_WIDTH;
|
|
462
|
+
|
|
463
|
+
// Reset to pill size before making visible
|
|
464
|
+
collapseGrip(el, type, pillSize);
|
|
465
|
+
|
|
466
|
+
if (this.isInsideTable) {
|
|
467
|
+
el.style.transition = 'none';
|
|
468
|
+
}
|
|
443
469
|
|
|
444
470
|
el.className = twMerge(GRIP_CAPSULE_CLASSES, GRIP_VISIBLE_CLASSES);
|
|
445
471
|
el.setAttribute('data-blok-table-grip-visible', '');
|
|
446
472
|
|
|
473
|
+
if (this.isInsideTable) {
|
|
474
|
+
void el.offsetHeight;
|
|
475
|
+
el.style.transition = '';
|
|
476
|
+
}
|
|
477
|
+
|
|
447
478
|
const svg = el.querySelector('svg');
|
|
448
479
|
|
|
449
480
|
if (svg) {
|
|
@@ -453,7 +484,7 @@ export class TableRowColControls {
|
|
|
453
484
|
}
|
|
454
485
|
|
|
455
486
|
private applyActiveClasses(grip: HTMLElement): void {
|
|
456
|
-
grip
|
|
487
|
+
Object.assign(grip, { className: twMerge(GRIP_CAPSULE_CLASSES, GRIP_ACTIVE_CLASSES) });
|
|
457
488
|
grip.setAttribute('data-blok-table-grip-visible', '');
|
|
458
489
|
|
|
459
490
|
const svg = grip.querySelector('svg');
|
|
@@ -476,11 +507,22 @@ export class TableRowColControls {
|
|
|
476
507
|
const el = grip;
|
|
477
508
|
const isCol = el.hasAttribute(GRIP_COL_ATTR);
|
|
478
509
|
const type: 'col' | 'row' = isCol ? 'col' : 'row';
|
|
479
|
-
|
|
510
|
+
// With border-box, pillSize must account for the 12px padding (6px each side)
|
|
511
|
+
const HIT_AREA_PADDING = 12;
|
|
512
|
+
const pillSize = isCol ? (COL_PILL_HEIGHT + HIT_AREA_PADDING) : (ROW_PILL_WIDTH + HIT_AREA_PADDING);
|
|
513
|
+
|
|
514
|
+
if (this.isInsideTable) {
|
|
515
|
+
el.style.transition = 'none';
|
|
516
|
+
}
|
|
480
517
|
|
|
481
518
|
collapseGrip(el, type, pillSize);
|
|
482
519
|
el.className = twMerge(GRIP_CAPSULE_CLASSES, GRIP_IDLE_CLASSES);
|
|
483
520
|
el.removeAttribute('data-blok-table-grip-visible');
|
|
521
|
+
|
|
522
|
+
if (this.isInsideTable) {
|
|
523
|
+
void el.offsetHeight;
|
|
524
|
+
el.style.transition = '';
|
|
525
|
+
}
|
|
484
526
|
}
|
|
485
527
|
|
|
486
528
|
private handleDragStateChange(isDragging: boolean, _dragType: 'row' | 'col' | null): void {
|
|
@@ -495,6 +537,7 @@ export class TableRowColControls {
|
|
|
495
537
|
this.hideTimeout = setTimeout(() => {
|
|
496
538
|
this.hideColGrip();
|
|
497
539
|
this.hideRowGrip();
|
|
540
|
+
this.isInsideTable = false;
|
|
498
541
|
this.hideTimeout = null;
|
|
499
542
|
}, HIDE_DELAY_MS);
|
|
500
543
|
}
|
|
@@ -553,175 +596,41 @@ export class TableRowColControls {
|
|
|
553
596
|
// ── Popover menus ────────────────────────────────────────────
|
|
554
597
|
|
|
555
598
|
private openPopover(type: 'row' | 'col', index: number): void {
|
|
556
|
-
this.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
// Track which grip has the popover so setGripsDisplay won't hide it
|
|
578
|
-
this.activePopoverGrip = grip;
|
|
579
|
-
|
|
580
|
-
this.activePopover.on(PopoverEvent.Closed, () => {
|
|
581
|
-
// Guard against re-entrant calls: destroyPopover() calls popover.destroy()
|
|
582
|
-
// which calls hide() and re-emits Closed. Skip the re-entrant invocation.
|
|
583
|
-
if (this.activePopover === null) {
|
|
584
|
-
return;
|
|
599
|
+
this.popoverState = createGripPopover(
|
|
600
|
+
type,
|
|
601
|
+
index,
|
|
602
|
+
{ col: this.colGrips, row: this.rowGrips },
|
|
603
|
+
{
|
|
604
|
+
getColumnCount: this.getColumnCount,
|
|
605
|
+
getRowCount: this.getRowCount,
|
|
606
|
+
isHeadingRow: this.isHeadingRow,
|
|
607
|
+
isHeadingColumn: this.isHeadingColumn,
|
|
608
|
+
onAction: this.onAction,
|
|
609
|
+
i18n: this.i18n,
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
clearHideTimeout: () => this.clearHideTimeout(),
|
|
613
|
+
hideAllGripsExcept: (grip) => this.hideAllGripsExcept(grip),
|
|
614
|
+
applyActiveClasses: (grip) => this.applyActiveClasses(grip),
|
|
615
|
+
applyVisibleClasses: (grip) => this.applyVisibleClasses(grip),
|
|
616
|
+
scheduleHideAll: () => this.scheduleHideAll(),
|
|
617
|
+
destroyPopover: () => this.destroyPopover(),
|
|
618
|
+
onGripPopoverClose: this.onGripPopoverClose,
|
|
585
619
|
}
|
|
620
|
+
);
|
|
586
621
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
this.onGripPopoverClose?.();
|
|
591
|
-
});
|
|
592
|
-
|
|
593
|
-
// Hide all other grips and make the active one blue
|
|
594
|
-
this.hideAllGripsExcept(grip);
|
|
595
|
-
this.applyActiveClasses(grip);
|
|
596
|
-
|
|
597
|
-
// Expand the grip to hover size so it remains visible while popover is open
|
|
598
|
-
if (type === 'col') {
|
|
599
|
-
grip.style.height = `${GRIP_HOVER_SIZE}px`;
|
|
600
|
-
} else {
|
|
601
|
-
grip.style.width = `${GRIP_HOVER_SIZE}px`;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
this.activePopover.show();
|
|
622
|
+
// Show after storing state so callbacks (e.g. onGripClick → setGripsDisplay)
|
|
623
|
+
// see the updated popoverState.grip reference
|
|
624
|
+
this.popoverState.popover?.show();
|
|
605
625
|
this.onGripClick?.(type, index);
|
|
606
626
|
}
|
|
607
627
|
|
|
608
628
|
private destroyPopover(): void {
|
|
609
|
-
if (this.
|
|
610
|
-
const
|
|
629
|
+
if (this.popoverState.popover !== null) {
|
|
630
|
+
const popoverRef = this.popoverState.popover;
|
|
611
631
|
|
|
612
|
-
this.
|
|
613
|
-
|
|
614
|
-
popover.destroy();
|
|
632
|
+
this.popoverState = { popover: null, grip: null };
|
|
633
|
+
popoverRef.destroy();
|
|
615
634
|
}
|
|
616
635
|
}
|
|
617
|
-
|
|
618
|
-
private buildColumnMenu(colIndex: number): PopoverItemParams[] {
|
|
619
|
-
const headingItems: PopoverItemParams[] = colIndex === 0
|
|
620
|
-
? [
|
|
621
|
-
{
|
|
622
|
-
type: PopoverItemType.Html,
|
|
623
|
-
element: createHeadingToggle({
|
|
624
|
-
icon: IconHeaderColumn,
|
|
625
|
-
label: 'Header column',
|
|
626
|
-
isActive: this.isHeadingColumn(),
|
|
627
|
-
onToggle: () => {
|
|
628
|
-
this.onAction({ type: 'toggle-heading-column' });
|
|
629
|
-
},
|
|
630
|
-
}),
|
|
631
|
-
},
|
|
632
|
-
{ type: PopoverItemType.Separator },
|
|
633
|
-
]
|
|
634
|
-
: [];
|
|
635
|
-
|
|
636
|
-
const baseItems: PopoverItemParams[] = [
|
|
637
|
-
{
|
|
638
|
-
icon: IconInsertLeft,
|
|
639
|
-
title: 'Insert Column Left',
|
|
640
|
-
closeOnActivate: true,
|
|
641
|
-
onActivate: (): void => {
|
|
642
|
-
this.onAction({ type: 'insert-col-left', index: colIndex });
|
|
643
|
-
},
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
icon: IconInsertRight,
|
|
647
|
-
title: 'Insert Column Right',
|
|
648
|
-
closeOnActivate: true,
|
|
649
|
-
onActivate: (): void => {
|
|
650
|
-
this.onAction({ type: 'insert-col-right', index: colIndex });
|
|
651
|
-
},
|
|
652
|
-
},
|
|
653
|
-
];
|
|
654
|
-
|
|
655
|
-
const canDelete = this.getColumnCount() > 1;
|
|
656
|
-
const deleteItems: PopoverItemParams[] = [
|
|
657
|
-
{ type: PopoverItemType.Separator },
|
|
658
|
-
{
|
|
659
|
-
icon: IconTrash,
|
|
660
|
-
title: 'Delete',
|
|
661
|
-
isDestructive: true,
|
|
662
|
-
isDisabled: !canDelete,
|
|
663
|
-
closeOnActivate: true,
|
|
664
|
-
onActivate: (): void => {
|
|
665
|
-
this.onAction({ type: 'delete-col', index: colIndex });
|
|
666
|
-
},
|
|
667
|
-
},
|
|
668
|
-
];
|
|
669
|
-
|
|
670
|
-
return [...headingItems, ...baseItems, ...deleteItems];
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
private buildRowMenu(rowIndex: number): PopoverItemParams[] {
|
|
674
|
-
const headingItems: PopoverItemParams[] = rowIndex === 0
|
|
675
|
-
? [
|
|
676
|
-
{
|
|
677
|
-
type: PopoverItemType.Html,
|
|
678
|
-
element: createHeadingToggle({
|
|
679
|
-
icon: IconHeaderRow,
|
|
680
|
-
label: 'Header row',
|
|
681
|
-
isActive: this.isHeadingRow(),
|
|
682
|
-
onToggle: () => {
|
|
683
|
-
this.onAction({ type: 'toggle-heading' });
|
|
684
|
-
},
|
|
685
|
-
}),
|
|
686
|
-
},
|
|
687
|
-
{ type: PopoverItemType.Separator },
|
|
688
|
-
]
|
|
689
|
-
: [];
|
|
690
|
-
|
|
691
|
-
const baseItems: PopoverItemParams[] = [
|
|
692
|
-
{
|
|
693
|
-
icon: IconInsertAbove,
|
|
694
|
-
title: 'Insert Row Above',
|
|
695
|
-
closeOnActivate: true,
|
|
696
|
-
onActivate: (): void => {
|
|
697
|
-
this.onAction({ type: 'insert-row-above', index: rowIndex });
|
|
698
|
-
},
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
icon: IconInsertBelow,
|
|
702
|
-
title: 'Insert Row Below',
|
|
703
|
-
closeOnActivate: true,
|
|
704
|
-
onActivate: (): void => {
|
|
705
|
-
this.onAction({ type: 'insert-row-below', index: rowIndex });
|
|
706
|
-
},
|
|
707
|
-
},
|
|
708
|
-
];
|
|
709
|
-
|
|
710
|
-
const canDelete = this.getRowCount() > 1;
|
|
711
|
-
const deleteItems: PopoverItemParams[] = [
|
|
712
|
-
{ type: PopoverItemType.Separator },
|
|
713
|
-
{
|
|
714
|
-
icon: IconTrash,
|
|
715
|
-
title: 'Delete',
|
|
716
|
-
isDestructive: true,
|
|
717
|
-
isDisabled: !canDelete,
|
|
718
|
-
closeOnActivate: true,
|
|
719
|
-
onActivate: (): void => {
|
|
720
|
-
this.onAction({ type: 'delete-row', index: rowIndex });
|
|
721
|
-
},
|
|
722
|
-
},
|
|
723
|
-
];
|
|
724
|
-
|
|
725
|
-
return [...headingItems, ...baseItems, ...deleteItems];
|
|
726
|
-
}
|
|
727
636
|
}
|
|
@@ -186,8 +186,8 @@ export class TableRowColDrag {
|
|
|
186
186
|
cells.forEach(node => {
|
|
187
187
|
const cellEl = node as HTMLElement;
|
|
188
188
|
|
|
189
|
-
cellEl.style.backgroundColor = '#
|
|
190
|
-
cellEl.style.opacity = '0.
|
|
189
|
+
cellEl.style.backgroundColor = '#f3f4f6';
|
|
190
|
+
cellEl.style.opacity = '0.7';
|
|
191
191
|
this.dragOverlayCells.push(cellEl);
|
|
192
192
|
});
|
|
193
193
|
}
|
|
@@ -202,8 +202,8 @@ export class TableRowColDrag {
|
|
|
202
202
|
|
|
203
203
|
const cellEl = cells[this.dragFromIndex] as HTMLElement;
|
|
204
204
|
|
|
205
|
-
cellEl.style.backgroundColor = '#
|
|
206
|
-
cellEl.style.opacity = '0.
|
|
205
|
+
cellEl.style.backgroundColor = '#f3f4f6';
|
|
206
|
+
cellEl.style.opacity = '0.7';
|
|
207
207
|
this.dragOverlayCells.push(cellEl);
|
|
208
208
|
});
|
|
209
209
|
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import type { I18n } from '../../../types/api';
|
|
2
|
+
import {
|
|
3
|
+
IconInsertAbove,
|
|
4
|
+
IconInsertBelow,
|
|
5
|
+
IconInsertLeft,
|
|
6
|
+
IconInsertRight,
|
|
7
|
+
IconTrash,
|
|
8
|
+
IconHeaderRow,
|
|
9
|
+
IconHeaderColumn,
|
|
10
|
+
} from '../../components/icons';
|
|
11
|
+
import { PopoverDesktop, PopoverItemType } from '../../components/utils/popover';
|
|
12
|
+
|
|
13
|
+
import { GRIP_HOVER_SIZE } from './table-grip-visuals';
|
|
14
|
+
import { createHeadingToggle } from './table-heading-toggle';
|
|
15
|
+
import type { RowColAction } from './table-row-col-controls';
|
|
16
|
+
|
|
17
|
+
import { PopoverEvent } from '@/types/utils/popover/popover-event';
|
|
18
|
+
import type { PopoverItemParams } from '@/types/utils/popover/popover-item';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* State for the currently active grip popover.
|
|
22
|
+
*/
|
|
23
|
+
export interface PopoverState {
|
|
24
|
+
popover: PopoverDesktop | null;
|
|
25
|
+
grip: HTMLElement | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Options for building popover menu items.
|
|
30
|
+
*/
|
|
31
|
+
export interface PopoverMenuOptions {
|
|
32
|
+
getColumnCount: () => number;
|
|
33
|
+
getRowCount: () => number;
|
|
34
|
+
isHeadingRow: () => boolean;
|
|
35
|
+
isHeadingColumn: () => boolean;
|
|
36
|
+
onAction: (action: RowColAction) => void;
|
|
37
|
+
i18n: I18n;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Callbacks the popover needs from the controls class.
|
|
42
|
+
*/
|
|
43
|
+
export interface OpenPopoverCallbacks {
|
|
44
|
+
clearHideTimeout: () => void;
|
|
45
|
+
hideAllGripsExcept: (grip: HTMLElement) => void;
|
|
46
|
+
applyActiveClasses: (grip: HTMLElement) => void;
|
|
47
|
+
applyVisibleClasses: (grip: HTMLElement) => void;
|
|
48
|
+
scheduleHideAll: () => void;
|
|
49
|
+
destroyPopover: () => void;
|
|
50
|
+
onGripPopoverClose?: () => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Build the popover menu items for a column grip.
|
|
55
|
+
*/
|
|
56
|
+
export const buildColumnMenuItems = (colIndex: number, options: PopoverMenuOptions): PopoverItemParams[] => {
|
|
57
|
+
const headingItems: PopoverItemParams[] = colIndex === 0
|
|
58
|
+
? [
|
|
59
|
+
{
|
|
60
|
+
type: PopoverItemType.Html,
|
|
61
|
+
element: createHeadingToggle({
|
|
62
|
+
icon: IconHeaderColumn,
|
|
63
|
+
label: options.i18n.t('tools.table.headerColumn'),
|
|
64
|
+
isActive: options.isHeadingColumn(),
|
|
65
|
+
onToggle: () => {
|
|
66
|
+
options.onAction({ type: 'toggle-heading-column' });
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
70
|
+
{ type: PopoverItemType.Separator },
|
|
71
|
+
]
|
|
72
|
+
: [];
|
|
73
|
+
|
|
74
|
+
const baseItems: PopoverItemParams[] = [
|
|
75
|
+
{
|
|
76
|
+
icon: IconInsertLeft,
|
|
77
|
+
title: options.i18n.t('tools.table.insertColumnLeft'),
|
|
78
|
+
closeOnActivate: true,
|
|
79
|
+
onActivate: (): void => {
|
|
80
|
+
options.onAction({ type: 'insert-col-left', index: colIndex });
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
icon: IconInsertRight,
|
|
85
|
+
title: options.i18n.t('tools.table.insertColumnRight'),
|
|
86
|
+
closeOnActivate: true,
|
|
87
|
+
onActivate: (): void => {
|
|
88
|
+
options.onAction({ type: 'insert-col-right', index: colIndex });
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const canDelete = options.getColumnCount() > 1;
|
|
94
|
+
const deleteItems: PopoverItemParams[] = [
|
|
95
|
+
{ type: PopoverItemType.Separator },
|
|
96
|
+
{
|
|
97
|
+
icon: IconTrash,
|
|
98
|
+
title: options.i18n.t('tools.table.deleteColumn'),
|
|
99
|
+
isDestructive: true,
|
|
100
|
+
isDisabled: !canDelete,
|
|
101
|
+
closeOnActivate: true,
|
|
102
|
+
onActivate: (): void => {
|
|
103
|
+
options.onAction({ type: 'delete-col', index: colIndex });
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
return [...headingItems, ...baseItems, ...deleteItems];
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Build the popover menu items for a row grip.
|
|
113
|
+
*/
|
|
114
|
+
export const buildRowMenuItems = (rowIndex: number, options: PopoverMenuOptions): PopoverItemParams[] => {
|
|
115
|
+
const headingItems: PopoverItemParams[] = rowIndex === 0
|
|
116
|
+
? [
|
|
117
|
+
{
|
|
118
|
+
type: PopoverItemType.Html,
|
|
119
|
+
element: createHeadingToggle({
|
|
120
|
+
icon: IconHeaderRow,
|
|
121
|
+
label: options.i18n.t('tools.table.headerRow'),
|
|
122
|
+
isActive: options.isHeadingRow(),
|
|
123
|
+
onToggle: () => {
|
|
124
|
+
options.onAction({ type: 'toggle-heading' });
|
|
125
|
+
},
|
|
126
|
+
}),
|
|
127
|
+
},
|
|
128
|
+
{ type: PopoverItemType.Separator },
|
|
129
|
+
]
|
|
130
|
+
: [];
|
|
131
|
+
|
|
132
|
+
const baseItems: PopoverItemParams[] = [
|
|
133
|
+
{
|
|
134
|
+
icon: IconInsertAbove,
|
|
135
|
+
title: options.i18n.t('tools.table.insertRowAbove'),
|
|
136
|
+
closeOnActivate: true,
|
|
137
|
+
onActivate: (): void => {
|
|
138
|
+
options.onAction({ type: 'insert-row-above', index: rowIndex });
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
icon: IconInsertBelow,
|
|
143
|
+
title: options.i18n.t('tools.table.insertRowBelow'),
|
|
144
|
+
closeOnActivate: true,
|
|
145
|
+
onActivate: (): void => {
|
|
146
|
+
options.onAction({ type: 'insert-row-below', index: rowIndex });
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
const canDelete = options.getRowCount() > 1;
|
|
152
|
+
const deleteItems: PopoverItemParams[] = [
|
|
153
|
+
{ type: PopoverItemType.Separator },
|
|
154
|
+
{
|
|
155
|
+
icon: IconTrash,
|
|
156
|
+
title: options.i18n.t('tools.table.deleteRow'),
|
|
157
|
+
isDestructive: true,
|
|
158
|
+
isDisabled: !canDelete,
|
|
159
|
+
closeOnActivate: true,
|
|
160
|
+
onActivate: (): void => {
|
|
161
|
+
options.onAction({ type: 'delete-row', index: rowIndex });
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
return [...headingItems, ...baseItems, ...deleteItems];
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Create a popover anchored to the given grip and prepare it for display.
|
|
171
|
+
* Returns the new state. The caller must call `popover.show()` after
|
|
172
|
+
* storing the state so that any callbacks fired during show see the
|
|
173
|
+
* updated popover reference.
|
|
174
|
+
*/
|
|
175
|
+
export const createGripPopover = (
|
|
176
|
+
type: 'row' | 'col',
|
|
177
|
+
index: number,
|
|
178
|
+
grips: { col: HTMLElement[]; row: HTMLElement[] },
|
|
179
|
+
menuOptions: PopoverMenuOptions,
|
|
180
|
+
callbacks: OpenPopoverCallbacks
|
|
181
|
+
): PopoverState => {
|
|
182
|
+
callbacks.destroyPopover();
|
|
183
|
+
callbacks.clearHideTimeout();
|
|
184
|
+
|
|
185
|
+
const grip = type === 'col'
|
|
186
|
+
? grips.col[index]
|
|
187
|
+
: grips.row[index];
|
|
188
|
+
|
|
189
|
+
if (!grip) {
|
|
190
|
+
return { popover: null, grip: null };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const items = type === 'col'
|
|
194
|
+
? buildColumnMenuItems(index, menuOptions)
|
|
195
|
+
: buildRowMenuItems(index, menuOptions);
|
|
196
|
+
|
|
197
|
+
const popover = new PopoverDesktop({
|
|
198
|
+
items,
|
|
199
|
+
trigger: grip,
|
|
200
|
+
flippable: true,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
popover.on(PopoverEvent.Closed, () => {
|
|
204
|
+
// The caller's destroyPopover handles nulling the shared state and
|
|
205
|
+
// calling popover.destroy(). The re-entrant Closed event is caught
|
|
206
|
+
// by the guard inside destroyPopover (checks if popover is already null).
|
|
207
|
+
callbacks.destroyPopover();
|
|
208
|
+
callbacks.applyVisibleClasses(grip);
|
|
209
|
+
callbacks.scheduleHideAll();
|
|
210
|
+
callbacks.onGripPopoverClose?.();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Hide all other grips and make the active one blue
|
|
214
|
+
callbacks.hideAllGripsExcept(grip);
|
|
215
|
+
callbacks.applyActiveClasses(grip);
|
|
216
|
+
|
|
217
|
+
// Expand the grip to hover size so it remains visible while popover is open
|
|
218
|
+
if (type === 'col') {
|
|
219
|
+
grip.style.height = `${GRIP_HOVER_SIZE}px`;
|
|
220
|
+
} else {
|
|
221
|
+
grip.style.width = `${GRIP_HOVER_SIZE}px`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return { popover, grip };
|
|
225
|
+
};
|
package/src/tools/table/types.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface TableData extends BlockToolData {
|
|
|
37
37
|
content: LegacyCellContent[][];
|
|
38
38
|
/** Column widths in pixels (e.g., [200, 300, 250]). Omit for equal widths. */
|
|
39
39
|
colWidths?: number[];
|
|
40
|
+
/** Original per-column width in pixels, set once at creation. New columns = initialColWidth / 2. */
|
|
41
|
+
initialColWidth?: number;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/**
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { BlocksAPI } from '../components/modules/api/blocks';
|
|
3
3
|
import { CaretAPI } from '../components/modules/api/caret';
|
|
4
4
|
import { EventsAPI } from '../components/modules/api/events';
|
|
5
|
+
import { HistoryAPI } from '../components/modules/api/history';
|
|
5
6
|
import { I18nAPI } from '../components/modules/api/i18n';
|
|
6
7
|
import { API } from '../components/modules/api/index';
|
|
7
8
|
import { InlineToolbarAPI } from '../components/modules/api/inlineToolbar';
|
|
@@ -45,6 +46,7 @@ export interface BlokModules {
|
|
|
45
46
|
CaretAPI: CaretAPI,
|
|
46
47
|
ToolsAPI: ToolsAPI,
|
|
47
48
|
EventsAPI: EventsAPI,
|
|
49
|
+
HistoryAPI: HistoryAPI,
|
|
48
50
|
I18nAPI: I18nAPI,
|
|
49
51
|
API: API,
|
|
50
52
|
InlineToolbarAPI: InlineToolbarAPI,
|