@jackuait/blok 0.10.3 → 0.10.5

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 (286) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-3wc3aInM.mjs → blok-DSP5zC_s.mjs} +2374 -2159
  3. package/dist/chunks/{constants-Bp622jic.mjs → constants-B0Tns0mh.mjs} +318 -227
  4. package/dist/chunks/{i18next-loader-CDnSPae_.mjs → i18next-loader-D_v0EmDP.mjs} +1 -1
  5. package/dist/chunks/{lightweight-i18n-DZmo8dAI.mjs → lightweight-i18n-DTYoSr_o.mjs} +21 -0
  6. package/dist/{messages-bkGniiaz.mjs → chunks/messages--X-ZzYSb.mjs} +24 -3
  7. package/dist/chunks/{messages-DrfRYiM32.mjs → messages--tSqMtkx2.mjs} +24 -3
  8. package/dist/chunks/{messages-CW35K1pq.mjs → messages-3w1e16T2.mjs} +25 -4
  9. package/dist/chunks/{messages-BHMiK51R.mjs → messages-B5BaA6AV.mjs} +24 -3
  10. package/dist/{messages-DKHbt-7l2.mjs → chunks/messages-B5ZVSxG4.mjs} +25 -4
  11. package/dist/chunks/{messages-kGmxkeFH.mjs → messages-B9PUHq4t.mjs} +24 -3
  12. package/dist/chunks/{messages-BlxwW7M6.mjs → messages-BAxCMQgm.mjs} +24 -3
  13. package/dist/chunks/{messages-BRAoJpOu.mjs → messages-BDhWRN6Y.mjs} +25 -4
  14. package/dist/{messages-CdEASHDp2.mjs → chunks/messages-BGpx2ecP2.mjs} +24 -3
  15. package/dist/{messages-C6ONf71u2.mjs → chunks/messages-BHUQs6402.mjs} +24 -3
  16. package/dist/{messages-BrOWqNCu2.mjs → chunks/messages-BIXCvkbG.mjs} +24 -3
  17. package/dist/chunks/{messages-DMoERagV2.mjs → messages-BKeL1zk-2.mjs} +24 -3
  18. package/dist/chunks/{messages-DjvaiALg2.mjs → messages-Bedied602.mjs} +24 -3
  19. package/dist/chunks/{messages-oMc7qugU2.mjs → messages-Bg8uBETk2.mjs} +24 -3
  20. package/dist/{messages-CRNogopy2.mjs → chunks/messages-Blg1X6YL.mjs} +24 -3
  21. package/dist/chunks/{messages-euM2m3wQ.mjs → messages-BmDMK9Dg.mjs} +24 -3
  22. package/dist/{messages-D3rwCtKn.mjs → chunks/messages-BmDw1fZF2.mjs} +24 -3
  23. package/dist/{messages-qfvXgPpu2.mjs → chunks/messages-BqKIunt0.mjs} +24 -3
  24. package/dist/chunks/{messages-BfAcUavP.mjs → messages-BszGK0ox.mjs} +26 -5
  25. package/dist/{messages-BckDk9aq2.mjs → chunks/messages-Buwm8xrX2.mjs} +24 -3
  26. package/dist/chunks/{messages-CC_noR8y.mjs → messages-BvoElEE_.mjs} +24 -3
  27. package/dist/chunks/{messages-zt6zdYWh.mjs → messages-ByHXyVi6.mjs} +23 -2
  28. package/dist/chunks/{messages-DBMaLL8b2.mjs → messages-C9HPruJj2.mjs} +24 -3
  29. package/dist/{messages-DQORja0D.mjs → chunks/messages-CDtmVcBc.mjs} +26 -5
  30. package/dist/chunks/{messages-wl8YrvGG.mjs → messages-CEWKcK-Q.mjs} +23 -2
  31. package/dist/chunks/{messages-CZSlfnkO2.mjs → messages-CRLvJfNU2.mjs} +22 -1
  32. package/dist/chunks/{messages-BRoa9tGl.mjs → messages-CXjSY5Fy.mjs} +24 -3
  33. package/dist/{messages-BesJaI6A.mjs → chunks/messages-CdWS0hvw.mjs} +29 -8
  34. package/dist/{messages-JNrYldAa2.mjs → chunks/messages-Cic0Y1z6.mjs} +24 -3
  35. package/dist/chunks/{messages-CTCe595D2.mjs → messages-CmGixnBb2.mjs} +24 -3
  36. package/dist/chunks/{messages-JSQjKQ8I.mjs → messages-CrCalcxK.mjs} +24 -3
  37. package/dist/chunks/{messages-DUr9WAkD.mjs → messages-D3wlt9eE.mjs} +22 -1
  38. package/dist/{messages-CdduYw-q.mjs → chunks/messages-D5NWb-B9.mjs} +23 -2
  39. package/dist/chunks/{messages-CRF7nNrO.mjs → messages-D5lY22F4.mjs} +24 -3
  40. package/dist/{messages-_PLyRfVw.mjs → chunks/messages-DGYjioKM.mjs} +26 -5
  41. package/dist/{messages-Che99vKP.mjs → chunks/messages-DIH2U0ZD.mjs} +24 -3
  42. package/dist/chunks/{messages-BJ-vT1SU2.mjs → messages-DIUegdwv2.mjs} +24 -3
  43. package/dist/chunks/{messages-BgM91Lxm2.mjs → messages-DKZHsfXy2.mjs} +25 -4
  44. package/dist/chunks/{messages-1_6UkKLS.mjs → messages-DKjUcEfs.mjs} +24 -3
  45. package/dist/{messages-C1vc5584.mjs → chunks/messages-DOPK-Xif2.mjs} +24 -3
  46. package/dist/chunks/{messages-DB_-5Xln.mjs → messages-DSMFg80t.mjs} +25 -4
  47. package/dist/{messages-A96tMxeU.mjs → chunks/messages-DT6eM0I22.mjs} +22 -1
  48. package/dist/chunks/{messages-DUeiPraX.mjs → messages-DZTQIS9F.mjs} +24 -3
  49. package/dist/{messages-apA6BStA.mjs → chunks/messages-DalLfJNC.mjs} +24 -3
  50. package/dist/chunks/{messages-QilfinOn2.mjs → messages-DggaAu362.mjs} +24 -3
  51. package/dist/chunks/{messages-CxxyR4vY.mjs → messages-DgoJDjHm.mjs} +24 -3
  52. package/dist/chunks/{messages-ElIGUi0O2.mjs → messages-DhgEjOjw2.mjs} +25 -4
  53. package/dist/chunks/{messages-sDdNf8O9.mjs → messages-Dk-d3mmM.mjs} +22 -1
  54. package/dist/{messages-BE_z-zrb.mjs → chunks/messages-DlTG06-j.mjs} +25 -4
  55. package/dist/chunks/{messages-C0IFfhnp.mjs → messages-Dle6Hv30.mjs} +22 -1
  56. package/dist/{messages-DBhvm8NK.mjs → chunks/messages-DoD9yWMu2.mjs} +22 -1
  57. package/dist/{messages-D0lLw9KM.mjs → chunks/messages-DpnhbDoK2.mjs} +24 -3
  58. package/dist/{messages-DODrhcop.mjs → chunks/messages-DqGv-lj6.mjs} +24 -3
  59. package/dist/{messages-CZbcxlZt2.mjs → chunks/messages-DslnYTHU2.mjs} +24 -3
  60. package/dist/chunks/{messages-Du2BffA7.mjs → messages-IjEU7XAq.mjs} +24 -3
  61. package/dist/chunks/{messages-BK8Cp2d0.mjs → messages-JRjsu_bC.mjs} +24 -3
  62. package/dist/chunks/{messages-CszmHAvQ.mjs → messages-PkO_43Eb.mjs} +24 -3
  63. package/dist/chunks/{messages-CQBo3lmL2.mjs → messages-W2zpf0Mu2.mjs} +24 -3
  64. package/dist/{messages-Do7Xjy0n.mjs → chunks/messages-adEATsLK.mjs} +23 -2
  65. package/dist/{messages-E8NjqzWq2.mjs → chunks/messages-b8XGiuAa2.mjs} +23 -2
  66. package/dist/{messages-CisR4PNV.mjs → chunks/messages-bteFpBer.mjs} +24 -3
  67. package/dist/chunks/{messages-DVr1sqfI2.mjs → messages-cR48x2Aq2.mjs} +24 -3
  68. package/dist/chunks/{messages-4Ck88DYZ2.mjs → messages-f-YBthdd2.mjs} +24 -3
  69. package/dist/{messages-Xc0KUbYl.mjs → chunks/messages-fUpUvsRN.mjs} +25 -4
  70. package/dist/{messages-Be_2RHZD.mjs → chunks/messages-gNK1EolD.mjs} +25 -4
  71. package/dist/{messages-DfFZ6Yj5.mjs → chunks/messages-vqR3RAU4.mjs} +24 -3
  72. package/dist/{messages-BbJ7ZXY8.mjs → chunks/messages-wSX_4fK1.mjs} +24 -3
  73. package/dist/chunks/{tools-BC1jRfoS.mjs → tools-KZmhOKEo.mjs} +3407 -1299
  74. package/dist/full.mjs +10 -10
  75. package/dist/locales.mjs +88 -67
  76. package/dist/{chunks/messages-D22e9h7V2.mjs → messages--zgIPYtb.mjs} +22 -1
  77. package/dist/{chunks/messages-EDMC5ukV.mjs → messages-4jULpVvw.mjs} +24 -3
  78. package/dist/{messages-DK6dA0O2.mjs → messages-AbwSlRf_.mjs} +26 -5
  79. package/dist/{messages-Ddq3Ce3E2.mjs → messages-B-dl7Pwb2.mjs} +25 -4
  80. package/dist/{chunks/messages-BAlZjPcl.mjs → messages-B3rCRhb1.mjs} +24 -3
  81. package/dist/{chunks/messages-DSrdy9Nw2.mjs → messages-B73L8nKc2.mjs} +24 -3
  82. package/dist/{messages-ClGvlFcH2.mjs → messages-BAjsD2Vm2.mjs} +24 -3
  83. package/dist/{chunks/messages-BbEW9bQz.mjs → messages-BBodSb5B2.mjs} +24 -3
  84. package/dist/{messages-DopaMHC42.mjs → messages-BTpn6H9x2.mjs} +22 -1
  85. package/dist/{messages-D0005ti32.mjs → messages-BWb0GjTj2.mjs} +24 -3
  86. package/dist/{messages-Q5sQeVap2.mjs → messages-BbCgnri12.mjs} +24 -3
  87. package/dist/{chunks/messages-BeGZqQwz.mjs → messages-Bfon_Y3q.mjs} +25 -4
  88. package/dist/{messages-CTTmWn4Y2.mjs → messages-BhOtow9J2.mjs} +24 -3
  89. package/dist/{messages-98nQiC7t2.mjs → messages-BoB7m0uu2.mjs} +25 -4
  90. package/dist/{messages-CT-Kdas6.mjs → messages-BsOZPjeg.mjs} +24 -3
  91. package/dist/{messages-D6VIFnSW.mjs → messages-BuzKUYPV.mjs} +24 -3
  92. package/dist/{chunks/messages-DEBy3nuJ2.mjs → messages-BzOKMdMQ.mjs} +22 -1
  93. package/dist/{messages-DOGbHYv-2.mjs → messages-C2H3PeQW2.mjs} +24 -3
  94. package/dist/{chunks/messages-DxHh0O8j2.mjs → messages-C5KNzSTk.mjs} +24 -3
  95. package/dist/{chunks/messages-eFd4YYzt.mjs → messages-CIDYjE6l.mjs} +24 -3
  96. package/dist/{messages-Dqu4aX9s.mjs → messages-CJmyF5ye.mjs} +23 -2
  97. package/dist/{messages-qbKjjvgd2.mjs → messages-CTwiYb2a2.mjs} +22 -1
  98. package/dist/{chunks/messages-CPBN4zWc.mjs → messages-CUHoJaDO.mjs} +24 -3
  99. package/dist/{messages-D05jqBIa2.mjs → messages-CVeuqUjQ2.mjs} +24 -3
  100. package/dist/{chunks/messages-BMD37y3q2.mjs → messages-CW75b4sz.mjs} +24 -3
  101. package/dist/{chunks/messages-CD_MnBln.mjs → messages-CXd7YeWV.mjs} +24 -3
  102. package/dist/{messages-DVL0KZE5.mjs → messages-CjlYkunD.mjs} +24 -3
  103. package/dist/{chunks/messages-BKN3YVIj.mjs → messages-CrGx64yd.mjs} +25 -4
  104. package/dist/{messages-BK_LsgY4.mjs → messages-Ct0jbgHd.mjs} +24 -3
  105. package/dist/{messages-BmH2cQHQ.mjs → messages-CtKrCYD1.mjs} +24 -3
  106. package/dist/{messages-neGD3WGq.mjs → messages-Cu2eLjfJ.mjs} +24 -3
  107. package/dist/{messages-Brd5R-da2.mjs → messages-CvwQ-fK_2.mjs} +24 -3
  108. package/dist/{messages-uwK7ktqk.mjs → messages-Cy6UYN9b.mjs} +22 -1
  109. package/dist/{chunks/messages-ChK7v1PV.mjs → messages-D01vnfA9.mjs} +24 -3
  110. package/dist/{messages-DpwMKDV0.mjs → messages-D0BAV45W.mjs} +24 -3
  111. package/dist/{messages-LMaR2_bE.mjs → messages-D5LGpdga.mjs} +24 -3
  112. package/dist/{messages-BcVB3osF.mjs → messages-DATK4ftv.mjs} +25 -4
  113. package/dist/{chunks/messages-Bz0-KNEB.mjs → messages-DEl77Urv2.mjs} +25 -4
  114. package/dist/{messages-DSmxJWju2.mjs → messages-DHNjM2nv2.mjs} +22 -1
  115. package/dist/{messages-DYuD5-rO.mjs → messages-DMW8b_sO.mjs} +24 -3
  116. package/dist/{chunks/messages-DPzHD51Y.mjs → messages-DNmgANKr.mjs} +23 -2
  117. package/dist/{chunks/messages-C1S9ztpF.mjs → messages-DQaa3cEM.mjs} +25 -4
  118. package/dist/{chunks/messages-a07QVz8U.mjs → messages-DSlD4bV9.mjs} +24 -3
  119. package/dist/{messages-DM4Gjc9h.mjs → messages-DTzbkXFt.mjs} +24 -3
  120. package/dist/{messages-LYJbLq_F.mjs → messages-DbZihxtV.mjs} +24 -3
  121. package/dist/{messages-C_Qn9SbQ.mjs → messages-DeE8fyKQ.mjs} +24 -3
  122. package/dist/{chunks/messages-Q7-4ZJLB2.mjs → messages-Dg-TpO2S2.mjs} +24 -3
  123. package/dist/{messages-BiTMwiKH.mjs → messages-DgP82LzF.mjs} +23 -2
  124. package/dist/{chunks/messages-QMOmwcZb.mjs → messages-Dh3Vt7WC.mjs} +23 -2
  125. package/dist/{messages-C0GSBBCo2.mjs → messages-DiVVyZD22.mjs} +25 -4
  126. package/dist/{chunks/messages-BONyZroH.mjs → messages-DpRnGjoe.mjs} +26 -5
  127. package/dist/{chunks/messages-8Ld7P_9j2.mjs → messages-DqZmrFaa2.mjs} +24 -3
  128. package/dist/{chunks/messages-CxiURE2X.mjs → messages-Dra9Fz5Q.mjs} +26 -5
  129. package/dist/{chunks/messages-Clku7Cf-2.mjs → messages-DuPBRgEF2.mjs} +23 -2
  130. package/dist/{messages-53w0fPZS2.mjs → messages-DuxEyAY-2.mjs} +25 -4
  131. package/dist/{chunks/messages-D7dx_6k8.mjs → messages-FmJD6lHR2.mjs} +24 -3
  132. package/dist/{chunks/messages-DTN1XGll.mjs → messages-ONielGl92.mjs} +24 -3
  133. package/dist/{chunks/messages-CIfUm1Oa.mjs → messages-RzgUqCGb2.mjs} +24 -3
  134. package/dist/{messages-DpJGbx3q.mjs → messages-U22AKGKs.mjs} +24 -3
  135. package/dist/{messages-2ZWBTerL.mjs → messages-XufeeRfO.mjs} +24 -3
  136. package/dist/{messages-CnuH-BZK2.mjs → messages-fprUm7SO2.mjs} +24 -3
  137. package/dist/{messages-C7lJg8fy2.mjs → messages-gFNdz3Tn2.mjs} +24 -3
  138. package/dist/{chunks/messages-C15z2r5U.mjs → messages-h_n5GBm6.mjs} +29 -8
  139. package/dist/{chunks/messages-CvANwuht2.mjs → messages-oOogIpsL2.mjs} +24 -3
  140. package/dist/{chunks/messages-DtoId_bw2.mjs → messages-otwg3KcK.mjs} +24 -3
  141. package/dist/{messages-D81w6AmW.mjs → messages-rDDoBMWb.mjs} +24 -3
  142. package/dist/{messages-Dnd5YSWv.mjs → messages-trQPxZIu.mjs} +24 -3
  143. package/dist/react.mjs +2 -2
  144. package/dist/tools.mjs +3 -3
  145. package/dist/vendor.LICENSE.txt +135 -0
  146. package/package.json +2 -1
  147. package/src/blok.ts +103 -0
  148. package/src/components/block/index.ts +21 -2
  149. package/src/components/block-tunes/block-tune-copy-link.ts +82 -0
  150. package/src/components/i18n/locales/am/messages.json +24 -3
  151. package/src/components/i18n/locales/ar/messages.json +24 -3
  152. package/src/components/i18n/locales/az/messages.json +24 -3
  153. package/src/components/i18n/locales/bg/messages.json +23 -2
  154. package/src/components/i18n/locales/bn/messages.json +24 -3
  155. package/src/components/i18n/locales/bs/messages.json +26 -5
  156. package/src/components/i18n/locales/cs/messages.json +25 -4
  157. package/src/components/i18n/locales/da/messages.json +25 -4
  158. package/src/components/i18n/locales/de/messages.json +24 -3
  159. package/src/components/i18n/locales/dv/messages.json +24 -3
  160. package/src/components/i18n/locales/el/messages.json +24 -3
  161. package/src/components/i18n/locales/en/messages.json +21 -0
  162. package/src/components/i18n/locales/es/messages.json +25 -4
  163. package/src/components/i18n/locales/et/messages.json +23 -2
  164. package/src/components/i18n/locales/fa/messages.json +24 -3
  165. package/src/components/i18n/locales/fi/messages.json +24 -3
  166. package/src/components/i18n/locales/fil/messages.json +29 -8
  167. package/src/components/i18n/locales/fr/messages.json +24 -3
  168. package/src/components/i18n/locales/gu/messages.json +24 -3
  169. package/src/components/i18n/locales/he/messages.json +24 -3
  170. package/src/components/i18n/locales/hi/messages.json +24 -3
  171. package/src/components/i18n/locales/hr/messages.json +26 -5
  172. package/src/components/i18n/locales/hu/messages.json +25 -4
  173. package/src/components/i18n/locales/hy/messages.json +24 -3
  174. package/src/components/i18n/locales/id/messages.json +23 -2
  175. package/src/components/i18n/locales/it/messages.json +26 -5
  176. package/src/components/i18n/locales/ja/messages.json +24 -3
  177. package/src/components/i18n/locales/ka/messages.json +24 -3
  178. package/src/components/i18n/locales/km/messages.json +22 -1
  179. package/src/components/i18n/locales/kn/messages.json +24 -3
  180. package/src/components/i18n/locales/ko/messages.json +24 -3
  181. package/src/components/i18n/locales/ku/messages.json +24 -3
  182. package/src/components/i18n/locales/lo/messages.json +22 -1
  183. package/src/components/i18n/locales/lt/messages.json +24 -3
  184. package/src/components/i18n/locales/lv/messages.json +24 -3
  185. package/src/components/i18n/locales/mk/messages.json +24 -3
  186. package/src/components/i18n/locales/ml/messages.json +24 -3
  187. package/src/components/i18n/locales/mn/messages.json +24 -3
  188. package/src/components/i18n/locales/mr/messages.json +24 -3
  189. package/src/components/i18n/locales/ms/messages.json +22 -1
  190. package/src/components/i18n/locales/my/messages.json +24 -3
  191. package/src/components/i18n/locales/ne/messages.json +24 -3
  192. package/src/components/i18n/locales/nl/messages.json +24 -3
  193. package/src/components/i18n/locales/no/messages.json +25 -4
  194. package/src/components/i18n/locales/pa/messages.json +24 -3
  195. package/src/components/i18n/locales/pl/messages.json +25 -4
  196. package/src/components/i18n/locales/ps/messages.json +24 -3
  197. package/src/components/i18n/locales/pt/messages.json +24 -3
  198. package/src/components/i18n/locales/ro/messages.json +24 -3
  199. package/src/components/i18n/locales/ru/messages.json +23 -2
  200. package/src/components/i18n/locales/sd/messages.json +24 -3
  201. package/src/components/i18n/locales/si/messages.json +24 -3
  202. package/src/components/i18n/locales/sk/messages.json +25 -4
  203. package/src/components/i18n/locales/sl/messages.json +25 -4
  204. package/src/components/i18n/locales/sq/messages.json +25 -4
  205. package/src/components/i18n/locales/sr/messages.json +24 -3
  206. package/src/components/i18n/locales/sv/messages.json +24 -3
  207. package/src/components/i18n/locales/sw/messages.json +22 -1
  208. package/src/components/i18n/locales/ta/messages.json +24 -3
  209. package/src/components/i18n/locales/te/messages.json +24 -3
  210. package/src/components/i18n/locales/th/messages.json +22 -1
  211. package/src/components/i18n/locales/tr/messages.json +24 -3
  212. package/src/components/i18n/locales/ug/messages.json +24 -3
  213. package/src/components/i18n/locales/uk/messages.json +23 -2
  214. package/src/components/i18n/locales/ur/messages.json +24 -3
  215. package/src/components/i18n/locales/vi/messages.json +22 -1
  216. package/src/components/i18n/locales/yi/messages.json +24 -3
  217. package/src/components/i18n/locales/zh/messages.json +24 -3
  218. package/src/components/icons/index.ts +65 -0
  219. package/src/components/inline-tools/inline-tool-bold.ts +10 -0
  220. package/src/components/inline-tools/inline-tool-code.ts +35 -1
  221. package/src/components/inline-tools/inline-tool-italic.ts +37 -1
  222. package/src/components/inline-tools/inline-tool-strikethrough.ts +35 -1
  223. package/src/components/inline-tools/inline-tool-underline.ts +35 -1
  224. package/src/components/inline-tools/services/bold-normalization-pass.ts +2 -4
  225. package/src/components/inline-tools/utils/formatting-range-utils.ts +83 -0
  226. package/src/components/modules/api/tools.ts +19 -0
  227. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +7 -1
  228. package/src/components/modules/blockManager/blockManager.ts +22 -0
  229. package/src/components/modules/blockManager/event-binder.ts +12 -1
  230. package/src/components/modules/blockManager/factory.ts +4 -0
  231. package/src/components/modules/blockManager/types.ts +4 -0
  232. package/src/components/modules/blockManager/yjs-sync.ts +16 -2
  233. package/src/components/modules/paste/google-docs-preprocessor.ts +49 -3
  234. package/src/components/modules/paste/handlers/table-cells-handler.ts +12 -2
  235. package/src/components/modules/paste/index.ts +8 -4
  236. package/src/components/modules/paste/types.ts +2 -0
  237. package/src/components/modules/renderer.ts +22 -2
  238. package/src/components/modules/saver.ts +19 -1
  239. package/src/components/modules/themeManager.ts +3 -1
  240. package/src/components/modules/toolbar/blockSettings.ts +51 -1
  241. package/src/components/modules/toolbar/inline/index.ts +0 -3
  242. package/src/components/modules/tools.ts +5 -0
  243. package/src/components/modules/ui.ts +1 -0
  244. package/src/components/modules/uiControllers/controllers/keyboard.ts +79 -0
  245. package/src/components/modules/uiControllers/controllers/selection.ts +14 -2
  246. package/src/components/modules/yjs/document-store.ts +22 -0
  247. package/src/components/modules/yjs/index.ts +10 -0
  248. package/src/components/modules/yjs/serializer.ts +20 -0
  249. package/src/components/ui/toolbox.ts +0 -1
  250. package/src/components/utils/id-generator.ts +11 -0
  251. package/src/components/utils/key-icon.ts +187 -0
  252. package/src/components/utils/popover/components/hint/hint.ts +3 -1
  253. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +18 -5
  254. package/src/components/utils/popover/popover-abstract.ts +45 -0
  255. package/src/components/utils/popover/popover-desktop.ts +1 -0
  256. package/src/components/utils/popover/popover-position.ts +4 -2
  257. package/src/components/utils/popover/popover.const.ts +2 -0
  258. package/src/components/utils.ts +1 -0
  259. package/src/styles/main.css +1272 -0
  260. package/src/tools/code/index.ts +4 -0
  261. package/src/tools/database/database-backend-sync.ts +132 -0
  262. package/src/tools/database/database-board-view.ts +410 -0
  263. package/src/tools/database/database-card-drag.ts +306 -0
  264. package/src/tools/database/database-card-drawer.ts +546 -0
  265. package/src/tools/database/database-column-controls.ts +141 -0
  266. package/src/tools/database/database-column-drag.ts +262 -0
  267. package/src/tools/database/database-keyboard.ts +35 -0
  268. package/src/tools/database/database-list-row-drag.ts +245 -0
  269. package/src/tools/database/database-list-view.ts +333 -0
  270. package/src/tools/database/database-model.ts +214 -0
  271. package/src/tools/database/database-property-type-popover.ts +108 -0
  272. package/src/tools/database/database-tab-bar.ts +558 -0
  273. package/src/tools/database/database-view-popover.ts +129 -0
  274. package/src/tools/database/database-view-renderer.ts +25 -0
  275. package/src/tools/database/database-view.ts +269 -0
  276. package/src/tools/database/index.ts +1223 -0
  277. package/src/tools/database/types.ts +168 -0
  278. package/src/tools/database-row/index.ts +74 -0
  279. package/src/tools/index.ts +4 -0
  280. package/types/api/tools.d.ts +18 -0
  281. package/types/configs/blok-config.d.ts +27 -0
  282. package/types/data-formats/output-data.d.ts +13 -0
  283. package/types/index.d.ts +17 -0
  284. package/types/tools/database.d.ts +152 -0
  285. package/types/tools-entry.d.ts +7 -4
  286. package/types/utils/popover/popover.d.ts +6 -0
