@jackuait/blok 0.8.2 → 0.8.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.
Files changed (377) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/am-CHDDMHkd.mjs +16490 -0
  3. package/dist/chunks/ar-DoqfNqut.mjs +19245 -0
  4. package/dist/chunks/az-C34P9iEa.mjs +14694 -0
  5. package/dist/chunks/bg-jroXLY8Y.mjs +15432 -0
  6. package/dist/chunks/{blok-GAbVCHTV.mjs → blok-0-8moMz9.mjs} +2090 -2052
  7. package/dist/chunks/bn-BRI-WqxY.mjs +16150 -0
  8. package/dist/chunks/bs-CCGUpNHu.mjs +12536 -0
  9. package/dist/chunks/{constants-CyDHDZyH.mjs → constants-PWnlOOrQ.mjs} +211 -172
  10. package/dist/chunks/cs-D5qZOGuc.mjs +22809 -0
  11. package/dist/chunks/da-DrJ7W37K.mjs +14573 -0
  12. package/dist/chunks/de-BW6-kp2c.mjs +16366 -0
  13. package/dist/chunks/el-C-Vc_Otu.mjs +16339 -0
  14. package/dist/chunks/es-B6fI5K9i.mjs +13597 -0
  15. package/dist/chunks/et-BhVlZ-Yz.mjs +14747 -0
  16. package/dist/chunks/fa-D55Ijdqa.mjs +16368 -0
  17. package/dist/chunks/fi-jNLjhKUQ.mjs +14408 -0
  18. package/dist/chunks/fil-DYd0T5aX.mjs +15915 -0
  19. package/dist/chunks/fr-yxy5xWw_.mjs +17010 -0
  20. package/dist/chunks/gu-CcY_LJe7.mjs +19021 -0
  21. package/dist/chunks/he-DL9s7wNw.mjs +15047 -0
  22. package/dist/chunks/hi-C8eGXgw5.mjs +15946 -0
  23. package/dist/chunks/hr-DLpybOhU.mjs +15099 -0
  24. package/dist/chunks/hu-BkT0gT00.mjs +16564 -0
  25. package/dist/chunks/hy-CVFDCp2S.mjs +12823 -0
  26. package/dist/chunks/{i18next-loader-p-7ioTwr.mjs → i18next-loader-BCAGutUy.mjs} +2 -2
  27. package/dist/chunks/id-0P4W9Az0.mjs +16690 -0
  28. package/dist/chunks/it-mLY6_uoW.mjs +19054 -0
  29. package/dist/chunks/ja-7RkeRNWG.mjs +15708 -0
  30. package/dist/chunks/ka-C7Lx-Qsh.mjs +13049 -0
  31. package/dist/chunks/km-Q8udaraH.mjs +12319 -0
  32. package/dist/chunks/kn-BiETM-iq.mjs +19123 -0
  33. package/dist/chunks/ko-tiB80pF1.mjs +17322 -0
  34. package/dist/chunks/ku-CY-OABkR.mjs +236 -0
  35. package/dist/chunks/{lightweight-i18n-BPeH69Dl.mjs → lightweight-i18n-CNUuUkuo.mjs} +31 -1
  36. package/dist/chunks/lo-CTBhEnyk.mjs +13576 -0
  37. package/dist/chunks/lt-BHKHEtqK.mjs +14587 -0
  38. package/dist/chunks/lv-DWxgtfUg.mjs +15042 -0
  39. package/dist/chunks/{messages-BHf_VcXb2.mjs → messages-2i0z2hFq2.mjs} +32 -2
  40. package/dist/{messages-8zo-T-Nx2.mjs → chunks/messages-4epWYTzK.mjs} +32 -2
  41. package/dist/chunks/{messages-DgZnRQRS.mjs → messages-B-x11A7Z.mjs} +32 -2
  42. package/dist/chunks/{messages-C03I_oR-2.mjs → messages-B1mCwtgm2.mjs} +32 -2
  43. package/dist/{messages-C5hD5pSd2.mjs → chunks/messages-B2Xnfn7m2.mjs} +32 -2
  44. package/dist/chunks/{messages-B-i-d1Bc.mjs → messages-B38lWmza.mjs} +32 -2
  45. package/dist/{messages-BRC9E_sp.mjs → chunks/messages-B3VMWaO8.mjs} +32 -2
  46. package/dist/{messages-BrcgNZOJ.mjs → chunks/messages-B6n2OYKJ.mjs} +32 -2
  47. package/dist/chunks/{messages-CIugNDDO2.mjs → messages-B847kJa02.mjs} +32 -2
  48. package/dist/chunks/{messages-CH_cexo62.mjs → messages-B8nL5cPA2.mjs} +32 -2
  49. package/dist/chunks/{messages-Bdk5tBNu.mjs → messages-BHMUmX3N.mjs} +32 -2
  50. package/dist/chunks/{messages-LL3Tflph.mjs → messages-BN78Am3l2.mjs} +32 -2
  51. package/dist/chunks/{messages-BIrkzbBP.mjs → messages-BRa1Itk_.mjs} +32 -2
  52. package/dist/chunks/{messages-BtS6JWMT.mjs → messages-BleThZm5.mjs} +32 -2
  53. package/dist/{messages-DHJ1fZLL.mjs → chunks/messages-Bo2PcQoc.mjs} +32 -2
  54. package/dist/{messages-D5rnT-BC.mjs → chunks/messages-Bqk7cuZY.mjs} +32 -2
  55. package/dist/chunks/{messages-Di7mfvB8.mjs → messages-BrsB1FRe.mjs} +32 -2
  56. package/dist/{messages-CsmTziC6.mjs → chunks/messages-ByeBRHpJ.mjs} +32 -2
  57. package/dist/{messages-C7Rz00Tp.mjs → chunks/messages-C35b_LVM.mjs} +32 -2
  58. package/dist/{messages-Co26RSCV2.mjs → chunks/messages-CAH4L_Mq2.mjs} +32 -2
  59. package/dist/chunks/{messages-BMzmli1K.mjs → messages-CBa6-NHn.mjs} +32 -2
  60. package/dist/chunks/{messages-wUoSWFsJ2.mjs → messages-CCywXuFz2.mjs} +32 -2
  61. package/dist/chunks/{messages-4OvVdaG52.mjs → messages-CDZrOiaR.mjs} +32 -2
  62. package/dist/{messages-C92tAUYT2.mjs → chunks/messages-CEVMB1TN2.mjs} +32 -2
  63. package/dist/{messages-CHeucLGl2.mjs → chunks/messages-CF7WlKOY.mjs} +32 -2
  64. package/dist/{messages-D_-rh8gl.mjs → chunks/messages-CLcwMAAe.mjs} +32 -2
  65. package/dist/chunks/{messages-Df69rfTF2.mjs → messages-CTGjizuJ2.mjs} +32 -2
  66. package/dist/chunks/{messages-Ehx9YYeb2.mjs → messages-CTI66ZU52.mjs} +32 -2
  67. package/dist/{messages-C9LsEUfG.mjs → chunks/messages-CTtFH-AE.mjs} +32 -2
  68. package/dist/{messages-BB8umWL1.mjs → chunks/messages-CbilQw5o2.mjs} +32 -2
  69. package/dist/chunks/{messages-BAgTIgPH.mjs → messages-CiSiPyKp.mjs} +32 -2
  70. package/dist/chunks/{messages-5thhSeME.mjs → messages-ClD_3Kmk.mjs} +32 -2
  71. package/dist/chunks/{messages--aM83pib2.mjs → messages-CqoOMgIb2.mjs} +32 -2
  72. package/dist/chunks/{messages-EDTq4Q52.mjs → messages-Cqxe2gIN.mjs} +32 -2
  73. package/dist/chunks/{messages-SsrFJhTN.mjs → messages-CxKX6wTt.mjs} +32 -2
  74. package/dist/chunks/{messages-DUp8NnKT.mjs → messages-CyrZJ9dG.mjs} +32 -2
  75. package/dist/{messages-EIeWKoc5.mjs → chunks/messages-D1eXOdyJ.mjs} +32 -2
  76. package/dist/chunks/{messages-ohtcmr1w.mjs → messages-D2QcrPYF.mjs} +32 -2
  77. package/dist/{messages-DV29fJMD2.mjs → chunks/messages-D6EtVUzk2.mjs} +32 -2
  78. package/dist/{messages-C4HpNHfK.mjs → chunks/messages-D7qp-JvC.mjs} +32 -2
  79. package/dist/chunks/{messages-Dr-Ig3sw.mjs → messages-DAhzpf-j.mjs} +32 -2
  80. package/dist/chunks/{messages-DKChC8Qu.mjs → messages-DEVxqfH0.mjs} +32 -2
  81. package/dist/{messages-CkIRmpfZ2.mjs → chunks/messages-DHJIlD2m.mjs} +32 -2
  82. package/dist/{messages-CmoTIebG2.mjs → chunks/messages-DJ_gZym52.mjs} +32 -2
  83. package/dist/{messages-Cu7Lr1wp.mjs → chunks/messages-DMENc4jZ.mjs} +32 -2
  84. package/dist/chunks/{messages-BAC7nLeM.mjs → messages-DVDFAJaw.mjs} +32 -2
  85. package/dist/chunks/{messages-Co4WFeQ8.mjs → messages-DYQ87v5m.mjs} +32 -2
  86. package/dist/chunks/{messages-BO_jtRbZ2.mjs → messages-Dc2wd0BC2.mjs} +32 -2
  87. package/dist/{messages-F7cRf-20.mjs → chunks/messages-DlSDBHih.mjs} +32 -2
  88. package/dist/chunks/{messages-Nz8C7Znm.mjs → messages-Dmxk7uOK.mjs} +32 -2
  89. package/dist/chunks/{messages-8pf7gRQm2.mjs → messages-Dqoj0eKD2.mjs} +32 -2
  90. package/dist/{messages-BD_U2EnE.mjs → chunks/messages-DvUNk-e7.mjs} +32 -2
  91. package/dist/{messages-CTFwu5-h2.mjs → chunks/messages-DvZa_OtS2.mjs} +32 -2
  92. package/dist/chunks/{messages-CSpfBhlK2.mjs → messages-Dxa27UhV2.mjs} +32 -2
  93. package/dist/chunks/{messages-D14soBOO.mjs → messages-JQR7Z2f0.mjs} +32 -2
  94. package/dist/{messages-bRqMCja-2.mjs → chunks/messages-K453lCht2.mjs} +32 -2
  95. package/dist/{messages-B9ythxux.mjs → chunks/messages-Kqu8QyYy2.mjs} +32 -2
  96. package/dist/{messages-CWzET_9H2.mjs → chunks/messages-LGqROvB5.mjs} +32 -2
  97. package/dist/{messages-JwMkLben.mjs → chunks/messages-LiQ7ni4i2.mjs} +32 -2
  98. package/dist/{messages-B21zLG6b.mjs → chunks/messages-PDaWSrFT.mjs} +32 -2
  99. package/dist/{messages-ouO9js8Z.mjs → chunks/messages-SOew8O6I.mjs} +32 -2
  100. package/dist/{messages-SepwOOcg.mjs → chunks/messages-cjqgX4JV2.mjs} +32 -2
  101. package/dist/chunks/{messages-BARPMN7R.mjs → messages-fdO2V2XC.mjs} +32 -2
  102. package/dist/chunks/{messages-DDpgr0B1.mjs → messages-lu4RI1A3.mjs} +32 -2
  103. package/dist/{messages-D_cAZ4Ic2.mjs → chunks/messages-qt_Tsj1u2.mjs} +32 -2
  104. package/dist/chunks/{messages-BDTgiBJY2.mjs → messages-uQOWdLDn2.mjs} +32 -2
  105. package/dist/chunks/{messages-FCmAVA792.mjs → messages-xG65ERBM2.mjs} +32 -2
  106. package/dist/chunks/mk-BjookGdx.mjs +16800 -0
  107. package/dist/chunks/ml-L-NnZcp9.mjs +13558 -0
  108. package/dist/chunks/mn-OMWi7Hl_.mjs +12107 -0
  109. package/dist/chunks/mr-B6JPzITo.mjs +17324 -0
  110. package/dist/chunks/ms-CG3S-sPB.mjs +14999 -0
  111. package/dist/chunks/my-BLAmGfhT.mjs +12534 -0
  112. package/dist/chunks/native-BPcABu9z.mjs +107 -0
  113. package/dist/chunks/ne-D1JHLfYw.mjs +13248 -0
  114. package/dist/chunks/nl-Ca7Q8FnY.mjs +16693 -0
  115. package/dist/chunks/no-Coxcohcz.mjs +14767 -0
  116. package/dist/chunks/pa-CCaXqpaI.mjs +17220 -0
  117. package/dist/chunks/pl-Cl_fAZ84.mjs +17221 -0
  118. package/dist/chunks/ps-WD5qGAWy.mjs +12185 -0
  119. package/dist/chunks/pt-C4zvLfvq.mjs +16334 -0
  120. package/dist/chunks/ro-DbefHcmM.mjs +18857 -0
  121. package/dist/chunks/ru-uU1J14jd.mjs +17485 -0
  122. package/dist/chunks/sd-DKu368Ip.mjs +10889 -0
  123. package/dist/chunks/si-BsJCiPkZ.mjs +12721 -0
  124. package/dist/chunks/sk-CD-a3SN6.mjs +19081 -0
  125. package/dist/chunks/sl-CXhrPJe_.mjs +15682 -0
  126. package/dist/chunks/sq-CTctCoFQ.mjs +15278 -0
  127. package/dist/chunks/sr-BZkhBwXj.mjs +14524 -0
  128. package/dist/chunks/sv-NmRZb_xi.mjs +12855 -0
  129. package/dist/chunks/sw-Be5ik3H6.mjs +14315 -0
  130. package/dist/chunks/ta-DsXh6neL.mjs +16836 -0
  131. package/dist/chunks/te-CwpCbM8M.mjs +18588 -0
  132. package/dist/chunks/th-CcZ15OLk.mjs +13894 -0
  133. package/dist/chunks/{tools-CW1RAIvp.mjs → tools-BBmJ8jqK.mjs} +1417 -761
  134. package/dist/chunks/tr-q3bTgvhW.mjs +16318 -0
  135. package/dist/chunks/ug-919EhLsL.mjs +9816 -0
  136. package/dist/chunks/uk-aNMEzd0Y.mjs +16725 -0
  137. package/dist/chunks/ur-BwQI77sh.mjs +18051 -0
  138. package/dist/chunks/vi-Dxq806-F.mjs +14006 -0
  139. package/dist/chunks/zh-BcHuy1Ti.mjs +16334 -0
  140. package/dist/full.mjs +10 -10
  141. package/dist/locales.mjs +98 -68
  142. package/dist/{messages-qV14y_oA2.mjs → messages--PYnorLu2.mjs} +32 -2
  143. package/dist/{messages-Cy3Ne_M9.mjs → messages-B2X5gO-s.mjs} +32 -2
  144. package/dist/{chunks/messages-D1SqLcxI2.mjs → messages-BD3lSUU_.mjs} +32 -2
  145. package/dist/{chunks/messages-CIZkNCpW.mjs → messages-BFbAM_pK2.mjs} +32 -2
  146. package/dist/{chunks/messages-CIBuZccC.mjs → messages-BMUQ7kA62.mjs} +32 -2
  147. package/dist/{messages-CrWsU4Xw2.mjs → messages-BR1Hlhdc2.mjs} +32 -2
  148. package/dist/{chunks/messages-D2uBlGXR2.mjs → messages-BRJBZB-H2.mjs} +32 -2
  149. package/dist/{chunks/messages-OIelQDL32.mjs → messages-BTFWPbHk2.mjs} +32 -2
  150. package/dist/{messages-EwoT2jof.mjs → messages-BXvE3YB4.mjs} +32 -2
  151. package/dist/{messages-CqNzlpWi.mjs → messages-BZg8xxIT.mjs} +32 -2
  152. package/dist/{messages-BAZK-8Zb.mjs → messages-B_idm-Pp.mjs} +32 -2
  153. package/dist/{messages-LyzjEEIj2.mjs → messages-BcrsCh5-2.mjs} +32 -2
  154. package/dist/{chunks/messages-DPoPrTiZ.mjs → messages-Bf0eqjDJ.mjs} +32 -2
  155. package/dist/{messages-CKmmJ9tW.mjs → messages-Bgu3IB_k.mjs} +32 -2
  156. package/dist/{chunks/messages-DeLzropc.mjs → messages-Bkv2sk7Y.mjs} +32 -2
  157. package/dist/{messages-rM6YFLZH.mjs → messages-Bn77ieXA.mjs} +32 -2
  158. package/dist/{messages-CTPFrtK92.mjs → messages-Buf_f_-32.mjs} +32 -2
  159. package/dist/{messages-ouRGTAKo2.mjs → messages-BvIBkUCG2.mjs} +32 -2
  160. package/dist/{chunks/messages-DVg69mRj.mjs → messages-Bw0kGTAV.mjs} +32 -2
  161. package/dist/{chunks/messages-CWp6-Y8f2.mjs → messages-C5MKR_WT2.mjs} +32 -2
  162. package/dist/{chunks/messages-N72K1hw3.mjs → messages-C6UkeZ0y.mjs} +32 -2
  163. package/dist/{messages-CzZAfGif.mjs → messages-C9AvcT0K.mjs} +32 -2
  164. package/dist/{chunks/messages-D0IKicWg.mjs → messages-CC596_yM.mjs} +32 -2
  165. package/dist/{messages-DiSeSE8p.mjs → messages-CGD9LR8l.mjs} +32 -2
  166. package/dist/{messages-Tx25QErT.mjs → messages-CH8tCpAX.mjs} +32 -2
  167. package/dist/{chunks/messages-DfsHFEWa.mjs → messages-CIGa1j8-2.mjs} +32 -2
  168. package/dist/{messages-TI0u6Ked.mjs → messages-CJ5pCncM.mjs} +32 -2
  169. package/dist/{chunks/messages-DEGzGmEQ2.mjs → messages-CJd52qP7.mjs} +32 -2
  170. package/dist/{messages-Bm8I_Li12.mjs → messages-CWIigMhw2.mjs} +32 -2
  171. package/dist/{messages-JZhs_0pf.mjs → messages-CY_Fj715.mjs} +32 -2
  172. package/dist/{messages-BSLYh59S.mjs → messages-C_YAmOyQ.mjs} +32 -2
  173. package/dist/{messages-CIxT1nSh.mjs → messages-CjCjr0wW.mjs} +32 -2
  174. package/dist/{messages-Dr9L1psl.mjs → messages-CqbeAhjH.mjs} +32 -2
  175. package/dist/{messages-BTR3QlIb2.mjs → messages-Cr2hTJyi2.mjs} +32 -2
  176. package/dist/{chunks/messages-BKjLgO5d.mjs → messages-Cuw_6akN.mjs} +32 -2
  177. package/dist/{messages-lEyiemqU2.mjs → messages-D0KBToO12.mjs} +32 -2
  178. package/dist/{messages-1_FCq0It.mjs → messages-D2Xo8E0P.mjs} +32 -2
  179. package/dist/{messages-Djhu5RJd.mjs → messages-D5Uk_qYf.mjs} +32 -2
  180. package/dist/{messages-CHWfj4ik.mjs → messages-D7dJJ7dx.mjs} +32 -2
  181. package/dist/{chunks/messages-DmrsEYQm2.mjs → messages-D8SS2hOs2.mjs} +32 -2
  182. package/dist/{chunks/messages-DQOk-dTH.mjs → messages-D9a5iSFC2.mjs} +32 -2
  183. package/dist/{messages-BSwhWcYw.mjs → messages-DAjtVSb6.mjs} +32 -2
  184. package/dist/{messages-BZXBdD_S2.mjs → messages-DBuHaabF2.mjs} +32 -2
  185. package/dist/{chunks/messages-CuRN1_ep2.mjs → messages-DCjAu6M72.mjs} +32 -2
  186. package/dist/{messages-CKX9iXIb2.mjs → messages-DFlT_TM02.mjs} +32 -2
  187. package/dist/{chunks/messages-DlM9TmqS2.mjs → messages-DPECmAwT.mjs} +32 -2
  188. package/dist/{chunks/messages-DhGHk-Ma2.mjs → messages-DR2Lgl002.mjs} +32 -2
  189. package/dist/{messages-DDiP6yex.mjs → messages-DUPXmcZh.mjs} +32 -2
  190. package/dist/{chunks/messages-CoRQE_Jc.mjs → messages-DVReQ5EC.mjs} +32 -2
  191. package/dist/{chunks/messages-BvlSf_pu.mjs → messages-DaZkRhoM.mjs} +32 -2
  192. package/dist/{chunks/messages-B9zocutJ.mjs → messages-Dc93MR86.mjs} +32 -2
  193. package/dist/{messages-Dc7ZzqYN.mjs → messages-Dd4OTpH3.mjs} +32 -2
  194. package/dist/{chunks/messages-BsYzg2le.mjs → messages-DffJ5W5G.mjs} +32 -2
  195. package/dist/{messages-D8iCBMg7.mjs → messages-DjWAR34D.mjs} +32 -2
  196. package/dist/{messages-BzZ8LahA2.mjs → messages-DkaJV53s2.mjs} +32 -2
  197. package/dist/{chunks/messages-stUQR58d.mjs → messages-Dl7LQ_fI.mjs} +32 -2
  198. package/dist/{chunks/messages-B_fFjpX12.mjs → messages-DlEdd01l2.mjs} +32 -2
  199. package/dist/{chunks/messages-5ohIWynJ.mjs → messages-ItP2i78l.mjs} +32 -2
  200. package/dist/{messages-DDJOu049.mjs → messages-Oqm_fCLp.mjs} +32 -2
  201. package/dist/{chunks/messages-DrXNb1gu.mjs → messages-UpoT1AS6.mjs} +32 -2
  202. package/dist/{chunks/messages-COkQfKa72.mjs → messages-Z8dpjy_K2.mjs} +32 -2
  203. package/dist/{messages-mVLfVtQX2.mjs → messages-ierNgYE02.mjs} +32 -2
  204. package/dist/{messages-DToWAonn2.mjs → messages-ikSI7M732.mjs} +32 -2
  205. package/dist/{chunks/messages-DKCoHa5D.mjs → messages-olK9oNtb.mjs} +32 -2
  206. package/dist/{messages-CsnglxbV2.mjs → messages-rgXeOQMh2.mjs} +32 -2
  207. package/dist/{chunks/messages-CDJLoStb.mjs → messages-syo0DKqf.mjs} +32 -2
  208. package/dist/{chunks/messages-BgaGPFuy2.mjs → messages-tFDVfvWL.mjs} +32 -2
  209. package/dist/react.mjs +2 -2
  210. package/dist/tools.mjs +3 -3
  211. package/dist/vendor.LICENSE.txt +34 -0
  212. package/package.json +3 -1
  213. package/src/components/i18n/locales/am/messages.json +32 -2
  214. package/src/components/i18n/locales/ar/messages.json +32 -2
  215. package/src/components/i18n/locales/az/messages.json +32 -2
  216. package/src/components/i18n/locales/bg/messages.json +32 -2
  217. package/src/components/i18n/locales/bn/messages.json +32 -2
  218. package/src/components/i18n/locales/bs/messages.json +32 -2
  219. package/src/components/i18n/locales/cs/messages.json +32 -2
  220. package/src/components/i18n/locales/da/messages.json +32 -2
  221. package/src/components/i18n/locales/de/messages.json +32 -2
  222. package/src/components/i18n/locales/dv/messages.json +32 -2
  223. package/src/components/i18n/locales/el/messages.json +32 -2
  224. package/src/components/i18n/locales/en/messages.json +31 -1
  225. package/src/components/i18n/locales/es/messages.json +32 -2
  226. package/src/components/i18n/locales/et/messages.json +32 -2
  227. package/src/components/i18n/locales/fa/messages.json +32 -2
  228. package/src/components/i18n/locales/fi/messages.json +32 -2
  229. package/src/components/i18n/locales/fil/messages.json +32 -2
  230. package/src/components/i18n/locales/fr/messages.json +32 -2
  231. package/src/components/i18n/locales/gu/messages.json +32 -2
  232. package/src/components/i18n/locales/he/messages.json +32 -2
  233. package/src/components/i18n/locales/hi/messages.json +32 -2
  234. package/src/components/i18n/locales/hr/messages.json +32 -2
  235. package/src/components/i18n/locales/hu/messages.json +32 -2
  236. package/src/components/i18n/locales/hy/messages.json +32 -2
  237. package/src/components/i18n/locales/id/messages.json +32 -2
  238. package/src/components/i18n/locales/it/messages.json +32 -2
  239. package/src/components/i18n/locales/ja/messages.json +32 -2
  240. package/src/components/i18n/locales/ka/messages.json +32 -2
  241. package/src/components/i18n/locales/km/messages.json +32 -2
  242. package/src/components/i18n/locales/kn/messages.json +32 -2
  243. package/src/components/i18n/locales/ko/messages.json +32 -2
  244. package/src/components/i18n/locales/ku/messages.json +32 -2
  245. package/src/components/i18n/locales/lo/messages.json +32 -2
  246. package/src/components/i18n/locales/lt/messages.json +32 -2
  247. package/src/components/i18n/locales/lv/messages.json +32 -2
  248. package/src/components/i18n/locales/mk/messages.json +32 -2
  249. package/src/components/i18n/locales/ml/messages.json +32 -2
  250. package/src/components/i18n/locales/mn/messages.json +32 -2
  251. package/src/components/i18n/locales/mr/messages.json +32 -2
  252. package/src/components/i18n/locales/ms/messages.json +32 -2
  253. package/src/components/i18n/locales/my/messages.json +32 -2
  254. package/src/components/i18n/locales/ne/messages.json +32 -2
  255. package/src/components/i18n/locales/nl/messages.json +32 -2
  256. package/src/components/i18n/locales/no/messages.json +32 -2
  257. package/src/components/i18n/locales/pa/messages.json +32 -2
  258. package/src/components/i18n/locales/pl/messages.json +32 -2
  259. package/src/components/i18n/locales/ps/messages.json +32 -2
  260. package/src/components/i18n/locales/pt/messages.json +32 -2
  261. package/src/components/i18n/locales/ro/messages.json +32 -2
  262. package/src/components/i18n/locales/ru/messages.json +32 -2
  263. package/src/components/i18n/locales/sd/messages.json +32 -2
  264. package/src/components/i18n/locales/si/messages.json +32 -2
  265. package/src/components/i18n/locales/sk/messages.json +32 -2
  266. package/src/components/i18n/locales/sl/messages.json +32 -2
  267. package/src/components/i18n/locales/sq/messages.json +32 -2
  268. package/src/components/i18n/locales/sr/messages.json +32 -2
  269. package/src/components/i18n/locales/sv/messages.json +32 -2
  270. package/src/components/i18n/locales/sw/messages.json +32 -2
  271. package/src/components/i18n/locales/ta/messages.json +32 -2
  272. package/src/components/i18n/locales/te/messages.json +32 -2
  273. package/src/components/i18n/locales/th/messages.json +32 -2
  274. package/src/components/i18n/locales/tr/messages.json +32 -2
  275. package/src/components/i18n/locales/ug/messages.json +32 -2
  276. package/src/components/i18n/locales/uk/messages.json +32 -2
  277. package/src/components/i18n/locales/ur/messages.json +32 -2
  278. package/src/components/i18n/locales/vi/messages.json +32 -2
  279. package/src/components/i18n/locales/yi/messages.json +32 -2
  280. package/src/components/i18n/locales/zh/messages.json +32 -2
  281. package/src/components/icons/index.ts +98 -0
  282. package/src/components/modules/api/i18n.ts +1 -0
  283. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +22 -5
  284. package/src/components/modules/blockManager/operations.ts +1 -0
  285. package/src/components/modules/toolbar/index.ts +102 -7
  286. package/src/components/modules/toolbar/plus-button.ts +17 -5
  287. package/src/components/modules/uiControllers/controllers/blockHover.ts +36 -9
  288. package/src/components/modules/uiControllers/handlers/touch.ts +20 -8
  289. package/src/components/tools/factory.ts +4 -0
  290. package/src/components/ui/toolbox.ts +38 -3
  291. package/src/components/utils/popover/popover-desktop.ts +48 -71
  292. package/src/components/utils/popover/popover-position.ts +105 -0
  293. package/src/stories/MarkerColors.stories.ts +8 -1
  294. package/src/styles/main.css +121 -17
  295. package/src/tools/callout/block-operations.ts +17 -0
  296. package/src/tools/callout/callout-keyboard.ts +45 -0
  297. package/src/tools/callout/constants.ts +30 -0
  298. package/src/tools/callout/dom-builder.ts +53 -0
  299. package/src/tools/callout/emoji-picker/emoji-data.ts +105 -0
  300. package/src/tools/callout/emoji-picker/emoji-locale.ts +165 -0
  301. package/src/tools/callout/emoji-picker/index.ts +762 -0
  302. package/src/tools/callout/emoji-picker/locales/am.json +1 -0
  303. package/src/tools/callout/emoji-picker/locales/ar.json +1 -0
  304. package/src/tools/callout/emoji-picker/locales/az.json +1 -0
  305. package/src/tools/callout/emoji-picker/locales/bg.json +1 -0
  306. package/src/tools/callout/emoji-picker/locales/bn.json +1 -0
  307. package/src/tools/callout/emoji-picker/locales/bs.json +1 -0
  308. package/src/tools/callout/emoji-picker/locales/cs.json +1 -0
  309. package/src/tools/callout/emoji-picker/locales/da.json +1 -0
  310. package/src/tools/callout/emoji-picker/locales/de.json +1 -0
  311. package/src/tools/callout/emoji-picker/locales/el.json +1 -0
  312. package/src/tools/callout/emoji-picker/locales/es.json +1 -0
  313. package/src/tools/callout/emoji-picker/locales/et.json +1 -0
  314. package/src/tools/callout/emoji-picker/locales/fa.json +1 -0
  315. package/src/tools/callout/emoji-picker/locales/fi.json +1 -0
  316. package/src/tools/callout/emoji-picker/locales/fil.json +1 -0
  317. package/src/tools/callout/emoji-picker/locales/fr.json +1 -0
  318. package/src/tools/callout/emoji-picker/locales/gu.json +1 -0
  319. package/src/tools/callout/emoji-picker/locales/he.json +1 -0
  320. package/src/tools/callout/emoji-picker/locales/hi.json +1 -0
  321. package/src/tools/callout/emoji-picker/locales/hr.json +1 -0
  322. package/src/tools/callout/emoji-picker/locales/hu.json +1 -0
  323. package/src/tools/callout/emoji-picker/locales/hy.json +1 -0
  324. package/src/tools/callout/emoji-picker/locales/id.json +1 -0
  325. package/src/tools/callout/emoji-picker/locales/it.json +1 -0
  326. package/src/tools/callout/emoji-picker/locales/ja.json +1 -0
  327. package/src/tools/callout/emoji-picker/locales/ka.json +1 -0
  328. package/src/tools/callout/emoji-picker/locales/km.json +1 -0
  329. package/src/tools/callout/emoji-picker/locales/kn.json +1 -0
  330. package/src/tools/callout/emoji-picker/locales/ko.json +1 -0
  331. package/src/tools/callout/emoji-picker/locales/ku.json +1 -0
  332. package/src/tools/callout/emoji-picker/locales/lo.json +1 -0
  333. package/src/tools/callout/emoji-picker/locales/lt.json +1 -0
  334. package/src/tools/callout/emoji-picker/locales/lv.json +1 -0
  335. package/src/tools/callout/emoji-picker/locales/mk.json +1 -0
  336. package/src/tools/callout/emoji-picker/locales/ml.json +1 -0
  337. package/src/tools/callout/emoji-picker/locales/mn.json +1 -0
  338. package/src/tools/callout/emoji-picker/locales/mr.json +1 -0
  339. package/src/tools/callout/emoji-picker/locales/ms.json +1 -0
  340. package/src/tools/callout/emoji-picker/locales/my.json +1 -0
  341. package/src/tools/callout/emoji-picker/locales/ne.json +1 -0
  342. package/src/tools/callout/emoji-picker/locales/nl.json +1 -0
  343. package/src/tools/callout/emoji-picker/locales/no.json +1 -0
  344. package/src/tools/callout/emoji-picker/locales/pa.json +1 -0
  345. package/src/tools/callout/emoji-picker/locales/pl.json +1 -0
  346. package/src/tools/callout/emoji-picker/locales/ps.json +1 -0
  347. package/src/tools/callout/emoji-picker/locales/pt.json +1 -0
  348. package/src/tools/callout/emoji-picker/locales/ro.json +1 -0
  349. package/src/tools/callout/emoji-picker/locales/ru.json +1 -0
  350. package/src/tools/callout/emoji-picker/locales/sd.json +1 -0
  351. package/src/tools/callout/emoji-picker/locales/si.json +1 -0
  352. package/src/tools/callout/emoji-picker/locales/sk.json +1 -0
  353. package/src/tools/callout/emoji-picker/locales/sl.json +1 -0
  354. package/src/tools/callout/emoji-picker/locales/sq.json +1 -0
  355. package/src/tools/callout/emoji-picker/locales/sr.json +1 -0
  356. package/src/tools/callout/emoji-picker/locales/sv.json +1 -0
  357. package/src/tools/callout/emoji-picker/locales/sw.json +1 -0
  358. package/src/tools/callout/emoji-picker/locales/ta.json +1 -0
  359. package/src/tools/callout/emoji-picker/locales/te.json +1 -0
  360. package/src/tools/callout/emoji-picker/locales/th.json +1 -0
  361. package/src/tools/callout/emoji-picker/locales/tr.json +1 -0
  362. package/src/tools/callout/emoji-picker/locales/ug.json +1 -0
  363. package/src/tools/callout/emoji-picker/locales/uk.json +1 -0
  364. package/src/tools/callout/emoji-picker/locales/ur.json +1 -0
  365. package/src/tools/callout/emoji-picker/locales/vi.json +1 -0
  366. package/src/tools/callout/emoji-picker/locales/zh.json +1 -0
  367. package/src/tools/callout/index.ts +338 -0
  368. package/src/tools/callout/types.ts +11 -0
  369. package/src/tools/header/header-toggle-keyboard.ts +3 -2
  370. package/src/tools/header/index.ts +1 -1
  371. package/src/tools/index.ts +2 -0
  372. package/src/tools/toggle/index.ts +1 -1
  373. package/src/tools/toggle/toggle-keyboard.ts +29 -1
  374. package/types/api/i18n.d.ts +7 -0
  375. package/types/tools-entry.d.ts +0 -4
  376. /package/dist/chunks/{i18next-DymC16cN.mjs → i18next-Ch0gVA3V.mjs} +0 -0
  377. /package/dist/chunks/{notifier-BqYxvxnV.mjs → notifier-Butv4Dvo.mjs} +0 -0
