@jackuait/blok 0.6.0 → 0.7.0-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 (257) hide show
  1. package/README.md +20 -4
  2. package/dist/blok.mjs +2 -2
  3. package/dist/chunks/{blok-BAh1rvUC.mjs → blok-D9Rs29Wo.mjs} +1928 -1793
  4. package/dist/chunks/{inline-tool-convert-DduRc0fF.mjs → constants-DmNIR3I8.mjs} +596 -475
  5. package/dist/chunks/{i18next-loader-CHtGO6IK.mjs → i18next-loader-C2-jYpLi.mjs} +1 -1
  6. package/dist/chunks/index-D7V1g7Oq.mjs +130 -0
  7. package/dist/chunks/{messages-D2NOpHn9.mjs → messages-0Pxnqd4N.mjs} +7 -0
  8. package/dist/chunks/{messages-GSByFygY.mjs → messages-0ZXYUq7S.mjs} +7 -0
  9. package/dist/{messages-BUl_Rcnj.mjs → chunks/messages-2OD2uUDS.mjs} +9 -2
  10. package/dist/{messages-CgTq3QhU.mjs → chunks/messages-7cEMfYzh.mjs} +7 -0
  11. package/dist/{messages-DlJbPF2T.mjs → chunks/messages-8mwfda1Q.mjs} +7 -0
  12. package/dist/{messages-D9ndgBnU.mjs → chunks/messages-B-FqWsBM.mjs} +7 -0
  13. package/dist/{messages-B217znr-.mjs → chunks/messages-B1jzqWiQ.mjs} +7 -0
  14. package/dist/{messages-BcpCubnC.mjs → chunks/messages-B5wk4Ezz.mjs} +7 -0
  15. package/dist/chunks/{messages-DRXWF0PV.mjs → messages-BAZ5Ld8x.mjs} +7 -0
  16. package/dist/{messages-CRJ_mchV.mjs → chunks/messages-BBhGp198.mjs} +7 -0
  17. package/dist/chunks/{messages-yHcs38yI.mjs → messages-BC9IjIb7.mjs} +7 -0
  18. package/dist/chunks/{messages-Cr94GzbX.mjs → messages-BFEmpeV-.mjs} +7 -0
  19. package/dist/chunks/{messages-ucTVgS5G.mjs → messages-BGqzTZy0.mjs} +7 -0
  20. package/dist/{messages-begYOTgC.mjs → chunks/messages-BICs1abK.mjs} +7 -0
  21. package/dist/chunks/{messages-DVQvl8Qj.mjs → messages-BJX6rOnd.mjs} +7 -0
  22. package/dist/chunks/{messages-Chb7k3Rg.mjs → messages-BL2bXRhN.mjs} +7 -0
  23. package/dist/{messages-Phkd7XmE.mjs → chunks/messages-BMs5qdlH.mjs} +7 -0
  24. package/dist/chunks/{messages-Cjjo7yHR.mjs → messages-BRsjUNwB.mjs} +7 -0
  25. package/dist/chunks/{messages-D4qqwVgQ.mjs → messages-BSqV8OUR.mjs} +7 -0
  26. package/dist/chunks/{messages-DviiFSv2.mjs → messages-BTqu3DfG.mjs} +7 -0
  27. package/dist/chunks/{messages-0AbcLMLm.mjs → messages-BXnDEsur.mjs} +7 -0
  28. package/dist/{messages-CmR9ftc_.mjs → chunks/messages-BYcre4-6.mjs} +7 -0
  29. package/dist/{messages-wmi-iFkH.mjs → chunks/messages-BZ9LRJf-.mjs} +7 -0
  30. package/dist/chunks/{messages-D00x4S8o.mjs → messages-BgypBy7y.mjs} +7 -0
  31. package/dist/{messages-96kNZDll.mjs → chunks/messages-BsuGf70G.mjs} +7 -0
  32. package/dist/chunks/{messages-v3GipbFl.mjs → messages-BwaoF4lQ.mjs} +7 -0
  33. package/dist/{messages-DDTQgImT.mjs → chunks/messages-C1l8_7-y.mjs} +7 -0
  34. package/dist/{messages-B1FZ8lxU.mjs → chunks/messages-C5NA_r9v.mjs} +7 -0
  35. package/dist/{messages-Cs8zmZ3L.mjs → chunks/messages-C6zgZ5pA.mjs} +7 -0
  36. package/dist/chunks/{messages-ZjUAIWb1.mjs → messages-CAo5ghFI.mjs} +7 -0
  37. package/dist/{messages-D5S1Dnpm.mjs → chunks/messages-CH9qlJ9I.mjs} +7 -0
  38. package/dist/{messages-D7u2bmP2.mjs → chunks/messages-CI0HqAeS.mjs} +7 -0
  39. package/dist/{messages-DH_jBeED.mjs → chunks/messages-CJJtms9k.mjs} +7 -0
  40. package/dist/{messages-CDBLbUOQ.mjs → chunks/messages-CM2hJqk6.mjs} +7 -0
  41. package/dist/chunks/{messages-8IPXkrDl.mjs → messages-CRMiDPIQ.mjs} +7 -0
  42. package/dist/chunks/{messages-Dzzn6XoD.mjs → messages-CWsZuBj1.mjs} +7 -0
  43. package/dist/chunks/{messages-CW4c4cRk.mjs → messages-C_gLHo6A.mjs} +7 -0
  44. package/dist/{messages-CH4hrauY.mjs → chunks/messages-Cbu-NUDn.mjs} +7 -0
  45. package/dist/{messages-RonBBCnh.mjs → chunks/messages-Cjb_MCeh.mjs} +7 -0
  46. package/dist/chunks/{messages-BJ6zrz2j.mjs → messages-ClXYO9Wn.mjs} +7 -0
  47. package/dist/chunks/{messages-CrCYPCk3.mjs → messages-CsH20vhP.mjs} +7 -0
  48. package/dist/{messages-CzK0LEhb.mjs → chunks/messages-CsjAGhzA.mjs} +7 -0
  49. package/dist/chunks/{messages-BZlmVRwn.mjs → messages-Cx7VKFOE.mjs} +7 -0
  50. package/dist/chunks/{messages-0E0AkrNu.mjs → messages-D3JeBwxo.mjs} +7 -0
  51. package/dist/chunks/{messages-D85FqxgY.mjs → messages-D541fieJ.mjs} +7 -0
  52. package/dist/{messages-4v4MuVEc.mjs → chunks/messages-D7XPdglc.mjs} +7 -0
  53. package/dist/{messages-BC8IN4Bf.mjs → chunks/messages-DBhylfvt.mjs} +7 -0
  54. package/dist/chunks/{messages-B8WNljW3.mjs → messages-DCA120lW.mjs} +7 -0
  55. package/dist/chunks/{messages-Cr49Nt3U.mjs → messages-DCf_xZMN.mjs} +7 -0
  56. package/dist/chunks/{messages-VDriF5Qy.mjs → messages-DDwXKCpe.mjs} +7 -0
  57. package/dist/{messages-b1EdvUm0.mjs → chunks/messages-DNKDlxcy.mjs} +7 -0
  58. package/dist/{messages-L_kl2Qvh.mjs → chunks/messages-DPvEjrGK.mjs} +7 -0
  59. package/dist/chunks/{messages-62v-CLC-.mjs → messages-DQ-AkNxA.mjs} +7 -0
  60. package/dist/chunks/{messages-DdK-nFGm.mjs → messages-DVuvkNap.mjs} +7 -0
  61. package/dist/{messages-DnVlmiNT.mjs → chunks/messages-DaglyqUT.mjs} +7 -0
  62. package/dist/{messages-Bm-E4iRC.mjs → chunks/messages-Di0bAfwA.mjs} +7 -0
  63. package/dist/{messages-D1mn7Zd5.mjs → chunks/messages-DuLct0Yr.mjs} +7 -0
  64. package/dist/{messages-8DeO60Oo.mjs → chunks/messages-DzEYYhZh.mjs} +7 -0
  65. package/dist/chunks/{messages-CfiyT2Wi.mjs → messages-DznNGAB2.mjs} +7 -0
  66. package/dist/chunks/{messages-DXktiao_.mjs → messages-DzoIzyu8.mjs} +7 -0
  67. package/dist/{messages-C_4otP7U.mjs → chunks/messages-QYOGmket.mjs} +7 -0
  68. package/dist/chunks/{messages-nefz1S71.mjs → messages-cEjGDAgI.mjs} +7 -0
  69. package/dist/chunks/{messages-jrncnb-H.mjs → messages-ddhvrdpE.mjs} +7 -0
  70. package/dist/chunks/{messages-DzqM3Fel.mjs → messages-mwfNK5nZ.mjs} +7 -0
  71. package/dist/chunks/{messages-Cl6ayUaq.mjs → messages-nG_vNDte.mjs} +7 -0
  72. package/dist/{messages-C4jL-90N.mjs → chunks/messages-tDq3Owh7.mjs} +7 -0
  73. package/dist/{messages-BI43k_BD.mjs → chunks/messages-x6VJVZKx.mjs} +7 -0
  74. package/dist/full.mjs +30 -27
  75. package/dist/locales.mjs +87 -80
  76. package/dist/{messages-D2NOpHn9.mjs → messages-0Pxnqd4N.mjs} +7 -0
  77. package/dist/{messages-GSByFygY.mjs → messages-0ZXYUq7S.mjs} +7 -0
  78. package/dist/{chunks/messages-BUl_Rcnj.mjs → messages-2OD2uUDS.mjs} +9 -2
  79. package/dist/{chunks/messages-CgTq3QhU.mjs → messages-7cEMfYzh.mjs} +7 -0
  80. package/dist/{chunks/messages-DlJbPF2T.mjs → messages-8mwfda1Q.mjs} +7 -0
  81. package/dist/{chunks/messages-D9ndgBnU.mjs → messages-B-FqWsBM.mjs} +7 -0
  82. package/dist/{chunks/messages-B217znr-.mjs → messages-B1jzqWiQ.mjs} +7 -0
  83. package/dist/{chunks/messages-BcpCubnC.mjs → messages-B5wk4Ezz.mjs} +7 -0
  84. package/dist/{messages-DRXWF0PV.mjs → messages-BAZ5Ld8x.mjs} +7 -0
  85. package/dist/{chunks/messages-CRJ_mchV.mjs → messages-BBhGp198.mjs} +7 -0
  86. package/dist/{messages-yHcs38yI.mjs → messages-BC9IjIb7.mjs} +7 -0
  87. package/dist/{messages-Cr94GzbX.mjs → messages-BFEmpeV-.mjs} +7 -0
  88. package/dist/{messages-ucTVgS5G.mjs → messages-BGqzTZy0.mjs} +7 -0
  89. package/dist/{chunks/messages-begYOTgC.mjs → messages-BICs1abK.mjs} +7 -0
  90. package/dist/{messages-DVQvl8Qj.mjs → messages-BJX6rOnd.mjs} +7 -0
  91. package/dist/{messages-Chb7k3Rg.mjs → messages-BL2bXRhN.mjs} +7 -0
  92. package/dist/{chunks/messages-Phkd7XmE.mjs → messages-BMs5qdlH.mjs} +7 -0
  93. package/dist/{messages-Cjjo7yHR.mjs → messages-BRsjUNwB.mjs} +7 -0
  94. package/dist/{messages-D4qqwVgQ.mjs → messages-BSqV8OUR.mjs} +7 -0
  95. package/dist/{messages-DviiFSv2.mjs → messages-BTqu3DfG.mjs} +7 -0
  96. package/dist/{messages-0AbcLMLm.mjs → messages-BXnDEsur.mjs} +7 -0
  97. package/dist/{chunks/messages-CmR9ftc_.mjs → messages-BYcre4-6.mjs} +7 -0
  98. package/dist/{chunks/messages-wmi-iFkH.mjs → messages-BZ9LRJf-.mjs} +7 -0
  99. package/dist/{messages-D00x4S8o.mjs → messages-BgypBy7y.mjs} +7 -0
  100. package/dist/{chunks/messages-96kNZDll.mjs → messages-BsuGf70G.mjs} +7 -0
  101. package/dist/{messages-v3GipbFl.mjs → messages-BwaoF4lQ.mjs} +7 -0
  102. package/dist/{chunks/messages-DDTQgImT.mjs → messages-C1l8_7-y.mjs} +7 -0
  103. package/dist/{chunks/messages-B1FZ8lxU.mjs → messages-C5NA_r9v.mjs} +7 -0
  104. package/dist/{chunks/messages-Cs8zmZ3L.mjs → messages-C6zgZ5pA.mjs} +7 -0
  105. package/dist/{messages-ZjUAIWb1.mjs → messages-CAo5ghFI.mjs} +7 -0
  106. package/dist/{chunks/messages-D5S1Dnpm.mjs → messages-CH9qlJ9I.mjs} +7 -0
  107. package/dist/{chunks/messages-D7u2bmP2.mjs → messages-CI0HqAeS.mjs} +7 -0
  108. package/dist/{chunks/messages-DH_jBeED.mjs → messages-CJJtms9k.mjs} +7 -0
  109. package/dist/{chunks/messages-CDBLbUOQ.mjs → messages-CM2hJqk6.mjs} +7 -0
  110. package/dist/{messages-8IPXkrDl.mjs → messages-CRMiDPIQ.mjs} +7 -0
  111. package/dist/{messages-Dzzn6XoD.mjs → messages-CWsZuBj1.mjs} +7 -0
  112. package/dist/{messages-CW4c4cRk.mjs → messages-C_gLHo6A.mjs} +7 -0
  113. package/dist/{chunks/messages-CH4hrauY.mjs → messages-Cbu-NUDn.mjs} +7 -0
  114. package/dist/{chunks/messages-RonBBCnh.mjs → messages-Cjb_MCeh.mjs} +7 -0
  115. package/dist/{messages-BJ6zrz2j.mjs → messages-ClXYO9Wn.mjs} +7 -0
  116. package/dist/{messages-CrCYPCk3.mjs → messages-CsH20vhP.mjs} +7 -0
  117. package/dist/{chunks/messages-CzK0LEhb.mjs → messages-CsjAGhzA.mjs} +7 -0
  118. package/dist/{messages-BZlmVRwn.mjs → messages-Cx7VKFOE.mjs} +7 -0
  119. package/dist/{messages-0E0AkrNu.mjs → messages-D3JeBwxo.mjs} +7 -0
  120. package/dist/{messages-D85FqxgY.mjs → messages-D541fieJ.mjs} +7 -0
  121. package/dist/{chunks/messages-4v4MuVEc.mjs → messages-D7XPdglc.mjs} +7 -0
  122. package/dist/{chunks/messages-BC8IN4Bf.mjs → messages-DBhylfvt.mjs} +7 -0
  123. package/dist/{messages-B8WNljW3.mjs → messages-DCA120lW.mjs} +7 -0
  124. package/dist/{messages-Cr49Nt3U.mjs → messages-DCf_xZMN.mjs} +7 -0
  125. package/dist/{messages-VDriF5Qy.mjs → messages-DDwXKCpe.mjs} +7 -0
  126. package/dist/{chunks/messages-b1EdvUm0.mjs → messages-DNKDlxcy.mjs} +7 -0
  127. package/dist/{chunks/messages-L_kl2Qvh.mjs → messages-DPvEjrGK.mjs} +7 -0
  128. package/dist/{messages-62v-CLC-.mjs → messages-DQ-AkNxA.mjs} +7 -0
  129. package/dist/{messages-DdK-nFGm.mjs → messages-DVuvkNap.mjs} +7 -0
  130. package/dist/{chunks/messages-DnVlmiNT.mjs → messages-DaglyqUT.mjs} +7 -0
  131. package/dist/{chunks/messages-Bm-E4iRC.mjs → messages-Di0bAfwA.mjs} +7 -0
  132. package/dist/{chunks/messages-D1mn7Zd5.mjs → messages-DuLct0Yr.mjs} +7 -0
  133. package/dist/{chunks/messages-8DeO60Oo.mjs → messages-DzEYYhZh.mjs} +7 -0
  134. package/dist/{messages-CfiyT2Wi.mjs → messages-DznNGAB2.mjs} +7 -0
  135. package/dist/{messages-DXktiao_.mjs → messages-DzoIzyu8.mjs} +7 -0
  136. package/dist/{chunks/messages-C_4otP7U.mjs → messages-QYOGmket.mjs} +7 -0
  137. package/dist/{messages-nefz1S71.mjs → messages-cEjGDAgI.mjs} +7 -0
  138. package/dist/{messages-jrncnb-H.mjs → messages-ddhvrdpE.mjs} +7 -0
  139. package/dist/{messages-DzqM3Fel.mjs → messages-mwfNK5nZ.mjs} +7 -0
  140. package/dist/{messages-Cl6ayUaq.mjs → messages-nG_vNDte.mjs} +7 -0
  141. package/dist/{chunks/messages-C4jL-90N.mjs → messages-tDq3Owh7.mjs} +7 -0
  142. package/dist/{chunks/messages-BI43k_BD.mjs → messages-x6VJVZKx.mjs} +7 -0
  143. package/dist/tools.mjs +1233 -801
  144. package/package.json +1 -1
  145. package/src/components/constants/data-attributes.ts +7 -0
  146. package/src/components/i18n/locales/am/messages.json +7 -0
  147. package/src/components/i18n/locales/ar/messages.json +7 -0
  148. package/src/components/i18n/locales/az/messages.json +7 -0
  149. package/src/components/i18n/locales/bg/messages.json +7 -0
  150. package/src/components/i18n/locales/bn/messages.json +7 -0
  151. package/src/components/i18n/locales/bs/messages.json +7 -0
  152. package/src/components/i18n/locales/cs/messages.json +7 -0
  153. package/src/components/i18n/locales/da/messages.json +7 -0
  154. package/src/components/i18n/locales/de/messages.json +7 -0
  155. package/src/components/i18n/locales/dv/messages.json +7 -0
  156. package/src/components/i18n/locales/el/messages.json +7 -0
  157. package/src/components/i18n/locales/en/messages.json +7 -0
  158. package/src/components/i18n/locales/es/messages.json +7 -0
  159. package/src/components/i18n/locales/et/messages.json +7 -0
  160. package/src/components/i18n/locales/fa/messages.json +7 -0
  161. package/src/components/i18n/locales/fi/messages.json +7 -0
  162. package/src/components/i18n/locales/fil/messages.json +7 -0
  163. package/src/components/i18n/locales/fr/messages.json +7 -0
  164. package/src/components/i18n/locales/gu/messages.json +7 -0
  165. package/src/components/i18n/locales/he/messages.json +7 -0
  166. package/src/components/i18n/locales/hi/messages.json +7 -0
  167. package/src/components/i18n/locales/hr/messages.json +7 -0
  168. package/src/components/i18n/locales/hu/messages.json +7 -0
  169. package/src/components/i18n/locales/hy/messages.json +7 -0
  170. package/src/components/i18n/locales/id/messages.json +7 -0
  171. package/src/components/i18n/locales/it/messages.json +7 -0
  172. package/src/components/i18n/locales/ja/messages.json +7 -0
  173. package/src/components/i18n/locales/ka/messages.json +7 -0
  174. package/src/components/i18n/locales/km/messages.json +7 -0
  175. package/src/components/i18n/locales/kn/messages.json +7 -0
  176. package/src/components/i18n/locales/ko/messages.json +7 -0
  177. package/src/components/i18n/locales/ku/messages.json +7 -0
  178. package/src/components/i18n/locales/lo/messages.json +7 -0
  179. package/src/components/i18n/locales/lt/messages.json +7 -0
  180. package/src/components/i18n/locales/lv/messages.json +7 -0
  181. package/src/components/i18n/locales/mk/messages.json +7 -0
  182. package/src/components/i18n/locales/ml/messages.json +7 -0
  183. package/src/components/i18n/locales/mn/messages.json +7 -0
  184. package/src/components/i18n/locales/mr/messages.json +7 -0
  185. package/src/components/i18n/locales/ms/messages.json +7 -0
  186. package/src/components/i18n/locales/my/messages.json +7 -0
  187. package/src/components/i18n/locales/ne/messages.json +7 -0
  188. package/src/components/i18n/locales/nl/messages.json +7 -0
  189. package/src/components/i18n/locales/no/messages.json +7 -0
  190. package/src/components/i18n/locales/pa/messages.json +7 -0
  191. package/src/components/i18n/locales/pl/messages.json +7 -0
  192. package/src/components/i18n/locales/ps/messages.json +7 -0
  193. package/src/components/i18n/locales/pt/messages.json +7 -0
  194. package/src/components/i18n/locales/ro/messages.json +7 -0
  195. package/src/components/i18n/locales/ru/messages.json +7 -0
  196. package/src/components/i18n/locales/sd/messages.json +7 -0
  197. package/src/components/i18n/locales/si/messages.json +7 -0
  198. package/src/components/i18n/locales/sk/messages.json +7 -0
  199. package/src/components/i18n/locales/sl/messages.json +7 -0
  200. package/src/components/i18n/locales/sq/messages.json +7 -0
  201. package/src/components/i18n/locales/sr/messages.json +7 -0
  202. package/src/components/i18n/locales/sv/messages.json +7 -0
  203. package/src/components/i18n/locales/sw/messages.json +7 -0
  204. package/src/components/i18n/locales/ta/messages.json +7 -0
  205. package/src/components/i18n/locales/te/messages.json +7 -0
  206. package/src/components/i18n/locales/th/messages.json +7 -0
  207. package/src/components/i18n/locales/tr/messages.json +7 -0
  208. package/src/components/i18n/locales/ug/messages.json +7 -0
  209. package/src/components/i18n/locales/uk/messages.json +7 -0
  210. package/src/components/i18n/locales/ur/messages.json +7 -0
  211. package/src/components/i18n/locales/vi/messages.json +7 -0
  212. package/src/components/i18n/locales/yi/messages.json +7 -0
  213. package/src/components/i18n/locales/zh/messages.json +7 -0
  214. package/src/components/icons/index.ts +44 -7
  215. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +44 -2
  216. package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +54 -2
  217. package/src/components/modules/blockEvents/constants.ts +12 -0
  218. package/src/components/modules/blockEvents/index.ts +1 -3
  219. package/src/components/modules/blockManager/blockManager.ts +16 -0
  220. package/src/components/modules/blockManager/operations.ts +106 -9
  221. package/src/components/modules/blockSelection.ts +2 -0
  222. package/src/components/modules/caret.ts +49 -4
  223. package/src/components/modules/drag/DragController.ts +34 -2
  224. package/src/components/modules/paste/handlers/blok-data-handler.ts +50 -3
  225. package/src/components/modules/toolbar/index.ts +11 -16
  226. package/src/components/modules/ui.ts +12 -0
  227. package/src/components/ui/toolbox.ts +26 -2
  228. package/src/components/utils/notifier/draw.ts +116 -14
  229. package/src/components/utils/notifier/index.ts +31 -4
  230. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -2
  231. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +7 -7
  232. package/src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.const.ts +2 -2
  233. package/src/components/utils/popover/components/search-input/search-input.const.ts +1 -1
  234. package/src/components/utils/popover/popover-abstract.ts +5 -2
  235. package/src/components/utils/popover/popover-desktop.ts +39 -2
  236. package/src/components/utils/popover/popover.const.ts +3 -3
  237. package/src/full.ts +4 -0
  238. package/src/stories/Placeholder.stories.ts +7 -2
  239. package/src/stories/helpers.ts +2 -0
  240. package/src/styles/main.css +64 -10
  241. package/src/tools/header/index.ts +307 -26
  242. package/src/tools/index.ts +3 -1
  243. package/src/tools/table/index.ts +2 -3
  244. package/src/tools/table/table-add-controls.ts +29 -1
  245. package/src/tools/table/table-cell-blocks.ts +93 -0
  246. package/src/tools/toggle/block-operations.ts +110 -0
  247. package/src/tools/toggle/constants.ts +49 -0
  248. package/src/tools/toggle/dom-builder.ts +152 -0
  249. package/src/tools/toggle/index.ts +302 -0
  250. package/src/tools/toggle/toggle-keyboard.ts +156 -0
  251. package/src/tools/toggle/toggle-lifecycle.ts +81 -0
  252. package/src/tools/toggle/toggle-shortcuts.ts +113 -0
  253. package/src/tools/toggle/types.ts +21 -0
  254. package/types/full.d.ts +2 -0
  255. package/types/tools-entry.d.ts +2 -1
  256. package/types/utils/popover/popover.d.ts +8 -0
  257. package/dist/chunks/index-DBWWKrDe.mjs +0 -78
