@jackuait/blok 0.6.0-beta.9 → 0.6.0
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-Bn6Q_o8h.mjs → blok-BAh1rvUC.mjs} +3410 -2927
- package/dist/chunks/i18next-B47TKgbU.mjs +1303 -0
- package/dist/chunks/{i18next-loader-DjR4d8M7.mjs → i18next-loader-CHtGO6IK.mjs} +2 -2
- package/dist/chunks/{index-oe38cp86.mjs → index-DBWWKrDe.mjs} +12 -12
- package/dist/chunks/{inline-tool-convert-SRTkyaZn.mjs → inline-tool-convert-DduRc0fF.mjs} +1467 -951
- package/dist/chunks/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
- package/dist/chunks/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
- package/dist/{messages-DnXLrlHh.mjs → chunks/messages-4v4MuVEc.mjs} +6 -0
- package/dist/chunks/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
- package/dist/chunks/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
- package/dist/chunks/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
- package/dist/{messages-uKX8WBaD.mjs → chunks/messages-96kNZDll.mjs} +6 -0
- package/dist/chunks/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
- package/dist/{messages-DBn76jVV.mjs → chunks/messages-B217znr-.mjs} +8 -2
- package/dist/{messages-DT4dP5uK.mjs → chunks/messages-B8WNljW3.mjs} +6 -0
- package/dist/chunks/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
- package/dist/{messages-CZygwLwM.mjs → chunks/messages-BI43k_BD.mjs} +6 -0
- package/dist/{messages-CzTufCHu.mjs → chunks/messages-BJ6zrz2j.mjs} +6 -0
- package/dist/{messages-BoJc_p1r.mjs → chunks/messages-BUl_Rcnj.mjs} +6 -0
- package/dist/chunks/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
- package/dist/{messages-C2htQ_3F.mjs → chunks/messages-BcpCubnC.mjs} +6 -0
- package/dist/{messages-D5C3J9qr.mjs → chunks/messages-Bm-E4iRC.mjs} +6 -0
- package/dist/chunks/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
- package/dist/chunks/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
- package/dist/chunks/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
- package/dist/{messages-Dz9L52ol.mjs → chunks/messages-CRJ_mchV.mjs} +6 -0
- package/dist/chunks/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
- package/dist/chunks/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
- package/dist/{messages-R3hUSvr3.mjs → chunks/messages-CfiyT2Wi.mjs} +6 -0
- package/dist/{messages-CJdUsQ-c.mjs → chunks/messages-CgTq3QhU.mjs} +6 -0
- package/dist/chunks/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
- package/dist/{messages-Q7AO_FLv.mjs → chunks/messages-Cjjo7yHR.mjs} +6 -0
- package/dist/{messages-C99mq906.mjs → chunks/messages-Cl6ayUaq.mjs} +6 -0
- package/dist/chunks/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
- package/dist/chunks/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
- package/dist/chunks/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
- package/dist/{messages-BWF-zUpY.mjs → chunks/messages-CrCYPCk3.mjs} +6 -0
- package/dist/{messages-D-ZtY5v0.mjs → chunks/messages-Cs8zmZ3L.mjs} +6 -0
- package/dist/{messages-DprmQg6V.mjs → chunks/messages-CzK0LEhb.mjs} +6 -0
- package/dist/chunks/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
- package/dist/chunks/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
- package/dist/chunks/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
- package/dist/{messages-kep5wtm4.mjs → chunks/messages-D4qqwVgQ.mjs} +6 -0
- package/dist/chunks/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
- package/dist/{messages-CY8_RyFE.mjs → chunks/messages-D7u2bmP2.mjs} +6 -0
- package/dist/chunks/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
- package/dist/{messages-DLfR5bMd.mjs → chunks/messages-D9ndgBnU.mjs} +6 -0
- package/dist/{messages-CVw84KdI.mjs → chunks/messages-DDTQgImT.mjs} +6 -0
- package/dist/{messages-_ErNTNhk.mjs → chunks/messages-DH_jBeED.mjs} +6 -0
- package/dist/chunks/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
- package/dist/chunks/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
- package/dist/chunks/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
- package/dist/chunks/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
- package/dist/chunks/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
- package/dist/chunks/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
- package/dist/{messages-Z9nEU2xK.mjs → chunks/messages-DviiFSv2.mjs} +6 -0
- package/dist/chunks/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
- package/dist/{messages-w7v1GNaE.mjs → chunks/messages-Dzzn6XoD.mjs} +6 -0
- package/dist/{messages-CqWJcCbY.mjs → chunks/messages-GSByFygY.mjs} +6 -0
- package/dist/chunks/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
- package/dist/chunks/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
- package/dist/{messages-BU2nlrLK.mjs → chunks/messages-RonBBCnh.mjs} +6 -0
- package/dist/{messages-Bmu_S7GM.mjs → chunks/messages-VDriF5Qy.mjs} +6 -0
- package/dist/{messages-CLhcMlTc.mjs → chunks/messages-ZjUAIWb1.mjs} +6 -0
- package/dist/{messages-9SihnaXQ.mjs → chunks/messages-b1EdvUm0.mjs} +6 -0
- package/dist/{messages-DvFLX36Q.mjs → chunks/messages-begYOTgC.mjs} +6 -0
- package/dist/{messages-BMv4xwIr.mjs → chunks/messages-jrncnb-H.mjs} +6 -0
- package/dist/{messages-D5iv1Kox.mjs → chunks/messages-nefz1S71.mjs} +6 -0
- package/dist/{messages-CQwpzUFp.mjs → chunks/messages-ucTVgS5G.mjs} +6 -0
- package/dist/chunks/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
- package/dist/{messages-C9eaarcK.mjs → chunks/messages-wmi-iFkH.mjs} +6 -0
- package/dist/chunks/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
- package/dist/full.mjs +2 -2
- package/dist/locales.mjs +90 -84
- package/dist/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
- package/dist/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
- package/dist/{chunks/messages-DnXLrlHh.mjs → messages-4v4MuVEc.mjs} +6 -0
- package/dist/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
- package/dist/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
- package/dist/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
- package/dist/{chunks/messages-uKX8WBaD.mjs → messages-96kNZDll.mjs} +6 -0
- package/dist/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
- package/dist/{chunks/messages-DBn76jVV.mjs → messages-B217znr-.mjs} +8 -2
- package/dist/{chunks/messages-DT4dP5uK.mjs → messages-B8WNljW3.mjs} +6 -0
- package/dist/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
- package/dist/{chunks/messages-CZygwLwM.mjs → messages-BI43k_BD.mjs} +6 -0
- package/dist/{chunks/messages-CzTufCHu.mjs → messages-BJ6zrz2j.mjs} +6 -0
- package/dist/{chunks/messages-BoJc_p1r.mjs → messages-BUl_Rcnj.mjs} +6 -0
- package/dist/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
- package/dist/{chunks/messages-C2htQ_3F.mjs → messages-BcpCubnC.mjs} +6 -0
- package/dist/{chunks/messages-D5C3J9qr.mjs → messages-Bm-E4iRC.mjs} +6 -0
- package/dist/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
- package/dist/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
- package/dist/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
- package/dist/{chunks/messages-Dz9L52ol.mjs → messages-CRJ_mchV.mjs} +6 -0
- package/dist/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
- package/dist/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
- package/dist/{chunks/messages-R3hUSvr3.mjs → messages-CfiyT2Wi.mjs} +6 -0
- package/dist/{chunks/messages-CJdUsQ-c.mjs → messages-CgTq3QhU.mjs} +6 -0
- package/dist/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
- package/dist/{chunks/messages-Q7AO_FLv.mjs → messages-Cjjo7yHR.mjs} +6 -0
- package/dist/{chunks/messages-C99mq906.mjs → messages-Cl6ayUaq.mjs} +6 -0
- package/dist/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
- package/dist/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
- package/dist/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
- package/dist/{chunks/messages-BWF-zUpY.mjs → messages-CrCYPCk3.mjs} +6 -0
- package/dist/{chunks/messages-D-ZtY5v0.mjs → messages-Cs8zmZ3L.mjs} +6 -0
- package/dist/{chunks/messages-DprmQg6V.mjs → messages-CzK0LEhb.mjs} +6 -0
- package/dist/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
- package/dist/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
- package/dist/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
- package/dist/{chunks/messages-kep5wtm4.mjs → messages-D4qqwVgQ.mjs} +6 -0
- package/dist/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
- package/dist/{chunks/messages-CY8_RyFE.mjs → messages-D7u2bmP2.mjs} +6 -0
- package/dist/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
- package/dist/{chunks/messages-DLfR5bMd.mjs → messages-D9ndgBnU.mjs} +6 -0
- package/dist/{chunks/messages-CVw84KdI.mjs → messages-DDTQgImT.mjs} +6 -0
- package/dist/{chunks/messages-_ErNTNhk.mjs → messages-DH_jBeED.mjs} +6 -0
- package/dist/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
- package/dist/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
- package/dist/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
- package/dist/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
- package/dist/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
- package/dist/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
- package/dist/{chunks/messages-Z9nEU2xK.mjs → messages-DviiFSv2.mjs} +6 -0
- package/dist/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
- package/dist/{chunks/messages-w7v1GNaE.mjs → messages-Dzzn6XoD.mjs} +6 -0
- package/dist/{chunks/messages-CqWJcCbY.mjs → messages-GSByFygY.mjs} +6 -0
- package/dist/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
- package/dist/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
- package/dist/{chunks/messages-BU2nlrLK.mjs → messages-RonBBCnh.mjs} +6 -0
- package/dist/{chunks/messages-Bmu_S7GM.mjs → messages-VDriF5Qy.mjs} +6 -0
- package/dist/{chunks/messages-CLhcMlTc.mjs → messages-ZjUAIWb1.mjs} +6 -0
- package/dist/{chunks/messages-9SihnaXQ.mjs → messages-b1EdvUm0.mjs} +6 -0
- package/dist/{chunks/messages-DvFLX36Q.mjs → messages-begYOTgC.mjs} +6 -0
- package/dist/{chunks/messages-BMv4xwIr.mjs → messages-jrncnb-H.mjs} +6 -0
- package/dist/{chunks/messages-D5iv1Kox.mjs → messages-nefz1S71.mjs} +6 -0
- package/dist/{chunks/messages-CQwpzUFp.mjs → messages-ucTVgS5G.mjs} +6 -0
- package/dist/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
- package/dist/{chunks/messages-C9eaarcK.mjs → messages-wmi-iFkH.mjs} +6 -0
- package/dist/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
- package/dist/tools.mjs +3190 -1690
- package/dist/vendor.LICENSE.txt +109 -109
- package/package.json +43 -57
- package/src/blok.ts +12 -0
- package/src/components/__module.ts +21 -0
- package/src/components/block/api.ts +17 -0
- package/src/components/block/style-manager.ts +6 -2
- package/src/components/block/tool-renderer.ts +33 -30
- package/src/components/blocks.ts +132 -15
- package/src/components/i18n/locales/am/messages.json +6 -0
- package/src/components/i18n/locales/ar/messages.json +6 -0
- package/src/components/i18n/locales/az/messages.json +6 -0
- package/src/components/i18n/locales/bg/messages.json +6 -0
- package/src/components/i18n/locales/bn/messages.json +6 -0
- package/src/components/i18n/locales/bs/messages.json +6 -0
- package/src/components/i18n/locales/cs/messages.json +6 -0
- package/src/components/i18n/locales/da/messages.json +6 -0
- package/src/components/i18n/locales/de/messages.json +6 -0
- package/src/components/i18n/locales/dv/messages.json +6 -0
- package/src/components/i18n/locales/el/messages.json +6 -0
- package/src/components/i18n/locales/en/messages.json +6 -0
- package/src/components/i18n/locales/es/messages.json +6 -0
- package/src/components/i18n/locales/et/messages.json +6 -0
- package/src/components/i18n/locales/fa/messages.json +6 -0
- package/src/components/i18n/locales/fi/messages.json +6 -0
- package/src/components/i18n/locales/fil/messages.json +6 -0
- package/src/components/i18n/locales/fr/messages.json +6 -0
- package/src/components/i18n/locales/gu/messages.json +6 -0
- package/src/components/i18n/locales/he/messages.json +6 -0
- package/src/components/i18n/locales/hi/messages.json +6 -0
- package/src/components/i18n/locales/hr/messages.json +6 -0
- package/src/components/i18n/locales/hu/messages.json +6 -0
- package/src/components/i18n/locales/hy/messages.json +6 -0
- package/src/components/i18n/locales/id/messages.json +6 -0
- package/src/components/i18n/locales/it/messages.json +6 -0
- package/src/components/i18n/locales/ja/messages.json +6 -0
- package/src/components/i18n/locales/ka/messages.json +6 -0
- package/src/components/i18n/locales/km/messages.json +6 -0
- package/src/components/i18n/locales/kn/messages.json +6 -0
- package/src/components/i18n/locales/ko/messages.json +6 -0
- package/src/components/i18n/locales/ku/messages.json +6 -0
- package/src/components/i18n/locales/lo/messages.json +6 -0
- package/src/components/i18n/locales/lt/messages.json +6 -0
- package/src/components/i18n/locales/lv/messages.json +6 -0
- package/src/components/i18n/locales/mk/messages.json +6 -0
- package/src/components/i18n/locales/ml/messages.json +6 -0
- package/src/components/i18n/locales/mn/messages.json +6 -0
- package/src/components/i18n/locales/mr/messages.json +6 -0
- package/src/components/i18n/locales/ms/messages.json +6 -0
- package/src/components/i18n/locales/my/messages.json +6 -0
- package/src/components/i18n/locales/ne/messages.json +6 -0
- package/src/components/i18n/locales/nl/messages.json +6 -0
- package/src/components/i18n/locales/no/messages.json +6 -0
- package/src/components/i18n/locales/pa/messages.json +6 -0
- package/src/components/i18n/locales/pl/messages.json +6 -0
- package/src/components/i18n/locales/ps/messages.json +6 -0
- package/src/components/i18n/locales/pt/messages.json +6 -0
- package/src/components/i18n/locales/ro/messages.json +6 -0
- package/src/components/i18n/locales/ru/messages.json +6 -0
- package/src/components/i18n/locales/sd/messages.json +6 -0
- package/src/components/i18n/locales/si/messages.json +6 -0
- package/src/components/i18n/locales/sk/messages.json +6 -0
- package/src/components/i18n/locales/sl/messages.json +6 -0
- package/src/components/i18n/locales/sq/messages.json +6 -0
- package/src/components/i18n/locales/sr/messages.json +6 -0
- package/src/components/i18n/locales/sv/messages.json +6 -0
- package/src/components/i18n/locales/sw/messages.json +6 -0
- package/src/components/i18n/locales/ta/messages.json +6 -0
- package/src/components/i18n/locales/te/messages.json +6 -0
- package/src/components/i18n/locales/th/messages.json +6 -0
- package/src/components/i18n/locales/tr/messages.json +6 -0
- package/src/components/i18n/locales/ug/messages.json +6 -0
- package/src/components/i18n/locales/uk/messages.json +6 -0
- package/src/components/i18n/locales/ur/messages.json +6 -0
- package/src/components/i18n/locales/vi/messages.json +6 -0
- package/src/components/i18n/locales/yi/messages.json +6 -0
- package/src/components/i18n/locales/zh/messages.json +6 -0
- package/src/components/icons/index.ts +17 -0
- package/src/components/inline-tools/inline-tool-link.ts +1 -1
- package/src/components/inline-tools/inline-tool-marker.ts +737 -0
- package/src/components/inline-tools/utils/formatting-range-utils.ts +6 -3
- package/src/components/inline-tools/utils/marker-dom-utils.ts +17 -0
- package/src/components/modules/api/blocks.ts +34 -9
- package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +75 -29
- package/src/components/modules/blockEvents/index.ts +13 -5
- package/src/components/modules/blockManager/blockManager.ts +81 -2
- package/src/components/modules/blockManager/hierarchy.ts +20 -2
- package/src/components/modules/blockManager/operations.ts +70 -35
- package/src/components/modules/blockManager/repository.ts +22 -0
- package/src/components/modules/blockManager/types.ts +3 -1
- package/src/components/modules/blockManager/yjs-sync.ts +173 -39
- package/src/components/modules/blockSelection.ts +3 -0
- package/src/components/modules/crossBlockSelection.ts +11 -3
- package/src/components/modules/drag/preview/DragPreview.ts +10 -2
- package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
- package/src/components/modules/drag/utils/drag.constants.ts +1 -1
- package/src/components/modules/normalizeInlineImages.ts +263 -0
- package/src/components/modules/paste/google-docs-preprocessor.ts +197 -0
- package/src/components/modules/paste/handlers/base.ts +43 -2
- package/src/components/modules/paste/handlers/html-handler.ts +1 -1
- package/src/components/modules/paste/handlers/index.ts +1 -0
- package/src/components/modules/paste/handlers/table-cells-handler.ts +104 -0
- package/src/components/modules/paste/index.ts +20 -3
- package/src/components/modules/readonly.ts +8 -2
- package/src/components/modules/rectangleSelection.ts +5 -2
- package/src/components/modules/renderer.ts +35 -0
- package/src/components/modules/saver.ts +52 -2
- package/src/components/modules/toolbar/blockSettings.ts +52 -44
- package/src/components/modules/toolbar/index.ts +124 -17
- package/src/components/modules/toolbar/inline/index.ts +4 -4
- package/src/components/modules/toolbar/plus-button.ts +3 -3
- package/src/components/modules/toolbar/settings-toggler.ts +3 -3
- package/src/components/modules/toolbar/styles.ts +7 -7
- package/src/components/modules/ui.ts +6 -6
- 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 +10 -7
- package/src/components/modules/yjs/types.ts +8 -6
- package/src/components/modules/yjs/undo-history.ts +90 -11
- package/src/components/selection/fake-background/shadows.ts +1 -1
- package/src/components/shared/color-picker.ts +211 -0
- package/src/components/shared/color-presets.ts +25 -0
- package/src/components/ui/toolbox.ts +19 -11
- package/src/components/utils/color-mapping.ts +241 -0
- package/src/components/utils/notifier/draw.ts +9 -9
- package/src/components/utils/placeholder.ts +24 -8
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -2
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +14 -12
- package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
- package/src/components/utils/popover/popover-abstract.ts +27 -3
- package/src/components/utils/popover/popover-desktop.ts +26 -3
- package/src/components/utils/popover/popover-inline.ts +14 -1
- package/src/components/utils/popover/popover-mobile.ts +4 -4
- package/src/components/utils/popover/popover.const.ts +2 -2
- package/src/components/utils/sanitizer.ts +24 -3
- package/src/components/utils/tw.ts +17 -5
- package/src/stories/Header.stories.ts +106 -0
- package/src/stories/MarkerColors.stories.ts +730 -0
- package/src/stories/Popover.stories.ts +1 -3
- package/src/stories/Table.stories.ts +1662 -0
- package/src/styles/main.css +207 -37
- package/src/tools/header/index.ts +1 -1
- package/src/tools/index.ts +3 -1
- package/src/tools/list/caret-manager.ts +28 -10
- package/src/tools/list/constants.ts +2 -2
- package/src/tools/list/dom-builder.ts +3 -3
- package/src/tools/list/static-configs.ts +0 -1
- package/src/tools/paragraph/index.ts +9 -5
- package/src/tools/table/core/table-commands.ts +99 -0
- package/src/tools/table/core/table-controller.ts +231 -0
- package/src/tools/table/core/table-events.ts +102 -0
- package/src/tools/table/index.ts +1070 -174
- package/src/tools/table/ownership/table-event-broker.ts +74 -0
- package/src/tools/table/ownership/table-ownership-registry.ts +126 -0
- package/src/tools/table/table-add-controls.ts +85 -15
- package/src/tools/table/table-cell-blocks.ts +336 -38
- package/src/tools/table/table-cell-clipboard.ts +415 -0
- package/src/tools/table/table-cell-color-picker.ts +34 -0
- package/src/tools/table/table-cell-selection.ts +264 -15
- package/src/tools/table/table-core.ts +3 -42
- package/src/tools/table/table-heading-toggle.ts +2 -2
- package/src/tools/table/table-model.ts +623 -0
- package/src/tools/table/table-operations.ts +59 -78
- package/src/tools/table/table-resize.ts +15 -11
- package/src/tools/table/table-restrictions.ts +69 -3
- package/src/tools/table/table-row-col-action-handler.ts +22 -7
- package/src/tools/table/table-row-col-controls.ts +129 -12
- package/src/tools/table/table-row-col-drag.ts +14 -0
- package/src/tools/table/table-scroll-haze.ts +152 -0
- package/src/tools/table/types.ts +22 -1
- package/src/tools/table/view/table-cell-blocks-adapter.ts +47 -0
- package/src/variants/blok-minimum.ts +13 -0
- package/types/api/block.d.ts +13 -0
- package/types/api/blocks.d.ts +16 -0
- package/types/tools/table.d.ts +2 -0
- package/dist/chunks/i18next-CugVlwWp.mjs +0 -1292
- package/src/tools/table/data-normalizer.ts +0 -32
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { COLOR_PRESETS } from '../shared/color-presets';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert an HSL color (H in degrees, S and L as 0-100 percentages) to an RGB tuple.
|
|
5
|
+
*/
|
|
6
|
+
function hslToRgb(h: number, s: number, l: number): [number, number, number] {
|
|
7
|
+
const sNorm = s / 100;
|
|
8
|
+
const lNorm = l / 100;
|
|
9
|
+
|
|
10
|
+
if (sNorm === 0) {
|
|
11
|
+
const gray = Math.round(lNorm * 255);
|
|
12
|
+
|
|
13
|
+
return [gray, gray, gray];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const wrapHue = (t: number): number => {
|
|
17
|
+
if (t < 0) {
|
|
18
|
+
return t + 1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (t > 1) {
|
|
22
|
+
return t - 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return t;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const hueToChannel = (p: number, q: number, t: number): number => {
|
|
29
|
+
const wrapped = wrapHue(t);
|
|
30
|
+
|
|
31
|
+
if (wrapped < 1 / 6) {
|
|
32
|
+
return p + (q - p) * 6 * wrapped;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (wrapped < 1 / 2) {
|
|
36
|
+
return q;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (wrapped < 2 / 3) {
|
|
40
|
+
return p + (q - p) * (2 / 3 - wrapped) * 6;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return p;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const q = lNorm < 0.5 ? lNorm * (1 + sNorm) : lNorm + sNorm - lNorm * sNorm;
|
|
47
|
+
const p = 2 * lNorm - q;
|
|
48
|
+
const hNorm = h / 360;
|
|
49
|
+
|
|
50
|
+
return [
|
|
51
|
+
Math.round(hueToChannel(p, q, hNorm + 1 / 3) * 255),
|
|
52
|
+
Math.round(hueToChannel(p, q, hNorm) * 255),
|
|
53
|
+
Math.round(hueToChannel(p, q, hNorm - 1 / 3) * 255),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parse a CSS color string to an [R, G, B] tuple.
|
|
59
|
+
*
|
|
60
|
+
* Supported formats:
|
|
61
|
+
* - `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`
|
|
62
|
+
* - `rgb(r, g, b)`, `rgba(r, g, b, a)`
|
|
63
|
+
* - `hsl(h, s%, l%)`, `hsla(h, s%, l%, a)`
|
|
64
|
+
*
|
|
65
|
+
* Alpha values are ignored since only RGB is needed for distance calculation.
|
|
66
|
+
* Returns null if the string cannot be parsed.
|
|
67
|
+
*/
|
|
68
|
+
export function parseColor(cssColor: string): [number, number, number] | null {
|
|
69
|
+
/* 6-digit hex: #rrggbb */
|
|
70
|
+
const hex6 = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(cssColor);
|
|
71
|
+
|
|
72
|
+
if (hex6) {
|
|
73
|
+
return [parseInt(hex6[1], 16), parseInt(hex6[2], 16), parseInt(hex6[3], 16)];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* 8-digit hex: #rrggbbaa (alpha ignored) */
|
|
77
|
+
const hex8 = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})[0-9a-f]{2}$/i.exec(cssColor);
|
|
78
|
+
|
|
79
|
+
if (hex8) {
|
|
80
|
+
return [parseInt(hex8[1], 16), parseInt(hex8[2], 16), parseInt(hex8[3], 16)];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* 3-digit hex: #rgb */
|
|
84
|
+
const hex3 = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(cssColor);
|
|
85
|
+
|
|
86
|
+
if (hex3) {
|
|
87
|
+
return [
|
|
88
|
+
parseInt(hex3[1] + hex3[1], 16),
|
|
89
|
+
parseInt(hex3[2] + hex3[2], 16),
|
|
90
|
+
parseInt(hex3[3] + hex3[3], 16),
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* 4-digit hex: #rgba (alpha ignored) */
|
|
95
|
+
const hex4 = /^#([0-9a-f])([0-9a-f])([0-9a-f])[0-9a-f]$/i.exec(cssColor);
|
|
96
|
+
|
|
97
|
+
if (hex4) {
|
|
98
|
+
return [
|
|
99
|
+
parseInt(hex4[1] + hex4[1], 16),
|
|
100
|
+
parseInt(hex4[2] + hex4[2], 16),
|
|
101
|
+
parseInt(hex4[3] + hex4[3], 16),
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* rgb() and rgba() — alpha component is optional and ignored */
|
|
106
|
+
const rgba = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*[\d.]+\s*)?\)$/i.exec(cssColor);
|
|
107
|
+
|
|
108
|
+
if (rgba) {
|
|
109
|
+
return [Number(rgba[1]), Number(rgba[2]), Number(rgba[3])];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* hsl() and hsla() — alpha component is optional and ignored */
|
|
113
|
+
const hsla = /^hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*(?:,\s*[\d.]+\s*)?\)$/i.exec(cssColor);
|
|
114
|
+
|
|
115
|
+
if (hsla) {
|
|
116
|
+
return hslToRgb(Number(hsla[1]), Number(hsla[2]), Number(hsla[3]));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Saturation threshold below which a color is considered achromatic (gray/black/white) */
|
|
123
|
+
const ACHROMATIC_THRESHOLD = 0.10;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Convert an RGB tuple (0-255 per channel) to HSL.
|
|
127
|
+
*
|
|
128
|
+
* @returns [H, S, L] where H is 0-360 degrees, S and L are 0-1
|
|
129
|
+
*/
|
|
130
|
+
function rgbToHsl(rgb: [number, number, number]): [number, number, number] {
|
|
131
|
+
const r = rgb[0] / 255;
|
|
132
|
+
const g = rgb[1] / 255;
|
|
133
|
+
const b = rgb[2] / 255;
|
|
134
|
+
|
|
135
|
+
const max = Math.max(r, g, b);
|
|
136
|
+
const min = Math.min(r, g, b);
|
|
137
|
+
const l = (max + min) / 2;
|
|
138
|
+
|
|
139
|
+
if (max === min) {
|
|
140
|
+
return [0, 0, l];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const d = max - min;
|
|
144
|
+
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
145
|
+
|
|
146
|
+
const hueFromMax = (channel: number): number => {
|
|
147
|
+
if (channel === r) {
|
|
148
|
+
return ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (channel === g) {
|
|
152
|
+
return ((b - r) / d + 2) / 6;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return ((r - g) / d + 4) / 6;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return [hueFromMax(max) * 360, s, l];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Compute the perceptual distance between two colors using HSL with hue weighting.
|
|
163
|
+
*
|
|
164
|
+
* Achromatic colors (saturation below threshold) are compared by lightness only,
|
|
165
|
+
* and are penalized heavily against chromatic colors to prevent gray mapping to
|
|
166
|
+
* a saturated preset.
|
|
167
|
+
*
|
|
168
|
+
* Chromatic colors use weighted distance: hue (most important), saturation, lightness.
|
|
169
|
+
* Hue distance is circular (wraps at 360 degrees).
|
|
170
|
+
*/
|
|
171
|
+
function hslDistance(
|
|
172
|
+
hsl1: [number, number, number],
|
|
173
|
+
hsl2: [number, number, number]
|
|
174
|
+
): number {
|
|
175
|
+
const HUE_WEIGHT = 8;
|
|
176
|
+
const SAT_WEIGHT = 1;
|
|
177
|
+
const LIGHT_WEIGHT = 1;
|
|
178
|
+
|
|
179
|
+
const isAchromatic1 = hsl1[1] < ACHROMATIC_THRESHOLD;
|
|
180
|
+
const isAchromatic2 = hsl2[1] < ACHROMATIC_THRESHOLD;
|
|
181
|
+
|
|
182
|
+
/* Both achromatic: compare lightness only */
|
|
183
|
+
if (isAchromatic1 && isAchromatic2) {
|
|
184
|
+
const lightDiff = Math.abs(hsl1[2] - hsl2[2]);
|
|
185
|
+
|
|
186
|
+
return lightDiff * lightDiff;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* One achromatic, one chromatic: large penalty so grays never match saturated presets */
|
|
190
|
+
if (isAchromatic1 !== isAchromatic2) {
|
|
191
|
+
return 1000;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Both chromatic: weighted HSL distance */
|
|
195
|
+
const hueDiff = Math.abs(hsl1[0] - hsl2[0]);
|
|
196
|
+
const circularHue = Math.min(hueDiff, 360 - hueDiff) / 180; // normalized 0-1
|
|
197
|
+
const satDiff = Math.abs(hsl1[1] - hsl2[1]);
|
|
198
|
+
const lightDiff = Math.abs(hsl1[2] - hsl2[2]);
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
HUE_WEIGHT * circularHue * circularHue +
|
|
202
|
+
SAT_WEIGHT * satDiff * satDiff +
|
|
203
|
+
LIGHT_WEIGHT * lightDiff * lightDiff
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Map an arbitrary CSS color to the nearest Blok preset color.
|
|
209
|
+
*
|
|
210
|
+
* Uses HSL-weighted distance with hue priority for perceptually intuitive results.
|
|
211
|
+
*
|
|
212
|
+
* @param cssColor - CSS color string (hex or rgb)
|
|
213
|
+
* @param mode - 'text' for text color presets, 'bg' for background presets
|
|
214
|
+
* @returns the nearest preset hex color, or the input unchanged if unparseable
|
|
215
|
+
*/
|
|
216
|
+
export function mapToNearestPresetColor(cssColor: string, mode: 'text' | 'bg'): string {
|
|
217
|
+
const rgb = parseColor(cssColor);
|
|
218
|
+
|
|
219
|
+
if (rgb === null) {
|
|
220
|
+
return cssColor;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const hsl = rgbToHsl(rgb);
|
|
224
|
+
|
|
225
|
+
const best = COLOR_PRESETS.reduce<{ color: string; distance: number }>(
|
|
226
|
+
(acc, preset) => {
|
|
227
|
+
const presetRgb = parseColor(preset[mode]);
|
|
228
|
+
|
|
229
|
+
if (presetRgb === null) {
|
|
230
|
+
return acc;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const distance = hslDistance(hsl, rgbToHsl(presetRgb));
|
|
234
|
+
|
|
235
|
+
return distance < acc.distance ? { color: preset[mode], distance } : acc;
|
|
236
|
+
},
|
|
237
|
+
{ color: cssColor, distance: Infinity }
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
return best.color;
|
|
241
|
+
}
|
|
@@ -4,19 +4,19 @@ import type { NotifierOptions, ConfirmNotifierOptions, PromptNotifierOptions } f
|
|
|
4
4
|
|
|
5
5
|
export const CSS = {
|
|
6
6
|
wrapper: twJoin(
|
|
7
|
-
'fixed z-
|
|
7
|
+
'fixed z-2 bottom-5 left-5',
|
|
8
8
|
'font-[-apple-system,BlinkMacSystemFont,"Segoe_UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira_Sans","Droid_Sans","Helvetica_Neue",sans-serif]'
|
|
9
9
|
),
|
|
10
10
|
notification: twJoin(
|
|
11
11
|
'relative w-[230px] mt-[15px] py-[13px] px-4',
|
|
12
|
-
'bg-white shadow-
|
|
13
|
-
'text-sm leading-[1.4em] break-
|
|
12
|
+
'bg-white shadow-notify rounded-[5px]',
|
|
13
|
+
'text-sm leading-[1.4em] wrap-break-word',
|
|
14
14
|
'before:content-[""] before:absolute before:block before:top-0 before:left-0',
|
|
15
15
|
'before:w-[3px] before:h-[calc(100%-6px)] before:m-[3px] before:rounded-[5px] before:bg-transparent'
|
|
16
16
|
),
|
|
17
17
|
crossBtn: twJoin(
|
|
18
18
|
'absolute top-[7px] right-[15px] w-2.5 h-2.5 p-[5px] opacity-55 cursor-pointer',
|
|
19
|
-
'before:content-[""] before:absolute before:left-[9px] before:top-[5px] before:h-3 before:w-0.5 before:bg-[#575d67] before
|
|
19
|
+
'before:content-[""] before:absolute before:left-[9px] before:top-[5px] before:h-3 before:w-0.5 before:bg-[#575d67] before:-rotate-45',
|
|
20
20
|
'after:content-[""] after:absolute after:left-[9px] after:top-[5px] after:h-3 after:w-0.5 after:bg-[#575d67] after:rotate-45',
|
|
21
21
|
'hover:opacity-100'
|
|
22
22
|
),
|
|
@@ -26,16 +26,16 @@ export const CSS = {
|
|
|
26
26
|
cancelBtn: 'bg-[#f2f5f7] shadow-[0_2px_1px_0_rgba(16,19,29,0)] text-[#656b7c] hover:bg-[#e9ecee]',
|
|
27
27
|
input: twJoin(
|
|
28
28
|
'max-w-[130px] py-[5px] px-2.5 bg-[#f7f7f7] border-0 rounded-[3px]',
|
|
29
|
-
'text-[13px] text-[#656b7c] outline-
|
|
29
|
+
'text-[13px] text-[#656b7c] outline-hidden',
|
|
30
30
|
'placeholder:text-[#656b7c] focus:placeholder:text-[rgba(101,107,124,0.3)]'
|
|
31
31
|
),
|
|
32
32
|
successNotification: twJoin(
|
|
33
|
-
'
|
|
34
|
-
'before
|
|
33
|
+
'bg-[#fafffe]!',
|
|
34
|
+
'before:bg-[#41ffb1]!'
|
|
35
35
|
),
|
|
36
36
|
errorNotification: twJoin(
|
|
37
|
-
'
|
|
38
|
-
'before
|
|
37
|
+
'bg-[#fffbfb]!',
|
|
38
|
+
'before:bg-[#fb5d5d]!'
|
|
39
39
|
),
|
|
40
40
|
};
|
|
41
41
|
|
|
@@ -19,10 +19,10 @@ export const PLACEHOLDER_CLASSES: string[] = [
|
|
|
19
19
|
'empty:before:text-gray-text',
|
|
20
20
|
'empty:before:cursor-text',
|
|
21
21
|
'empty:before:content-[attr(data-placeholder)]',
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
22
|
+
'data-[blok-empty=true]:before:pointer-events-none',
|
|
23
|
+
'data-[blok-empty=true]:before:text-gray-text',
|
|
24
|
+
'data-[blok-empty=true]:before:cursor-text',
|
|
25
|
+
'data-[blok-empty=true]:before:content-[attr(data-placeholder)]',
|
|
26
26
|
];
|
|
27
27
|
|
|
28
28
|
/**
|
|
@@ -34,10 +34,10 @@ export const PLACEHOLDER_ACTIVE_CLASSES: string[] = [
|
|
|
34
34
|
'empty:before:text-gray-text',
|
|
35
35
|
'empty:before:cursor-text',
|
|
36
36
|
'empty:before:content-[attr(data-blok-placeholder-active)]',
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
37
|
+
'data-[empty=true]:before:pointer-events-none',
|
|
38
|
+
'data-[empty=true]:before:text-gray-text',
|
|
39
|
+
'data-[empty=true]:before:cursor-text',
|
|
40
|
+
'data-[empty=true]:before:content-[attr(data-blok-placeholder-active)]',
|
|
41
41
|
];
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -56,6 +56,22 @@ export const PLACEHOLDER_FOCUS_ONLY_CLASSES: string[] = [
|
|
|
56
56
|
'[&[data-empty=true]:focus]:before:content-[attr(data-blok-placeholder-active)]',
|
|
57
57
|
];
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Placeholder classes that show when the editor is empty (ancestor has data-blok-empty="true").
|
|
61
|
+
* Shows placeholder without requiring focus — used for initial empty-state hint.
|
|
62
|
+
* Uses data-blok-placeholder-active attribute for the placeholder text.
|
|
63
|
+
*/
|
|
64
|
+
export const PLACEHOLDER_EMPTY_EDITOR_CLASSES: string[] = [
|
|
65
|
+
'empty:in-data-[blok-empty=true]:before:pointer-events-none',
|
|
66
|
+
'empty:in-data-[blok-empty=true]:before:text-gray-text',
|
|
67
|
+
'empty:in-data-[blok-empty=true]:before:cursor-text',
|
|
68
|
+
'empty:in-data-[blok-empty=true]:before:content-[attr(data-blok-placeholder-active)]',
|
|
69
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:pointer-events-none',
|
|
70
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:text-gray-text',
|
|
71
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:cursor-text',
|
|
72
|
+
'[[data-blok-empty=true]_&[data-empty=true]]:before:content-[attr(data-blok-placeholder-active)]',
|
|
73
|
+
];
|
|
74
|
+
|
|
59
75
|
/**
|
|
60
76
|
* Check if an element's content is empty
|
|
61
77
|
*
|
|
@@ -10,7 +10,7 @@ export const css = {
|
|
|
10
10
|
* Note: noHover state is handled via [data-blok-popover-item-no-hover] which disables hover
|
|
11
11
|
* Priority order: active < hover < focus (focus wins when navigating with keyboard)
|
|
12
12
|
*/
|
|
13
|
-
item: 'flex items-center select-none border-none bg-transparent rounded-md px-2 py-
|
|
13
|
+
item: 'flex items-center select-none border-none bg-transparent rounded-md px-2 py-(--item-padding) text-text-primary mb-px data-blok-popover-item-active:bg-icon-active-bg data-blok-popover-item-active:text-icon-active-text can-hover:hover:cursor-pointer can-hover:hover:bg-item-hover-bg data-blok-force-hover:cursor-pointer data-blok-force-hover:bg-item-hover-bg data-[blok-focused="true"]:bg-item-focus-bg data-blok-popover-item-no-hover:hover:bg-transparent data-blok-popover-item-no-hover:cursor-default can-hover:data-blok-popover-item-destructive:hover:text-item-destructive-text can-hover:data-blok-popover-item-destructive:hover:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-force-hover]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-force-hover]]:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:bg-item-destructive-hover-bg',
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Item disabled state
|
|
@@ -37,7 +37,7 @@ export const cssInline = {
|
|
|
37
37
|
/**
|
|
38
38
|
* Item in inline context - more compact styling
|
|
39
39
|
*/
|
|
40
|
-
item: 'rounded p-1',
|
|
40
|
+
item: 'rounded-sm p-1',
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -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
|
+
? '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-14 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 or chevron occupies right edge
|
|
330
|
+
!isInline && !isNestedInline && (this.params.secondaryLabel || (this.hasChildren && !this.isChevronHidden) ? '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
|
|
@@ -341,8 +343,8 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
341
343
|
isInline && 'w-auto h-auto [&_svg]:w-icon [&_svg]:h-icon mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile',
|
|
342
344
|
isNestedInline && 'w-toolbox-btn h-toolbox-btn',
|
|
343
345
|
iconWithGap && 'mr-3',
|
|
344
|
-
iconWithGap && isInline && 'shadow-none bg-transparent
|
|
345
|
-
iconWithGap && isNestedInline && '
|
|
346
|
+
iconWithGap && isInline && 'shadow-none bg-transparent mr-0!',
|
|
347
|
+
iconWithGap && isNestedInline && 'mr-2!',
|
|
346
348
|
isWobbling && 'animate-wobble'
|
|
347
349
|
);
|
|
348
350
|
}
|
|
@@ -382,10 +384,10 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
382
384
|
|
|
383
385
|
if (isHidden) {
|
|
384
386
|
this.nodes.root.setAttribute(DATA_ATTR.hidden, 'true');
|
|
385
|
-
this.nodes.root.classList.add('!
|
|
387
|
+
this.nodes.root.classList.add('hidden!');
|
|
386
388
|
} else {
|
|
387
389
|
this.nodes.root.removeAttribute(DATA_ATTR.hidden);
|
|
388
|
-
this.nodes.root.classList.remove('!
|
|
390
|
+
this.nodes.root.classList.remove('hidden!');
|
|
389
391
|
}
|
|
390
392
|
}
|
|
391
393
|
|
|
@@ -400,10 +402,10 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
400
402
|
|
|
401
403
|
if (isFocused) {
|
|
402
404
|
this.nodes.root.setAttribute(DATA_ATTR.focused, 'true');
|
|
403
|
-
this.nodes.root.classList.add('
|
|
405
|
+
this.nodes.root.classList.add('bg-item-focus-bg!');
|
|
404
406
|
} else {
|
|
405
407
|
this.nodes.root.removeAttribute(DATA_ATTR.focused);
|
|
406
|
-
this.nodes.root.classList.remove('
|
|
408
|
+
this.nodes.root.classList.remove('bg-item-focus-bg!');
|
|
407
409
|
}
|
|
408
410
|
}
|
|
409
411
|
|
|
@@ -486,7 +488,7 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
486
488
|
}
|
|
487
489
|
|
|
488
490
|
this.nodes.root.removeAttribute(DATA_ATTR.popoverItemConfirmation);
|
|
489
|
-
this.nodes.root.classList.remove('
|
|
491
|
+
this.nodes.root.classList.remove('bg-item-confirm-bg!', 'text-white!');
|
|
490
492
|
|
|
491
493
|
this.restoreOriginalIcon();
|
|
492
494
|
this.restoreOriginalTitle();
|
|
@@ -502,7 +504,7 @@ export class PopoverItemDefault extends PopoverItem {
|
|
|
502
504
|
}
|
|
503
505
|
|
|
504
506
|
this.nodes.root.setAttribute(DATA_ATTR.popoverItemConfirmation, 'true');
|
|
505
|
-
this.nodes.root.classList.add('
|
|
507
|
+
this.nodes.root.classList.add('bg-item-confirm-bg!', 'text-white!');
|
|
506
508
|
|
|
507
509
|
this.updateIcon(params.icon);
|
|
508
510
|
this.updateTitle(params);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* CSS class names to be used in popover search input class
|
|
3
3
|
*/
|
|
4
4
|
export const css = {
|
|
5
|
-
wrapper: 'bg-[#F8F8F8] border border-[rgba(226,226,229,0.20)] rounded p-0.5 grid grid-cols-[auto_auto_1fr] grid-rows-[auto]',
|
|
5
|
+
wrapper: 'bg-[#F8F8F8] border border-[rgba(226,226,229,0.20)] rounded-sm p-0.5 grid grid-cols-[auto_auto_1fr] grid-rows-[auto]',
|
|
6
6
|
icon: 'w-toolbox-btn h-toolbox-btn flex items-center justify-center mr-2 [&_svg]:w-icon [&_svg]:h-icon [&_svg]:text-gray-text',
|
|
7
|
-
input: "text-sm outline-
|
|
7
|
+
input: "text-sm outline-hidden font-medium font-inherit border-0 bg-transparent m-0 p-0 leading-[22px] min-w-[calc(100%-(--spacing(6))-10px)] placeholder:text-gray-text placeholder:font-medium",
|
|
8
8
|
};
|
|
@@ -114,7 +114,10 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
|
|
|
114
114
|
|
|
115
115
|
// Update DOM state
|
|
116
116
|
this.nodes.popover.setAttribute(DATA_ATTR.popoverOpened, 'true');
|
|
117
|
-
this.nodes.popoverContainer.
|
|
117
|
+
this.nodes.popoverContainer.className = twMerge(
|
|
118
|
+
this.nodes.popoverContainer.className,
|
|
119
|
+
css.popoverContainerOpened
|
|
120
|
+
);
|
|
118
121
|
|
|
119
122
|
/**
|
|
120
123
|
* Refresh active states for all items.
|
|
@@ -142,7 +145,7 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
|
|
|
142
145
|
this.nodes.popover.removeAttribute(DATA_ATTR.popoverOpened);
|
|
143
146
|
this.nodes.popover.removeAttribute(DATA_ATTR.popoverOpenTop);
|
|
144
147
|
this.nodes.popover.removeAttribute(DATA_ATTR.popoverOpenLeft);
|
|
145
|
-
this.nodes.popoverContainer.
|
|
148
|
+
this.nodes.popoverContainer.className = css.popoverContainer;
|
|
146
149
|
|
|
147
150
|
this.itemsDefault.forEach(item => item.reset());
|
|
148
151
|
|
|
@@ -174,6 +177,12 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
|
|
|
174
177
|
// No-op in base class. PopoverDesktop overrides this.
|
|
175
178
|
}
|
|
176
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Names of items that have been explicitly hidden via toggleItemHiddenByName.
|
|
182
|
+
* These items must stay hidden even when filterItems would normally show them.
|
|
183
|
+
*/
|
|
184
|
+
private readonly permanentlyHiddenNames = new Set<string>();
|
|
185
|
+
|
|
177
186
|
/**
|
|
178
187
|
* Toggles hidden state of all items matching the given name
|
|
179
188
|
* @param name - name of the items to toggle
|
|
@@ -183,6 +192,21 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
|
|
|
183
192
|
this.items
|
|
184
193
|
.filter(item => item.name === name)
|
|
185
194
|
.forEach(item => item.toggleHidden(isHidden));
|
|
195
|
+
|
|
196
|
+
if (isHidden) {
|
|
197
|
+
this.permanentlyHiddenNames.add(name);
|
|
198
|
+
} else {
|
|
199
|
+
this.permanentlyHiddenNames.delete(name);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Returns true if the given item name was explicitly hidden via toggleItemHiddenByName.
|
|
205
|
+
* Used by subclasses to prevent filter logic from un-hiding restricted items.
|
|
206
|
+
* @param name - item name to check
|
|
207
|
+
*/
|
|
208
|
+
protected isNamePermanentlyHidden(name: string): boolean {
|
|
209
|
+
return this.permanentlyHiddenNames.has(name);
|
|
186
210
|
}
|
|
187
211
|
|
|
188
212
|
/**
|
|
@@ -326,7 +350,7 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
|
|
|
326
350
|
* This is useful for items that determine their active state dynamically (e.g., inline tools).
|
|
327
351
|
* @param item - popover item to refresh
|
|
328
352
|
*/
|
|
329
|
-
|
|
353
|
+
protected refreshItemActiveState(item: PopoverItem): void {
|
|
330
354
|
if (!(item instanceof PopoverItemDefault)) {
|
|
331
355
|
return;
|
|
332
356
|
}
|
|
@@ -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
|
*/
|
|
@@ -453,6 +465,17 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
453
465
|
// Apply nested popover positioning (moved from popover.css)
|
|
454
466
|
this.applyNestedPopoverPositioning(nestedPopoverEl);
|
|
455
467
|
|
|
468
|
+
/**
|
|
469
|
+
* Refresh trigger item's active state after any click inside the nested popover.
|
|
470
|
+
* This handles the case where a child action (e.g. color swatch click) changes
|
|
471
|
+
* the trigger tool's active state but the parent popover is not aware of it.
|
|
472
|
+
*/
|
|
473
|
+
this.listeners.on(nestedPopoverEl, 'click', () => {
|
|
474
|
+
if (this.nestedPopoverTriggerItem !== null) {
|
|
475
|
+
this.refreshItemActiveState(this.nestedPopoverTriggerItem);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
456
479
|
this.nestedPopover.show();
|
|
457
480
|
this.flipper?.deactivate();
|
|
458
481
|
|
|
@@ -481,8 +504,8 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
481
504
|
// Apply position: absolute for nested container
|
|
482
505
|
nestedContainer.style.position = 'absolute';
|
|
483
506
|
|
|
484
|
-
// Get parent width - use computed width if --width
|
|
485
|
-
const parentWidth = this.params.width === 'auto'
|
|
507
|
+
// Get parent width - use computed width if --width resolves to 'auto'
|
|
508
|
+
const parentWidth = this.params.width === undefined || this.params.width === 'auto'
|
|
486
509
|
? `${this.nodes.popoverContainer.offsetWidth}px`
|
|
487
510
|
: 'var(--width)';
|
|
488
511
|
|
|
@@ -677,7 +700,7 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
677
700
|
const isDefaultItem = item instanceof PopoverItemDefault;
|
|
678
701
|
const isSeparatorOrHtml = item instanceof PopoverItemSeparator || item instanceof PopoverItemHtml;
|
|
679
702
|
const isHidden = isDefaultItem
|
|
680
|
-
? !matchingItems.includes(item)
|
|
703
|
+
? !matchingItems.includes(item) || (item.name !== undefined && this.isNamePermanentlyHidden(item.name))
|
|
681
704
|
: isSeparatorOrHtml && (isNothingFound || !isEmptyQuery);
|
|
682
705
|
|
|
683
706
|
item.toggleHidden(isHidden);
|
|
@@ -7,6 +7,7 @@ import type { PopoverItem } from './components/popover-item';
|
|
|
7
7
|
import { PopoverItemDefault, PopoverItemType , css as popoverItemCls } from './components/popover-item';
|
|
8
8
|
import { PopoverItemHtml } from './components/popover-item/popover-item-html/popover-item-html';
|
|
9
9
|
import { PopoverDesktop } from './popover-desktop';
|
|
10
|
+
import { PopoverRegistry } from './popover-registry';
|
|
10
11
|
import { css, cssInline, CSSVariables, getNestedLevelAttrValue } from './popover.const';
|
|
11
12
|
|
|
12
13
|
import type { PopoverParams } from '@/types/utils/popover/popover';
|
|
@@ -66,6 +67,9 @@ export class PopoverInline extends PopoverDesktop {
|
|
|
66
67
|
this.nodes.popoverContainer.style.height = '';
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
// Unregister from PopoverRegistry (from abstract)
|
|
71
|
+
PopoverRegistry.instance.unregister(this);
|
|
72
|
+
|
|
69
73
|
// Emit closed event (from abstract)
|
|
70
74
|
this.emit(PopoverEvent.Closed);
|
|
71
75
|
};
|
|
@@ -307,7 +311,16 @@ export class PopoverInline extends PopoverDesktop {
|
|
|
307
311
|
|
|
308
312
|
// Apply level-1 specific positioning styles
|
|
309
313
|
if (nestedPopover.nestingLevel === 1 && nestedContainer instanceof HTMLElement) {
|
|
310
|
-
|
|
314
|
+
// Position near the trigger item, clamped to stay within the toolbar bounds
|
|
315
|
+
const itemEl = item.getElement();
|
|
316
|
+
const triggerLeft = itemEl ? itemEl.offsetLeft + this.offsetLeft : 0;
|
|
317
|
+
const nestedWidth = nestedPopover.size.width;
|
|
318
|
+
const toolbarWidth = this.nodes.popoverContainer.offsetWidth;
|
|
319
|
+
const maxLeft = Math.max(0, toolbarWidth - nestedWidth);
|
|
320
|
+
const left = Math.max(0, Math.min(triggerLeft, maxLeft));
|
|
321
|
+
|
|
322
|
+
nestedContainer.style.left = `${left}px`;
|
|
323
|
+
|
|
311
324
|
// Set top position based on height
|
|
312
325
|
const topOffset = isMobileScreen() ? 'calc(var(--height-mobile) + 3px)' : 'calc(var(--height) + 3px)';
|
|
313
326
|
nestedContainer.style.top = topOffset;
|
|
@@ -90,19 +90,19 @@ export class PopoverMobile extends PopoverAbstract<PopoverMobileNodes> {
|
|
|
90
90
|
*/
|
|
91
91
|
public show(): void {
|
|
92
92
|
this.nodes.overlay.removeAttribute(DATA_ATTR.overlayHidden);
|
|
93
|
-
this.nodes.overlay.className = twMerge(css.popoverOverlay, 'fixed inset-0 block visible z-
|
|
93
|
+
this.nodes.overlay.className = twMerge(css.popoverOverlay, 'fixed inset-0 block visible z-3 opacity-50 transition-opacity duration-120 ease-in will-change-[opacity]');
|
|
94
94
|
|
|
95
95
|
super.show();
|
|
96
96
|
|
|
97
97
|
// Apply mobile opened state classes AFTER super.show() to override base class styles
|
|
98
|
-
// For mobile, we use max-h-none instead of max-h-
|
|
98
|
+
// For mobile, we use max-h-none instead of max-h-(--max-height) since mobile popovers
|
|
99
99
|
// should expand to fit their content
|
|
100
|
-
// Use z-
|
|
100
|
+
// Use z-4 to ensure container is above the overlay (z-[3])
|
|
101
101
|
this.nodes.popoverContainer.className = twMerge(
|
|
102
102
|
css.popoverContainer,
|
|
103
103
|
css.popoverContainerMobile,
|
|
104
104
|
css.popoverContainerOpened,
|
|
105
|
-
'max-h-none z-
|
|
105
|
+
'max-h-none z-4 animate-[panelShowingMobile_250ms_ease]'
|
|
106
106
|
);
|
|
107
107
|
|
|
108
108
|
this.scrollLocker.lock();
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export const css = {
|
|
7
7
|
// Popover container - base styles
|
|
8
|
-
popoverContainer: 'absolute flex flex-col overflow-hidden box-border opacity-0 pointer-events-none p-0 border-none z-
|
|
8
|
+
popoverContainer: 'absolute flex flex-col overflow-hidden box-border opacity-0 pointer-events-none p-0 border-none z-4 max-h-0 min-w-(--width) w-(--width) rounded-lg shadow-[0_3px_15px_-3px_var(--color-popover-shadow)] left-(--popover-left) top-(--popover-top) bg-popover-bg',
|
|
9
9
|
|
|
10
10
|
// Popover container - mobile styles (applied conditionally)
|
|
11
11
|
// Reset left/top from base class since inset shorthand may not properly override them in twMerge
|
|
12
12
|
popoverContainerMobile: 'fixed max-w-none rounded-[10px] min-w-[calc(100%-var(--offset)*2)] left-auto top-auto inset-[auto_var(--offset)_calc(var(--offset)+env(safe-area-inset-bottom))_var(--offset)]',
|
|
13
13
|
|
|
14
14
|
// Popover container - opened state
|
|
15
|
-
popoverContainerOpened: 'opacity-100 pointer-events-auto p-1 max-h-
|
|
15
|
+
popoverContainerOpened: 'opacity-100 pointer-events-auto p-1 max-h-(--max-height) border border-popover-border animate-[panelShowing_100ms_ease]',
|
|
16
16
|
|
|
17
17
|
// Popover overlay
|
|
18
18
|
popoverOverlay: 'hidden bg-dark',
|