@@ -167,10 +167,22 @@ export class SelectionController extends Controller {
167
167
  * @returns true if current block should be updated
168
168
  */
169
169
  private shouldUpdateCurrentBlock(): boolean {
170
+ const focusedElement = Selection.anchorElement;
171
+
172
+ if (!focusedElement || !this.wrapperElement) {
173
+ return false;
174
+ }
175
+
170
176
  /**
171
- * Always update current block when focus moves to a different block.
172
- * This handles Tab key navigation, programmatic focus, and accessibility tools.
177
+ * Skip updating current block when focus is inside a nested editor instance.
178
+ * The closest editor wrapper must match this instance's wrapper.
173
179
  */
180
+ const closestEditor = focusedElement.closest('[data-blok-testid="blok-editor"]');
181
+
182
+ if (closestEditor !== null && closestEditor !== this.wrapperElement) {
183
+ return false;
184
+ }
185
+
174
186
  return true;
175
187
  }
176
188
  }
@@ -193,6 +193,28 @@ export class DocumentStore {
193
193
  }, 'local');
194
194
  }
195
195
 
196
+ /**
197
+ * Update a block's edit metadata fields directly on the Y.Map.
198
+ * @param id - Block id
199
+ * @param lastEditedAt - Timestamp in milliseconds
200
+ * @param lastEditedBy - User display name, or null
201
+ */
202
+ public updateBlockMetadata(id: string, lastEditedAt: number, lastEditedBy: string | null): void {
203
+ const yblock = this.getBlockById(id);
204
+
205
+ if (yblock === undefined) {
206
+ return;
207
+ }
208
+
209
+ this.transact(() => {
210
+ yblock.set('lastEditedAt', lastEditedAt);
211
+
212
+ if (lastEditedBy !== null) {
213
+ yblock.set('lastEditedBy', lastEditedBy);
214
+ }
215
+ }, 'local');
216
+ }
217
+
196
218
  /**
197
219
  * Find block index by id.
198
220
  * @param id - Block id to find
@@ -164,6 +164,16 @@ export class YjsManager extends Module {
164
164
  this.documentStore.updateBlockTune(id, tuneName, tuneData);
165
165
  }
166
166
 
167
+ /**
168
+ * Update a block's edit metadata.
169
+ * @param id - Block id
170
+ * @param lastEditedAt - Timestamp in milliseconds
171
+ * @param lastEditedBy - User display name, or null
172
+ */
173
+ public updateBlockMetadata(id: string, lastEditedAt: number, lastEditedBy: string | null): void {
174
+ this.documentStore.updateBlockMetadata(id, lastEditedAt, lastEditedBy);
175
+ }
176
+
167
177
  /**
168
178
  * Get block Y.Map by id.
169
179
  * @param id - Block id
@@ -74,6 +74,14 @@ export class YBlockSerializer {
74
74
  yblock.set('contentIds', Y.Array.from(blockData.content));
75
75
  }
76
76
 
77
+ if (blockData.lastEditedAt !== undefined) {
78
+ yblock.set('lastEditedAt', blockData.lastEditedAt);
79
+ }
80
+
81
+ if (blockData.lastEditedBy !== undefined) {
82
+ yblock.set('lastEditedBy', blockData.lastEditedBy);
83
+ }
84
+
77
85
  return yblock;
78
86
  }
79
87
 
@@ -122,6 +130,18 @@ export class YBlockSerializer {
122
130
  block.content = contentIds.toArray();
123
131
  }
124
132
 
133
+ const lastEditedAt = yblock.get('lastEditedAt');
134
+
135
+ if (typeof lastEditedAt === 'number') {
136
+ block.lastEditedAt = lastEditedAt;
137
+ }
138
+
139
+ const lastEditedBy = yblock.get('lastEditedBy');
140
+
141
+ if (typeof lastEditedBy === 'string') {
142
+ block.lastEditedBy = lastEditedBy;
143
+ }
144
+
125
145
  return block;
126
146
  }
127
147
 
@@ -427,7 +427,6 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
427
427
  const PopoverClass = isMobileScreen() ? PopoverMobile : PopoverDesktop;
428
428
 
429
429
  this.popover = new PopoverClass({
430
- scopeElement: this.api.ui.nodes.redactor,
431
430
  trigger: this.triggerElement || this.nodes.toolbox,
432
431
  leftAlignElement: this.leftAlignElement,
433
432
  messages: {
@@ -20,6 +20,17 @@ export const generateBlockId = (): string => {
20
20
  return nanoid(idLen);
21
21
  };
22
22
 
23
+ /**
24
+ * Nanoid-compatible block ID pattern: exactly 10 URL-safe characters (A-Z, a-z, 0-9, _, -)
25
+ */
26
+ const BLOCK_ID_PATTERN = /^[A-Za-z0-9_-]{10}$/;
27
+
28
+ /**
29
+ * Returns true if the given string is a valid block ID (nanoid format).
30
+ * @param id - string to check
31
+ */
32
+ export const isValidBlockId = (id: string): boolean => BLOCK_ID_PATTERN.test(id);
33
+
23
34
  /**
24
35
  * Returns random generated identifier
25
36
  * @param prefix - identifier prefix
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Utilities for rendering keyboard shortcut keys as inline SVG icons.
3
+ *
4
+ * Each key token is wrapped in a minimal inline SVG that renders the Unicode
5
+ * glyph as SVG <text>. No borders, no boxes — visually identical to plain
6
+ * Unicode text, but each symbol is a proper SVG element.
7
+ *
8
+ * The result matches the compact Mac-style shortcut display:
9
+ * ⌘⌃L ⌘D ⌘⇧P Del
10
+ *
11
+ * Usage:
12
+ * element.innerHTML = makeShortcutHtml('⌘ + B');
13
+ */
14
+
15
+ /**
16
+ * Canonical Unicode glyph for each key name.
17
+ * All modifier symbols and common key names are covered.
18
+ */
19
+ const KEY_LABEL_MAP: Record<string, string> = {
20
+ '⌘': '⌘',
21
+ '⇧': '⇧',
22
+ '⌥': '⌥',
23
+ '⌃': '⌃',
24
+ '⌫': '⌫',
25
+ '⏎': '⏎',
26
+ '⎋': '⎋',
27
+ '␡': '⌦',
28
+ '↑': '↑',
29
+ '↓': '↓',
30
+ '←': '←',
31
+ '→': '→',
32
+ 'ctrl': '⌃',
33
+ 'alt': '⌥',
34
+ 'shift': '⇧',
35
+ 'enter': '↵',
36
+ 'backspace': '⌫',
37
+ 'escape': '⎋',
38
+ 'esc': '⎋',
39
+ 'delete': '⌦',
40
+ 'del': 'Del',
41
+ 'tab': '⇥',
42
+ 'ins': 'Ins',
43
+ 'win': '⊞',
44
+ };
45
+
46
+ /**
47
+ * Resolves a raw token string to its canonical display glyph.
48
+ */
49
+ function resolveLabel(token: string): string {
50
+ const trimmed = token.trim();
51
+
52
+ return KEY_LABEL_MAP[trimmed.toLowerCase()] ?? KEY_LABEL_MAP[trimmed] ?? trimmed;
53
+ }
54
+
55
+ /**
56
+ * Splits a shortcut segment into individual key tokens.
57
+ * Handles concatenated modifier symbols like "⌃⌘L" → ['⌃', '⌘', 'L'].
58
+ */
59
+ function tokenizeSegment(segment: string): string[] {
60
+ const modifierPattern = /([⌘⇧⌥⌃⌫⏎⎋⌦↑↓←→↵⇥])|([^⌘⇧⌥⌃⌫⏎⎋⌦↑↓←→↵⇥]+)/gu;
61
+ const tokens: string[] = [];
62
+
63
+ for (const match of segment.matchAll(modifierPattern)) {
64
+ const token = match[0].trim();
65
+
66
+ if (token) {
67
+ tokens.push(token);
68
+ }
69
+ }
70
+
71
+ return tokens;
72
+ }
73
+
74
+ /**
75
+ * Renders a single key glyph as an inline SVG <text> element.
76
+ * No border, no background — just the Unicode character as SVG.
77
+ * Font size and width adapt to single-char symbols vs multi-char labels.
78
+ */
79
+ function makeKeySvg(label: string): string {
80
+ const isSymbol = label.length === 1;
81
+ // Symbols (⌘, ⇧, …) are wider glyphs; short text (Del, Ins) is narrower per-char
82
+ const fontSize = isSymbol ? 13 : 11;
83
+ const charWidth = isSymbol ? 13 : 7.5;
84
+ const w = Math.ceil(label.length * charWidth);
85
+ const h = 16;
86
+
87
+ return (
88
+ `<svg xmlns="http://www.w3.org/2000/svg"` +
89
+ ` width="${w}" height="${h}"` +
90
+ ` viewBox="0 0 ${w} ${h}"` +
91
+ ` style="display:inline-block;vertical-align:middle;flex-shrink:0"` +
92
+ ` aria-hidden="true">` +
93
+ `<text` +
94
+ ` x="${w / 2}"` +
95
+ ` y="${h / 2 + 1}"` +
96
+ ` text-anchor="middle"` +
97
+ ` dominant-baseline="middle"` +
98
+ ` font-family="-apple-system,BlinkMacSystemFont,'SF Pro Text','Helvetica Neue',sans-serif"` +
99
+ ` font-size="${fontSize}"` +
100
+ ` font-weight="400"` +
101
+ ` fill="currentColor"` +
102
+ `>${label}</text>` +
103
+ `</svg>`
104
+ );
105
+ }
106
+
107
+ /**
108
+ * Converts a beautified shortcut string (e.g. "⌘ + B" or "⌃⌘L") into an
109
+ * HTML string of inline SVG glyph elements, tightly concatenated with no
110
+ * separator — matching the compact Mac shortcut display style.
111
+ *
112
+ * Accepts the output of `beautifyShortcut()` which uses " + " as separator.
113
+ */
114
+ export function makeShortcutHtml(shortcut: string): string {
115
+ const tokens = shortcut
116
+ .split(' + ')
117
+ .flatMap(tokenizeSegment);
118
+
119
+ if (tokens.length === 0) {
120
+ return shortcut;
121
+ }
122
+
123
+ const svgs = tokens.map((token) => makeKeySvg(resolveLabel(token)));
124
+
125
+ return `<span style="display:inline-flex;align-items:center;line-height:1">${svgs.join('')}</span>`;
126
+ }
127
+
128
+ /**
129
+ * Maps Unicode glyphs and short labels back to full English key names
130
+ * for use in human-readable tooltip descriptions.
131
+ */
132
+ const READABLE_KEY_MAP: Record<string, string> = {
133
+ '⌘': 'Command',
134
+ '⇧': 'Shift',
135
+ '⌥': 'Option',
136
+ '⌃': 'Control',
137
+ '⌫': 'Backspace',
138
+ '⌦': 'Delete',
139
+ '⏎': 'Return',
140
+ '↵': 'Return',
141
+ '⎋': 'Escape',
142
+ '⇥': 'Tab',
143
+ '↑': 'Up',
144
+ '↓': 'Down',
145
+ '←': 'Left',
146
+ '→': 'Right',
147
+ 'del': 'Delete',
148
+ 'ins': 'Insert',
149
+ '⊞': 'Win',
150
+ };
151
+
152
+ /**
153
+ * Converts a shortcut string (e.g. "⌃⌘L" or "⌘ + C") into a human-readable
154
+ * description like "Control+Command+L" or "Command+C".
155
+ *
156
+ * Each token is expanded to its full English key name. Plain letter/number
157
+ * tokens are uppercased. Unknown glyphs are passed through as-is.
158
+ */
159
+ export function shortcutToReadable(shortcut: string): string {
160
+ const tokens = shortcut
161
+ .split(' + ')
162
+ .flatMap(tokenizeSegment);
163
+
164
+ if (tokens.length === 0) {
165
+ return shortcut;
166
+ }
167
+
168
+ return tokens
169
+ .map((token) => {
170
+ const trimmed = token.trim();
171
+ const lower = trimmed.toLowerCase();
172
+
173
+ return READABLE_KEY_MAP[trimmed] ?? READABLE_KEY_MAP[lower] ?? trimmed.toUpperCase();
174
+ })
175
+ .join('+');
176
+ }
177
+
178
+ /**
179
+ * Creates a DOM element containing the SVG glyph icons for a shortcut.
180
+ */
181
+ export function makeShortcutElement(shortcut: string): HTMLElement {
182
+ const el = document.createElement('span');
183
+
184
+ el.innerHTML = makeShortcutHtml(shortcut);
185
+
186
+ return el.firstElementChild as HTMLElement ?? el;
187
+ }
@@ -1,4 +1,5 @@
1
1
  import { Dom } from '../../../../dom';