@@ -2,22 +2,39 @@ import { twMerge, twJoin } from '../tw';
2
2
 
3
3
  import type { NotifierOptions, ConfirmNotifierOptions, PromptNotifierOptions } from './types';
4
4
 
5
+ /**
6
+ * SVG icons for notification styles.
7
+ * Each icon is 16x16, stroke-based for consistency.
8
+ */
9
+ const ICONS = {
10
+ success: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6.25"/><path d="M5.5 8.25l1.75 1.75 3.25-3.5"/></svg>`,
11
+ error: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6.25"/><path d="M8 5.25v3"/><circle cx="8" cy="10.75" r="0.5" fill="currentColor" stroke="none"/></svg>`,
12
+ default: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6.25"/><path d="M8 7.25v3.25"/><circle cx="8" cy="5.25" r="0.5" fill="currentColor" stroke="none"/></svg>`,
13
+ };
14
+
15
+ const CLOSE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M2 2l6 6M8 2l-6 6"/></svg>`;
16
+
5
17
  export const CSS = {
6
18
  wrapper: twJoin(
7
19
  'fixed z-2 bottom-5 left-5',
8
20
  'font-[-apple-system,BlinkMacSystemFont,"Segoe_UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira_Sans","Droid_Sans","Helvetica_Neue",sans-serif]'
9
21
  ),
10
22
  notification: twJoin(
11
- 'relative w-[230px] mt-[15px] py-[13px] px-4',
12
- 'bg-white shadow-notify rounded-[5px]',
13
- 'text-sm leading-[1.4em] wrap-break-word',
23
+ 'relative flex items-start gap-2.5 w-[230px] mt-[15px] py-[13px] px-4',
24
+ 'bg-white shadow-notify rounded-[6px]',
25
+ 'text-sm leading-[1.4em] wrap-break-word overflow-hidden',
14
26
  'before:content-[""] before:absolute before:block before:top-0 before:left-0',
15
27
  'before:w-[3px] before:h-[calc(100%-6px)] before:m-[3px] before:rounded-[5px] before:bg-transparent'
16
28
  ),
29
+ icon: 'shrink-0 mt-px',
30
+ iconSuccess: 'text-[#34c992]',
31
+ iconError: 'text-[#fb5d5d]',
32
+ iconDefault: 'text-[#9ca3af]',
33
+ messageWrapper: 'flex-1 min-w-0',
17
34
  crossBtn: twJoin(
18
- 'absolute top-[7px] right-[15px] w-2.5 h-2.5 p-[5px] opacity-55 cursor-pointer',
19
- 'before:content-[""] before:absolute before:left-[9px] before:top-[5px] before:h-3 before:w-0.5 before:bg-[#575d67] before:-rotate-45',
20
- 'after:content-[""] after:absolute after:left-[9px] after:top-[5px] after:h-3 after:w-0.5 after:bg-[#575d67] after:rotate-45',
35
+ 'absolute top-[7px] right-[7px] flex items-center justify-center',
36
+ 'w-6 h-6 rounded opacity-40 cursor-pointer',
37
+ 'transition-opacity duration-150',
21
38
  'hover:opacity-100'
22
39
  ),
23
40
  btnsWrapper: 'flex flex-row flex-nowrap mt-[5px]',
@@ -37,6 +54,70 @@ export const CSS = {
37
54
  'bg-[#fffbfb]!',
38
55
  'before:bg-[#fb5d5d]!'
39
56
  ),
57
+ progressBar: twJoin(
58
+ 'absolute bottom-0 left-0 h-[2px] rounded-b-[6px]',
59
+ 'animate-notify-progress'
60
+ ),
61
+ progressDefault: 'bg-[#d1d5db]',
62
+ progressSuccess: 'bg-[#41ffb1]',
63
+ progressError: 'bg-[#fb5d5d]',
64
+ };
65
+
66
+ /**
67
+ * Creates an icon element for the notification.
68
+ */
69
+ const createIcon = (style?: string): HTMLElement => {
70
+ const iconWrapper = document.createElement('span');
71
+ const resolvedStyle = style === 'success' || style === 'error' ? style : 'default';
72
+
73
+ iconWrapper.innerHTML = ICONS[resolvedStyle];
74
+ iconWrapper.setAttribute('data-blok-testid', 'notification-icon');
75
+ iconWrapper.setAttribute('data-blok-style', resolvedStyle);
76
+
77
+ const iconColorMap: Record<string, string> = {
78
+ success: CSS.iconSuccess,
79
+ error: CSS.iconError,
80
+ default: CSS.iconDefault,
81
+ };
82
+
83
+ const colorClass = iconColorMap[resolvedStyle] ?? CSS.iconDefault;
84
+
85
+ iconWrapper.className = twJoin(CSS.icon, colorClass);
86
+
87
+ return iconWrapper;
88
+ };
89
+
90
+ /**
91
+ * Creates a close (cross) button with an SVG icon.
92
+ */
93
+ const createCloseButton = (): HTMLElement => {
94
+ const cross = document.createElement('div');
95
+
96
+ cross.className = CSS.crossBtn;
97
+ cross.setAttribute('data-blok-testid', 'notification-cross');
98
+ cross.innerHTML = CLOSE_ICON;
99
+
100
+ return cross;
101
+ };
102
+
103
+ /**
104
+ * Creates a progress bar element for auto-dismissing alerts.
105
+ */
106
+ export const createProgressBar = (style?: string, time?: number): HTMLElement => {
107
+ const bar = document.createElement('div');
108
+
109
+ const progressColorMap: Record<string, string> = {
110
+ success: CSS.progressSuccess,
111
+ error: CSS.progressError,
112
+ };
113
+
114
+ const colorClass = progressColorMap[style ?? ''] ?? CSS.progressDefault;
115
+
116
+ bar.className = twJoin(CSS.progressBar, colorClass);
117
+ bar.setAttribute('data-blok-testid', 'notification-progress');
118
+ bar.style.animationDuration = `${time ?? 8000}ms`;
119
+
120
+ return bar;
40
121
  };
