@jackuait/blok 0.6.0-beta.13 → 0.6.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blok.mjs +2 -2
- package/dist/chunks/{blok-DzeTRJ_i.mjs → blok-Cl30YOLl.mjs} +1398 -1132
- package/dist/chunks/{i18next-loader-CgW4H90H.mjs → i18next-loader-DbTDlMux.mjs} +1 -1
- package/dist/chunks/{index-BWKk7PIS.mjs → index-DJmaYswj.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-DrSwadw_.mjs → inline-tool-convert-MjSaP8r7.mjs} +161 -145
- package/dist/{messages-B1Aww8q7.mjs → chunks/messages-1mYyrppy.mjs} +1 -0
- package/dist/chunks/{messages-DnIhyAJk.mjs → messages-4gHfbcDp.mjs} +1 -0
- package/dist/{messages-CQwpzUFp.mjs → chunks/messages-6xYv-U8A.mjs} +1 -0
- package/dist/chunks/{messages-CMkNSDTo.mjs → messages-7jqF79FO.mjs} +1 -0
- package/dist/chunks/{messages-BSbjsyHY.mjs → messages-B3EUuA7o.mjs} +1 -0
- package/dist/{messages-LPVfA-8K.mjs → chunks/messages-B6srtRn7.mjs} +1 -0
- package/dist/chunks/{messages-DJDG55Vq.mjs → messages-B85OIs0E.mjs} +1 -0
- package/dist/{messages-_ErNTNhk.mjs → chunks/messages-BCYBBG_u.mjs} +1 -0
- package/dist/{messages-CZygwLwM.mjs → chunks/messages-BDLNPiaW.mjs} +1 -0
- package/dist/{messages-C2htQ_3F.mjs → chunks/messages-BKpNd1Zb.mjs} +1 -0
- package/dist/chunks/{messages-CnwibSvh.mjs → messages-BLFUid_o.mjs} +1 -0
- package/dist/{messages-CVw84KdI.mjs → chunks/messages-BNPTVKnc.mjs} +1 -0
- package/dist/{messages-BMv4xwIr.mjs → chunks/messages-BQPXSkri.mjs} +1 -0
- package/dist/{messages-Dz9L52ol.mjs → chunks/messages-BQu6VNDq.mjs} +1 -0
- package/dist/{messages-DprmQg6V.mjs → chunks/messages-BRodFKUo.mjs} +1 -0
- package/dist/{messages-CznZadDf.mjs → chunks/messages-BWIikA8H.mjs} +1 -0
- package/dist/{messages-CqWJcCbY.mjs → chunks/messages-BXQvMilx.mjs} +1 -0
- package/dist/chunks/{messages-Z9nEU2xK.mjs → messages-BZ92luiw.mjs} +1 -0
- package/dist/chunks/{messages-BC86qLvI.mjs → messages-Bg0Phlcj.mjs} +1 -0
- package/dist/chunks/{messages-DnXLrlHh.mjs → messages-Bh6RBIu5.mjs} +1 -0
- package/dist/chunks/{messages-DhLKYm2j.mjs → messages-BnFHdIpg.mjs} +1 -0
- package/dist/{messages-BU2nlrLK.mjs → chunks/messages-Bq82EVsw.mjs} +1 -0
- package/dist/chunks/{messages-Diu6jAaR.mjs → messages-BxbcTiHh.mjs} +1 -0
- package/dist/{messages-BoJc_p1r.mjs → chunks/messages-ByO6bSV2.mjs} +1 -0
- package/dist/chunks/{messages-BrPFGbM-.mjs → messages-ByUNPiQ4.mjs} +1 -0
- package/dist/chunks/{messages-BB5z9Uba.mjs → messages-Byw0EHyf.mjs} +1 -0
- package/dist/chunks/{messages-D1Hv8XGo.mjs → messages-C-aP90zq.mjs} +1 -0
- package/dist/chunks/{messages-DBRw-7Zc.mjs → messages-C2f44jci.mjs} +1 -0
- package/dist/chunks/{messages-CJdUsQ-c.mjs → messages-CKYoAmm9.mjs} +1 -0
- package/dist/chunks/{messages-CvGLfqmV.mjs → messages-CSQJrJ_N.mjs} +1 -0
- package/dist/chunks/{messages-1fC8IMyX.mjs → messages-CX_o4Cgc.mjs} +1 -0
- package/dist/chunks/{messages-BdeLo0N9.mjs → messages-C_tfXllT.mjs} +1 -0
- package/dist/chunks/{messages-DBn76jVV.mjs → messages-Cj6TZ_By.mjs} +1 -0
- package/dist/{messages-CLhcMlTc.mjs → chunks/messages-CjdYkfzj.mjs} +1 -0
- package/dist/{messages-7W4d0DwD.mjs → chunks/messages-CmvWFWR6.mjs} +1 -0
- package/dist/{messages-CzTufCHu.mjs → chunks/messages-CnV-kxh6.mjs} +1 -0
- package/dist/chunks/{messages-BMXCuEKO.mjs → messages-CpuDfpdi.mjs} +1 -0
- package/dist/chunks/{messages-DT4dP5uK.mjs → messages-Cspe1oXk.mjs} +1 -0
- package/dist/{messages-D-ZtY5v0.mjs → chunks/messages-D2_d-Jt4.mjs} +1 -0
- package/dist/{messages-BELRf6DU.mjs → chunks/messages-DADSbW8l.mjs} +1 -0
- package/dist/chunks/{messages-O5tQus_0.mjs → messages-DHSeTQ4S.mjs} +1 -0
- package/dist/{messages-BFG6Wlgy.mjs → chunks/messages-DKeO2RsW.mjs} +1 -0
- package/dist/chunks/{messages-9SihnaXQ.mjs → messages-DLdlX_dY.mjs} +1 -0
- package/dist/chunks/{messages-BL0tXcDf.mjs → messages-DVxlJ4DU.mjs} +1 -0
- package/dist/chunks/{messages-CY8_RyFE.mjs → messages-DWSxENRk.mjs} +1 -0
- package/dist/{messages-Q7AO_FLv.mjs → chunks/messages-D_bVNZ12.mjs} +1 -0
- package/dist/chunks/{messages-BYyy6Wqf.mjs → messages-DdzjVwmG.mjs} +1 -0
- package/dist/chunks/{messages-DLfR5bMd.mjs → messages-DhyBKTi0.mjs} +1 -0
- package/dist/chunks/{messages-DvFLX36Q.mjs → messages-DlC9jDXa.mjs} +1 -0
- package/dist/chunks/{messages-D5C3J9qr.mjs → messages-DmBGk8ed.mjs} +1 -0
- package/dist/chunks/{messages-R3hUSvr3.mjs → messages-Dm_VqpU6.mjs} +1 -0
- package/dist/chunks/{messages-w7v1GNaE.mjs → messages-Dn9hI_ER.mjs} +1 -0
- package/dist/{messages-uKX8WBaD.mjs → chunks/messages-Dssp4AXT.mjs} +1 -0
- package/dist/chunks/{messages-Xq8UmkVs.mjs → messages-DzCc0JgS.mjs} +1 -0
- package/dist/chunks/{messages-JELdtT6E.mjs → messages-N6THNxo0.mjs} +1 -0
- package/dist/chunks/{messages-DqM1LFg5.mjs → messages-OctOxF2l.mjs} +1 -0
- package/dist/chunks/{messages-_ncGrKHh.mjs → messages-QT3JA95K.mjs} +1 -0
- package/dist/{messages-C9eaarcK.mjs → chunks/messages-QqWK83BF.mjs} +1 -0
- package/dist/chunks/{messages-BogRq8lt.mjs → messages-RsGaDzbb.mjs} +1 -0
- package/dist/chunks/{messages-Dzwxv9v1.mjs → messages-c7YlI6Wm.mjs} +1 -0
- package/dist/{messages-D5iv1Kox.mjs → chunks/messages-lZ8aF-4r.mjs} +1 -0
- package/dist/chunks/{messages-7QoX8DkW.mjs → messages-uGDrchjb.mjs} +1 -0
- package/dist/chunks/{messages-CKI54h6O.mjs → messages-xc2yNvog.mjs} +1 -0
- package/dist/{messages-Bmu_S7GM.mjs → chunks/messages-y5Q-ymIx.mjs} +1 -0
- package/dist/{messages-BWF-zUpY.mjs → chunks/messages-yJnyedAd.mjs} +1 -0
- package/dist/{messages-kep5wtm4.mjs → chunks/messages-yQ_4upHh.mjs} +1 -0
- package/dist/chunks/{messages-C99mq906.mjs → messages-ysbWD56Q.mjs} +1 -0
- package/dist/full.mjs +2 -2
- package/dist/locales.mjs +68 -67
- package/dist/{chunks/messages-B1Aww8q7.mjs → messages-1mYyrppy.mjs} +1 -0
- package/dist/{messages-DnIhyAJk.mjs → messages-4gHfbcDp.mjs} +1 -0
- package/dist/{chunks/messages-CQwpzUFp.mjs → messages-6xYv-U8A.mjs} +1 -0
- package/dist/{messages-CMkNSDTo.mjs → messages-7jqF79FO.mjs} +1 -0
- package/dist/{messages-BSbjsyHY.mjs → messages-B3EUuA7o.mjs} +1 -0
- package/dist/{chunks/messages-LPVfA-8K.mjs → messages-B6srtRn7.mjs} +1 -0
- package/dist/{messages-DJDG55Vq.mjs → messages-B85OIs0E.mjs} +1 -0
- package/dist/{chunks/messages-_ErNTNhk.mjs → messages-BCYBBG_u.mjs} +1 -0
- package/dist/{chunks/messages-CZygwLwM.mjs → messages-BDLNPiaW.mjs} +1 -0
- package/dist/{chunks/messages-C2htQ_3F.mjs → messages-BKpNd1Zb.mjs} +1 -0
- package/dist/{messages-CnwibSvh.mjs → messages-BLFUid_o.mjs} +1 -0
- package/dist/{chunks/messages-CVw84KdI.mjs → messages-BNPTVKnc.mjs} +1 -0
- package/dist/{chunks/messages-BMv4xwIr.mjs → messages-BQPXSkri.mjs} +1 -0
- package/dist/{chunks/messages-Dz9L52ol.mjs → messages-BQu6VNDq.mjs} +1 -0
- package/dist/{chunks/messages-DprmQg6V.mjs → messages-BRodFKUo.mjs} +1 -0
- package/dist/{chunks/messages-CznZadDf.mjs → messages-BWIikA8H.mjs} +1 -0
- package/dist/{chunks/messages-CqWJcCbY.mjs → messages-BXQvMilx.mjs} +1 -0
- package/dist/{messages-Z9nEU2xK.mjs → messages-BZ92luiw.mjs} +1 -0
- package/dist/{messages-BC86qLvI.mjs → messages-Bg0Phlcj.mjs} +1 -0
- package/dist/{messages-DnXLrlHh.mjs → messages-Bh6RBIu5.mjs} +1 -0
- package/dist/{messages-DhLKYm2j.mjs → messages-BnFHdIpg.mjs} +1 -0
- package/dist/{chunks/messages-BU2nlrLK.mjs → messages-Bq82EVsw.mjs} +1 -0
- package/dist/{messages-Diu6jAaR.mjs → messages-BxbcTiHh.mjs} +1 -0
- package/dist/{chunks/messages-BoJc_p1r.mjs → messages-ByO6bSV2.mjs} +1 -0
- package/dist/{messages-BrPFGbM-.mjs → messages-ByUNPiQ4.mjs} +1 -0
- package/dist/{messages-BB5z9Uba.mjs → messages-Byw0EHyf.mjs} +1 -0
- package/dist/{messages-D1Hv8XGo.mjs → messages-C-aP90zq.mjs} +1 -0
- package/dist/{messages-DBRw-7Zc.mjs → messages-C2f44jci.mjs} +1 -0
- package/dist/{messages-CJdUsQ-c.mjs → messages-CKYoAmm9.mjs} +1 -0
- package/dist/{messages-CvGLfqmV.mjs → messages-CSQJrJ_N.mjs} +1 -0
- package/dist/{messages-1fC8IMyX.mjs → messages-CX_o4Cgc.mjs} +1 -0
- package/dist/{messages-BdeLo0N9.mjs → messages-C_tfXllT.mjs} +1 -0
- package/dist/{messages-DBn76jVV.mjs → messages-Cj6TZ_By.mjs} +1 -0
- package/dist/{chunks/messages-CLhcMlTc.mjs → messages-CjdYkfzj.mjs} +1 -0
- package/dist/{chunks/messages-7W4d0DwD.mjs → messages-CmvWFWR6.mjs} +1 -0
- package/dist/{chunks/messages-CzTufCHu.mjs → messages-CnV-kxh6.mjs} +1 -0
- package/dist/{messages-BMXCuEKO.mjs → messages-CpuDfpdi.mjs} +1 -0
- package/dist/{messages-DT4dP5uK.mjs → messages-Cspe1oXk.mjs} +1 -0
- package/dist/{chunks/messages-D-ZtY5v0.mjs → messages-D2_d-Jt4.mjs} +1 -0
- package/dist/{chunks/messages-BELRf6DU.mjs → messages-DADSbW8l.mjs} +1 -0
- package/dist/{messages-O5tQus_0.mjs → messages-DHSeTQ4S.mjs} +1 -0
- package/dist/{chunks/messages-BFG6Wlgy.mjs → messages-DKeO2RsW.mjs} +1 -0
- package/dist/{messages-9SihnaXQ.mjs → messages-DLdlX_dY.mjs} +1 -0
- package/dist/{messages-BL0tXcDf.mjs → messages-DVxlJ4DU.mjs} +1 -0
- package/dist/{messages-CY8_RyFE.mjs → messages-DWSxENRk.mjs} +1 -0
- package/dist/{chunks/messages-Q7AO_FLv.mjs → messages-D_bVNZ12.mjs} +1 -0
- package/dist/{messages-BYyy6Wqf.mjs → messages-DdzjVwmG.mjs} +1 -0
- package/dist/{messages-DLfR5bMd.mjs → messages-DhyBKTi0.mjs} +1 -0
- package/dist/{messages-DvFLX36Q.mjs → messages-DlC9jDXa.mjs} +1 -0
- package/dist/{messages-D5C3J9qr.mjs → messages-DmBGk8ed.mjs} +1 -0
- package/dist/{messages-R3hUSvr3.mjs → messages-Dm_VqpU6.mjs} +1 -0
- package/dist/{messages-w7v1GNaE.mjs → messages-Dn9hI_ER.mjs} +1 -0
- package/dist/{chunks/messages-uKX8WBaD.mjs → messages-Dssp4AXT.mjs} +1 -0
- package/dist/{messages-Xq8UmkVs.mjs → messages-DzCc0JgS.mjs} +1 -0
- package/dist/{messages-JELdtT6E.mjs → messages-N6THNxo0.mjs} +1 -0
- package/dist/{messages-DqM1LFg5.mjs → messages-OctOxF2l.mjs} +1 -0
- package/dist/{messages-_ncGrKHh.mjs → messages-QT3JA95K.mjs} +1 -0
- package/dist/{chunks/messages-C9eaarcK.mjs → messages-QqWK83BF.mjs} +1 -0
- package/dist/{messages-BogRq8lt.mjs → messages-RsGaDzbb.mjs} +1 -0
- package/dist/{messages-Dzwxv9v1.mjs → messages-c7YlI6Wm.mjs} +1 -0
- package/dist/{chunks/messages-D5iv1Kox.mjs → messages-lZ8aF-4r.mjs} +1 -0
- package/dist/{messages-7QoX8DkW.mjs → messages-uGDrchjb.mjs} +1 -0
- package/dist/{messages-CKI54h6O.mjs → messages-xc2yNvog.mjs} +1 -0
- package/dist/{chunks/messages-Bmu_S7GM.mjs → messages-y5Q-ymIx.mjs} +1 -0
- package/dist/{chunks/messages-BWF-zUpY.mjs → messages-yJnyedAd.mjs} +1 -0
- package/dist/{chunks/messages-kep5wtm4.mjs → messages-yQ_4upHh.mjs} +1 -0
- package/dist/{messages-C99mq906.mjs → messages-ysbWD56Q.mjs} +1 -0
- package/dist/tools.mjs +887 -701
- package/package.json +2 -1
- package/src/components/block/style-manager.ts +5 -1
- package/src/components/blocks.ts +109 -9
- package/src/components/i18n/locales/am/messages.json +1 -0
- package/src/components/i18n/locales/ar/messages.json +1 -0
- package/src/components/i18n/locales/az/messages.json +1 -0
- package/src/components/i18n/locales/bg/messages.json +1 -0
- package/src/components/i18n/locales/bn/messages.json +1 -0
- package/src/components/i18n/locales/bs/messages.json +1 -0
- package/src/components/i18n/locales/cs/messages.json +1 -0
- package/src/components/i18n/locales/da/messages.json +1 -0
- package/src/components/i18n/locales/de/messages.json +1 -0
- package/src/components/i18n/locales/dv/messages.json +1 -0
- package/src/components/i18n/locales/el/messages.json +1 -0
- package/src/components/i18n/locales/en/messages.json +1 -0
- package/src/components/i18n/locales/es/messages.json +1 -0
- package/src/components/i18n/locales/et/messages.json +1 -0
- package/src/components/i18n/locales/fa/messages.json +1 -0
- package/src/components/i18n/locales/fi/messages.json +1 -0
- package/src/components/i18n/locales/fil/messages.json +1 -0
- package/src/components/i18n/locales/fr/messages.json +1 -0
- package/src/components/i18n/locales/gu/messages.json +1 -0
- package/src/components/i18n/locales/he/messages.json +1 -0
- package/src/components/i18n/locales/hi/messages.json +1 -0
- package/src/components/i18n/locales/hr/messages.json +1 -0
- package/src/components/i18n/locales/hu/messages.json +1 -0
- package/src/components/i18n/locales/hy/messages.json +1 -0
- package/src/components/i18n/locales/id/messages.json +1 -0
- package/src/components/i18n/locales/it/messages.json +1 -0
- package/src/components/i18n/locales/ja/messages.json +1 -0
- package/src/components/i18n/locales/ka/messages.json +1 -0
- package/src/components/i18n/locales/km/messages.json +1 -0
- package/src/components/i18n/locales/kn/messages.json +1 -0
- package/src/components/i18n/locales/ko/messages.json +1 -0
- package/src/components/i18n/locales/ku/messages.json +1 -0
- package/src/components/i18n/locales/lo/messages.json +1 -0
- package/src/components/i18n/locales/lt/messages.json +1 -0
- package/src/components/i18n/locales/lv/messages.json +1 -0
- package/src/components/i18n/locales/mk/messages.json +1 -0
- package/src/components/i18n/locales/ml/messages.json +1 -0
- package/src/components/i18n/locales/mn/messages.json +1 -0
- package/src/components/i18n/locales/mr/messages.json +1 -0
- package/src/components/i18n/locales/ms/messages.json +1 -0
- package/src/components/i18n/locales/my/messages.json +1 -0
- package/src/components/i18n/locales/ne/messages.json +1 -0
- package/src/components/i18n/locales/nl/messages.json +1 -0
- package/src/components/i18n/locales/no/messages.json +1 -0
- package/src/components/i18n/locales/pa/messages.json +1 -0
- package/src/components/i18n/locales/pl/messages.json +1 -0
- package/src/components/i18n/locales/ps/messages.json +1 -0
- package/src/components/i18n/locales/pt/messages.json +1 -0
- package/src/components/i18n/locales/ro/messages.json +1 -0
- package/src/components/i18n/locales/ru/messages.json +1 -0
- package/src/components/i18n/locales/sd/messages.json +1 -0
- package/src/components/i18n/locales/si/messages.json +1 -0
- package/src/components/i18n/locales/sk/messages.json +1 -0
- package/src/components/i18n/locales/sl/messages.json +1 -0
- package/src/components/i18n/locales/sq/messages.json +1 -0
- package/src/components/i18n/locales/sr/messages.json +1 -0
- package/src/components/i18n/locales/sv/messages.json +1 -0
- package/src/components/i18n/locales/sw/messages.json +1 -0
- package/src/components/i18n/locales/ta/messages.json +1 -0
- package/src/components/i18n/locales/te/messages.json +1 -0
- package/src/components/i18n/locales/th/messages.json +1 -0
- package/src/components/i18n/locales/tr/messages.json +1 -0
- package/src/components/i18n/locales/ug/messages.json +1 -0
- package/src/components/i18n/locales/uk/messages.json +1 -0
- package/src/components/i18n/locales/ur/messages.json +1 -0
- package/src/components/i18n/locales/vi/messages.json +1 -0
- package/src/components/i18n/locales/yi/messages.json +1 -0
- package/src/components/i18n/locales/zh/messages.json +1 -0
- package/src/components/icons/index.ts +8 -0
- package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +51 -10
- package/src/components/modules/blockEvents/index.ts +2 -5
- package/src/components/modules/blockManager/blockManager.ts +10 -0
- package/src/components/modules/blockManager/operations.ts +11 -0
- package/src/components/modules/blockManager/repository.ts +22 -0
- package/src/components/modules/blockManager/yjs-sync.ts +148 -31
- package/src/components/modules/crossBlockSelection.ts +11 -3
- package/src/components/modules/drag/preview/DragPreview.ts +8 -0
- package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
- package/src/components/modules/paste/handlers/base.ts +3 -4
- package/src/components/modules/paste/index.ts +1 -1
- package/src/components/modules/rectangleSelection.ts +5 -2
- package/src/components/modules/toolbar/blockSettings.ts +52 -44
- package/src/components/modules/toolbar/index.ts +27 -7
- package/src/components/modules/toolbar/inline/index.ts +1 -1
- package/src/components/modules/uiControllers/controllers/blockHover.ts +16 -2
- package/src/components/modules/uiControllers/handlers/touch.ts +83 -10
- package/src/components/modules/yjs/block-observer.ts +9 -3
- package/src/components/modules/yjs/document-store.ts +4 -2
- package/src/components/modules/yjs/types.ts +8 -6
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -4
- package/src/components/utils/popover/popover-desktop.ts +12 -0
- package/src/stories/Popover.stories.ts +0 -2
- package/src/styles/main.css +9 -1
- package/src/tools/list/caret-manager.ts +28 -10
- package/src/tools/table/index.ts +180 -37
- package/src/tools/table/table-add-controls.ts +51 -14
- package/src/tools/table/table-cell-blocks.ts +41 -2
- package/src/tools/table/table-cell-selection.ts +27 -1
- package/src/tools/table/table-operations.ts +12 -15
- package/src/tools/table/table-row-col-controls.ts +69 -6
- package/src/tools/table/table-scroll-haze.ts +152 -0
|
@@ -157,13 +157,27 @@ export class BlockHoverController extends Controller {
|
|
|
157
157
|
return null;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Filter out blocks whose holders are inside a table cell container.
|
|
162
|
+
* Cell blocks should not participate in nearest-block detection —
|
|
163
|
+
* the parent table block should be found instead.
|
|
164
|
+
* This matches the direct-hit path which also resolves cell blocks to their parent table block.
|
|
165
|
+
*/
|
|
166
|
+
const topLevelBlocks = blocks.filter(block =>
|
|
167
|
+
block.holder.closest('[data-blok-table-cell-blocks]') === null
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
if (topLevelBlocks.length === 0) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const result = topLevelBlocks.reduce<{ block: Block; distance: number }>((nearest, block) => {
|
|
161
175
|
const rect = block.holder.getBoundingClientRect();
|
|
162
176
|
const centerY = (rect.top + rect.bottom) / 2;
|
|
163
177
|
const distance = Math.abs(clientY - centerY);
|
|
164
178
|
|
|
165
179
|
return distance < nearest.distance ? { block, distance } : nearest;
|
|
166
|
-
}, { block:
|
|
180
|
+
}, { block: topLevelBlocks[0], distance: Infinity });
|
|
167
181
|
|
|
168
182
|
return result.block;
|
|
169
183
|
}
|
|
@@ -35,15 +35,34 @@ export const createRedactorTouchHandler = (
|
|
|
35
35
|
/**
|
|
36
36
|
* Select clicked Block as Current
|
|
37
37
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
const block = deps.Blok.BlockManager.setCurrentBlockByChildNode(clickedNode);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* If clicked outside first-level Blocks and it is not RectSelection, set Caret to the last empty Block
|
|
42
|
+
*/
|
|
43
|
+
if (!block && !deps.Blok.RectangleSelection.isRectActivated()) {
|
|
44
|
+
deps.Blok.Caret.setToTheLastBlock();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* If the click landed below the last block's content area (in the holder padding zone),
|
|
49
|
+
* create/focus a new paragraph instead of keeping the block selected.
|
|
50
|
+
*/
|
|
51
|
+
const isBelowLastBlock = block !== undefined
|
|
52
|
+
&& block === deps.Blok.BlockManager.lastBlock
|
|
53
|
+
&& isClickBelowLastBlockContent(block.holder, event);
|
|
54
|
+
|
|
55
|
+
if (isBelowLastBlock && !deps.Blok.ReadOnly.isEnabled) {
|
|
56
|
+
deps.Blok.Caret.setToTheLastBlock();
|
|
57
|
+
deps.Blok.Toolbar.moveAndOpen(deps.Blok.BlockManager.lastBlock);
|
|
58
|
+
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isBelowLastBlock) {
|
|
63
|
+
deps.Blok.Caret.setToTheLastBlock();
|
|
64
|
+
|
|
65
|
+
return;
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
/**
|
|
@@ -51,7 +70,19 @@ export const createRedactorTouchHandler = (
|
|
|
51
70
|
* (used for showing Block Settings toggler after opening and closing Inline Toolbar)
|
|
52
71
|
*/
|
|
53
72
|
if (!deps.Blok.ReadOnly.isEnabled && !deps.Blok.Toolbar.contains(initialTarget)) {
|
|
54
|
-
|
|
73
|
+
/**
|
|
74
|
+
* When the clicked node is inside a table cell, resolve to the parent table block
|
|
75
|
+
* so moveAndOpen receives the table block (not undefined / the inner cell paragraph).
|
|
76
|
+
* Without this, moveAndOpen falls back to currentBlock (the cell paragraph), detects
|
|
77
|
+
* it's inside a table cell, and hides the plus button and settings toggler.
|
|
78
|
+
*/
|
|
79
|
+
const tableCellContainer = clickedNode.closest?.('[data-blok-table-cell-blocks]');
|
|
80
|
+
const tableBlockWrapper = tableCellContainer?.closest('[data-blok-testid="block-wrapper"]');
|
|
81
|
+
const resolvedBlock = tableBlockWrapper
|
|
82
|
+
? deps.Blok.BlockManager.getBlockByChildNode(tableBlockWrapper)
|
|
83
|
+
: undefined;
|
|
84
|
+
|
|
85
|
+
deps.Blok.Toolbar.moveAndOpen(resolvedBlock, clickedNode);
|
|
55
86
|
}
|
|
56
87
|
};
|
|
57
88
|
}
|
|
@@ -93,3 +124,45 @@ export const getClickedNode = (
|
|
|
93
124
|
|
|
94
125
|
return initialTarget;
|
|
95
126
|
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Extracts the clientY coordinate from a mouse or touch event
|
|
130
|
+
*
|
|
131
|
+
* @param event - The event to extract clientY from
|
|
132
|
+
* @returns The clientY value, or null if not available
|
|
133
|
+
*/
|
|
134
|
+
const getClientY = (event: Event): number | null => {
|
|
135
|
+
if (event instanceof MouseEvent) {
|
|
136
|
+
return event.clientY;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (event instanceof TouchEvent && event.touches.length > 0) {
|
|
140
|
+
return event.touches[0].clientY;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks whether a click event landed below a block's content area.
|
|
148
|
+
* Used to detect clicks in the holder padding zone below the last block.
|
|
149
|
+
*
|
|
150
|
+
* @param blockHolder - The block's holder element
|
|
151
|
+
* @param event - The mouse or touch event
|
|
152
|
+
* @returns True if the click was below the block content's bottom edge
|
|
153
|
+
*/
|
|
154
|
+
const isClickBelowLastBlockContent = (
|
|
155
|
+
blockHolder: HTMLElement,
|
|
156
|
+
event: Event
|
|
157
|
+
): boolean => {
|
|
158
|
+
const clientY = getClientY(event);
|
|
159
|
+
|
|
160
|
+
if (clientY === null) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const contentEl = blockHolder.querySelector('[data-blok-element-content]');
|
|
165
|
+
const contentRect = contentEl?.getBoundingClientRect();
|
|
166
|
+
|
|
167
|
+
return contentRect !== undefined && clientY > contentRect.bottom;
|
|
168
|
+
};
|
|
@@ -169,9 +169,15 @@ export class BlockObserver {
|
|
|
169
169
|
this.emitChange({ type: 'move', blockId, origin });
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// Emit pure adds
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
// Emit pure adds — batch when there are multiple so that parent and
|
|
173
|
+
// child blocks can be registered in BlockManager before any lifecycle
|
|
174
|
+
// hooks (like Table.rendered → initializeCells) fire.
|
|
175
|
+
if (pureAdds.length === 1) {
|
|
176
|
+
this.emitChange({ type: 'add', blockId: pureAdds[0], origin });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (pureAdds.length > 1) {
|
|
180
|
+
this.emitChange({ type: 'batch-add', blockIds: pureAdds, origin });
|
|
175
181
|
}
|
|
176
182
|
|
|
177
183
|
// Emit pure removes
|
|
@@ -2,6 +2,7 @@ import * as Y from 'yjs';
|
|
|
2
2
|
|
|
3
3
|
import type { YBlockSerializer, YjsOutputBlockData } from './serializer';
|
|
4
4
|
import type { TransactionOrigin } from './types';
|
|
5
|
+
import { equals } from '../../utils/object';
|
|
5
6
|
|
|
6
7
|
// Re-export YjsOutputBlockData as DocumentStoreBlockData for consistency
|
|
7
8
|
type DocumentStoreBlockData = YjsOutputBlockData;
|
|
@@ -162,8 +163,9 @@ export class DocumentStore {
|
|
|
162
163
|
|
|
163
164
|
// Skip if value hasn't changed - this prevents creating unnecessary undo entries
|
|
164
165
|
// when block data is synced after mutations that don't actually change data
|
|
165
|
-
// (e.g., marker updates in list items during undo/redo
|
|
166
|
-
|
|
166
|
+
// (e.g., marker updates in list items during undo/redo, or table content
|
|
167
|
+
// arrays that are reference-different but structurally identical)
|
|
168
|
+
if (equals(currentValue, value)) {
|
|
167
169
|
return;
|
|
168
170
|
}
|
|
169
171
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Event emitted when blocks change
|
|
2
|
+
* Event emitted when blocks change.
|
|
3
|
+
*
|
|
4
|
+
* Most events carry a single `blockId`. The `batch-add` type carries
|
|
5
|
+
* multiple IDs so that parent and child blocks can be created together
|
|
6
|
+
* before any lifecycle hooks fire.
|
|
3
7
|
*/
|
|
4
|
-
export
|
|
5
|
-
type: 'add' | 'remove' | 'update' | 'move';
|
|
6
|
-
|
|
7
|
-
origin: TransactionOrigin;
|
|
8
|
-
}
|
|
8
|
+
export type BlockChangeEvent =
|
|
9
|
+
| { type: 'add' | 'remove' | 'update' | 'move'; blockId: string; origin: TransactionOrigin }
|
|
10
|
+
| { type: 'batch-add'; blockIds: string[]; origin: TransactionOrigin };
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Transaction origin types.
|
|
@@ -257,7 +257,9 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
257
257
|
if (title !== undefined) {
|
|
258
258
|
const titleEl = document.createElement('div');
|
|
259
259
|
|
|
260
|
-
titleEl.className =
|
|
260
|
+
titleEl.className = params.secondaryLabel
|
|
261
|
+
? 'flex-grow truncate text-sm font-medium leading-5'
|
|
262
|
+
: 'mr-auto truncate text-sm font-medium leading-5';
|
|
261
263
|
titleEl.setAttribute(DATA_ATTR.popoverItemTitle, '');
|
|
262
264
|
titleEl.setAttribute('data-blok-testid', 'popover-item-title');
|
|
263
265
|
titleEl.textContent = title;
|
|
@@ -270,7 +272,7 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
270
272
|
if (params.secondaryLabel) {
|
|
271
273
|
const secondaryEl = document.createElement('div');
|
|
272
274
|
|
|
273
|
-
secondaryEl.className = 'whitespace-nowrap pr-1.5 text-xs font-light tracking-[0.25px] text-text-secondary opacity-60';
|
|
275
|
+
secondaryEl.className = 'min-w-[3.5rem] text-right whitespace-nowrap pl-3 pr-1.5 text-xs font-light tracking-[0.25px] text-text-secondary opacity-60';
|
|
274
276
|
secondaryEl.setAttribute(DATA_ATTR.popoverItemSecondaryTitle, '');
|
|
275
277
|
secondaryEl.setAttribute('data-blok-testid', 'popover-item-secondary-title');
|
|
276
278
|
secondaryEl.textContent = params.secondaryLabel;
|
|
@@ -324,8 +326,8 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
324
326
|
|
|
325
327
|
return twMerge(
|
|
326
328
|
css.item,
|
|
327
|
-
// Asymmetric padding for
|
|
328
|
-
!isInline && !isNestedInline && 'pl-2 pr-8',
|
|
329
|
+
// Asymmetric padding: pr-8 for visual balance, pr-2 when secondary label occupies right edge
|
|
330
|
+
!isInline && !isNestedInline && (this.params.secondaryLabel ? 'pl-2 pr-2' : 'pl-2 pr-8'),
|
|
329
331
|
isInline && cssInline.item,
|
|
330
332
|
isNestedInline && cssNestedInline.item,
|
|
331
333
|
this.params.isDisabled && css.itemDisabled
|
|
@@ -138,6 +138,18 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
138
138
|
return this.flipper.hasFocus();
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Toggles hidden state of all items matching the given name.
|
|
143
|
+
* Invalidates the cached size so the next access re-measures the popover.
|
|
144
|
+
* @param name - name of the items to toggle
|
|
145
|
+
* @param isHidden - true to hide, false to show
|
|
146
|
+
*/
|
|
147
|
+
public override toggleItemHiddenByName(name: string, isHidden: boolean): void {
|
|
148
|
+
super.toggleItemHiddenByName(name, isHidden);
|
|
149
|
+
|
|
150
|
+
this._size = undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
141
153
|
/**
|
|
142
154
|
* Scroll position inside items container of the popover
|
|
143
155
|
*/
|
|
@@ -351,7 +351,6 @@ export const ConfirmationState: Story = {
|
|
|
351
351
|
deleteButton.setAttribute('data-blok-popover-item-confirmation', 'true');
|
|
352
352
|
deleteButton.setAttribute('data-blok-popover-item-no-hover', 'true');
|
|
353
353
|
deleteButton.setAttribute('data-blok-popover-item-no-focus', 'true');
|
|
354
|
-
// eslint-disable-next-line internal-storybook/no-class-selectors
|
|
355
354
|
deleteButton.classList.add('!bg-item-confirm-bg', '!text-white');
|
|
356
355
|
}
|
|
357
356
|
|
|
@@ -516,7 +515,6 @@ export const DisabledItem: Story = {
|
|
|
516
515
|
// Add the proper disabled classes and attribute that match the real implementation
|
|
517
516
|
// The itemDisabled class from popover-item-default.const.ts is:
|
|
518
517
|
// 'cursor-default pointer-events-none text-text-secondary'
|
|
519
|
-
// eslint-disable-next-line internal-storybook/no-class-selectors
|
|
520
518
|
popoverItem.classList.add('cursor-default', 'pointer-events-none', 'text-text-secondary');
|
|
521
519
|
popoverItem.setAttribute('data-blok-disabled', 'true');
|
|
522
520
|
}
|
package/src/styles/main.css
CHANGED
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
[data-blok-table-cell-blocks] .blok-block {
|
|
138
|
-
@apply p-0 m-0;
|
|
138
|
+
@apply p-0 m-0 min-h-[1.6em];
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
/**
|
|
@@ -146,3 +146,11 @@
|
|
|
146
146
|
[data-blok-table-heading-col] {
|
|
147
147
|
@apply font-semibold bg-gray-50;
|
|
148
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Table scroll haze overlays
|
|
152
|
+
* Gradient indicators that show horizontal scroll availability
|
|
153
|
+
*/
|
|
154
|
+
[data-blok-table-haze][data-blok-table-haze-visible] {
|
|
155
|
+
@apply opacity-100;
|
|
156
|
+
}
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
import type { API } from '../../../types';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Sets caret to the content element of a block
|
|
11
|
-
*
|
|
10
|
+
* Sets caret to the content element of a block.
|
|
11
|
+
* Operates synchronously so subsequent keystrokes land in the correct block
|
|
12
|
+
* (deferring via requestAnimationFrame causes a race where characters typed
|
|
13
|
+
* between the block split and the next animation frame go to the wrong element).
|
|
14
|
+
* Falls back to requestAnimationFrame only when the content element is not yet
|
|
15
|
+
* available (e.g. async rendering).
|
|
12
16
|
*
|
|
13
17
|
* @param api - The API instance
|
|
14
18
|
* @param block - BlockAPI to set caret to
|
|
@@ -19,8 +23,7 @@ export const setCaretToBlockContent = (
|
|
|
19
23
|
block: ReturnType<API['blocks']['insert']>,
|
|
20
24
|
position: 'start' | 'end' = 'end'
|
|
21
25
|
): void => {
|
|
22
|
-
|
|
23
|
-
requestAnimationFrame(() => {
|
|
26
|
+
const applyFocus = (deferred: boolean): void => {
|
|
24
27
|
const holder = block.holder;
|
|
25
28
|
if (!holder) return;
|
|
26
29
|
|
|
@@ -29,8 +32,10 @@ export const setCaretToBlockContent = (
|
|
|
29
32
|
if (!(contentEl instanceof HTMLElement)) {
|
|
30
33
|
// Fallback to setToBlock if no content element found
|
|
31
34
|
api.caret.setToBlock(block, position);
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
|
|
36
|
+
if (deferred) {
|
|
37
|
+
api.caret.updateLastCaretAfterPosition();
|
|
38
|
+
}
|
|
34
39
|
|
|
35
40
|
return;
|
|
36
41
|
}
|
|
@@ -55,8 +60,21 @@ export const setCaretToBlockContent = (
|
|
|
55
60
|
selection.removeAllRanges();
|
|
56
61
|
selection.addRange(range);
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
if (deferred) {
|
|
64
|
+
// Update the caret "after" position for undo/redo since we moved the caret
|
|
65
|
+
// asynchronously via requestAnimationFrame after the Yjs transaction committed
|
|
66
|
+
api.caret.updateLastCaretAfterPosition();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Try synchronous focus first — the block is already in the DOM after insert()
|
|
71
|
+
const holder = block.holder;
|
|
72
|
+
const contentEl = holder?.querySelector('[contenteditable="true"]');
|
|
73
|
+
|
|
74
|
+
if (contentEl instanceof HTMLElement) {
|
|
75
|
+
applyFocus(false);
|
|
76
|
+
} else {
|
|
77
|
+
// Content element not available yet — fall back to next frame
|
|
78
|
+
requestAnimationFrame(() => applyFocus(true));
|
|
79
|
+
}
|
|
62
80
|
}
|