2
+ import { makeShortcutHtml } from '../../../key-icon';
2
3
 
3
4
  import { css } from './hint.const';
4
5
 
@@ -33,7 +34,8 @@ export class Hint {
33
34
  this.nodes.root.appendChild(this.nodes.title);
34
35
 
35
36
  if (params.description !== undefined) {
36
- this.nodes.description = Dom.make('div', css.description, { textContent: params.description });
37
+ this.nodes.description = Dom.make('div', css.description);
38
+ this.nodes.description.innerHTML = makeShortcutHtml(params.description);
37
39
 
38
40
  this.nodes.root.appendChild(this.nodes.description);
39
41
  }
@@ -1,5 +1,7 @@
1
1
  import { DATA_ATTR } from '../../../../../constants/data-attributes';
2
2
  import { IconChevronRight } from '../../../../../icons';
3
+ import { makeShortcutHtml, shortcutToReadable } from '../../../../key-icon';
4
+ import { onHover } from '../../../../tooltip';
3
5
  import { twMerge } from '../../../../tw';
4
6
  import { PopoverItem } from '../popover-item';
5
7
 
@@ -272,13 +274,22 @@ export class PopoverItemDefault extends PopoverItem {
272
274
  if (params.secondaryLabel) {
273
275
  const secondaryEl = document.createElement('div');
274
276
 
275
- secondaryEl.className = 'ml-auto shrink-0 flex items-center whitespace-nowrap pl-20 font-mono text-[13px] tracking-wide text-text-secondary/60';
277
+ secondaryEl.className = 'ml-auto shrink-0 inline-flex items-center whitespace-nowrap pl-20 leading-none text-text-secondary/60';
276
278
  secondaryEl.setAttribute(DATA_ATTR.popoverItemSecondaryTitle, '');
277
279
  secondaryEl.setAttribute('data-blok-testid', 'popover-item-secondary-title');
278
- secondaryEl.textContent = params.secondaryLabel;
280
+ secondaryEl.innerHTML = makeShortcutHtml(params.secondaryLabel);
279
281
 
280
282
  root.appendChild(secondaryEl);
281
283
  this.nodes.secondaryLabelEl = secondaryEl;
284
+
285
+ if (params.title !== undefined) {
286
+ // Anchor tooltip to the inner SVG span (the visible glyphs), not the
287
+ // outer container which has large left padding — so the tooltip centers
288
+ // directly over the shortcut keys rather than over the padded div.
289
+ const glyphSpan = (secondaryEl.firstElementChild ?? secondaryEl) as HTMLElement;
290
+
291
+ onHover(glyphSpan, shortcutToReadable(params.secondaryLabel), { placement: 'top' });
292
+ }
282
293
  }
283
294
 
284
295
  // Trailing icon (right-side indicator, e.g. checkmark)
@@ -552,8 +563,10 @@ export class PopoverItemDefault extends PopoverItem {
552
563
  return;
553
564
  }
554
565
 
555
- this.nodes.secondaryLabelEl.textContent = this.params.secondaryLabel ?? '';
556
- this.nodes.secondaryLabelEl.style.display = this.params.secondaryLabel ? '' : 'none';
566
+ const label = this.params.secondaryLabel;
567
+
568
+ this.nodes.secondaryLabelEl.innerHTML = label ? makeShortcutHtml(label) : '';
569
+ this.nodes.secondaryLabelEl.style.display = label ? '' : 'none';
557
570
  }
558
571
 
559
572
  /**
@@ -586,7 +599,7 @@ export class PopoverItemDefault extends PopoverItem {
586
599
  return;
587
600
  }
588
601
 
589
- this.nodes.secondaryLabelEl.textContent = secondaryLabel ?? '';
602
+ this.nodes.secondaryLabelEl.innerHTML = secondaryLabel ? makeShortcutHtml(secondaryLabel) : '';
590
603
  this.nodes.secondaryLabelEl.style.display = secondaryLabel ? '' : 'none';
591
604
  }
592
605
 
@@ -86,6 +86,11 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
86
86
  if (this.nodes.popoverContainer) {
87
87
  this.listeners.on(this.nodes.popoverContainer, 'click', (event: Event) => this.handleClick(event));
88
88
  }
89
+
90
+ // Set up scroll listener on items container for scroll hazes
91
+ if (this.nodes.items) {
92
+ this.listeners.on(this.nodes.items, 'scroll', () => this.updateScrollHazes());
93
+ }
89
94
  }
90
95
 
91
96
  /**
@@ -136,6 +141,8 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
136
141
  this.search.focus();
137
142
  }
138
143
 
144
+ this.updateScrollHazes();
145
+
139
146
  const { trigger } = this.params;
140
147
  const isRootWithTrigger = (this.params.nestingLevel ?? 0) === 0 && trigger !== undefined;
141
148
 
@@ -156,6 +163,9 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
156
163
 
157
164
  this.itemsDefault.forEach(item => item.reset());
158
165
 
166
+ this.nodes.scrollHazeTop.style.opacity = '0';
167
+ this.nodes.scrollHazeBottom.style.opacity = '0';
168
+
159
169
  if (this.search !== undefined) {
160
170
  this.search.clear();
161
171
  }
@@ -429,6 +439,24 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
429
439
  }
430
440
  }
431
441
 
442
+ /**
443
+ * Updates scroll haze visibility based on the items container scroll state.
444
+ * Shows top haze when scrolled down, bottom haze when more content below.
445
+ */
446
+ protected updateScrollHazes(): void {
447
+ const { items, scrollHazeTop, scrollHazeBottom } = this.nodes;
448
+
449
+ const hasOverflow = items.scrollHeight > items.clientHeight;
450
+ const isAtTop = items.scrollTop <= 0;
451
+ const isAtBottom = items.scrollTop + items.clientHeight >= items.scrollHeight - 1;
452
+
453
+ scrollHazeTop.style.opacity = hasOverflow && !isAtTop ? '1' : '0';
454
+ scrollHazeBottom.style.opacity = hasOverflow && !isAtBottom ? '1' : '0';
455
+
456
+ scrollHazeTop.style.top = `${items.offsetTop}px`;
457
+ scrollHazeBottom.style.top = `${items.offsetTop + items.clientHeight - scrollHazeBottom.offsetHeight}px`;
458
+ }
459
+
432
460
  /**
433
461
  * Checks if popover contains the node
434
462
  * @param node - node to check
@@ -485,9 +513,24 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
485
513
  items.setAttribute(DATA_ATTR.popoverItems, '');
486
514
  items.setAttribute('data-blok-testid', 'popover-items');
487
515
 
516
+ // Create scroll haze overlays
517
+ const scrollHazeTop = document.createElement('div');
518
+
519
+ scrollHazeTop.className = css.scrollHaze;
520
+ scrollHazeTop.style.background = 'linear-gradient(to bottom, var(--blok-popover-bg), transparent)';
521
+ scrollHazeTop.style.opacity = '0';
522
+
523
+ const scrollHazeBottom = document.createElement('div');
524
+
525
+ scrollHazeBottom.className = css.scrollHaze;
526
+ scrollHazeBottom.style.background = 'linear-gradient(to top, var(--blok-popover-bg), transparent)';
527
+ scrollHazeBottom.style.opacity = '0';
528
+
488
529
  // Assemble DOM structure
489
530
  popoverContainer.appendChild(nothingFoundMessage);
490
531
  popoverContainer.appendChild(items);
532
+ popoverContainer.appendChild(scrollHazeTop);
533
+ popoverContainer.appendChild(scrollHazeBottom);
491
534
  popover.appendChild(popoverContainer);
492
535
 
493
536
  return {
@@ -495,6 +538,8 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
495
538
  popoverContainer,
496
539
  nothingFoundMessage,
497
540
  items,
541
+ scrollHazeTop,
542
+ scrollHazeBottom,
498
543
  };
499
544
  }
500
545
 
@@ -1077,6 +1077,7 @@ export class PopoverDesktop extends PopoverAbstract {
1077
1077
  }
1078
1078
 
1079
1079
  this.toggleNothingFoundMessage(isNothingFound);
1080
+ this.updateScrollHazes();
1080
1081
 
1081
1082
  // Recalculate position since popover height may have changed (trigger-based popovers only;
1082
1083
  // non-trigger popovers use CSS variable positioning that doesn't need pixel recalculation)
@@ -32,7 +32,9 @@ export interface ResolvedPosition {
32
32
 
33
33
  /**
34
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.
35
+ * Returns true only when the popover fits on the alternate side but not the preferred side.
36
+ * When neither side fits, stays on the preferred side so the popover remains adjacent
37
+ * to the anchor instead of getting clamped to a distant boundary edge.
36
38
  */
37
39
  function shouldFlip(popoverDimension: number, spaceOnPreferred: number, spaceOnAlternate: number): boolean {
38
40
  if (popoverDimension <= spaceOnPreferred) {
@@ -43,7 +45,7 @@ function shouldFlip(popoverDimension: number, spaceOnPreferred: number, spaceOnA
43
45
  return true;
44
46
  }
45
47
 
46
- return spaceOnAlternate > spaceOnPreferred;
48
+ return false;
47
49
  }
48
50
 
49
51
  /**
@@ -18,6 +18,8 @@ export const css = {
18
18
  popoverOverlay: 'hidden bg-dark',
19
19
 
20
20
  items: 'overflow-y-auto overscroll-contain',
21
+
22
+ scrollHaze: 'absolute inset-x-0 h-6 pointer-events-none z-1 transition-opacity duration-300 ease-in-out',
21
23
  };
22
24
 
23
25
  /**
@@ -73,6 +73,7 @@ export {
73
73
  export {
74
74
  generateBlockId,
75
75
  generateId,
76
+ isValidBlockId,
76
77
  } from './utils/id-generator';
77
78
 
78
79
  // HTML utilities