41
122
 
42
123
  /**
@@ -45,8 +126,6 @@ export const CSS = {
45
126
  */
46
127
  export const alert = (options: NotifierOptions): HTMLElement => {
47
128
  const notify = document.createElement('DIV');
48
- const cross = document.createElement('DIV');
49
- const message = options.message;
50
129
  const style = options.style;
51
130
 
52
131
  const getStyleClasses = (): string => {
@@ -69,12 +148,23 @@ export const alert = (options: NotifierOptions): HTMLElement => {
69
148
  notify.setAttribute('data-blok-testid', 'notification');
70
149
  }
71
150
 
72
- notify.innerHTML = message;
151
+ // Icon
152
+ const icon = createIcon(style);
73
153
 
74
- cross.className = CSS.crossBtn;
75
- cross.setAttribute('data-blok-testid', 'notification-cross');
76
- cross.addEventListener('click', () => notify.remove());
154
+ notify.appendChild(icon);
155
+
156
+ // Message wrapper (flex child that holds message + buttons)
157
+ const messageWrapper = document.createElement('div');
158
+
159
+ messageWrapper.className = CSS.messageWrapper;
160
+ messageWrapper.setAttribute('data-blok-testid', 'notification-message');
161
+ messageWrapper.innerHTML = options.message;
162
+ notify.appendChild(messageWrapper);
163
+
164
+ // Close button
165
+ const cross = createCloseButton();
77
166
 
167
+ cross.addEventListener('click', () => notify.remove());
78
168
  notify.appendChild(cross);
79
169
 
80
170
  return notify;
@@ -86,6 +176,7 @@ export const alert = (options: NotifierOptions): HTMLElement => {
86
176
  */
87
177
  export const confirm = (options: ConfirmNotifierOptions): HTMLElement => {
88
178
  const notify = alert(options);
179
+ const messageWrapper = notify.querySelector('[data-blok-testid="notification-message"]') as HTMLElement;
89
180
  const btnsWrapper = document.createElement('div');
90
181
  const okBtn = document.createElement('button');
91
182
  const cancelBtn = document.createElement('button');
@@ -123,7 +214,12 @@ export const confirm = (options: ConfirmNotifierOptions): HTMLElement => {
123
214
  btnsWrapper.appendChild(okBtn);
124
215
  btnsWrapper.appendChild(cancelBtn);
125
216
 
126
- notify.appendChild(btnsWrapper);
217
+ // Append buttons to the message wrapper so they flow under the message text
218
+ if (messageWrapper) {
219
+ messageWrapper.appendChild(btnsWrapper);
220
+ } else {
221
+ notify.appendChild(btnsWrapper);
222
+ }
127
223
 
128
224
  return notify;
129
225
  };
@@ -134,6 +230,7 @@ export const confirm = (options: ConfirmNotifierOptions): HTMLElement => {
134
230
  */
135
231
  export const prompt = (options: PromptNotifierOptions): HTMLElement => {
136
232
  const notify = alert(options);
233
+ const messageWrapper = notify.querySelector('[data-blok-testid="notification-message"]') as HTMLElement;
137
234
  const btnsWrapper = document.createElement('div');
138
235
  const okBtn = document.createElement('button');
139
236
  const input = document.createElement('input');
@@ -176,7 +273,12 @@ export const prompt = (options: PromptNotifierOptions): HTMLElement => {
176
273
  btnsWrapper.appendChild(input);
177
274
  btnsWrapper.appendChild(okBtn);
178
275
 
179
- notify.appendChild(btnsWrapper);
276
+ // Append to message wrapper for proper flex layout
277
+ if (messageWrapper) {
278
+ messageWrapper.appendChild(btnsWrapper);
279
+ } else {
280
+ notify.appendChild(btnsWrapper);
281
+ }
180
282
 
181
283
  return notify;
182
284
  };
@@ -1,8 +1,19 @@
1
- import { alert, confirm, getWrapper, prompt } from './draw';
1
+ import { alert, confirm, createProgressBar, getWrapper, prompt } from './draw';
2
2
  import type { NotifierOptions, ConfirmNotifierOptions, PromptNotifierOptions } from './types';
3
3
 
4
4
  const DEFAULT_TIME = 8000;
5
5
 
6
+ /**
7
+ * Applies the exit animation and removes the element after it finishes.
8
+ */
9
+ const dismissWithAnimation = (element: HTMLElement): void => {
10
+ element.classList.add('animate-notify-slide-out');
11
+
12
+ element.addEventListener('animationend', () => {
13
+ element.remove();
14
+ }, { once: true });
15
+ };
16
+
6
17
  /**
7
18
  * Prepare wrapper for notifications
8
19
  * @returns {HTMLElement}
@@ -48,8 +59,24 @@ export const show = (options: NotifierOptions | ConfirmNotifierOptions | PromptN
48
59
  // type is 'alert' or undefined
49
60
  const alertElement = alert(options);
50
61
 
62
+ // Add progress bar for auto-dismissing alerts
63
+ const progressBar = createProgressBar(options.style, time);
64
+
65
+ alertElement.appendChild(progressBar);
66
+
67
+ // Wire up the close button to use animated dismissal
68
+ const crossBtn = alertElement.querySelector('[data-blok-testid="notification-cross"]');
69
+
70
+ if (crossBtn) {
71
+ // Replace the basic remove handler with animated dismissal
72
+ const newCross = crossBtn.cloneNode(true) as HTMLElement;
73
+
74
+ crossBtn.replaceWith(newCross);
75
+ newCross.addEventListener('click', () => dismissWithAnimation(alertElement));
76
+ }
77
+
51
78
  window.setTimeout(() => {
52
- alertElement.remove();
79
+ dismissWithAnimation(alertElement);
53
80
  }, time);
54
81
 
55
82
  return alertElement;
@@ -57,11 +84,11 @@ export const show = (options: NotifierOptions | ConfirmNotifierOptions | PromptN
57
84
 
58
85
  if (wrapper && notify) {
59
86
  wrapper.appendChild(notify);
60
- notify.className = `${notify.className} animate-notify-bounce-in`;
87
+ notify.className = `${notify.className} animate-notify-slide-in`;
61
88
  notify.setAttribute('data-blok-bounce-in', 'true');
62
89
  }
63
90
  };
64
91
 
65
92
  export const Notifier = {
66
93
  show,
67
- };
94
+ };
@@ -10,7 +10,7 @@ export const css = {
10
10
  * Note: noHover state is handled via [data-blok-popover-item-no-hover] which disables hover
11
11
  * Priority order: active < hover < focus (focus wins when navigating with keyboard)
12
12
  */
13
- item: 'flex items-center select-none border-none bg-transparent rounded-md px-2 py-(--item-padding) text-text-primary mb-px data-blok-popover-item-active:bg-icon-active-bg data-blok-popover-item-active:text-icon-active-text can-hover:hover:cursor-pointer can-hover:hover:bg-item-hover-bg data-blok-force-hover:cursor-pointer data-blok-force-hover:bg-item-hover-bg data-[blok-focused="true"]:bg-item-focus-bg data-blok-popover-item-no-hover:hover:bg-transparent data-blok-popover-item-no-hover:cursor-default can-hover:data-blok-popover-item-destructive:hover:text-item-destructive-text can-hover:data-blok-popover-item-destructive:hover:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-force-hover]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-force-hover]]:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:bg-item-destructive-hover-bg',
13
+ item: 'flex items-center select-none border-none bg-transparent rounded-lg px-2 py-(--item-padding) text-text-primary mb-0.5 transition-[color,background-color,border-color,opacity,max-height,padding,margin] duration-150 max-h-10 overflow-hidden data-blok-popover-item-active:bg-icon-active-bg data-blok-popover-item-active:text-icon-active-text can-hover:hover:cursor-pointer can-hover:hover:bg-item-hover-bg data-blok-force-hover:cursor-pointer data-blok-force-hover:bg-item-hover-bg data-[blok-focused="true"]:bg-item-focus-bg data-blok-popover-item-no-hover:hover:bg-transparent data-blok-popover-item-no-hover:cursor-default can-hover:data-blok-popover-item-destructive:hover:text-item-destructive-text can-hover:data-blok-popover-item-destructive:hover:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-force-hover]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-force-hover]]:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:bg-item-destructive-hover-bg',
14
14
 
15
15
  /**
16
16
  * Item disabled state
@@ -21,7 +21,7 @@ export const css = {
21
21
  /**
22
22
  * Icon container styles
23
23
  */
24
- icon: 'flex items-center justify-center w-[26px] h-[26px] [&_svg]:w-icon [&_svg]:h-icon',
24
+ icon: 'flex items-center justify-center w-[26px] h-[26px] shrink-0 rounded-lg [&_svg]:w-icon [&_svg]:h-icon',
25
25
 
26
26
  /**
27
27
  * Focused state class for DomIterator/Flipper keyboard navigation.
@@ -258,8 +258,8 @@ export class PopoverItemDefault extends PopoverItem {
258
258
  const titleEl = document.createElement('div');
259
259
 
260
260
  titleEl.className = params.secondaryLabel
261
- ? 'grow truncate text-sm font-medium leading-5'
262
- : 'mr-auto truncate text-sm font-medium leading-5';
261
+ ? 'grow whitespace-nowrap text-sm font-medium leading-5'
262
+ : 'mr-auto whitespace-nowrap text-sm font-medium leading-5';
263
263
  titleEl.setAttribute(DATA_ATTR.popoverItemTitle, '');
264
264
  titleEl.setAttribute('data-blok-testid', 'popover-item-title');
265
265
  titleEl.textContent = title;
@@ -272,7 +272,7 @@ export class PopoverItemDefault extends PopoverItem {
272
272
  if (params.secondaryLabel) {
273
273
  const secondaryEl = document.createElement('div');
274
274
 
275
- secondaryEl.className = 'min-w-14 text-right whitespace-nowrap pl-3 pr-1.5 text-xs font-light tracking-[0.25px] text-text-secondary opacity-60';
275
+ secondaryEl.className = 'ml-auto shrink-0 flex items-center whitespace-nowrap pl-20 text-[11px] font-medium tracking-wide text-text-secondary/50';
276
276
  secondaryEl.setAttribute(DATA_ATTR.popoverItemSecondaryTitle, '');
277
277
  secondaryEl.setAttribute('data-blok-testid', 'popover-item-secondary-title');
278
278
  secondaryEl.textContent = params.secondaryLabel;
@@ -326,8 +326,7 @@ export class PopoverItemDefault extends PopoverItem {
326
326
 
327
327
  return twMerge(
328
328
  css.item,
329
- // Asymmetric padding: pr-8 for visual balance, pr-2 when secondary label or chevron occupies right edge
330
- !isInline && !isNestedInline && (this.params.secondaryLabel || (this.hasChildren && !this.isChevronHidden) ? 'pl-2 pr-2' : 'pl-2 pr-8'),
329
+ !isInline && !isNestedInline && 'pl-2 pr-4',
331
330
  isInline && cssInline.item,
332
331
  isNestedInline && cssNestedInline.item,
333
332
  this.params.isDisabled && css.itemDisabled
@@ -343,6 +342,7 @@ export class PopoverItemDefault extends PopoverItem {
343
342
  isInline && 'w-auto h-auto [&_svg]:w-icon [&_svg]:h-icon mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile',
344
343
  isNestedInline && 'w-toolbox-btn h-toolbox-btn',
345
344
  iconWithGap && 'mr-3',
345
+ iconWithGap && !isInline && 'bg-icon-bg',
346
346
  iconWithGap && isInline && 'shadow-none bg-transparent mr-0!',
347
347
  iconWithGap && isNestedInline && 'mr-2!',
348
348
  isWobbling && 'animate-wobble'
@@ -384,10 +384,10 @@ export class PopoverItemDefault extends PopoverItem {
384
384
 
385
385
  if (isHidden) {
386
386
  this.nodes.root.setAttribute(DATA_ATTR.hidden, 'true');
387
- this.nodes.root.classList.add('hidden!');
387
+ this.nodes.root.classList.add('opacity-0', 'max-h-0!', 'py-0!', 'mb-0!');
388
388
  } else {
389
389
  this.nodes.root.removeAttribute(DATA_ATTR.hidden);
390
- this.nodes.root.classList.remove('hidden!');
390
+ this.nodes.root.classList.remove('opacity-0', 'max-h-0!', 'py-0!', 'mb-0!');
391
391
  }
392
392
  }
393
393
 
@@ -2,8 +2,8 @@
2
2
  * Tailwind CSS classes for popover separator component
3
3
  */
4
4
  export const css = {
5
- container: 'py-1 px-[3px]',
6
- containerHidden: 'hidden',
5
+ container: 'py-1 px-[3px] transition-[opacity,max-height,padding] duration-150 max-h-4 overflow-hidden',
6
+ containerHidden: 'opacity-0 max-h-0! py-0!',
7
7
  line: 'h-px w-full bg-popover-border',
8
8
  };
9
9
 
@@ -2,7 +2,7 @@
2
2
  * CSS class names to be used in popover search input class
3
3
  */
4
4
  export const css = {
5
- wrapper: 'bg-[#F8F8F8] border border-[rgba(226,226,229,0.20)] rounded-sm p-0.5 grid grid-cols-[auto_auto_1fr] grid-rows-[auto]',
5
+ wrapper: 'bg-[#F8F8F8] border border-[rgba(226,226,229,0.20)] rounded-lg p-0.5 grid grid-cols-[auto_auto_1fr] grid-rows-[auto] transition-colors duration-150 focus-within:bg-white focus-within:border-[rgba(56,138,229,0.3)]',
6
6
  icon: 'w-toolbox-btn h-toolbox-btn flex items-center justify-center mr-2 [&_svg]:w-icon [&_svg]:h-icon [&_svg]:text-gray-text',
7
7
  input: "text-sm outline-hidden font-medium font-inherit border-0 bg-transparent m-0 p-0 leading-[22px] min-w-[calc(100%-(--spacing(6))-10px)] placeholder:text-gray-text placeholder:font-medium",
8
8
  };
@@ -391,9 +391,11 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
391
391
  protected toggleNothingFoundMessage(isDisplayed: boolean): void {
392
392
  if (isDisplayed) {
393
393
  this.nodes.nothingFoundMessage.classList.remove('hidden');
394
+ this.nodes.nothingFoundMessage.classList.add('animate-[fade-in_150ms_ease_forwards]');
394
395
  this.nodes.nothingFoundMessage.setAttribute(DATA_ATTR.nothingFoundDisplayed, 'true');
395
396
  } else {
396
397
  this.nodes.nothingFoundMessage.classList.add('hidden');
398
+ this.nodes.nothingFoundMessage.classList.remove('animate-[fade-in_150ms_ease_forwards]');
397
399
  this.nodes.nothingFoundMessage.removeAttribute(DATA_ATTR.nothingFoundDisplayed);
398
400
  }
399
401
  }
@@ -449,11 +451,12 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
449
451
 
450
452
  // Set CSS variables
451
453
  popover.style.setProperty('--width', this.params.width ?? 'auto');
452
- popover.style.setProperty('--item-padding', '3px');
454
+ popover.style.setProperty('--item-padding', '4px');
453
455
  popover.style.setProperty('--item-height', 'calc(1.25rem + 2 * var(--item-padding))');
454
456
  popover.style.setProperty('--popover-top', 'calc(100% + 0.5rem)');
455
457
  popover.style.setProperty('--popover-left', '0');
456
458
  popover.style.setProperty('--nested-popover-overlap', '0.25rem');
459
+ popover.style.setProperty('--max-height', '400px');
457
460
 
458
461
  // Create popover container
459
462
  const popoverContainer = document.createElement('div');
@@ -464,7 +467,7 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
464
467
  // Create nothing found message
465
468
  const nothingFoundMessage = document.createElement('div');
466
469
  nothingFoundMessage.className = twMerge(
467
- 'cursor-default text-sm leading-5 font-medium whitespace-nowrap overflow-hidden text-ellipsis text-gray-text p-[3px]',
470
+ 'cursor-default text-sm leading-5 font-medium whitespace-nowrap overflow-hidden text-ellipsis text-gray-text px-3 py-3 text-center',
468
471
  'hidden'
469
472
  );
470
473
  nothingFoundMessage.setAttribute('data-blok-testid', 'popover-nothing-found');
@@ -60,6 +60,12 @@ export class PopoverDesktop extends PopoverAbstract {
60
60
  */
61
61
  private trigger: HTMLElement | undefined;
62
62
 
63
+ /**
64
+ * Optional element whose left edge is used for horizontal positioning
65
+ * instead of the trigger's left edge.
66
+ */
67
+ private leftAlignElement: HTMLElement | undefined;
68
+
63
69
  /**
64
70
  * Popover size cache
65
71
  */
@@ -78,6 +84,10 @@ export class PopoverDesktop extends PopoverAbstract {
78
84
  this.trigger = params.trigger;
79
85
  }
80
86
 
87
+ if (params.leftAlignElement) {
88
+ this.leftAlignElement = params.leftAlignElement;
89
+ }
90
+
81
91
  if (params.nestingLevel !== undefined) {
82
92
  this.nestingLevel = params.nestingLevel;
83
93
  }
@@ -191,7 +201,13 @@ export class PopoverDesktop extends PopoverAbstract {
191
201
  this.nodes.popover.style.setProperty(CSSVariables.PopoverLeft, '0px');
192
202
  }
193
203
 
194
- this.nodes.popover.style.setProperty(CSSVariables.PopoverHeight, this.size.height + 'px');
204
+ const measuredSize = this.size;
205
+
206
+ this.nodes.popover.style.setProperty(CSSVariables.PopoverHeight, measuredSize.height + 'px');
207
+
208
+ if (this.params.width === undefined || this.params.width === 'auto') {
209
+ this.nodes.popover.style.setProperty('--width', measuredSize.width + 'px');
210
+ }
195
211
 
196
212
  if (!this.trigger && !this.shouldOpenBottom) {
197
213
  this.setOpenTop(true);
@@ -270,7 +286,7 @@ export class PopoverDesktop extends PopoverAbstract {
270
286
  (rect.top - offset - popoverRect.height > window.scrollY);
271
287
  const top = shouldFlipTop ? rect.top - offset - popoverRect.height + window.scrollY : initialTop;
272
288
 
273
- const initialLeft = rect.left + window.scrollX;
289
+ const initialLeft = (this.leftAlignElement?.getBoundingClientRect().left ?? rect.left) + window.scrollX;
274
290
  const shouldFlipLeft = initialLeft + popoverRect.width > windowWidth + window.scrollX;
275
291
  const left = shouldFlipLeft ? Math.max(0, rect.right - popoverRect.width + window.scrollX) : initialLeft;
276
292
 
@@ -695,6 +711,18 @@ export class PopoverDesktop extends PopoverAbstract {
695
711
  // Cast data.items to PopoverItemDefault[] since we know that's what filterItems passes
696
712
  const matchingItems = data.items as unknown as PopoverItemDefault[];
697
713
 
714
+ /**
715
+ * When nothing is found, disable transitions so items hide instantly.
716
+ * The "Nothing found" message fade-in provides the visual transition;
717
+ * animating the last items' collapse simultaneously causes a jarring
718
+ * height bounce in the popover container.
719
+ */
720
+ if (isNothingFound) {
721
+ this.items.forEach(item => {
722
+ item.getElement()?.style.setProperty('transition-duration', '0s');
723
+ });
724
+ }
725
+
698
726
  this.items
699
727
  .forEach((item) => {
700
728
  const isDefaultItem = item instanceof PopoverItemDefault;
@@ -705,6 +733,15 @@ export class PopoverDesktop extends PopoverAbstract {
705
733
 
706
734
  item.toggleHidden(isHidden);
707
735
  });
736
+
737
+ if (isNothingFound) {
738
+ // Force reflow so the instant hide takes effect, then restore transitions
739
+ this.nodes.popoverContainer.offsetHeight;
740
+ this.items.forEach(item => {
741
+ item.getElement()?.style.removeProperty('transition-duration');
742
+ });
743
+ }
744
+
708
745
  this.toggleNothingFoundMessage(isNothingFound);
709
746
 
710
747
  /** List of elements available for keyboard navigation considering search query applied */
@@ -5,19 +5,19 @@
5
5
  */
6
6
  export const css = {
7
7
  // Popover container - base styles
8
- popoverContainer: 'absolute flex flex-col overflow-hidden box-border opacity-0 pointer-events-none p-0 border-none z-4 max-h-0 min-w-(--width) w-(--width) rounded-lg shadow-[0_3px_15px_-3px_var(--color-popover-shadow)] left-(--popover-left) top-(--popover-top) bg-popover-bg',
8
+ popoverContainer: 'absolute flex flex-col overflow-hidden box-border opacity-0 pointer-events-none p-0 border-none z-4 max-h-0 min-w-(--width) w-(--width) rounded-xl shadow-[0_4px_20px_-4px_var(--color-popover-shadow),0_0_0_0.5px_rgba(0,0,0,0.06)] left-(--popover-left) top-(--popover-top) bg-popover-bg',
9
9
 
10
10
  // Popover container - mobile styles (applied conditionally)
11
11
  // Reset left/top from base class since inset shorthand may not properly override them in twMerge
12
12
  popoverContainerMobile: 'fixed max-w-none rounded-[10px] min-w-[calc(100%-var(--offset)*2)] left-auto top-auto inset-[auto_var(--offset)_calc(var(--offset)+env(safe-area-inset-bottom))_var(--offset)]',
13
13
 
14
14
  // Popover container - opened state
15
- popoverContainerOpened: 'opacity-100 pointer-events-auto p-1 max-h-(--max-height) border border-popover-border animate-[panelShowing_100ms_ease]',
15
+ popoverContainerOpened: 'opacity-100 pointer-events-auto p-1.5 max-h-(--max-height) border border-popover-border animate-[panelShowing_100ms_ease]',
16
16
 
17
17
  // Popover overlay
18
18
  popoverOverlay: 'hidden bg-dark',
19
19
 
20
- items: 'overflow-y-auto overscroll-contain',
20
+ items: 'overflow-y-auto overscroll-contain [scrollbar-gutter:stable] pr-1',
21
21
  };
22
22
 
23
23
  /**
package/src/full.ts CHANGED
@@ -18,6 +18,7 @@
18
18
  import { BoldInlineTool as Bold } from './components/inline-tools/inline-tool-bold';
19
19
  import { ItalicInlineTool as Italic } from './components/inline-tools/inline-tool-italic';
20
20
  import { LinkInlineTool as Link } from './components/inline-tools/inline-tool-link';
21
+ import { MarkerInlineTool as Marker } from './components/inline-tools/inline-tool-marker';
21
22
  import { Header } from './tools/header';
22
23
  import { ListItem as List } from './tools/list';
23
24
  import { Paragraph } from './tools/paragraph';
@@ -29,9 +30,11 @@ export {
29
30
  Paragraph,
30
31
  Header,
31
32
  List,
33
+ Toggle,
32
34
  Bold,
33
35
  Italic,
34
36
  Link,
37
+ Marker,
35
38
  defaultBlockTools,
36
39
  defaultInlineTools,
37
40
  } from './tools';
@@ -66,4 +69,5 @@ export const allTools = {
66
69
  bold: { class: Bold },
67
70
  italic: { class: Italic },
68
71
  link: { class: Link },
72
+ marker: { class: Marker },
69
73
  } as const;
@@ -171,10 +171,15 @@ export const TypeAndClearPlaceholder: Story = {
171
171
 
172
172
  if (contentEditable) {
173
173
  await userEvent.click(contentEditable);
174
- await userEvent.type(contentEditable, 'Hello world');
174
+ await userEvent.keyboard('Hello world');
175
175
  }
176
176
 
177
- expect(contentEditable?.textContent).toContain('Hello world');
177
+ await waitFor(
178
+ () => {
179
+ expect(contentEditable?.textContent).toContain('Hello world');
180
+ },
181
+ TIMEOUT_ACTION
182
+ );
178
183
  });
179
184
 
180
185
  await step('Clear content to restore placeholder', async () => {
@@ -8,6 +8,7 @@ import { BoldInlineTool } from '../components/inline-tools/inline-tool-bold';
8
8
  import { ConvertInlineTool } from '../components/inline-tools/inline-tool-convert';
9
9
  import { ItalicInlineTool } from '../components/inline-tools/inline-tool-italic';
10
10
  import { LinkInlineTool } from '../components/inline-tools/inline-tool-link';
11
+ import { MarkerInlineTool } from '../components/inline-tools/inline-tool-marker';
11
12
  import { Header } from '../tools/header';
12
13
  import { ListItem } from '../tools/list';
13
14
  import { Paragraph } from '../tools/paragraph';
@@ -35,6 +36,7 @@ export const defaultTools: { [toolName: string]: ToolConstructable | ToolSetting
35
36
  bold: BoldInlineTool,
36
37
  italic: ItalicInlineTool,
37
38
  link: LinkInlineTool,
39
+ marker: MarkerInlineTool,
38
40
  convertTo: ConvertInlineTool,
39
41
  };
40
42