@@ -166,11 +166,21 @@ export class PlusButtonHandler {
166
166
  return;
167
167
  }
168
168
 
169
- // Determine target block: reuse empty/slash paragraph, or create new one
169
+ // Determine target block: reuse any empty block, or create a new one
170
170
  const hoveredBlock = this.hoveredBlockInternal;
171
171
  const isParagraph = hoveredBlock?.name === 'paragraph';
172
172
  const startsWithSlash = isParagraph && hoveredBlock.pluginsContent.textContent?.startsWith('/');
173
- const isEmptyParagraph = isParagraph && hoveredBlock.isEmpty;
173
+
174
+ // Reuse the hovered block if it's empty (any type, not just paragraphs).
175
+ // If hoveredBlock is not empty (e.g. a table), check if the focused block
176
+ // is empty and nested inside it (e.g. an empty paragraph in a table cell).
177
+ const currentBlock = BlockManager.currentBlock ?? null;
178
+ const hoveredIsEmpty = hoveredBlock !== null && hoveredBlock.isEmpty;
179
+ const nestedCurrentBlockIsEmpty = !hoveredIsEmpty && currentBlock !== null
180
+ && currentBlock !== hoveredBlock && currentBlock.isEmpty
181
+ && hoveredBlock !== null && hoveredBlock.holder.contains(currentBlock.holder);
182
+ const emptyBlockToReuse: Block | null =
183
+ (hoveredIsEmpty && hoveredBlock) || (nestedCurrentBlockIsEmpty && currentBlock) || null;
174
184
 
