@jackuait/blok 0.7.2 → 0.7.3-beta.2
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 +3 -3
- package/dist/chunks/{blok-3RuPZd3G.mjs → blok-Cv1zWiST.mjs} +2147 -2099
- package/dist/chunks/{constants-BkelccB1.mjs → constants-DWpV4hCh.mjs} +186 -58
- package/dist/chunks/{i18next-loader-qjweOJ-t.mjs → i18next-loader-D5HxE5ZQ.mjs} +1 -1
- package/dist/chunks/{lightweight-i18n-vbtPx5C4.mjs → lightweight-i18n-Safdy0ua.mjs} +0 -1
- package/dist/chunks/{messages-CjcSWeud.mjs → messages-1C3OS98e.mjs} +0 -1
- package/dist/chunks/{messages-3bOAVT3X2.mjs → messages-3ePgbbpx2.mjs} +0 -1
- package/dist/chunks/{messages-CG2xl0IV.mjs → messages-6EJxSImH.mjs} +0 -1
- package/dist/{messages-BjnJajTO2.mjs → chunks/messages-6z-ULVyk.mjs} +0 -1
- package/dist/{messages-B8jjwMLK.mjs → chunks/messages-BKtWlK39.mjs} +0 -1
- package/dist/chunks/{messages-CpnXbVOK2.mjs → messages-BM1Su_Uy2.mjs} +0 -1
- package/dist/{messages-DZo0x7Bd.mjs → chunks/messages-BUy3odZo.mjs} +0 -1
- package/dist/{messages-BflWzIcP2.mjs → chunks/messages-BZ45xBlV.mjs} +0 -1
- package/dist/chunks/{messages-Dr7yA3xM.mjs → messages-B_90PYaG.mjs} +0 -1
- package/dist/{messages-49ZJ_ISf.mjs → chunks/messages-B_nVGWdk.mjs} +0 -1
- package/dist/{messages-cOqXp22e.mjs → chunks/messages-BjkDJuqh.mjs} +0 -1
- package/dist/chunks/{messages-CvamFN6x.mjs → messages-BtNOlsMj.mjs} +0 -1
- package/dist/{messages-DmX52AQr.mjs → chunks/messages-C1iQkKu82.mjs} +0 -1
- package/dist/{messages-CaAdEXoh2.mjs → chunks/messages-C1lqY56F2.mjs} +0 -1
- package/dist/chunks/{messages-BoTtYEct2.mjs → messages-C232njMF2.mjs} +0 -1
- package/dist/chunks/{messages-DPe7kW6J.mjs → messages-C3AJz_i6.mjs} +0 -1
- package/dist/{messages-BEDVb3ZX.mjs → chunks/messages-C9XSSqS5.mjs} +0 -1
- package/dist/chunks/{messages-DriB5lEF.mjs → messages-CRxkRJRN.mjs} +0 -1
- package/dist/{messages-XwPD18Kk.mjs → chunks/messages-CVzvKl6U.mjs} +0 -1
- package/dist/chunks/{messages-B_Qcy8kr2.mjs → messages-Cb-x47kY2.mjs} +0 -1
- package/dist/{messages-DvTVsLOK2.mjs → chunks/messages-CejEH4FW2.mjs} +0 -1
- package/dist/{messages-CicggErN2.mjs → chunks/messages-CficsmSH2.mjs} +0 -1
- package/dist/chunks/{messages-CFr0Ha6p2.mjs → messages-ClOxDE0y2.mjs} +0 -1
- package/dist/chunks/{messages-BRrtoRdw2.mjs → messages-Cn5n0nHe2.mjs} +0 -1
- package/dist/{messages-DwPfgL_u.mjs → chunks/messages-CnzaTbel.mjs} +0 -1
- package/dist/chunks/{messages-CIGX0FfW.mjs → messages-Cq6wj6FG.mjs} +0 -1
- package/dist/chunks/{messages-Csq7JatN.mjs → messages-CteKp81J.mjs} +0 -1
- package/dist/{messages-Dr-YJYIK2.mjs → chunks/messages-CvLXClh9.mjs} +0 -1
- package/dist/chunks/{messages-43N0Vfg42.mjs → messages-CxTq0x772.mjs} +0 -1
- package/dist/chunks/{messages-DkSwQvmi2.mjs → messages-CzCqu58X2.mjs} +0 -1
- package/dist/{messages-CkVfziK_2.mjs → chunks/messages-D6SAC8Lc2.mjs} +0 -1
- package/dist/chunks/{messages-Doxcj7Qy.mjs → messages-D7aoKTPD.mjs} +0 -1
- package/dist/chunks/{messages-B0cg-ThO2.mjs → messages-D9nReG4C2.mjs} +0 -1
- package/dist/{messages-g58itYPI.mjs → chunks/messages-D9qyilS0.mjs} +0 -1
- package/dist/chunks/{messages-BQZtOYxr2.mjs → messages-DDRCk44J2.mjs} +0 -1
- package/dist/chunks/{messages-B87-89os.mjs → messages-DDr8J4FE.mjs} +0 -1
- package/dist/{messages-DzhR8Klk.mjs → chunks/messages-DJWRON2S.mjs} +0 -1
- package/dist/{messages-DBwaWI0X.mjs → chunks/messages-DK6pBwD2.mjs} +0 -1
- package/dist/chunks/{messages-BFiMCfDX2.mjs → messages-DNrK8lCg2.mjs} +0 -1
- package/dist/chunks/{messages-D7fI9Pj52.mjs → messages-DQ4VyVJf2.mjs} +0 -1
- package/dist/{messages-BHOI7R4K.mjs → chunks/messages-DacahKek.mjs} +0 -1
- package/dist/chunks/{messages-Bn6LwI4B.mjs → messages-DbS9Oibb.mjs} +0 -1
- package/dist/chunks/{messages-Dg6kSnxq.mjs → messages-DcPtg90i.mjs} +0 -1
- package/dist/{messages-BpA30dPf.mjs → chunks/messages-DfTU2I8J.mjs} +0 -1
- package/dist/{messages-BdA_xvxj.mjs → chunks/messages-Dhe8_mnQ.mjs} +0 -1
- package/dist/{messages-CCKZS2f4.mjs → chunks/messages-DjOY_EqX.mjs} +0 -1
- package/dist/chunks/{messages-DRYKKPk8.mjs → messages-DnPkoMz1.mjs} +0 -1
- package/dist/chunks/{messages-B_uTiuQ-.mjs → messages-DoDbCS02.mjs} +0 -1
- package/dist/chunks/{messages-CRMdL0jG.mjs → messages-DotEkUpQ.mjs} +0 -1
- package/dist/chunks/{messages-DV5c_ZRQ.mjs → messages-Dxrg70jo.mjs} +0 -1
- package/dist/chunks/{messages-CwRhVVui.mjs → messages-DziA-L3p.mjs} +0 -1
- package/dist/{messages-CkAWTSc4.mjs → chunks/messages-IJhiftj5.mjs} +0 -1
- package/dist/chunks/{messages-yuqArCc6.mjs → messages-JRavIeeW.mjs} +0 -1
- package/dist/{messages-CERs9LC9.mjs → chunks/messages-Ul43l29K2.mjs} +0 -1
- package/dist/chunks/{messages-BU_YdaAf.mjs → messages-Yk__PXZQ.mjs} +0 -1
- package/dist/{messages-BX2KVzJp2.mjs → chunks/messages-h474TGR72.mjs} +0 -1
- package/dist/chunks/{messages-M8noQ6Kp2.mjs → messages-hngFJrES2.mjs} +0 -1
- package/dist/chunks/{messages-D0v0Xa_i2.mjs → messages-kHTrX3wo2.mjs} +0 -1
- package/dist/chunks/{messages-DqGQvcXv2.mjs → messages-m6bLP64R2.mjs} +0 -1
- package/dist/chunks/{messages-ClDJuy8K2.mjs → messages-nE9Ko73n2.mjs} +0 -1
- package/dist/chunks/{messages-C0ZWDShx2.mjs → messages-ni0ahgYk2.mjs} +0 -1
- package/dist/chunks/{messages-B7LU-b6n2.mjs → messages-pKUiAqlX2.mjs} +0 -1
- package/dist/{messages-BSlQrYwp.mjs → chunks/messages-rJdSnvyi.mjs} +0 -1
- package/dist/{messages-BrPEPj382.mjs → chunks/messages-tBHnC2Rj2.mjs} +0 -1
- package/dist/chunks/{messages-Cimsel4e.mjs → messages-tg78NAmW.mjs} +0 -1
- package/dist/{messages-CCm71gq3.mjs → chunks/messages-uLIUXFmU.mjs} +0 -1
- package/dist/{messages-BfgHOkAy.mjs → chunks/messages-yJmwc3zD.mjs} +0 -1
- package/dist/chunks/{tools-rsbC2UUN.mjs → tools-CUIpIxxP.mjs} +645 -641
- package/dist/full.mjs +3 -3
- package/dist/locales.mjs +67 -68
- package/dist/{chunks/messages-BhZcNoIQ.mjs → messages--XEfVx572.mjs} +0 -1
- package/dist/{messages-BTNuOkhL.mjs → messages-3aRjZXpv.mjs} +0 -1
- package/dist/{chunks/messages-JyZvGvrN.mjs → messages-6G0Eia-2.mjs} +0 -1
- package/dist/{messages-C3tLCwJp2.mjs → messages-B2bHgIcC2.mjs} +0 -1
- package/dist/{messages-aNMLsF8T2.mjs → messages-B8M4YRFO2.mjs} +0 -1
- package/dist/{messages-Bt_9ptDu.mjs → messages-B9qltgXa.mjs} +0 -1
- package/dist/{messages-CLQvtc_8.mjs → messages-BBgyeB_N.mjs} +0 -1
- package/dist/{messages-BigRnQS92.mjs → messages-BENRci-_2.mjs} +0 -1
- package/dist/{chunks/messages-DihczS7L.mjs → messages-BOxe7ewT.mjs} +0 -1
- package/dist/{chunks/messages-CA-jms9R.mjs → messages-BP8ZuVaD.mjs} +0 -1
- package/dist/{messages-DYlxQEIv.mjs → messages-BQJzUYP-.mjs} +0 -1
- package/dist/{chunks/messages-Cn1AC0Qk.mjs → messages-BU9luYgO.mjs} +0 -1
- package/dist/{messages-CYLYnOV82.mjs → messages-BZgGD0zf2.mjs} +0 -1
- package/dist/{messages-MBBSKGjJ2.mjs → messages-BbLCMWln2.mjs} +0 -1
- package/dist/{chunks/messages-elZUbCrN.mjs → messages-BdJ1lCo_.mjs} +0 -1
- package/dist/{chunks/messages-D3JVx_CH2.mjs → messages-Be1CCcsp2.mjs} +0 -1
- package/dist/{messages-D5KmRsUV2.mjs → messages-BlnZ8CkJ2.mjs} +0 -1
- package/dist/{messages-DDGzypb4.mjs → messages-Bsz7Qgj_.mjs} +0 -1
- package/dist/{messages-DdUpYaJ1.mjs → messages-Bw-GC0m5.mjs} +0 -1
- package/dist/{chunks/messages-FB_MePlt.mjs → messages-BwdowdYD.mjs} +0 -1
- package/dist/{chunks/messages-kC92TJI72.mjs → messages-BxQ1gzJF2.mjs} +0 -1
- package/dist/{messages-C45IBZtA2.mjs → messages-BztXgybv2.mjs} +0 -1
- package/dist/{chunks/messages-M0HT-kBW.mjs → messages-C0gyqo4h2.mjs} +0 -1
- package/dist/{messages-DhdWq5oQ2.mjs → messages-C7R0m6oE2.mjs} +0 -1
- package/dist/{chunks/messages-CtufKbaD.mjs → messages-C8iAUPzI.mjs} +0 -1
- package/dist/{messages-BaGwIHPb2.mjs → messages-CAffVeAE2.mjs} +0 -1
- package/dist/{messages-vssmW7KO.mjs → messages-CB0RKGVM.mjs} +0 -1
- package/dist/{messages-CPx1R-PH.mjs → messages-CE305J0p.mjs} +0 -1
- package/dist/{chunks/messages-Byp0YFMg.mjs → messages-CEhkWwqI.mjs} +0 -1
- package/dist/{messages-D0i5Vdyy2.mjs → messages-CJYE0_hr2.mjs} +0 -1
- package/dist/{messages-CYFdbooL2.mjs → messages-COU4L-pL2.mjs} +0 -1
- package/dist/{messages-BRPH_a6a.mjs → messages-CRMZ79Xf.mjs} +0 -1
- package/dist/{messages-CA0hwajz.mjs → messages-CVBsztOg.mjs} +0 -1
- package/dist/{messages-YfjdnhUF.mjs → messages-C_4VGaBC.mjs} +0 -1
- package/dist/{chunks/messages-D4jR5Oc-.mjs → messages-C_RPN2GV.mjs} +0 -1
- package/dist/{messages-CsM2iz1H2.mjs → messages-CaJRIGUu2.mjs} +0 -1
- package/dist/{messages-BeJaje7e2.mjs → messages-Cb5JJ8C_2.mjs} +0 -1
- package/dist/{chunks/messages-KdvbGwLH.mjs → messages-Cgy54529.mjs} +0 -1
- package/dist/{chunks/messages-CRdl14uE.mjs → messages-CkmVEyEQ2.mjs} +0 -1
- package/dist/{chunks/messages-CzCezryo.mjs → messages-CzSLUJQt.mjs} +0 -1
- package/dist/{chunks/messages-BWbZYIs12.mjs → messages-D6Sr5cUE.mjs} +0 -1
- package/dist/{messages-C0cXOCHN2.mjs → messages-DAssrN5L2.mjs} +0 -1
- package/dist/{messages-CYZVFnaF.mjs → messages-DB9U3VIh.mjs} +0 -1
- package/dist/{messages-DxKIxLKw.mjs → messages-DCOKudVN.mjs} +0 -1
- package/dist/{chunks/messages-DLrmLkco2.mjs → messages-DGZQXeav2.mjs} +0 -1
- package/dist/{chunks/messages-CqsES1wk2.mjs → messages-DZbsds_k2.mjs} +0 -1
- package/dist/{messages-RNusm48G2.mjs → messages-DkkrjINb2.mjs} +0 -1
- package/dist/{messages-DQGzw4IC.mjs → messages-DlrZrm3s.mjs} +0 -1
- package/dist/{messages-D-12TeCM2.mjs → messages-DpY9s4Qi2.mjs} +0 -1
- package/dist/{chunks/messages-BrvAiuWT.mjs → messages-DrouoDgp.mjs} +0 -1
- package/dist/{messages-DWZyaZNA.mjs → messages-GrVSCmXW.mjs} +0 -1
- package/dist/{chunks/messages-BLxyso1L.mjs → messages-K7ROT6ea.mjs} +0 -1
- package/dist/{chunks/messages-B3StvafX.mjs → messages-Kye1BINC.mjs} +0 -1
- package/dist/{chunks/messages-BdWTM73p.mjs → messages-MaHxNgKA.mjs} +0 -1
- package/dist/{messages-2iHnlF0U.mjs → messages-TseLyyoU.mjs} +0 -1
- package/dist/{chunks/messages-iWMOMK822.mjs → messages-e-KHuxtY2.mjs} +0 -1
- package/dist/{messages-DgstU8GH.mjs → messages-eCyczLYY.mjs} +0 -1
- package/dist/{messages-BFT0F9pw.mjs → messages-gldjQk7M.mjs} +0 -1
- package/dist/{chunks/messages-v1HkA3kF2.mjs → messages-huTzItxA.mjs} +0 -1
- package/dist/{messages-BEEr6Vh82.mjs → messages-m1uf_AMy2.mjs} +0 -1
- package/dist/{messages-Dc1yFFBM.mjs → messages-mVFAkdcY.mjs} +0 -1
- package/dist/{chunks/messages-tfyq1JIh2.mjs → messages-oH0ADQ362.mjs} +0 -1
- package/dist/{chunks/messages-Cuk0QaLM.mjs → messages-pgqtPci-.mjs} +0 -1
- package/dist/{messages-DuubRyFf.mjs → messages-q7HzQPVt.mjs} +0 -1
- package/dist/{messages-vfkwiKQo.mjs → messages-ruU_e2LK.mjs} +0 -1
- package/dist/{chunks/messages-Dgfbmyf-.mjs → messages-voUPclMU.mjs} +0 -1
- package/dist/{chunks/messages-DGodJU2R.mjs → messages-wRvz0vQ3.mjs} +0 -1
- package/dist/react.mjs +2 -2
- package/dist/tools.mjs +2 -2
- package/package.json +1 -1
- package/src/blok.ts +0 -1
- package/src/components/constants/data-attributes.ts +2 -0
- package/src/components/core.ts +1 -1
- package/src/components/i18n/locales/am/messages.json +0 -1
- package/src/components/i18n/locales/ar/messages.json +0 -1
- package/src/components/i18n/locales/az/messages.json +0 -1
- package/src/components/i18n/locales/bg/messages.json +0 -1
- package/src/components/i18n/locales/bn/messages.json +0 -1
- package/src/components/i18n/locales/bs/messages.json +0 -1
- package/src/components/i18n/locales/cs/messages.json +0 -1
- package/src/components/i18n/locales/da/messages.json +0 -1
- package/src/components/i18n/locales/de/messages.json +0 -1
- package/src/components/i18n/locales/dv/messages.json +0 -1
- package/src/components/i18n/locales/el/messages.json +0 -1
- package/src/components/i18n/locales/en/messages.json +0 -1
- package/src/components/i18n/locales/es/messages.json +0 -1
- package/src/components/i18n/locales/et/messages.json +0 -1
- package/src/components/i18n/locales/fa/messages.json +0 -1
- package/src/components/i18n/locales/fi/messages.json +0 -1
- package/src/components/i18n/locales/fil/messages.json +0 -1
- package/src/components/i18n/locales/fr/messages.json +1 -2
- package/src/components/i18n/locales/gu/messages.json +0 -1
- package/src/components/i18n/locales/he/messages.json +0 -1
- package/src/components/i18n/locales/hi/messages.json +0 -1
- package/src/components/i18n/locales/hr/messages.json +0 -1
- package/src/components/i18n/locales/hu/messages.json +0 -1
- package/src/components/i18n/locales/hy/messages.json +0 -1
- package/src/components/i18n/locales/id/messages.json +0 -1
- package/src/components/i18n/locales/it/messages.json +0 -1
- package/src/components/i18n/locales/ja/messages.json +0 -1
- package/src/components/i18n/locales/ka/messages.json +0 -1
- package/src/components/i18n/locales/km/messages.json +0 -1
- package/src/components/i18n/locales/kn/messages.json +0 -1
- package/src/components/i18n/locales/ko/messages.json +0 -1
- package/src/components/i18n/locales/ku/messages.json +0 -1
- package/src/components/i18n/locales/lo/messages.json +0 -1
- package/src/components/i18n/locales/lt/messages.json +0 -1
- package/src/components/i18n/locales/lv/messages.json +0 -1
- package/src/components/i18n/locales/mk/messages.json +0 -1
- package/src/components/i18n/locales/ml/messages.json +0 -1
- package/src/components/i18n/locales/mn/messages.json +0 -1
- package/src/components/i18n/locales/mr/messages.json +0 -1
- package/src/components/i18n/locales/ms/messages.json +0 -1
- package/src/components/i18n/locales/my/messages.json +0 -1
- package/src/components/i18n/locales/ne/messages.json +0 -1
- package/src/components/i18n/locales/nl/messages.json +0 -1
- package/src/components/i18n/locales/no/messages.json +0 -1
- package/src/components/i18n/locales/pa/messages.json +0 -1
- package/src/components/i18n/locales/pl/messages.json +0 -1
- package/src/components/i18n/locales/ps/messages.json +0 -1
- package/src/components/i18n/locales/pt/messages.json +0 -1
- package/src/components/i18n/locales/ro/messages.json +0 -1
- package/src/components/i18n/locales/ru/messages.json +0 -1
- package/src/components/i18n/locales/sd/messages.json +0 -1
- package/src/components/i18n/locales/si/messages.json +0 -1
- package/src/components/i18n/locales/sk/messages.json +0 -1
- package/src/components/i18n/locales/sl/messages.json +0 -1
- package/src/components/i18n/locales/sq/messages.json +0 -1
- package/src/components/i18n/locales/sr/messages.json +0 -1
- package/src/components/i18n/locales/sv/messages.json +0 -1
- package/src/components/i18n/locales/sw/messages.json +0 -1
- package/src/components/i18n/locales/ta/messages.json +0 -1
- package/src/components/i18n/locales/te/messages.json +0 -1
- package/src/components/i18n/locales/th/messages.json +0 -1
- package/src/components/i18n/locales/tr/messages.json +0 -1
- package/src/components/i18n/locales/ug/messages.json +0 -1
- package/src/components/i18n/locales/uk/messages.json +0 -1
- package/src/components/i18n/locales/ur/messages.json +0 -1
- package/src/components/i18n/locales/vi/messages.json +0 -1
- package/src/components/i18n/locales/yi/messages.json +0 -1
- package/src/components/i18n/locales/zh/messages.json +0 -1
- package/src/components/icons/index.ts +0 -16
- package/src/components/modules/api/index.ts +1 -1
- package/src/components/modules/api/theme.ts +17 -0
- package/src/components/modules/index.ts +8 -6
- package/src/components/modules/themeManager.ts +160 -0
- package/src/components/modules/toolbar/blockSettings.ts +12 -0
- package/src/components/modules/toolbar/index.ts +27 -1
- package/src/components/ui/toolbox.ts +3 -1
- package/src/components/utils/data-model-transform.ts +149 -5
- package/src/components/utils/popover/popover-desktop.ts +329 -44
- package/src/styles/main.css +1 -1
- package/src/tools/toggle/index.ts +14 -0
- package/src/types-internal/blok-modules.d.ts +6 -4
- package/types/api/index.d.ts +2 -1
- package/types/api/theme.d.ts +29 -0
- package/types/configs/blok-config.d.ts +10 -20
- package/types/index.d.ts +8 -4
- package/types/utils/popover/popover.d.ts +7 -0
- package/src/components/block-tunes/block-tune-width.ts +0 -39
- package/src/components/modules/api/width.ts +0 -17
- package/src/components/modules/widthManager.ts +0 -69
- package/types/api/width.d.ts +0 -19
|
@@ -3,7 +3,8 @@ import { Flipper } from '../../flipper';
|
|
|
3
3
|
import { keyCodes } from '../../utils';
|
|
4
4
|
|
|
5
5
|
import type { PopoverItem, PopoverItemRenderParamsMap } from './components/popover-item';
|
|
6
|
-
import { PopoverItemSeparator, css as popoverItemCls
|
|
6
|
+
import { PopoverItemSeparator, css as popoverItemCls, PopoverItemDefault, PopoverItemType } from './components/popover-item';
|
|
7
|
+
import type { PopoverItemParams } from '@/types/utils/popover/popover-item';
|
|
7
8
|
import { PopoverItemHtml } from './components/popover-item/popover-item-html/popover-item-html';
|
|
8
9
|
import type { SearchableItem } from './components/search-input';
|
|
9
10
|
import { SearchInput, SearchInputEvent, scoreSearchMatch } from './components/search-input';
|
|
@@ -86,6 +87,20 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
86
87
|
*/
|
|
87
88
|
private originalItemOrder: Element[] | undefined;
|
|
88
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Cache of promoted items built from nested children.
|
|
92
|
+
* Built once on first non-empty search, destroyed on clear/hide/destroy.
|
|
93
|
+
*/
|
|
94
|
+
private promotedItemCache: {
|
|
95
|
+
items: PopoverItemDefault[];
|
|
96
|
+
parentChains: Map<PopoverItemDefault, string[]>;
|
|
97
|
+
} | null = null;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Temporary group separator elements injected during search.
|
|
101
|
+
*/
|
|
102
|
+
private promotedSeparators: HTMLElement[] = [];
|
|
103
|
+
|
|
89
104
|
/**
|
|
90
105
|
* Construct the instance
|
|
91
106
|
* @param params - popover params
|
|
@@ -222,7 +237,10 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
222
237
|
this.nodes.popover.style.setProperty(CSSVariables.PopoverHeight, measuredSize.height + 'px');
|
|
223
238
|
|
|
224
239
|
if (this.params.width === undefined || this.params.width === 'auto') {
|
|
225
|
-
this.
|
|
240
|
+
const minWidth = this.params.minWidth !== undefined ? parseFloat(this.params.minWidth) : 0;
|
|
241
|
+
const width = Math.max(measuredSize.width, minWidth);
|
|
242
|
+
|
|
243
|
+
this.nodes.popover.style.setProperty('--width', width + 'px');
|
|
226
244
|
}
|
|
227
245
|
|
|
228
246
|
if (!this.trigger && !this.shouldOpenBottom) {
|
|
@@ -321,6 +339,7 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
321
339
|
* Closes popover
|
|
322
340
|
*/
|
|
323
341
|
public hide = (): void => {
|
|
342
|
+
this.cleanupPromotedItems();
|
|
324
343
|
super.hide();
|
|
325
344
|
|
|
326
345
|
this.destroyNestedPopoverIfExists();
|
|
@@ -430,6 +449,31 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
430
449
|
this.previouslyHoveredItem = null;
|
|
431
450
|
}
|
|
432
451
|
|
|
452
|
+
/**
|
|
453
|
+
* Retrieves popover item that is the target of the specified event.
|
|
454
|
+
* Overridden to include promoted items from recursive search.
|
|
455
|
+
* @param event - event to retrieve popover item from
|
|
456
|
+
*/
|
|
457
|
+
protected override getTargetItem(event: Event): PopoverItemDefault | PopoverItemHtml | undefined {
|
|
458
|
+
const allItems = this.promotedItemCache !== null
|
|
459
|
+
? [...this.items, ...this.promotedItemCache.items]
|
|
460
|
+
: this.items;
|
|
461
|
+
|
|
462
|
+
return allItems
|
|
463
|
+
.filter((item): item is PopoverItemDefault | PopoverItemHtml =>
|
|
464
|
+
item instanceof PopoverItemDefault || item instanceof PopoverItemHtml
|
|
465
|
+
)
|
|
466
|
+
.find(item => {
|
|
467
|
+
const itemEl = item.getElement();
|
|
468
|
+
|
|
469
|
+
if (itemEl === null) {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
return event.composedPath().includes(itemEl);
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
433
477
|
/**
|
|
434
478
|
* Sets CSS variable with position of item near which nested popover should be displayed.
|
|
435
479
|
* Is used for correct positioning of the nested popover
|
|
@@ -577,7 +621,7 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
577
621
|
const actualPopoverEl: HTMLElement = queriedPopoverEl instanceof HTMLElement ? queriedPopoverEl : nestedPopoverEl;
|
|
578
622
|
|
|
579
623
|
// Check if parent popover has openTop or openLeft state
|
|
580
|
-
const
|
|
624
|
+
const _isParentOpenTop = this.nodes.popover.hasAttribute(DATA_ATTR.popoverOpenTop);
|
|
581
625
|
const isParentOpenLeft = this.nodes.popover.hasAttribute(DATA_ATTR.popoverOpenLeft);
|
|
582
626
|
|
|
583
627
|
// Apply position: absolute for nested container
|
|
@@ -598,14 +642,8 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
598
642
|
actualPopoverEl.style.setProperty(CSSVariables.PopoverLeft, `calc(var(--nesting-level) * (${parentWidth} - var(--nested-popover-overlap)))`);
|
|
599
643
|
}
|
|
600
644
|
|
|
601
|
-
//
|
|
602
|
-
|
|
603
|
-
// Open upward
|
|
604
|
-
nestedContainer.style.top = 'calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + 0.5rem + var(--nested-popover-overlap))';
|
|
605
|
-
} else {
|
|
606
|
-
// Open downward
|
|
607
|
-
nestedContainer.style.top = 'calc(var(--trigger-item-top) - var(--nested-popover-overlap))';
|
|
608
|
-
}
|
|
645
|
+
// Center nested popover vertically on the trigger item
|
|
646
|
+
nestedContainer.style.top = 'calc(var(--trigger-item-top) - var(--popover-height) / 2 + var(--item-height) / 2)';
|
|
609
647
|
}
|
|
610
648
|
|
|
611
649
|
/**
|
|
@@ -732,6 +770,153 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
732
770
|
focusedItem?.onFocus();
|
|
733
771
|
};
|
|
734
772
|
|
|
773
|
+
/**
|
|
774
|
+
* Builds cache of PopoverItemDefault instances from nested children.
|
|
775
|
+
* Recursively walks the item tree to arbitrary depth.
|
|
776
|
+
* Each cached item is mapped to its parent chain for group labeling.
|
|
777
|
+
*/
|
|
778
|
+
private buildPromotedItemCache(): { items: PopoverItemDefault[]; parentChains: Map<PopoverItemDefault, string[]> } {
|
|
779
|
+
const cache = {
|
|
780
|
+
items: [] as PopoverItemDefault[],
|
|
781
|
+
parentChains: new Map<PopoverItemDefault, string[]>(),
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
this.collectPromotedChildren(this.items, [], cache);
|
|
785
|
+
|
|
786
|
+
return cache;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Recursively collects default child items from items that have children.
|
|
791
|
+
* @param items - items to inspect for children
|
|
792
|
+
* @param parentChain - ancestor label chain accumulated so far
|
|
793
|
+
* @param cache - mutable cache to populate
|
|
794
|
+
*/
|
|
795
|
+
private collectPromotedChildren(
|
|
796
|
+
items: PopoverItem[],
|
|
797
|
+
parentChain: string[],
|
|
798
|
+
cache: { items: PopoverItemDefault[]; parentChains: Map<PopoverItemDefault, string[]> }
|
|
799
|
+
): void {
|
|
800
|
+
for (const item of items) {
|
|
801
|
+
if (!(item instanceof PopoverItemDefault) || !item.hasChildren) {
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
const label = item.title ?? item.name ?? '';
|
|
806
|
+
const newChain = [...parentChain, label];
|
|
807
|
+
|
|
808
|
+
this.collectDefaultChildren(item.children, newChain, cache);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Constructs PopoverItemDefault instances from raw params and adds them to the cache.
|
|
814
|
+
* @param childParams - raw child item params from a parent item
|
|
815
|
+
* @param parentChain - ancestor label chain for this group
|
|
816
|
+
* @param cache - mutable cache to populate
|
|
817
|
+
*/
|
|
818
|
+
private collectDefaultChildren(
|
|
819
|
+
childParams: PopoverItemParams[],
|
|
820
|
+
parentChain: string[],
|
|
821
|
+
cache: { items: PopoverItemDefault[]; parentChains: Map<PopoverItemDefault, string[]> }
|
|
822
|
+
): void {
|
|
823
|
+
for (const childParam of childParams) {
|
|
824
|
+
if (childParam.type !== undefined && childParam.type !== PopoverItemType.Default) {
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
const childInstance = new PopoverItemDefault(childParam);
|
|
829
|
+
|
|
830
|
+
if (childInstance.name !== undefined && this.isNamePermanentlyHidden(childInstance.name)) {
|
|
831
|
+
childInstance.destroy();
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
cache.items.push(childInstance);
|
|
836
|
+
cache.parentChains.set(childInstance, parentChain);
|
|
837
|
+
|
|
838
|
+
if (childInstance.hasChildren) {
|
|
839
|
+
this.collectPromotedChildren([childInstance], parentChain, cache);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Removes promoted items and group separators from DOM and destroys cached instances.
|
|
846
|
+
* Idempotent — safe to call when cache is already null.
|
|
847
|
+
*/
|
|
848
|
+
private cleanupPromotedItems(): void {
|
|
849
|
+
for (const separator of this.promotedSeparators) {
|
|
850
|
+
separator.remove();
|
|
851
|
+
}
|
|
852
|
+
this.promotedSeparators = [];
|
|
853
|
+
|
|
854
|
+
if (this.promotedItemCache !== null) {
|
|
855
|
+
for (const item of this.promotedItemCache.items) {
|
|
856
|
+
item.getElement()?.remove();
|
|
857
|
+
item.destroy();
|
|
858
|
+
}
|
|
859
|
+
this.promotedItemCache = null;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Creates a group separator element for promoted search results.
|
|
865
|
+
* @param label - the parent chain label (e.g., "Convert to" or "Parent › Child")
|
|
866
|
+
*/
|
|
867
|
+
private createGroupSeparator(label: string): HTMLElement {
|
|
868
|
+
const el = document.createElement('div');
|
|
869
|
+
|
|
870
|
+
el.setAttribute(DATA_ATTR.promotedGroupLabel, '');
|
|
871
|
+
el.setAttribute('role', 'separator');
|
|
872
|
+
el.className = 'px-3 pt-2.5 pb-1 text-[11px] font-medium uppercase tracking-wide text-gray-text/50 cursor-default';
|
|
873
|
+
el.textContent = label;
|
|
874
|
+
|
|
875
|
+
return el;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Appends DOM elements for a group of promoted items to the items container.
|
|
880
|
+
* @param groupItems - promoted items with their scores
|
|
881
|
+
*/
|
|
882
|
+
private appendPromotedGroupElements(groupItems: Array<{ item: PopoverItemDefault; score: number }>): void {
|
|
883
|
+
for (const { item } of groupItems) {
|
|
884
|
+
const el = item.getElement();
|
|
885
|
+
|
|
886
|
+
if (el !== null) {
|
|
887
|
+
this.nodes.items?.appendChild(el);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Filters out top-level items whose title duplicates a promoted item's title.
|
|
894
|
+
* Prevents the same entry from appearing both at the top level and under a group
|
|
895
|
+
* like "Convert to" during search.
|
|
896
|
+
* @param topLevel - top-level items matching the search query
|
|
897
|
+
* @param promoted - promoted items from nested children
|
|
898
|
+
*/
|
|
899
|
+
private deduplicateAgainstPromoted(
|
|
900
|
+
topLevel: PopoverItemDefault[],
|
|
901
|
+
promoted: Array<{ item: PopoverItemDefault }>
|
|
902
|
+
): PopoverItemDefault[] {
|
|
903
|
+
const promotedTitles = new Set<string>();
|
|
904
|
+
|
|
905
|
+
for (const { item } of promoted) {
|
|
906
|
+
if (item.title !== undefined) {
|
|
907
|
+
promotedTitles.add(item.title.toLowerCase());
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
return topLevel.filter(item => {
|
|
912
|
+
if (!(item instanceof PopoverItemDefault) || item.title === undefined) {
|
|
913
|
+
return true;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
return !promotedTitles.has(item.title.toLowerCase());
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
|
|
735
920
|
/**
|
|
736
921
|
* Adds search to the popover
|
|
737
922
|
*/
|
|
@@ -741,7 +926,42 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
741
926
|
placeholder: this.messages.search,
|
|
742
927
|
});
|
|
743
928
|
|
|
744
|
-
this.search.on(SearchInputEvent.Search,
|
|
929
|
+
this.search.on(SearchInputEvent.Search, (searchData: { query: string; items: SearchableItem[] }) => {
|
|
930
|
+
const isEmptyQuery = searchData.query === '';
|
|
931
|
+
|
|
932
|
+
if (isEmptyQuery) {
|
|
933
|
+
this.cleanupPromotedItems();
|
|
934
|
+
this.onSearch({
|
|
935
|
+
query: searchData.query,
|
|
936
|
+
topLevelItems: searchData.items as unknown as PopoverItemDefault[],
|
|
937
|
+
promotedItems: [],
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
// Build cache on first non-empty search
|
|
944
|
+
if (this.promotedItemCache === null) {
|
|
945
|
+
this.promotedItemCache = this.buildPromotedItemCache();
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// Score promoted items against the query
|
|
949
|
+
const { parentChains } = this.promotedItemCache;
|
|
950
|
+
const promotedScored = this.promotedItemCache.items
|
|
951
|
+
.map(item => ({
|
|
952
|
+
item,
|
|
953
|
+
score: scoreSearchMatch(item, searchData.query),
|
|
954
|
+
chain: parentChains.get(item) ?? [],
|
|
955
|
+
}))
|
|
956
|
+
.filter(({ score }) => score > 0)
|
|
957
|
+
.sort((a, b) => b.score - a.score);
|
|
958
|
+
|
|
959
|
+
this.onSearch({
|
|
960
|
+
query: searchData.query,
|
|
961
|
+
topLevelItems: searchData.items as unknown as PopoverItemDefault[],
|
|
962
|
+
promotedItems: promotedScored,
|
|
963
|
+
});
|
|
964
|
+
});
|
|
745
965
|
|
|
746
966
|
const searchElement = this.search.getElement();
|
|
747
967
|
|
|
@@ -757,45 +977,66 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
757
977
|
*/
|
|
758
978
|
public override filterItems(query: string): void {
|
|
759
979
|
if (query === '') {
|
|
980
|
+
this.cleanupPromotedItems();
|
|
760
981
|
this.onSearch({
|
|
761
982
|
query,
|
|
762
|
-
|
|
983
|
+
topLevelItems: this.itemsDefault,
|
|
984
|
+
promotedItems: [],
|
|
763
985
|
});
|
|
764
986
|
|
|
765
987
|
return;
|
|
766
988
|
}
|
|
767
989
|
|
|
768
|
-
|
|
990
|
+
// Build cache on first non-empty search
|
|
991
|
+
if (this.promotedItemCache === null) {
|
|
992
|
+
this.promotedItemCache = this.buildPromotedItemCache();
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// Score top-level items
|
|
996
|
+
const topLevelScored = this.itemsDefault
|
|
769
997
|
.map(item => ({ item, score: scoreSearchMatch(item, query) }))
|
|
770
998
|
.filter(({ score }) => score > 0)
|
|
771
999
|
.sort((a, b) => b.score - a.score);
|
|
772
1000
|
|
|
773
|
-
|
|
1001
|
+
// Score promoted items from cache
|
|
1002
|
+
const { parentChains: chains } = this.promotedItemCache;
|
|
1003
|
+
const promotedScored = this.promotedItemCache.items
|
|
1004
|
+
.map(item => ({
|
|
1005
|
+
item,
|
|
1006
|
+
score: scoreSearchMatch(item, query),
|
|
1007
|
+
chain: chains.get(item) ?? [],
|
|
1008
|
+
}))
|
|
1009
|
+
.filter(({ score }) => score > 0)
|
|
1010
|
+
.sort((a, b) => b.score - a.score);
|
|
774
1011
|
|
|
775
1012
|
this.onSearch({
|
|
776
1013
|
query,
|
|
777
|
-
|
|
1014
|
+
topLevelItems: topLevelScored.map(({ item }) => item),
|
|
1015
|
+
promotedItems: promotedScored,
|
|
778
1016
|
});
|
|
779
1017
|
}
|
|
780
1018
|
|
|
781
1019
|
/**
|
|
782
|
-
* Handles
|
|
783
|
-
*
|
|
784
|
-
* @param data.query - search query text
|
|
785
|
-
* @param data.items - search results
|
|
1020
|
+
* Handles search results from both filterItems and SearchInput.
|
|
1021
|
+
* Renders top-level matches and promoted children with group separators.
|
|
786
1022
|
*/
|
|
787
|
-
private onSearch = (data: {
|
|
1023
|
+
private onSearch = (data: {
|
|
1024
|
+
query: string;
|
|
1025
|
+
topLevelItems: PopoverItemDefault[] | SearchableItem[];
|
|
1026
|
+
promotedItems: Array<{ item: PopoverItemDefault; score: number; chain: string[] }>;
|
|
1027
|
+
}): void => {
|
|
788
1028
|
const isEmptyQuery = data.query === '';
|
|
789
|
-
const
|
|
1029
|
+
const allTopLevel = data.topLevelItems as unknown as PopoverItemDefault[];
|
|
1030
|
+
|
|
1031
|
+
// Deduplicate: hide top-level items whose title matches a promoted item
|
|
1032
|
+
const matchingTopLevel = !isEmptyQuery && data.promotedItems.length > 0
|
|
1033
|
+
? this.deduplicateAgainstPromoted(allTopLevel, data.promotedItems)
|
|
1034
|
+
: allTopLevel;
|
|
790
1035
|
|
|
791
|
-
|
|
792
|
-
const matchingItems = data.items as unknown as PopoverItemDefault[];
|
|
1036
|
+
const isNothingFound = matchingTopLevel.length === 0 && data.promotedItems.length === 0;
|
|
793
1037
|
|
|
794
1038
|
/**
|
|
795
1039
|
* When nothing is found, disable transitions so items hide instantly.
|
|
796
|
-
* The "Nothing found" message fade-in provides the visual transition;
|
|
797
|
-
* animating the last items' collapse simultaneously causes a jarring
|
|
798
|
-
* height bounce in the popover container.
|
|
799
1040
|
*/
|
|
800
1041
|
if (isNothingFound) {
|
|
801
1042
|
this.items.forEach(item => {
|
|
@@ -808,48 +1049,92 @@ export class PopoverDesktop extends PopoverAbstract {
|
|
|
808
1049
|
const isDefaultItem = item instanceof PopoverItemDefault;
|
|
809
1050
|
const isSeparatorOrHtml = item instanceof PopoverItemSeparator || item instanceof PopoverItemHtml;
|
|
810
1051
|
const isHidden = isDefaultItem
|
|
811
|
-
? !
|
|
1052
|
+
? !matchingTopLevel.includes(item) || (item.name !== undefined && this.isNamePermanentlyHidden(item.name))
|
|
812
1053
|
: isSeparatorOrHtml && (isNothingFound || !isEmptyQuery);
|
|
813
1054
|
|
|
814
1055
|
item.toggleHidden(isHidden);
|
|
815
1056
|
});
|
|
816
1057
|
|
|
817
1058
|
if (isNothingFound) {
|
|
818
|
-
// Force reflow so the instant hide takes effect, then restore transitions
|
|
819
1059
|
this.nodes.popoverContainer.offsetHeight;
|
|
820
1060
|
this.items.forEach(item => {
|
|
821
1061
|
item.getElement()?.style.removeProperty('transition-duration');
|
|
822
1062
|
});
|
|
823
1063
|
}
|
|
824
1064
|
|
|
825
|
-
// Reorder DOM elements to reflect ranking
|
|
826
|
-
if (!isEmptyQuery &&
|
|
827
|
-
this.reorderItemsByRank(
|
|
1065
|
+
// Reorder top-level DOM elements to reflect ranking
|
|
1066
|
+
if (!isEmptyQuery && matchingTopLevel.length > 0) {
|
|
1067
|
+
this.reorderItemsByRank(matchingTopLevel);
|
|
828
1068
|
} else if (isEmptyQuery && this.originalItemOrder !== undefined) {
|
|
829
1069
|
this.restoreOriginalItemOrder();
|
|
830
1070
|
}
|
|
831
1071
|
|
|
1072
|
+
// Detach previous promoted elements from DOM (don't destroy cache)
|
|
1073
|
+
for (const separator of this.promotedSeparators) {
|
|
1074
|
+
separator.remove();
|
|
1075
|
+
}
|
|
1076
|
+
this.promotedSeparators = [];
|
|
1077
|
+
|
|
1078
|
+
if (this.promotedItemCache !== null) {
|
|
1079
|
+
for (const item of this.promotedItemCache.items) {
|
|
1080
|
+
item.getElement()?.remove();
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// Render promoted items grouped by parent chain
|
|
1085
|
+
if (data.promotedItems.length > 0) {
|
|
1086
|
+
const groups = new Map<string, Array<{ item: PopoverItemDefault; score: number }>>();
|
|
1087
|
+
|
|
1088
|
+
for (const entry of data.promotedItems) {
|
|
1089
|
+
const label = entry.chain.join(' \u203A ');
|
|
1090
|
+
const existing = groups.get(label);
|
|
1091
|
+
|
|
1092
|
+
if (existing !== undefined) {
|
|
1093
|
+
existing.push({ item: entry.item, score: entry.score });
|
|
1094
|
+
} else {
|
|
1095
|
+
groups.set(label, [{ item: entry.item, score: entry.score }]);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// Sort groups by best score in each group
|
|
1100
|
+
const sortedGroups = [...groups.entries()].sort((a, b) => {
|
|
1101
|
+
const bestA = Math.max(...a[1].map(e => e.score));
|
|
1102
|
+
const bestB = Math.max(...b[1].map(e => e.score));
|
|
1103
|
+
|
|
1104
|
+
return bestB - bestA;
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
for (const [label, groupItems] of sortedGroups) {
|
|
1108
|
+
const separator = this.createGroupSeparator(label);
|
|
1109
|
+
|
|
1110
|
+
this.promotedSeparators.push(separator);
|
|
1111
|
+
this.nodes.items?.appendChild(separator);
|
|
1112
|
+
|
|
1113
|
+
this.appendPromotedGroupElements(groupItems);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
832
1117
|
this.toggleNothingFoundMessage(isNothingFound);
|
|
833
1118
|
|
|
834
|
-
|
|
835
|
-
const
|
|
1119
|
+
// Build flippable elements list: top-level matches + promoted items
|
|
1120
|
+
const topLevelFlippable = isEmptyQuery
|
|
1121
|
+
? this.flippableElements
|
|
1122
|
+
: matchingTopLevel.map(item => item.getElement());
|
|
1123
|
+
|
|
1124
|
+
const promotedFlippable = data.promotedItems.map(({ item }) => item.getElement());
|
|
1125
|
+
|
|
1126
|
+
const flippableElements = [
|
|
1127
|
+
...topLevelFlippable,
|
|
1128
|
+
...promotedFlippable,
|
|
1129
|
+
].filter((el): el is HTMLElement => el !== null);
|
|
836
1130
|
|
|
837
1131
|
if (!this.flipper?.isActivated) {
|
|
838
1132
|
return;
|
|
839
1133
|
}
|
|
840
1134
|
|
|
841
|
-
/** Update flipper items with only visible */
|
|
842
1135
|
this.flipper.deactivate();
|
|
843
|
-
this.flipper.activate(flippableElements
|
|
1136
|
+
this.flipper.activate(flippableElements);
|
|
844
1137
|
|
|
845
|
-
/**
|
|
846
|
-
* Focus first item after filtering.
|
|
847
|
-
* Always skip the first Tab press so it just "enters" the menu rather than
|
|
848
|
-
* advancing to second item. This applies regardless of whether the query is
|
|
849
|
-
* empty (initial "/" open) or non-empty (user is typing to filter), because
|
|
850
|
-
* the user's keyboard focus is still in the search input - pressing Tab
|
|
851
|
-
* should enter the list at item 0, not advance from 0 to 1.
|
|
852
|
-
*/
|
|
853
1138
|
if (flippableElements.length > 0) {
|
|
854
1139
|
this.flipper.focusItem(0, { skipNextTab: true });
|
|
855
1140
|
}
|
package/src/styles/main.css
CHANGED
|
@@ -74,6 +74,20 @@ export class ToggleItem implements BlockTool {
|
|
|
74
74
|
return normalized;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// Handle legacy toggleList format: { title, isExpanded }
|
|
78
|
+
if (typeof data === 'object' && data !== null && 'title' in data) {
|
|
79
|
+
const legacyData = data as Record<string, unknown>;
|
|
80
|
+
const normalized: ToggleItemData = {
|
|
81
|
+
text: typeof legacyData.title === 'string' ? legacyData.title : '',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (typeof legacyData.isExpanded === 'boolean') {
|
|
85
|
+
normalized.isOpen = legacyData.isExpanded;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return normalized;
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
return { text: '' };
|
|
78
92
|
}
|
|
79
93
|
|
|
@@ -16,7 +16,8 @@ import { StylesAPI } from '../components/modules/api/styles';
|
|
|
16
16
|
import { ToolbarAPI } from '../components/modules/api/toolbar';
|
|
17
17
|
import { TooltipAPI } from '../components/modules/api/tooltip';
|
|
18
18
|
import { UiAPI } from '../components/modules/api/ui';
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
import { ThemeAPI } from '../components/modules/api/theme';
|
|
20
21
|
/** ./toolbar */
|
|
21
22
|
import { BlockSettings } from '../components/modules/toolbar/blockSettings';
|
|
22
23
|
import { Toolbar } from '../components/modules/toolbar/index';
|
|
@@ -39,7 +40,8 @@ import { Tools } from '../components/modules/tools';
|
|
|
39
40
|
import { UI } from '../components/modules/ui';
|
|
40
41
|
import { ToolsAPI } from '../components/modules/api/tools';
|
|
41
42
|
import { I18n } from '../components/modules/i18n';
|
|
42
|
-
|
|
43
|
+
|
|
44
|
+
import { ThemeManager } from '../components/modules/themeManager';
|
|
43
45
|
import { YjsManager } from '../components/modules/yjs';
|
|
44
46
|
|
|
45
47
|
export interface BlokModules {
|
|
@@ -62,7 +64,7 @@ export interface BlokModules {
|
|
|
62
64
|
ToolbarAPI: ToolbarAPI,
|
|
63
65
|
TooltipAPI: TooltipAPI,
|
|
64
66
|
UiAPI: UiAPI,
|
|
65
|
-
|
|
67
|
+
ThemeAPI: ThemeAPI,
|
|
66
68
|
|
|
67
69
|
// Toolbar Modules
|
|
68
70
|
BlockSettings: BlockSettings,
|
|
@@ -85,6 +87,6 @@ export interface BlokModules {
|
|
|
85
87
|
Saver: Saver,
|
|
86
88
|
Tools: Tools,
|
|
87
89
|
UI: UI,
|
|
88
|
-
|
|
90
|
+
ThemeManager: ThemeManager,
|
|
89
91
|
YjsManager: YjsManager,
|
|
90
92
|
}
|
package/types/api/index.d.ts
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme mode set by the user.
|
|
3
|
+
*/
|
|
4
|
+
export type ThemeMode = 'dark' | 'light' | 'auto';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolved theme after evaluating OS preference (for 'auto' mode).
|
|
8
|
+
*/
|
|
9
|
+
export type ResolvedTheme = 'dark' | 'light';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Describes the theme API.
|
|
13
|
+
*/
|
|
14
|
+
export interface Theme {
|
|
15
|
+
/**
|
|
16
|
+
* Returns the current theme mode.
|
|
17
|
+
*/
|
|
18
|
+
get(): ThemeMode;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Sets the theme mode.
|
|
22
|
+
*/
|
|
23
|
+
set(mode: ThemeMode): void;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Returns the resolved theme ('dark' or 'light'), evaluating OS preference if mode is 'auto'.
|
|
27
|
+
*/
|
|
28
|
+
getResolved(): ResolvedTheme;
|
|
29
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ThemeMode, ResolvedTheme } from '../api/theme';
|
|
1
2
|
import {ToolConstructable, ToolSettings} from '../tools';
|
|
2
3
|
import {API, LogLevels, OutputData} from '../index';
|
|
3
4
|
import {SanitizerConfig} from './sanitizer-config';
|
|
@@ -162,28 +163,17 @@ export interface BlokConfig {
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
/**
|
|
165
|
-
*
|
|
166
|
+
* Color theme mode.
|
|
167
|
+
* - 'auto': follow OS preference via prefers-color-scheme (default)
|
|
168
|
+
* - 'light': force light theme
|
|
169
|
+
* - 'dark': force dark theme
|
|
166
170
|
*/
|
|
167
|
-
|
|
171
|
+
theme?: ThemeMode;
|
|
168
172
|
|
|
169
173
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
174
|
+
* Called when the resolved theme changes (e.g. OS preference switches in 'auto' mode).
|
|
175
|
+
* Does not fire on initialization — only on subsequent changes.
|
|
176
|
+
* @param resolvedTheme - the resolved theme ('dark' or 'light')
|
|
173
177
|
*/
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* CSS max-width value for full width mode.
|
|
178
|
-
* Any valid CSS length, or 'none' for no constraint.
|
|
179
|
-
* Defaults to 'none'.
|
|
180
|
-
*/
|
|
181
|
-
fullWidth?: string;
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Called when the editor width mode changes.
|
|
185
|
-
* @param mode - the new mode ('narrow' or 'full')
|
|
186
|
-
* @param value - the resolved CSS max-width value
|
|
187
|
-
*/
|
|
188
|
-
onWidthChange?: (mode: 'narrow' | 'full', value: string) => void;
|
|
178
|
+
onThemeChange?: (resolvedTheme: ResolvedTheme) => void;
|
|
189
179
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -30,7 +30,9 @@ import {
|
|
|
30
30
|
I18n,
|
|
31
31
|
Ui,
|
|
32
32
|
Tools,
|
|
33
|
-
|
|
33
|
+
Theme,
|
|
34
|
+
ThemeMode,
|
|
35
|
+
ResolvedTheme,
|
|
34
36
|
} from './api';
|
|
35
37
|
|
|
36
38
|
import { OutputData } from './data-formats';
|
|
@@ -106,7 +108,9 @@ export {
|
|
|
106
108
|
I18n,
|
|
107
109
|
Ui,
|
|
108
110
|
Tools,
|
|
109
|
-
|
|
111
|
+
Theme,
|
|
112
|
+
ThemeMode,
|
|
113
|
+
ResolvedTheme,
|
|
110
114
|
} from './api';
|
|
111
115
|
export {
|
|
112
116
|
BlockMutationType,
|
|
@@ -144,7 +148,7 @@ export interface API {
|
|
|
144
148
|
i18n: I18n;
|
|
145
149
|
readOnly: ReadOnly;
|
|
146
150
|
ui: Ui;
|
|
147
|
-
|
|
151
|
+
theme: Theme;
|
|
148
152
|
rectangleSelection: {
|
|
149
153
|
cancelActiveSelection: () => void;
|
|
150
154
|
isRectActivated: () => boolean;
|
|
@@ -179,7 +183,7 @@ export class Blok {
|
|
|
179
183
|
public inlineToolbar: InlineToolbar;
|
|
180
184
|
public tooltip: Tooltip;
|
|
181
185
|
public readOnly: ReadOnly;
|
|
182
|
-
public
|
|
186
|
+
public theme: Theme;
|
|
183
187
|
constructor(configuration?: BlokConfig|string);
|
|
184
188
|
|
|
185
189
|
/**
|