175
185
  // Calculate insert index based on direction
176
186
  const hoveredBlockIndex = hoveredBlock !== null
@@ -191,15 +201,17 @@ export class PlusButtonHandler {
191
201
  : 0;
192
202
  const insertIndex = baseInsertIndex + (firstNonNestedOffset === -1 ? blocksAfterInsert.length : firstNonNestedOffset);
193
203
 
194
- const targetBlock = isEmptyParagraph || startsWithSlash
204
+ // startsWithSlash is only true when isParagraph is true, which requires
205
+ // hoveredBlock to be non-null. TypeScript narrows this correctly.
206
+ const targetBlock: Block = startsWithSlash
195
207
  ? hoveredBlock
196
- : BlockManager.insertDefaultBlockAtIndex(insertIndex, true);
208
+ : (emptyBlockToReuse ?? BlockManager.insertDefaultBlockAtIndex(insertIndex, true));
197
209
 
198
210
  // The DOM insertion may place the new block's holder inside a nested
199
211
  // container (e.g. a table cell) because the previous block in the array
200
212
  // is inside another block's DOM. Move the holder to be a sibling after
201
213
  // the hovered block so it becomes a top-level block.
202
- if (targetBlock !== hoveredBlock && isNested(targetBlock)) {
214
+ if (targetBlock !== hoveredBlock && emptyBlockToReuse === null && isNested(targetBlock)) {
203
215
  hoveredBlock?.holder.after(targetBlock.holder);
204
216
  }
205
217
 
@@ -67,12 +67,39 @@ export class BlockHoverController extends Controller {
67
67
  const closestBlockWrapper = (event.target as Element | null)?.closest('[data-blok-testid="block-wrapper"]');
68
68
 
69
69
  /**
70
- * If the hovered block is inside a table cell, resolve to the table block instead.
71
- * Without this, the toolbar hides itself for nested cell blocks and the table's
70
+ * When the cursor is in the gap between children inside a [data-blok-child-toolbar]
71
+ * container, the closest block-wrapper is the parent not a child.
72
+ * Skip the event so the toolbar stays on the previous child block.
73
+ */
74
+ const targetChildToolbar = (event.target as Element | null)?.closest('[data-blok-child-toolbar]');
75
+
76
+ if (targetChildToolbar && closestBlockWrapper && !targetChildToolbar.contains(closestBlockWrapper)) {
77
+ return;
78
+ }
79
+
80
+ /**
81
+ * If the hovered block is inside a table cell or toggle-children container,
82
+ * resolve to the parent block instead.
83
+ * Without this, the toolbar targets nested child blocks and the parent's
72
84
  * block tune settings become inaccessible.
85
+ *
86
+ * Containers with [data-blok-child-toolbar] opt out of parent resolution,
87
+ * allowing non-first children to have independent toolbars (e.g. callout blocks).
88
+ * The first child still resolves to parent so the container's own controls display.
73
89
  */
74
- const hoveredBlockElement = closestBlockWrapper?.closest('[data-blok-table-cell-blocks]')
75
- ? closestBlockWrapper.closest('[data-blok-table-cell-blocks]')?.closest('[data-blok-testid="block-wrapper"]') ?? null
90
+ const alwaysResolveContainer = closestBlockWrapper?.closest(
91
+ '[data-blok-table-cell-blocks], [data-blok-toggle-children]:not([data-blok-child-toolbar])'
92
+ );
93
+ const childToolbarContainer = !alwaysResolveContainer
94
+ ? closestBlockWrapper?.closest('[data-blok-child-toolbar]') ?? null
95
+ : null;
96
+ const isFirstChildOfContainer = childToolbarContainer !== null
97
+ && childToolbarContainer.querySelector(':scope > [data-blok-testid="block-wrapper"]') === closestBlockWrapper;
98
+
99
+ const nestedContainer = alwaysResolveContainer
100
+ ?? (isFirstChildOfContainer ? childToolbarContainer : null);
101
+ const hoveredBlockElement = nestedContainer
102
+ ? nestedContainer.closest('[data-blok-testid="block-wrapper"]') ?? null
76
103
  : closestBlockWrapper;
77
104
 
78
105
  /**
@@ -158,13 +185,13 @@ export class BlockHoverController extends Controller {
158
185
  }
159
186
 
160
187
  /**
161
- * Filter out blocks whose holders are inside a table cell container.
162
- * Cell blocks should not participate in nearest-block detection —
163
- * the parent table block should be found instead.
164
- * This matches the direct-hit path which also resolves cell blocks to their parent table block.
188
+ * Filter out blocks whose holders are inside a table cell or toggle-children container.
189
+ * Nested child blocks should not participate in nearest-block detection —
190
+ * the parent block should be found instead.
191
+ * This matches the direct-hit path which also resolves nested blocks to their parent.
165
192
  */
166
193
  const topLevelBlocks = blocks.filter(block =>
167
- block.holder.closest('[data-blok-table-cell-blocks]') === null
194
+ block.holder.closest('[data-blok-table-cell-blocks], [data-blok-toggle-children]') === null
168
195
  );
169
196
 
170
197
  if (topLevelBlocks.length === 0) {
@@ -71,15 +71,27 @@ export const createRedactorTouchHandler = (
71
71
  */
72
72
  if (!deps.Blok.ReadOnly.isEnabled && !deps.Blok.Toolbar.contains(initialTarget)) {
73
73
  /**
74
- * When the clicked node is inside a table cell, resolve to the parent table block
75
- * so moveAndOpen receives the table block (not undefined / the inner cell paragraph).
76
- * Without this, moveAndOpen falls back to currentBlock (the cell paragraph), detects
77
- * it's inside a table cell, and hides the plus button and settings toggler.
74
+ * When the clicked node is inside a table cell or toggle-children container,
75
+ * resolve to the parent block so moveAndOpen receives the correct parent block.
76
+ * Without this, moveAndOpen falls back to currentBlock (the nested child),
77
+ * and the parent's block tune settings become inaccessible.
78
+ *
79
+ * For child-toolbar containers (e.g. callout), the first child still resolves
80
+ * to the parent so the container's own controls (settings, drag) are accessible.
81
+ * Non-first children keep their own toolbar via the block argument being undefined.
78
82
  */
79
- const tableCellContainer = clickedNode.closest?.('[data-blok-table-cell-blocks]');
80
- const tableBlockWrapper = tableCellContainer?.closest('[data-blok-testid="block-wrapper"]');
81
- const resolvedBlock = tableBlockWrapper
82
- ? deps.Blok.BlockManager.getBlockByChildNode(tableBlockWrapper)
83
+ const alwaysResolve = clickedNode.closest?.('[data-blok-table-cell-blocks], [data-blok-toggle-children]:not([data-blok-child-toolbar])');
84
+ const childToolbar = !alwaysResolve
85
+ ? clickedNode.closest?.('[data-blok-child-toolbar]') ?? null
86
+ : null;
87
+ const closestBlockWrapper = clickedNode.closest?.('[data-blok-testid="block-wrapper"]') ?? null;
88
+ const isFirstChild = childToolbar !== null
89
+ && closestBlockWrapper !== null
90
+ && childToolbar.querySelector(':scope > [data-blok-testid="block-wrapper"]') === closestBlockWrapper;
91
+ const nestedContainer = alwaysResolve ?? (isFirstChild ? childToolbar : null);
92
+ const parentBlockWrapper = nestedContainer?.closest('[data-blok-testid="block-wrapper"]');
93
+ const resolvedBlock = parentBlockWrapper
94
+ ? deps.Blok.BlockManager.getBlockByChildNode(parentBlockWrapper)
83
95
  : undefined;
84
96
 
85
97
  deps.Blok.Toolbar.moveAndOpen(resolvedBlock, clickedNode);
@@ -114,6 +114,10 @@ export class ToolsFactory {
114
114
  getEnglishTranslation: (key: string): string => {
115
115
  return baseApi.i18n.getEnglishTranslation(key);
116
116
  },
117
+
118
+ getLocale: (): string => {
119
+ return baseApi.i18n.getLocale();
120
+ },
117
121
  };
118
122
 
119
123
  return {
@@ -226,6 +226,28 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
226
226
  }
227
227
  }
228
228
 
229
+ /**
230
+ * Applies or clears callout background color on the popover's search input.
231
+ * When the toolbox opens inside a callout with a custom background, the search
232
+ * input container should match the callout background instead of its default.
233
+ *
234
+ * @param color - the callout background CSS value, or null to clear
235
+ */
236
+ public setCalloutBackground(color: string | null): void {
237
+ const popoverEl = this.popover?.getElement();
238
+
239
+ if (!popoverEl) {
240
+ return;
241
+ }
242
+
243
+ if (color) {
244
+ popoverEl.style.setProperty('--blok-search-input-bg', `light-dark(color-mix(in srgb, ${color} 70%, white), color-mix(in srgb, ${color} 85%, white))`);
245
+ } else {
246
+ popoverEl.style.removeProperty('--blok-search-input-bg');
247
+ popoverEl.style.removeProperty('--blok-search-input-border');
248
+ }
249
+ }
250
+
229
251
  /**
230
252
  * Returns root block settings element
231
253
  */
@@ -323,7 +345,9 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
323
345
  * instead of at the trigger element (which is outside the table).
324
346
  * Must be called after show() so the popover is in the DOM.
325
347
  */
326
- if (this.isInsideTableCell && this.popover instanceof PopoverDesktop) {
348
+ const triggerHidden = this.triggerElement?.getBoundingClientRect().height === 0;
349
+
350
+ if ((this.isInsideTableCell || triggerHidden) && this.popover instanceof PopoverDesktop) {
327
351
  const caretRect = SelectionUtils.rect;
328
352
 
329
353
  this.popover.updatePosition(caretRect);
@@ -629,8 +653,13 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
629
653
  /**
630
654
  * Check if the block contains only slash search text (e.g., "/head").
631
655
  * If so, treat it as empty and replace it with the new block.
656
+ *
657
+ * When opened without slash (via plus button), any text in the block
658
+ * is a search query, not user content — always replace.
632
659
  */
633
- const shouldReplaceBlock = currentBlock.isEmpty || this.isBlockSlashSearchOnly(currentBlock.holder);
660
+ const shouldReplaceBlock = currentBlock.isEmpty
661
+ || this.isBlockSlashSearchOnly(currentBlock.holder)
662
+ || !this.openedWithSlash;
634
663
 
635
664
  /**
636
665
  * On mobile version, we see the Plus Button even near non-empty blocks,
@@ -721,7 +750,13 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
721
750
  }
722
751
 
723
752
  this.currentBlockForSearch = currentBlock.holder;
724
- this.currentContentEditable = this.currentBlockForSearch.querySelector('[contenteditable="true"]');
753
+
754
+ const activeEl = document.activeElement;
755
+
756
+ this.currentContentEditable = activeEl instanceof HTMLElement && activeEl.isContentEditable && this.currentBlockForSearch.contains(activeEl)
757
+ ? activeEl
758
+ : this.currentBlockForSearch.querySelector('[contenteditable="true"]');
759
+
725
760
  if (this.currentContentEditable instanceof HTMLElement) {
726
761
  this.currentContentEditable.setAttribute(DATA_ATTR.slashSearch, this.i18nLabels.slashSearchPlaceholder);
727
762
  }
@@ -10,6 +10,7 @@ import type { SearchableItem } from './components/search-input';
10
10
  import { SearchInput, SearchInputEvent, scoreSearchMatch } from './components/search-input';
11
11
  import { PopoverAbstract } from './popover-abstract';
12
12
  import { CSSVariables, css as popoverCss } from './popover.const';
13
+ import { resolvePosition } from './popover-position';
13
14
  import { twMerge } from '../tw';
14
15
 
15
16
  import type { PopoverParams } from '@/types/utils/popover/popover';
@@ -224,12 +225,14 @@ export class PopoverDesktop extends PopoverAbstract {
224
225
  }
225
226
 
226
227
  if (this.trigger) {
227
- const { top, left } = this.calculatePosition();
228
+ const { top, left, openTop, openLeft } = this.calculatePosition();
228
229
  this.nodes.popover.style.position = 'absolute';
229
230
  this.nodes.popover.style.top = `${top}px`;
230
231
  this.nodes.popover.style.left = `${left}px`;
231
232
  this.nodes.popover.style.setProperty(CSSVariables.PopoverTop, '0px');
232
233
  this.nodes.popover.style.setProperty(CSSVariables.PopoverLeft, '0px');
234
+ this.setOpenTop(openTop);
235
+ this.setOpenLeft(openLeft);
233
236
  }
234
237
 
235
238
  const measuredSize = this.size;
@@ -243,16 +246,27 @@ export class PopoverDesktop extends PopoverAbstract {
243
246
  this.nodes.popover.style.setProperty('--width', width + 'px');
244
247
  }
245
248
 
246
- if (!this.trigger && !this.shouldOpenBottom) {
247
- this.setOpenTop(true);
248
- // Apply open-top positioning (moved from popover.css)
249
- this.nodes.popover.style.setProperty(CSSVariables.PopoverTop, 'calc(-1 * (0.5rem + var(--popover-height)))');
250
- }
249
+ if (!this.trigger) {
250
+ const containerRect = this.nodes.popoverContainer.getBoundingClientRect();
251
+ // offset: 0 because the visual gap is handled by CSS calc (0.5rem), not pixel positioning
252
+ const { openTop, openLeft } = resolvePosition({
253
+ anchor: containerRect,
254
+ popoverSize: measuredSize,
255
+ scopeBounds: this.scopeElement.getBoundingClientRect(),
256
+ viewportSize: { width: window.innerWidth, height: window.innerHeight },
257
+ scrollOffset: { x: window.scrollX, y: window.scrollY },
258
+ offset: 0,
259
+ });
260
+
261
+ if (openTop) {
262
+ this.setOpenTop(true);
263
+ this.nodes.popover.style.setProperty(CSSVariables.PopoverTop, 'calc(-1 * (0.5rem + var(--popover-height)))');
264
+ }
251
265
 
252
- if (!this.trigger && !this.shouldOpenRight) {
253
- this.setOpenLeft(true);
254
- // Apply open-left positioning (moved from popover.css)
255
- this.nodes.popover.style.setProperty(CSSVariables.PopoverLeft, 'calc(-1 * var(--width) + 100%)');
266
+ if (openLeft) {
267
+ this.setOpenLeft(true);
268
+ this.nodes.popover.style.setProperty(CSSVariables.PopoverLeft, 'calc(-1 * var(--width) + 100%)');
269
+ }
256
270
  }
257
271
 
258
272
  super.show();
@@ -294,45 +308,34 @@ export class PopoverDesktop extends PopoverAbstract {
294
308
 
295
309
  // Recalculate and apply position if already shown
296
310
  if (this.nodes.popover.hasAttribute('data-blok-popover-opened')) {
297
- const { top, left } = this.calculatePosition();
311
+ const { top, left, openTop, openLeft } = this.calculatePosition();
298
312
 
299
313
  this.nodes.popover.style.top = `${top}px`;
300
314
  this.nodes.popover.style.left = `${left}px`;
315
+ this.setOpenTop(openTop);
316
+ this.setOpenLeft(openLeft);
301
317
  }
302
318
  }
303
319
 
304
320
  /**
305
321
  * Calculates position for the popover
306
322
  */
307
- private calculatePosition(): { top: number; left: number } {
308
- // Use provided position if available, otherwise fall back to trigger element
323
+ private calculatePosition(): { top: number; left: number; openTop: boolean; openLeft: boolean } {
309
324
  const rect = this.params.position ?? this.trigger?.getBoundingClientRect();
310
325
 
311
326
  if (!rect) {
312
- return {
313
- top: 0,
314
- left: 0,
315
- };
327
+ return { top: 0, left: 0, openTop: false, openLeft: false };
316
328
  }
317
329
 
318
- const popoverRect = this.size;
319
- const windowWidth = window.innerWidth;
320
- const windowHeight = window.innerHeight;
321
- const offset = 8;
322
-
323
- const initialTop = rect.bottom + offset + window.scrollY;
324
- const shouldFlipTop = (rect.bottom + offset + popoverRect.height > windowHeight + window.scrollY) &&
325
- (rect.top - offset - popoverRect.height > window.scrollY);
326
- const top = shouldFlipTop ? rect.top - offset - popoverRect.height + window.scrollY : initialTop;
327
-
328
- const initialLeft = (this.leftAlignElement?.getBoundingClientRect().left ?? rect.left) + window.scrollX;
329
- const shouldFlipLeft = initialLeft + popoverRect.width > windowWidth + window.scrollX;
330
- const left = shouldFlipLeft ? Math.max(0, rect.right - popoverRect.width + window.scrollX) : initialLeft;
331
-
332
- return {
333
- top,
334
- left,
335
- };
330
+ return resolvePosition({
331
+ anchor: rect,
332
+ popoverSize: this.size,
333
+ scopeBounds: this.scopeElement.getBoundingClientRect(),
334
+ viewportSize: { width: window.innerWidth, height: window.innerHeight },
335
+ scrollOffset: { x: window.scrollX, y: window.scrollY },
336
+ offset: 8,
337
+ leftAlignRect: this.leftAlignElement?.getBoundingClientRect(),
338
+ });
336
339
  }
337
340
 
338
341
  /**
@@ -647,42 +650,6 @@ export class PopoverDesktop extends PopoverAbstract {
647
650
  nestedContainer.style.top = 'calc(var(--trigger-item-top) - var(--popover-height) / 2 + var(--item-height) / 2)';
648
651
  }
649
652
 
650
- /**
651
- * Checks if popover should be opened bottom.
652
- * It should happen when there is enough space below or not enough space above
653
- */
654
- private get shouldOpenBottom(): boolean {
655
- if (this.nodes.popover === undefined || this.nodes.popover === null) {
656
- return false;
657
- }
658
- const popoverRect = this.nodes.popoverContainer.getBoundingClientRect();
659
- const scopeElementRect = this.scopeElement.getBoundingClientRect();
660
- const popoverHeight = this.size.height;
661
- const popoverPotentialBottomEdge = popoverRect.top + popoverHeight;
662
- const popoverPotentialTopEdge = popoverRect.top - popoverHeight;
663
- const bottomEdgeForComparison = Math.min(window.innerHeight, scopeElementRect.bottom);
664
-
665
- return popoverPotentialTopEdge < scopeElementRect.top || popoverPotentialBottomEdge <= bottomEdgeForComparison;
666
- }
667
-
668
- /**
669
- * Checks if popover should be opened left.
670
- * It should happen when there is enough space in the right or not enough space in the left
671
- */
672
- private get shouldOpenRight(): boolean {
673
- if (this.nodes.popover === undefined || this.nodes.popover === null) {
674
- return false;
675
- }
676
-
677
- const popoverRect = this.nodes.popover.getBoundingClientRect();
678
- const scopeElementRect = this.scopeElement.getBoundingClientRect();
679
- const popoverWidth = this.size.width;
680
- const popoverPotentialRightEdge = popoverRect.right + popoverWidth;
681
- const popoverPotentialLeftEdge = popoverRect.left - popoverWidth;
682
- const rightEdgeForComparison = Math.min(window.innerWidth, scopeElementRect.right);
683
-
684
- return popoverPotentialLeftEdge < scopeElementRect.left || popoverPotentialRightEdge <= rightEdgeForComparison;
685
- }
686
653
 
687
654
  /**
688
655
  * Helps to calculate size of popover that is only resolved when popover is displayed on screen.
@@ -726,6 +693,13 @@ export class PopoverDesktop extends PopoverAbstract {
726
693
  return size;
727
694
  }
728
695
 
696
+ /**
697
+ * Invalidates the cached popover size so the next access to `size` re-measures.
698
+ */
699
+ public invalidateSizeCache(): void {
700
+ this._size = undefined;
701
+ }
702
+
729
703
  /**
730
704
  * Returns list of elements available for keyboard navigation.
731
705
  */
@@ -1047,6 +1021,9 @@ export class PopoverDesktop extends PopoverAbstract {
1047
1021
  item.toggleHidden(isHidden);
1048
1022
  });
1049
1023
 
1024
+ // Invalidate size cache since item visibility changed
1025
+ this._size = undefined;
1026
+
1050
1027
  // Reorder top-level DOM elements to reflect ranking
1051
1028
  if (!isEmptyQuery && matchingTopLevel.length > 0) {
1052
1029
  this.reorderItemsByRank(matchingTopLevel);
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Input for popover position resolution.
3
+ * All rects/sizes are in viewport coordinates unless noted.
4
+ */
5
+ export interface PositionInput {
6
+ /** Bounding rect of the anchor element (trigger or popover container) */
7
+ anchor: DOMRect;
8
+ /** Measured popover dimensions */
9
+ popoverSize: { width: number; height: number };
10
+ /** Bounding rect of the scope element that constrains the popover */
11
+ scopeBounds: DOMRect;
12
+ /** Viewport dimensions */
13
+ viewportSize: { width: number; height: number };
14
+ /** Current scroll offset */
15
+ scrollOffset: { x: number; y: number };
16
+ /** Gap between anchor and popover edge (default 8) */
17
+ offset?: number;
18
+ /** Element rect whose left edge overrides anchor's left for horizontal alignment */
19
+ leftAlignRect?: DOMRect;
20
+ }
21
+
22
+ export interface ResolvedPosition {
23
+ /** Final top coordinate in document (scroll-adjusted) coordinates */
24
+ top: number;
25
+ /** Final left coordinate in document (scroll-adjusted) coordinates */
26
+ left: number;
27
+ /** True if popover opens above the anchor */
28
+ openTop: boolean;
29
+ /** True if popover opens to the left of the anchor */
30
+ openLeft: boolean;
31
+ }
32
+
33
+ /**
34
+ * Determines whether the popover should flip to the alternate side.
35
+ * Returns true when the popover doesn't fit on the preferred side and the alternate side has more (or equal) space.
36
+ */
37
+ function shouldFlip(popoverDimension: number, spaceOnPreferred: number, spaceOnAlternate: number): boolean {
38
+ if (popoverDimension <= spaceOnPreferred) {
39
+ return false;
40
+ }
41
+
42
+ if (popoverDimension <= spaceOnAlternate) {
43
+ return true;
44
+ }
45
+
46
+ return spaceOnAlternate > spaceOnPreferred;
47
+ }
48
+
49
+ /**
50
+ * Pure function that resolves popover position.
51
+ * Picks the direction with more available space when the popover doesn't fit on the preferred side.
52
+ * Clamps to scope/viewport boundaries on both edges.
53
+ */
54
+ export function resolvePosition(input: PositionInput): ResolvedPosition {
55
+ const {
56
+ anchor,
57
+ popoverSize,
58
+ scopeBounds,
59
+ viewportSize,
60
+ scrollOffset,
61
+ offset = 8,
62
+ leftAlignRect,
63
+ } = input;
64
+
65
+ // --- Vertical ---
66
+ const boundaryBottom = Math.min(viewportSize.height, scopeBounds.bottom);
67
+ const boundaryTop = Math.max(0, scopeBounds.top);
68
+
69
+ const spaceBelow = boundaryBottom - anchor.bottom - offset;
70
+ const spaceAbove = anchor.top - offset - boundaryTop;
71
+
72
+ const openTop = shouldFlip(popoverSize.height, spaceBelow, spaceAbove);
73
+
74
+ const rawTop = openTop
75
+ ? anchor.top - offset - popoverSize.height + scrollOffset.y
76
+ : anchor.bottom + offset + scrollOffset.y;
77
+
78
+ // Clamp: ensure popover doesn't overflow above top boundary
79
+ const top = rawTop < boundaryTop + scrollOffset.y
80
+ ? boundaryTop + scrollOffset.y
81
+ : rawTop;
82
+
83
+ // --- Horizontal ---
84
+ const boundaryRight = Math.min(viewportSize.width, scopeBounds.right);
85
+ const boundaryLeft = Math.max(0, scopeBounds.left);
86
+
87
+ const alignLeft = (leftAlignRect?.left ?? anchor.left) + scrollOffset.x;
88
+ const alignRight = anchor.right + scrollOffset.x;
89
+
90
+ const spaceRight = boundaryRight + scrollOffset.x - alignLeft;
91
+ const spaceLeft = alignRight - boundaryLeft - scrollOffset.x;
92
+
93
+ const openLeft = shouldFlip(popoverSize.width, spaceRight, spaceLeft);
94
+
95
+ const rawLeft = openLeft
96
+ ? Math.max(boundaryLeft + scrollOffset.x, anchor.right - popoverSize.width + scrollOffset.x)
97
+ : alignLeft;
98
+
99
+ // Clamp: ensure popover doesn't overflow right boundary
100
+ const left = rawLeft + popoverSize.width > boundaryRight + scrollOffset.x
101
+ ? Math.max(boundaryLeft + scrollOffset.x, boundaryRight + scrollOffset.x - popoverSize.width)
102
+ : rawLeft;
103
+
104
+ return { top, left, openTop, openLeft };
105
+ }
@@ -496,7 +496,14 @@ export const PickerNoActiveSwatch: Story = {
496
496
  expect(swatches?.length).toBe(10);
497
497
 
498
498
  swatches?.forEach((swatch) => {
499
- expect(swatch.className).not.toContain('ring-swatch-ring-hover');
499
+ // Default swatch correctly shows active ring when no color is set
500
+ if (swatch.getAttribute('data-blok-testid')?.endsWith('-default')) {
501
+ return;
502
+ }
503
+
504
+ // Use classList.contains for exact token match — className.includes
505
+ // would false-positive on the hover:ring-swatch-ring-hover variant
506
+ expect(swatch.classList.contains('ring-swatch-ring-hover')).toBe(false);
500
507
  });
501
508
  },
502
509
  TIMEOUT_ACTION