@jackuait/blok 0.13.0 → 0.13.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 (330) hide show
  1. package/codemod/migrate-editorjs-to-blok.js +7 -2
  2. package/codemod/test.js +22 -2
  3. package/dist/blok.cjs +1 -1
  4. package/dist/blok.iife.js +29 -29
  5. package/dist/blok.mjs +2 -2
  6. package/dist/chunks/{blok-Cy7bijNZ.mjs → blok-Du6vYONn.mjs} +2166 -2182
  7. package/dist/chunks/{blok-DsB9tzWP.cjs → blok-Xu27QC2G.cjs} +13 -13
  8. package/dist/chunks/constants-DDTVRO2H.cjs +457 -0
  9. package/dist/chunks/{constants-CnxI96Oy.mjs → constants-DUuYY64n.mjs} +451 -246
  10. package/dist/chunks/{i18next-loader-BObGIOaH.cjs → i18next-loader-DC1uN-wc.cjs} +1 -1
  11. package/dist/chunks/{i18next-loader-BrDbxldT.mjs → i18next-loader-GIrBCFrC.mjs} +1 -1
  12. package/dist/chunks/{lightweight-i18n-Bw9zJMpT.cjs → lightweight-i18n-Bbl1cNYK.cjs} +1 -1
  13. package/dist/chunks/{lightweight-i18n-CFXiOjGR.mjs → lightweight-i18n-DF9Pupws.mjs} +2 -0
  14. package/dist/chunks/{messages-DLaesq4h2.cjs → messages-1qYt6EhZ2.cjs} +1 -1
  15. package/dist/chunks/{messages-BzCMWDCa.cjs → messages-2fxvN3Nb.cjs} +1 -1
  16. package/dist/chunks/{messages-CloQj-t82.mjs → messages-5AxgjKgf2.mjs} +2 -0
  17. package/dist/{messages-ByaREXXn.mjs → chunks/messages-AgmrT2Id.mjs} +2 -0
  18. package/dist/{messages-DV7zSwcU2.mjs → chunks/messages-AtUsRyWK2.mjs} +2 -0
  19. package/dist/chunks/{messages-23LJg97F.cjs → messages-B1Vs2HmR.cjs} +1 -1
  20. package/dist/{messages-Bgub7yIr.mjs → chunks/messages-B1k4DgVe.mjs} +4 -2
  21. package/dist/chunks/{messages-CyNE9mfW.cjs → messages-B1xgsCNQ.cjs} +1 -1
  22. package/dist/chunks/{messages-CK6NQlei2.mjs → messages-B2zrJyAc2.mjs} +2 -0
  23. package/dist/chunks/{messages-D9KllT5S.mjs → messages-B5CFhyI8.mjs} +2 -0
  24. package/dist/chunks/{messages-BFPJInnK.mjs → messages-B6You-RA.mjs} +7 -5
  25. package/dist/{messages-B8Ps9X7Q.mjs → chunks/messages-B6t1xShv.mjs} +2 -0
  26. package/dist/chunks/{messages-B5P29HKO2.cjs → messages-B780gS332.cjs} +1 -1
  27. package/dist/chunks/{messages-BBD0GeAN.mjs → messages-B7KbtBAE.mjs} +5 -3
  28. package/dist/chunks/{messages-CG1tpK3F.cjs → messages-B7T5Notn.cjs} +1 -1
  29. package/dist/{messages-DemkV5oa2.mjs → chunks/messages-BA2sVGrR2.mjs} +2 -0
  30. package/dist/chunks/{messages-B9q8LdZT.cjs → messages-BE9aZQ1Q.cjs} +1 -1
  31. package/dist/chunks/{messages-CPTia1Ip.cjs → messages-BIQpTYfm.cjs} +1 -1
  32. package/dist/chunks/{messages-BT-EUB5N.cjs → messages-BIRvUJ0t.cjs} +1 -1
  33. package/dist/chunks/{messages-BEkcSJKV.cjs → messages-BIodfkjv.cjs} +1 -1
  34. package/dist/chunks/{messages-_ysQiWQr.cjs → messages-BL-zBcuM.cjs} +1 -1
  35. package/dist/chunks/{messages-CSZTOxAh.mjs → messages-BNxTGhHu.mjs} +2 -0
  36. package/dist/chunks/{messages-CzG5xDaO.mjs → messages-BP77P9ER.mjs} +2 -0
  37. package/dist/chunks/{messages-BEM-ySlb2.cjs → messages-BQr0zpmu2.cjs} +1 -1
  38. package/dist/chunks/{messages-D4P5aWos2.cjs → messages-BTHi6rVW2.cjs} +1 -1
  39. package/dist/chunks/{messages-KTUVKXJd.mjs → messages-BVZONUH9.mjs} +3 -1
  40. package/dist/{messages-BvHpSkAX2.mjs → chunks/messages-BVarbXYD2.mjs} +2 -0
  41. package/dist/{messages-DiOm0iFp.mjs → chunks/messages-BWGqOZ9J.mjs} +2 -0
  42. package/dist/{messages-DIBytW9u.mjs → chunks/messages-BZ4d5yNH.mjs} +2 -0
  43. package/dist/chunks/{messages-WUvriTcu2.cjs → messages-BZOAdcmO2.cjs} +1 -1
  44. package/dist/chunks/{messages-CN9LNhoS2.mjs → messages-B_U10evN2.mjs} +4 -2
  45. package/dist/chunks/{messages-DPrZ8Z6d2.cjs → messages-BbsGeVs_2.cjs} +1 -1
  46. package/dist/chunks/{messages-3_7JWqT0.cjs → messages-Bc1NYJVS.cjs} +1 -1
  47. package/dist/chunks/{messages-D3EU-LRS.cjs → messages-BdORNG8X.cjs} +1 -1
  48. package/dist/chunks/{messages-BIOk-aTQ.cjs → messages-Bg2kheTv.cjs} +1 -1
  49. package/dist/chunks/{messages-DsAkJt8M.cjs → messages-Bj1eQtQw.cjs} +1 -1
  50. package/dist/chunks/{messages-CD6xvMw1.cjs → messages-BkJJCHNK.cjs} +1 -1
  51. package/dist/chunks/{messages-BIN5-zeZ.cjs → messages-BkdGQfIX.cjs} +1 -1
  52. package/dist/chunks/{messages-pKpKbxTh2.cjs → messages-BkgsB-cj2.cjs} +1 -1
  53. package/dist/{messages-DXCKUB0_.mjs → chunks/messages-BmdkDNYv.mjs} +4 -2
  54. package/dist/{messages-B66o_tQ42.mjs → chunks/messages-BmiN0JGP2.mjs} +2 -0
  55. package/dist/chunks/{messages-BG17trOF.cjs → messages-Bn0vGFEP.cjs} +1 -1
  56. package/dist/{messages-BpJopIVL2.mjs → chunks/messages-BoCUgrkI.mjs} +2 -0
  57. package/dist/chunks/{messages-B7dSyfsy.cjs → messages-BoIUXwWe.cjs} +1 -1
  58. package/dist/chunks/{messages-7oeFTHO4.cjs → messages-BpDEh8rW.cjs} +1 -1
  59. package/dist/{messages-DVSJBYhD.mjs → chunks/messages-BuYnNUtU2.mjs} +3 -1
  60. package/dist/{messages-D8SUKrMB.mjs → chunks/messages-BvuEffoe.mjs} +4 -2
  61. package/dist/{messages-DvIwCnTR.mjs → chunks/messages-BvupGuDw2.mjs} +2 -0
  62. package/dist/chunks/{messages-BZr0xR7X.cjs → messages-BwknPZJ8.cjs} +1 -1
  63. package/dist/{messages-5s1gGSm4.mjs → chunks/messages-BxKobpJ22.mjs} +2 -0
  64. package/dist/chunks/{messages-D_OfKMtO2.cjs → messages-ByicRCge2.cjs} +1 -1
  65. package/dist/{messages-DNDonN-x.mjs → chunks/messages-C03LZxma.mjs} +2 -0
  66. package/dist/{messages-CqrBLC_P.mjs → chunks/messages-C24IC_eR.mjs} +2 -0
  67. package/dist/chunks/{messages-CucO-8OV.cjs → messages-C2oBmyTn.cjs} +1 -1
  68. package/dist/chunks/{messages-CXZtG3Xs2.mjs → messages-C4bHKGnB2.mjs} +4 -2
  69. package/dist/chunks/{messages-DTceHV5d2.mjs → messages-C4sIqArW2.mjs} +2 -0
  70. package/dist/chunks/{messages-Ds1jRRkJ2.cjs → messages-C9wBMmxr2.cjs} +1 -1
  71. package/dist/chunks/{messages-DdMhxYfW.cjs → messages-CDK5-8vW.cjs} +1 -1
  72. package/dist/chunks/{messages-CP3f0qkN.cjs → messages-CKHbPcfh.cjs} +1 -1
  73. package/dist/{messages-Dt4Cw2PN2.mjs → chunks/messages-CMRjQYxi2.mjs} +3 -1
  74. package/dist/chunks/{messages-BJVhJhdz.cjs → messages-CNFfwTfw.cjs} +1 -1
  75. package/dist/chunks/{messages-C99hDoeM2.cjs → messages-CNiuofck2.cjs} +1 -1
  76. package/dist/chunks/{messages-CjgjbJ1H2.mjs → messages-COMdnGQV2.mjs} +4 -2
  77. package/dist/{messages-BfsTqQCr2.mjs → chunks/messages-CQg2_vmm.mjs} +2 -0
  78. package/dist/{messages-_OjohrXs.mjs → chunks/messages-CTWXEx_o.mjs} +6 -4
  79. package/dist/{messages-BJBdgowf.mjs → chunks/messages-CWTFEPbA2.mjs} +2 -0
  80. package/dist/chunks/{messages-l73qDsKl.cjs → messages-CWszAGkF.cjs} +1 -1
  81. package/dist/chunks/{messages-BGcdiqDM2.cjs → messages-CWzQNagc2.cjs} +1 -1
  82. package/dist/{messages-CaC0BVP72.mjs → chunks/messages-CXxz5HYQ.mjs} +2 -0
  83. package/dist/chunks/{messages-BvJTJwoq2.cjs → messages-CYf1gv722.cjs} +1 -1
  84. package/dist/{messages-DN_N2jK1.mjs → chunks/messages-CcboYTP8.mjs} +2 -0
  85. package/dist/{messages-DdGG7T30.mjs → chunks/messages-CdWXgq_r.mjs} +2 -0
  86. package/dist/chunks/{messages-pZC8rTng.cjs → messages-CfcCwbQo.cjs} +1 -1
  87. package/dist/chunks/{messages-DFJTssY7.cjs → messages-CkvqOnAR.cjs} +1 -1
  88. package/dist/chunks/{messages-BzbW5tIB2.cjs → messages-Cnrug7nz2.cjs} +1 -1
  89. package/dist/chunks/{messages-BUp0i-9G.cjs → messages-Cr51zCHy.cjs} +1 -1
  90. package/dist/chunks/{messages-Cz63p8bt2.cjs → messages-CsLvvl2F2.cjs} +1 -1
  91. package/dist/chunks/{messages-DrIzpqee.cjs → messages-CuO-Rx4g.cjs} +1 -1
  92. package/dist/chunks/messages-Cv4I3k1W2.cjs +1 -0
  93. package/dist/chunks/{messages-BScbCwsN.cjs → messages-CwHRv6g8.cjs} +1 -1
  94. package/dist/chunks/{messages-EUS1-T0-.mjs → messages-CyCl8la6.mjs} +2 -0
  95. package/dist/chunks/{messages-DOUT2sT62.cjs → messages-CzXnHfGb2.cjs} +1 -1
  96. package/dist/chunks/{messages-ndFXaPuJ.cjs → messages-D2QxLx1a.cjs} +1 -1
  97. package/dist/chunks/{messages-CDLJmxWA.cjs → messages-D4LUPpX_.cjs} +1 -1
  98. package/dist/{messages-DpQjOxzP.mjs → chunks/messages-D7YPlNAK.mjs} +2 -0
  99. package/dist/{messages-S0krg7sB.mjs → chunks/messages-DGHTTk1S2.mjs} +3 -1
  100. package/dist/chunks/{messages-wZhc9mFF2.mjs → messages-DHdoaaFq2.mjs} +6 -4
  101. package/dist/chunks/{messages-C0BMFvdy.mjs → messages-DI9Ifrgt.mjs} +2 -0
  102. package/dist/chunks/messages-DJFL-bxd2.cjs +1 -0
  103. package/dist/chunks/messages-DLEeNpMi2.cjs +1 -0
  104. package/dist/chunks/{messages-BpI1875E.mjs → messages-DNqFlfOd.mjs} +3 -1
  105. package/dist/chunks/{messages-mtoLIsYL.cjs → messages-DTNU_cq0.cjs} +1 -1
  106. package/dist/chunks/{messages-BxXGCWit.cjs → messages-DVKsYqpJ.cjs} +1 -1
  107. package/dist/chunks/{messages-BJNTs8dY.cjs → messages-DXlfz-nC.cjs} +1 -1
  108. package/dist/chunks/{messages-DKdgRSvy.cjs → messages-DbA_Zja3.cjs} +1 -1
  109. package/dist/chunks/{messages-CZ2th1UV2.cjs → messages-Dc2TTEx_2.cjs} +1 -1
  110. package/dist/chunks/{messages-Bh-GPq0T2.mjs → messages-Dd4nzvLj2.mjs} +2 -0
  111. package/dist/chunks/{messages-BISkpo37.cjs → messages-DeDMMmRC.cjs} +1 -1
  112. package/dist/chunks/{messages-C0Fr1grN.mjs → messages-DefZ3ihx.mjs} +2 -0
  113. package/dist/{messages-DC1fWdjB2.mjs → chunks/messages-DhZwMl9x2.mjs} +2 -0
  114. package/dist/chunks/{messages-BYT844Pj.mjs → messages-DiGsu5XN.mjs} +6 -4
  115. package/dist/chunks/{messages-xeJ5eVFo.cjs → messages-DlQNXqzr.cjs} +1 -1
  116. package/dist/{messages-CZYocA-2.mjs → chunks/messages-DlcI-0Sy.mjs} +2 -0
  117. package/dist/{messages-ZJE9VNzB2.mjs → chunks/messages-DmErSGPk2.mjs} +2 -0
  118. package/dist/chunks/{messages-h9Zi_9Gr.cjs → messages-DqMqZLcn.cjs} +1 -1
  119. package/dist/chunks/{messages-D_w-pjpG2.cjs → messages-DqqDuEE22.cjs} +1 -1
  120. package/dist/chunks/{messages-DW0CNDiw.mjs → messages-DsyO86r3.mjs} +2 -0
  121. package/dist/chunks/{messages-DgdjQ2JT.mjs → messages-DzY53I67.mjs} +2 -0
  122. package/dist/chunks/{messages-PeAC6FL2.cjs → messages-DzppdmWe.cjs} +1 -1
  123. package/dist/chunks/{messages-CkCgWAJW2.mjs → messages-GHsufIGi2.mjs} +4 -2
  124. package/dist/chunks/{messages-Diinl7nA2.cjs → messages-HzLF-BQL2.cjs} +1 -1
  125. package/dist/chunks/{messages-CoWmNHyu2.cjs → messages-Jb9n97oP2.cjs} +1 -1
  126. package/dist/chunks/{messages-2sqZ51ZE2.cjs → messages-K_vSdSoF2.cjs} +1 -1
  127. package/dist/{messages-D-K9TXl02.mjs → chunks/messages-LTkIIrSe2.mjs} +6 -4
  128. package/dist/chunks/{messages-zqNVwsuv.mjs → messages-MPF8o3EP.mjs} +2 -0
  129. package/dist/chunks/{messages-5HoTbob5.cjs → messages-Nh7wrRdm.cjs} +1 -1
  130. package/dist/chunks/{messages-B6ALGrrK2.mjs → messages-OSIAf0Wk2.mjs} +5 -3
  131. package/dist/chunks/{messages-P9sjeERx.mjs → messages-OYoN_rp1.mjs} +4 -2
  132. package/dist/chunks/messages-QHS-Ydg_.cjs +1 -0
  133. package/dist/chunks/{messages-DLphNjiM2.cjs → messages-SpiG5vT-2.cjs} +1 -1
  134. package/dist/chunks/{messages-RumMLtL32.mjs → messages-Uc3Uc2862.mjs} +3 -1
  135. package/dist/chunks/{messages-BP9zsQtc.mjs → messages-V8K7-1l2.mjs} +2 -0
  136. package/dist/chunks/{messages-BR1Rd5-u2.cjs → messages-XFaJzdhP2.cjs} +1 -1
  137. package/dist/{messages-B3GO2TNx2.mjs → chunks/messages-Z9mDYT3w.mjs} +2 -0
  138. package/dist/chunks/{messages-CEroCDzi.mjs → messages-ZHNvKiIX.mjs} +2 -0
  139. package/dist/chunks/{messages-C2irZQlh.mjs → messages-bSVgJ1cu.mjs} +3 -1
  140. package/dist/chunks/{messages-DlNTalkx2.mjs → messages-bjSJwsXK2.mjs} +2 -0
  141. package/dist/{messages-D_jk0Apm.mjs → chunks/messages-eyGOcbhV.mjs} +2 -0
  142. package/dist/chunks/{messages-DlvmJJK6.mjs → messages-fSeXd6-z.mjs} +3 -1
  143. package/dist/{messages-BYooY4mP2.mjs → chunks/messages-l5xHQb_m.mjs} +7 -5
  144. package/dist/{messages-D_pfhYg5.mjs → chunks/messages-rEsI_fAk.mjs} +5 -3
  145. package/dist/chunks/{messages-MxqZVywa2.mjs → messages-sqdfYuVj2.mjs} +2 -0
  146. package/dist/chunks/{messages-C-D80jVE.mjs → messages-vQ5kblO8.mjs} +2 -0
  147. package/dist/chunks/{messages-BwNXKlvA2.cjs → messages-y03BGg692.cjs} +1 -1
  148. package/dist/chunks/tools-DOuVjow8.cjs +116 -0
  149. package/dist/chunks/{tools-1xd7TPfu.mjs → tools-Tt-NXbRZ.mjs} +1816 -1637
  150. package/dist/full.cjs +1 -1
  151. package/dist/full.mjs +3 -3
  152. package/dist/locales.mjs +69 -67
  153. package/dist/{chunks/messages-CkdgHogc2.mjs → messages-1ufJbdRv2.mjs} +3 -1
  154. package/dist/{messages-cBA8dKoi.mjs → messages-3j4yi-DF.mjs} +5 -3
  155. package/dist/{chunks/messages-BGCpxpgG.mjs → messages-5USazVPA2.mjs} +2 -0
  156. package/dist/{chunks/messages-Cf9wwoye2.mjs → messages-7fwJIrld2.mjs} +2 -0
  157. package/dist/{messages-hVVP_eZE.mjs → messages-AycxTjmw.mjs} +2 -0
  158. package/dist/{messages-Bg5tERmS.mjs → messages-B3PWaMcw.mjs} +6 -4
  159. package/dist/{chunks/messages-Diozu4lJ.mjs → messages-B3oFjWq3.mjs} +4 -2
  160. package/dist/{chunks/messages-ByJ-nSXK.mjs → messages-B8Tq9Txy.mjs} +2 -0
  161. package/dist/{messages-CDJP_fbb2.mjs → messages-BDwU9rYR2.mjs} +4 -2
  162. package/dist/{messages-6ukS6d5Z.mjs → messages-BGzpwNrz.mjs} +2 -0
  163. package/dist/{chunks/messages-CHXG6lEA2.mjs → messages-BKCuCTFM.mjs} +2 -0
  164. package/dist/{chunks/messages-aGEPK1g12.mjs → messages-BSHFypGE2.mjs} +2 -0
  165. package/dist/{chunks/messages-OMGVF8X52.mjs → messages-BcD7xtJA.mjs} +3 -1
  166. package/dist/{messages-DA2x_UvX2.mjs → messages-Bj03XD-02.mjs} +6 -4
  167. package/dist/{chunks/messages-C3NrnRWC.mjs → messages-BkTBwYet.mjs} +2 -0
  168. package/dist/{messages-ZjCwxd3_2.mjs → messages-BmWP4vpV2.mjs} +2 -0
  169. package/dist/{chunks/messages-DDtwOfXf.mjs → messages-Bt4TLGth.mjs} +2 -0
  170. package/dist/{chunks/messages-Bly_2YUk.mjs → messages-BtDz-sw92.mjs} +2 -0
  171. package/dist/{messages-CTcNzaJJ2.mjs → messages-C2TRJroV2.mjs} +2 -0
  172. package/dist/{messages-CDRUbL17.mjs → messages-C31VIrlL.mjs} +2 -0
  173. package/dist/{messages-Yg8Y6PlG.mjs → messages-C8RMjnBe.mjs} +2 -0
  174. package/dist/{chunks/messages-BciKgfP4.mjs → messages-C9GFRcVj.mjs} +6 -4
  175. package/dist/{chunks/messages-0cSP25RB.mjs → messages-CAGQtm7T.mjs} +5 -3
  176. package/dist/{messages-_6tu8F-N.mjs → messages-CITYhXUz.mjs} +2 -0
  177. package/dist/{messages-BbaS2xgR2.mjs → messages-CIjSE2_O2.mjs} +5 -3
  178. package/dist/{messages-BQ7jJt9m.mjs → messages-CRR1VRO6.mjs} +2 -0
  179. package/dist/{chunks/messages-Da-9fv3U.mjs → messages-CTzO11jz.mjs} +2 -0
  180. package/dist/{messages-DaSzBuLF2.mjs → messages-CX8egsiA2.mjs} +2 -0
  181. package/dist/{messages-DccIq7002.mjs → messages-C_gdsU952.mjs} +4 -2
  182. package/dist/{messages-CXXQC9Vz.mjs → messages-C_mN4lx0.mjs} +3 -1
  183. package/dist/{chunks/messages-BI7NfKFe.mjs → messages-CacRpQpm.mjs} +4 -2
  184. package/dist/{chunks/messages-BCRpttn3.mjs → messages-Cdgz3urh.mjs} +2 -0
  185. package/dist/{messages-BaC-sNb4.mjs → messages-CgVEHCQ-.mjs} +3 -1
  186. package/dist/{chunks/messages-D_24p8E62.mjs → messages-CgaGkQi32.mjs} +2 -0
  187. package/dist/{chunks/messages-D3AyiRbO.mjs → messages-CmN2OfuB.mjs} +2 -0
  188. package/dist/{chunks/messages-CSierpa_2.mjs → messages-CntTlSE22.mjs} +2 -0
  189. package/dist/{messages-BK1sXq7X.mjs → messages-Cp0fjsey.mjs} +3 -1
  190. package/dist/{messages-DHOj5syv2.mjs → messages-Cx7sqvx02.mjs} +2 -0
  191. package/dist/{messages-CQUbgCd62.mjs → messages-CxX23Jsk2.mjs} +4 -2
  192. package/dist/{chunks/messages-DTqb7T61.mjs → messages-D-rvoUSJ.mjs} +2 -0
  193. package/dist/{messages-Bkbhk9kJ2.mjs → messages-D1Fjr4OK2.mjs} +2 -0
  194. package/dist/{chunks/messages-CSkYL3AP.mjs → messages-D4U4wkYM.mjs} +2 -0
  195. package/dist/{chunks/messages-DwuvQpsD.mjs → messages-D5qgCWmB2.mjs} +7 -5
  196. package/dist/{chunks/messages-a_XmI-x5.mjs → messages-D788KtGe.mjs} +2 -0
  197. package/dist/{chunks/messages-B4-oaYBZ.mjs → messages-DFfhoDWZ2.mjs} +2 -0
  198. package/dist/{messages-BgcWyc4R.mjs → messages-DKsyrVp5.mjs} +2 -0
  199. package/dist/{messages-B_Js-HRK.mjs → messages-DL7JAwpC.mjs} +2 -0
  200. package/dist/{chunks/messages-CSioKJVK2.mjs → messages-DNlrcG5Z.mjs} +2 -0
  201. package/dist/{chunks/messages-vGRE1OPk2.mjs → messages-DPqFBtJR.mjs} +2 -0
  202. package/dist/{chunks/messages-BTKAxpmi.mjs → messages-DQik3_xv2.mjs} +2 -0
  203. package/dist/{messages-BUksRT7Q.mjs → messages-DTkd9ND8.mjs} +7 -5
  204. package/dist/{messages-Br4tspi_2.mjs → messages-DXCyNanc2.mjs} +2 -0
  205. package/dist/{chunks/messages-CdJq8h3E.mjs → messages-D_WzyzUt.mjs} +2 -0
  206. package/dist/{chunks/messages-DC0r7l8x2.mjs → messages-Ddz6eH0-2.mjs} +2 -0
  207. package/dist/{messages-BqCRuWLo.mjs → messages-DiL61awK.mjs} +2 -0
  208. package/dist/{chunks/messages-DXaps_uI.mjs → messages-Dq2WEsEu.mjs} +2 -0
  209. package/dist/{chunks/messages-8qsQ7qZX2.mjs → messages-DqXJJPx9.mjs} +3 -1
  210. package/dist/{messages-jh3qE8dL.mjs → messages-Duk7VVeY.mjs} +3 -1
  211. package/dist/{messages-DQHRgl_P.mjs → messages-DzkZ434Z.mjs} +4 -2
  212. package/dist/{messages-DUdZKtlE.mjs → messages-JKXCsFKZ.mjs} +2 -0
  213. package/dist/{chunks/messages-C9-UAJuq.mjs → messages-NVepzgE3.mjs} +4 -2
  214. package/dist/{messages-omcUe0Za.mjs → messages-PQVh93mt.mjs} +2 -0
  215. package/dist/{chunks/messages-xRQMQj4w2.mjs → messages-ftPYsH6d2.mjs} +6 -4
  216. package/dist/{chunks/messages-Ddb_L6gp2.mjs → messages-gQ5PFa2t2.mjs} +2 -0
  217. package/dist/{messages-DzqQWiFx.mjs → messages-oIa8wahx.mjs} +2 -0
  218. package/dist/{messages-DO62ugjy2.mjs → messages-rpO1POP02.mjs} +3 -1
  219. package/dist/{messages-63r3O0932.mjs → messages-uy3FE24_2.mjs} +4 -2
  220. package/dist/react.cjs +1 -1
  221. package/dist/react.mjs +1 -1
  222. package/dist/tools.cjs +1 -1
  223. package/dist/tools.mjs +2 -2
  224. package/package.json +1 -1
  225. package/src/blok.ts +2 -0
  226. package/src/cli/commands/convert-html/block-builder.ts +13 -3
  227. package/src/components/i18n/locales/am/messages.json +2 -1
  228. package/src/components/i18n/locales/ar/messages.json +2 -1
  229. package/src/components/i18n/locales/az/messages.json +3 -2
  230. package/src/components/i18n/locales/bg/messages.json +2 -1
  231. package/src/components/i18n/locales/bn/messages.json +2 -1
  232. package/src/components/i18n/locales/bs/messages.json +6 -5
  233. package/src/components/i18n/locales/cs/messages.json +4 -3
  234. package/src/components/i18n/locales/da/messages.json +6 -5
  235. package/src/components/i18n/locales/de/messages.json +4 -3
  236. package/src/components/i18n/locales/dv/messages.json +2 -1
  237. package/src/components/i18n/locales/el/messages.json +2 -1
  238. package/src/components/i18n/locales/en/messages.json +2 -0
  239. package/src/components/i18n/locales/es/messages.json +3 -2
  240. package/src/components/i18n/locales/et/messages.json +3 -2
  241. package/src/components/i18n/locales/fa/messages.json +2 -1
  242. package/src/components/i18n/locales/fi/messages.json +3 -2
  243. package/src/components/i18n/locales/fil/messages.json +7 -6
  244. package/src/components/i18n/locales/fr/messages.json +4 -3
  245. package/src/components/i18n/locales/gu/messages.json +2 -1
  246. package/src/components/i18n/locales/he/messages.json +2 -1
  247. package/src/components/i18n/locales/hi/messages.json +2 -1
  248. package/src/components/i18n/locales/hr/messages.json +5 -4
  249. package/src/components/i18n/locales/hu/messages.json +4 -3
  250. package/src/components/i18n/locales/hy/messages.json +2 -1
  251. package/src/components/i18n/locales/id/messages.json +2 -1
  252. package/src/components/i18n/locales/it/messages.json +5 -4
  253. package/src/components/i18n/locales/ja/messages.json +2 -1
  254. package/src/components/i18n/locales/ka/messages.json +2 -1
  255. package/src/components/i18n/locales/km/messages.json +2 -1
  256. package/src/components/i18n/locales/kn/messages.json +2 -1
  257. package/src/components/i18n/locales/ko/messages.json +2 -1
  258. package/src/components/i18n/locales/ku/messages.json +2 -1
  259. package/src/components/i18n/locales/lo/messages.json +2 -1
  260. package/src/components/i18n/locales/lt/messages.json +3 -2
  261. package/src/components/i18n/locales/lv/messages.json +3 -2
  262. package/src/components/i18n/locales/mk/messages.json +2 -1
  263. package/src/components/i18n/locales/ml/messages.json +2 -1
  264. package/src/components/i18n/locales/mn/messages.json +2 -1
  265. package/src/components/i18n/locales/mr/messages.json +2 -1
  266. package/src/components/i18n/locales/ms/messages.json +4 -3
  267. package/src/components/i18n/locales/my/messages.json +2 -1
  268. package/src/components/i18n/locales/ne/messages.json +2 -1
  269. package/src/components/i18n/locales/nl/messages.json +4 -3
  270. package/src/components/i18n/locales/no/messages.json +4 -3
  271. package/src/components/i18n/locales/pa/messages.json +2 -1
  272. package/src/components/i18n/locales/pl/messages.json +4 -3
  273. package/src/components/i18n/locales/ps/messages.json +2 -1
  274. package/src/components/i18n/locales/pt/messages.json +6 -5
  275. package/src/components/i18n/locales/ro/messages.json +3 -2
  276. package/src/components/i18n/locales/ru/messages.json +2 -1
  277. package/src/components/i18n/locales/sd/messages.json +2 -1
  278. package/src/components/i18n/locales/si/messages.json +2 -1
  279. package/src/components/i18n/locales/sk/messages.json +6 -5
  280. package/src/components/i18n/locales/sl/messages.json +5 -4
  281. package/src/components/i18n/locales/sq/messages.json +3 -2
  282. package/src/components/i18n/locales/sr/messages.json +2 -1
  283. package/src/components/i18n/locales/sv/messages.json +7 -6
  284. package/src/components/i18n/locales/sw/messages.json +2 -1
  285. package/src/components/i18n/locales/ta/messages.json +2 -1
  286. package/src/components/i18n/locales/te/messages.json +2 -1
  287. package/src/components/i18n/locales/th/messages.json +2 -1
  288. package/src/components/i18n/locales/tr/messages.json +2 -1
  289. package/src/components/i18n/locales/ug/messages.json +2 -1
  290. package/src/components/i18n/locales/uk/messages.json +2 -1
  291. package/src/components/i18n/locales/ur/messages.json +2 -1
  292. package/src/components/i18n/locales/vi/messages.json +2 -1
  293. package/src/components/i18n/locales/yi/messages.json +2 -1
  294. package/src/components/i18n/locales/zh/messages.json +2 -1
  295. package/src/components/icons/index.ts +6 -3
  296. package/src/components/inline-tools/inline-tool-marker.ts +12 -0
  297. package/src/components/modules/api/blocks.ts +3 -0
  298. package/src/components/modules/paste/google-docs-preprocessor.ts +64 -28
  299. package/src/components/modules/paste/sanitizer-config.ts +10 -1
  300. package/src/components/modules/renderer.ts +7 -1
  301. package/src/components/modules/toolbar/blockSettings.ts +54 -7
  302. package/src/components/modules/toolbar/content-alignment.ts +89 -0
  303. package/src/components/modules/toolbar/index.ts +85 -61
  304. package/src/components/modules/ui.ts +28 -6
  305. package/src/components/modules/uiControllers/controllers/blockHover.ts +20 -0
  306. package/src/components/utils/color-mapping.ts +15 -0
  307. package/src/components/utils/color-migration.ts +10 -0
  308. package/src/components/utils/data-model-transform.ts +200 -0
  309. package/src/components/utils/default-page-colors.ts +130 -0
  310. package/src/components/utils/highlight-block-arrival.ts +50 -0
  311. package/src/components/utils/popover/popover-desktop.ts +23 -1
  312. package/src/styles/image.css +86 -0
  313. package/src/styles/keyframes.css +6 -0
  314. package/src/styles/main.css +17 -0
  315. package/src/tools/database/index.ts +3 -4
  316. package/src/tools/image/dimensions-from-svg.ts +53 -0
  317. package/src/tools/image/dimensions-from-url.ts +87 -0
  318. package/src/tools/image/error-state.ts +7 -2
  319. package/src/tools/image/index.ts +81 -7
  320. package/src/tools/image/probe-dimensions.ts +36 -0
  321. package/src/tools/image/ui.ts +46 -2
  322. package/src/tools/image/uploader.ts +12 -8
  323. package/src/tools/table/table-cell-clipboard.ts +17 -3
  324. package/types/tools/image.d.ts +16 -2
  325. package/dist/chunks/constants-JFG5JxhI.cjs +0 -457
  326. package/dist/chunks/messages-C-FUK4Ki2.cjs +0 -1
  327. package/dist/chunks/messages-CLkrVqVp.cjs +0 -1
  328. package/dist/chunks/messages-D9qYuzOY2.cjs +0 -1
  329. package/dist/chunks/messages-DEdX7dXt2.cjs +0 -1
  330. package/dist/chunks/tools-Cnlc1TxG.cjs +0 -116
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Detect default page background colors that should NOT be mapped to a Blok preset.
3
+ *
4
+ * When browsers natively copy from a contenteditable, computed styles include
5
+ * the resolved page background (e.g. `rgb(255, 255, 255)` in light mode,
6
+ * `rgb(25, 25, 24)` in Blok's dark mode). These are not intentional formatting
7
+ * and would otherwise collapse onto the gray bg preset since gray is the only
8
+ * achromatic background.
9
+ *
10
+ * Centralized here so every consumer (paste preprocessors, table clipboard,
11
+ * HTML import, color-mapping itself) shares the same definition.
12
+ *
13
+ * Kept dependency-free (no import of color-mapping) to avoid a circular
14
+ * import — color-mapping uses these predicates as a defense-in-depth guard.
15
+ */
16
+
17
+ /**
18
+ * True when bgColor is the default white page background
19
+ * (`#fff`, `#ffffff`, `rgb(255,255,255)`, or the keyword `white`).
20
+ */
21
+ export function isDefaultWhiteBackground(bgColor: string): boolean {
22
+ const normalized = bgColor.replace(/\s/g, '').toLowerCase();
23
+
24
+ return (
25
+ normalized === 'rgb(255,255,255)' ||
26
+ normalized === '#ffffff' ||
27
+ normalized === '#fff' ||
28
+ normalized === 'white'
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Compute simplified linear luminance (no gamma correction) of a CSS color
34
+ * value. Adequate for threshold comparisons used to spot default page bgs.
35
+ *
36
+ * Supports: `#rgb`, `#rrggbb`, `rgb(...)`, `rgba(...)`, `hsl(...)`, `hsla(...)`.
37
+ * Alpha is ignored. Returns -1 if the format is unrecognized.
38
+ */
39
+ function computeRelativeLuminance(color: string): number {
40
+ const normalized = color.replace(/\s/g, '').toLowerCase();
41
+
42
+ const rgbMatch = /^rgba?\((\d+),(\d+),(\d+)(?:,[\d.]+)?\)$/.exec(normalized);
43
+
44
+ if (rgbMatch) {
45
+ const r = parseInt(rgbMatch[1], 10) / 255;
46
+ const g = parseInt(rgbMatch[2], 10) / 255;
47
+ const b = parseInt(rgbMatch[3], 10) / 255;
48
+
49
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
50
+ }
51
+
52
+ const hslMatch = /^hsla?\(([\d.]+),([\d.]+)%,([\d.]+)%(?:,[\d.]+)?\)$/.exec(normalized);
53
+
54
+ if (hslMatch) {
55
+ const h = parseFloat(hslMatch[1]) / 360;
56
+ const s = parseFloat(hslMatch[2]) / 100;
57
+ const l = parseFloat(hslMatch[3]) / 100;
58
+
59
+ if (s === 0) {
60
+ /* achromatic — r = g = b = l */
61
+ return 0.2126 * l + 0.7152 * l + 0.0722 * l;
62
+ }
63
+
64
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
65
+ const p = 2 * l - q;
66
+ const wrap = (t: number): number => {
67
+ if (t < 0) {
68
+ return t + 1;
69
+ }
70
+
71
+ if (t > 1) {
72
+ return t - 1;
73
+ }
74
+
75
+ return t;
76
+ };
77
+ const hueToChannel = (t: number): number => {
78
+ const wrapped = wrap(t);
79
+
80
+ if (wrapped < 1 / 6) {
81
+ return p + (q - p) * 6 * wrapped;
82
+ }
83
+
84
+ if (wrapped < 1 / 2) {
85
+ return q;
86
+ }
87
+
88
+ if (wrapped < 2 / 3) {
89
+ return p + (q - p) * (2 / 3 - wrapped) * 6;
90
+ }
91
+
92
+ return p;
93
+ };
94
+
95
+ const r = hueToChannel(h + 1 / 3);
96
+ const g = hueToChannel(h);
97
+ const b = hueToChannel(h - 1 / 3);
98
+
99
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
100
+ }
101
+
102
+ const hexMatch = /^#([0-9a-f]{6}|[0-9a-f]{3})$/.exec(normalized);
103
+
104
+ if (hexMatch) {
105
+ const hex = hexMatch[1];
106
+ const expand = hex.length === 3
107
+ ? [hex[0] + hex[0], hex[1] + hex[1], hex[2] + hex[2]]
108
+ : [hex.substring(0, 2), hex.substring(2, 4), hex.substring(4, 6)];
109
+ const r = parseInt(expand[0], 16) / 255;
110
+ const g = parseInt(expand[1], 16) / 255;
111
+ const b = parseInt(expand[2], 16) / 255;
112
+
113
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
114
+ }
115
+
116
+ return -1;
117
+ }
118
+
119
+ /**
120
+ * True when bgColor is a near-black (dark mode page) background.
121
+ *
122
+ * Uses simplified linear luminance < 0.12 — below all Blok dark bg presets
123
+ * (~18% minimum lightness for #2f2f2f, lin-luminance ≈ 0.184) while catching
124
+ * typical dark page backgrounds (`#191918` ≈ 0.098, `rgb(25,25,24)` ≈ 0.098).
125
+ */
126
+ export function isDefaultDarkBackground(bgColor: string): boolean {
127
+ const luminance = computeRelativeLuminance(bgColor);
128
+
129
+ return luminance >= 0 && luminance < 0.12;
130
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Applies a brief "target" highlight pulse to a block holder after the editor
3
+ * scrolls to it from a `#<block-id>` URL (Notion/Google Docs behaviour).
4
+ *
5
+ * The caller is responsible for choosing the right moment (after scroll + select).
6
+ * We toggle the `blok-block--target` class on the element; removal happens on
7
+ * `animationend` (preferred, avoids timer drift) with a defensive timeout
8
+ * fallback in case the animation is cancelled / never runs (e.g. element
9
+ * detached, reduced-motion stack collapses the keyframes to 0ms).
10
+ */
11
+
12
+ const TARGET_CLASS = 'blok-block--target';
13
+ const FALLBACK_REMOVE_MS = 1800;
14
+
15
+ /**
16
+ * Briefly highlight the given element to signal arrival from a hash link.
17
+ * Safe to call repeatedly — re-triggers a fresh pulse.
18
+ */
19
+ export function highlightBlockArrival(el: Element): void {
20
+ // Re-add: if class is already there (repeat navigation), force a reflow so
21
+ // the keyframes restart.
22
+ el.classList.remove(TARGET_CLASS);
23
+ // Force reflow to guarantee the animation restarts when class is re-added.
24
+ void (el as HTMLElement).offsetWidth;
25
+ el.classList.add(TARGET_CLASS);
26
+
27
+ const state = { removed: false };
28
+
29
+ const clear = (): void => {
30
+ if (state.removed) {
31
+ return;
32
+ }
33
+ state.removed = true;
34
+ el.classList.remove(TARGET_CLASS);
35
+ el.removeEventListener('animationend', onAnimationEnd);
36
+ };
37
+
38
+ const onAnimationEnd = (event: Event): void => {
39
+ // Only react to the holder's own animation, not a descendant's.
40
+ if (event.target === el) {
41
+ clear();
42
+ }
43
+ };
44
+
45
+ el.addEventListener('animationend', onAnimationEnd);
46
+
47
+ // Fallback: if animationend never fires (reduced motion, detached element,
48
+ // CSS not loaded) remove the class after the animation window.
49
+ window.setTimeout(clear, FALLBACK_REMOVE_MS);
50
+ }
@@ -124,6 +124,15 @@ export class PopoverDesktop extends PopoverAbstract {
124
124
  */
125
125
  private trigger: HTMLElement | undefined;
126
126
 
127
+ /**
128
+ * Trigger rect captured at construction time. Used as a fallback if the
129
+ * live trigger rect has collapsed to zero size by the time `show()` runs
130
+ * (e.g. because a subscriber to an "opened" event set the trigger to
131
+ * `display:none`). Prevents the popover from rendering at the viewport's
132
+ * top-left corner when the trigger is no longer measurable.
133
+ */
134
+ private capturedTriggerRect: DOMRect | undefined;
135
+
127
136
  /**
128
137
  * Optional element whose left edge is used for horizontal positioning
129
138
  * instead of the trigger's left edge.
@@ -189,6 +198,12 @@ export class PopoverDesktop extends PopoverAbstract {
189
198
 
190
199
  if (params.trigger) {
191
200
  this.trigger = params.trigger;
201
+
202
+ const initialRect = params.trigger.getBoundingClientRect();
203
+
204
+ if (initialRect.width > 0 || initialRect.height > 0) {
205
+ this.capturedTriggerRect = initialRect;
206
+ }
192
207
  }
193
208
 
194
209
  if (params.leftAlignElement) {
@@ -413,7 +428,14 @@ export class PopoverDesktop extends PopoverAbstract {
413
428
  */
414
429
  private calculatePosition(): { top: number; left: number; openTop: boolean; openLeft: boolean } {
415
430
  const explicitPosition = this.params.position;
416
- const rect = explicitPosition ?? this.trigger?.getBoundingClientRect();
431
+ const liveRect = this.trigger?.getBoundingClientRect();
432
+ const isLiveRectCollapsed = liveRect !== undefined
433
+ && liveRect.width === 0
434
+ && liveRect.height === 0;
435
+ const fallbackRect = isLiveRectCollapsed && this.capturedTriggerRect !== undefined
436
+ ? this.capturedTriggerRect
437
+ : liveRect;
438
+ const rect = explicitPosition ?? fallbackRect;
417
439
 
418
440
  if (!rect) {
419
441
  return { top: 0, left: 0, openTop: false, openLeft: false };
@@ -19,6 +19,9 @@
19
19
  [data-blok-tool="image"][data-size="md"] .blok-image-inner { width: 520px; }
20
20
  [data-blok-tool="image"][data-size="lg"] .blok-image-inner { width: 100%; }
21
21
  [data-blok-tool="image"][data-size="full"] .blok-image-inner { width: 100%; }
22
+ /* banner-shaped / tiny-natural images: force full width so resize handles
23
+ and toolbar row don't collide with a short figure. */
24
+ [data-blok-tool="image"][data-auto-full="true"] .blok-image-inner { width: 100%; }
22
25
 
23
26
  [data-blok-tool="image"] .blok-image-inner img {
24
27
  display: block;
@@ -63,6 +66,10 @@
63
66
  }
64
67
  [data-blok-tool="image"][data-caption="off"] .blok-image-caption { display: none; }
65
68
 
69
+ /* Hide caption row while image is loading — nothing to caption yet. */
70
+ [data-blok-tool="image"]:has(.blok-image-inner[data-loading="true"]) .blok-image-caption-row,
71
+ [data-blok-tool="image"]:has(.blok-image-inner[data-loading="true"]) .blok-image-caption { display: none; }
72
+
66
73
  /* caption row — caption text + inline alt button revealed on hover */
67
74
  [data-blok-tool="image"] .blok-image-caption-row {
68
75
  display: flex;
@@ -1019,3 +1026,82 @@
1019
1026
  animation: blok-image-retry-spin 0.65s linear infinite;
1020
1027
  }
1021
1028
 
1029
+ /* Auto-retry loading overlay — img failed once; re-fetching.
1030
+ Ambient blur backdrop + shimmer sweep + soft-glow spinner. */
1031
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"] {
1032
+ overflow: hidden;
1033
+ border-radius: var(--blok-radius-md);
1034
+ isolation: isolate;
1035
+ min-height: 220px;
1036
+ background: color-mix(in srgb, var(--blok-bg-secondary) 65%, var(--blok-bg-primary));
1037
+ }
1038
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"] img {
1039
+ min-height: 220px;
1040
+ }
1041
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"] img {
1042
+ opacity: 0.35;
1043
+ filter: blur(18px) saturate(1.1);
1044
+ transform: scale(1.08);
1045
+ color: transparent; /* suppress alt-text fallback while loading */
1046
+ }
1047
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"]::before {
1048
+ content: "";
1049
+ position: absolute;
1050
+ inset: 0;
1051
+ background:
1052
+ radial-gradient(
1053
+ 120% 80% at 50% 50%,
1054
+ color-mix(in srgb, var(--blok-bg-primary) 55%, transparent) 0%,
1055
+ color-mix(in srgb, var(--blok-bg-secondary) 45%, transparent) 55%,
1056
+ transparent 100%
1057
+ ),
1058
+ linear-gradient(
1059
+ 115deg,
1060
+ transparent 20%,
1061
+ color-mix(in srgb, var(--blok-text-primary) 10%, transparent) 48%,
1062
+ color-mix(in srgb, var(--blok-text-primary) 14%, transparent) 50%,
1063
+ color-mix(in srgb, var(--blok-text-primary) 10%, transparent) 52%,
1064
+ transparent 80%
1065
+ );
1066
+ background-size: 100% 100%, 220% 100%;
1067
+ background-position: 0 0, 120% 0;
1068
+ background-repeat: no-repeat;
1069
+ animation: blok-image-loading-sheen 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
1070
+ pointer-events: none;
1071
+ z-index: 1;
1072
+ }
1073
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"]::after {
1074
+ content: "";
1075
+ position: absolute;
1076
+ inset: 0;
1077
+ width: 34px;
1078
+ height: 34px;
1079
+ margin: auto;
1080
+ border-radius: 50%;
1081
+ border: 2px solid color-mix(in srgb, var(--blok-text-primary) 14%, transparent);
1082
+ border-top-color: var(--blok-text-primary);
1083
+ border-right-color: color-mix(in srgb, var(--blok-text-primary) 55%, transparent);
1084
+ box-shadow:
1085
+ 0 0 0 6px color-mix(in srgb, var(--blok-bg-primary) 22%, transparent),
1086
+ 0 8px 28px color-mix(in srgb, var(--blok-color-accent, var(--blok-text-primary)) 22%, transparent);
1087
+ animation:
1088
+ blok-image-retry-spin 0.9s cubic-bezier(0.65, 0, 0.35, 1) infinite,
1089
+ blok-image-loading-pulse 1.8s ease-in-out infinite;
1090
+ pointer-events: none;
1091
+ z-index: 2;
1092
+ }
1093
+ @keyframes blok-image-loading-sheen {
1094
+ 0% { background-position: 0 0, 120% 0; }
1095
+ 100% { background-position: 0 0, -120% 0; }
1096
+ }
1097
+ @keyframes blok-image-loading-pulse {
1098
+ 0%, 100% { opacity: 0.85; }
1099
+ 50% { opacity: 1; }
1100
+ }
1101
+ @media (prefers-reduced-motion: reduce) {
1102
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"]::before { animation: none; }
1103
+ [data-blok-tool="image"] .blok-image-inner[data-loading="true"]::after {
1104
+ animation: blok-image-retry-spin 1.4s linear infinite;
1105
+ }
1106
+ }
1107
+
@@ -60,3 +60,9 @@
60
60
  @keyframes blok-image-retry-spin {
61
61
  to { transform: rotate(360deg); }
62
62
  }
63
+
64
+ @keyframes blok-block-target-pulse {
65
+ 0% { background-color: var(--blok-selection); }
66
+ 60% { background-color: var(--blok-selection); }
67
+ 100% { background-color: transparent; }
68
+ }
@@ -193,6 +193,23 @@
193
193
  border-radius: var(--blok-space-1);
194
194
  }
195
195
 
196
+ /*
197
+ * Arrival pulse: briefly highlight the block that a #<id> URL points to
198
+ * after scroll + select. Class is applied/removed by highlightBlockArrival().
199
+ */
200
+ .blok-block--target {
201
+ animation: blok-block-target-pulse 1.5s ease-out;
202
+ border-radius: var(--blok-space-1);
203
+ }
204
+
205
+ @media (prefers-reduced-motion: reduce) {
206
+ .blok-block--target {
207
+ /* Skip the keyframe tween but keep the hold so the class still clears. */
208
+ animation: none;
209
+ background-color: var(--blok-selection);
210
+ }
211
+ }
212
+
196
213
  /**
197
214
  * Content alignment
198
215
  * Applies horizontal alignment to block content based on the editor's contentAlign setting.
@@ -260,12 +260,11 @@ export class DatabaseTool implements BlockTool {
260
260
  }
261
261
 
262
262
  /**
263
- * Returns the outer wrapper element as the toolbar anchor so the toolbar
264
- * vertically centers on the block's visual top, not on a deeply nested
265
- * descendant (or falls back to pluginsContent when no contenteditable exists).
263
+ * Returns the title element so the block toolbar vertically centers on the
264
+ * database title line rather than on the outer wrapper's top edge.
266
265
  */
267
266
  getToolbarAnchorElement(): HTMLElement | undefined {
268
- return this.element ?? undefined;
267
+ return this.titleElement ?? undefined;
269
268
  }
270
269
 
271
270
  // ---------------------------------------------------------------------------
@@ -0,0 +1,53 @@
1
+ type Dims = { width: number; height: number };
2
+
3
+ function parseNumber(raw: string | null): number | null {
4
+ if (raw == null) return null;
5
+ const match = /^(-?\d+(?:\.\d+)?)(px)?$/.exec(raw.trim());
6
+ if (!match) return null;
7
+ const n = Number(match[1]);
8
+ return Number.isFinite(n) && n > 0 ? n : null;
9
+ }
10
+
11
+ function isSvgUrl(url: string): boolean {
12
+ try {
13
+ const { pathname } = new URL(url, 'https://base.local');
14
+ return /\.svg(?:$|\?|#)/i.test(pathname);
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+
20
+ async function fetchSvgText(url: string): Promise<string | null> {
21
+ try {
22
+ const res = await fetch(url);
23
+ if (!res.ok) return null;
24
+ return await res.text();
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+
30
+ function dimsFromViewBox(viewBox: string | null): Dims | null {
31
+ if (!viewBox) return null;
32
+ const parts = viewBox.trim().split(/[\s,]+/);
33
+ if (parts.length !== 4) return null;
34
+ const vw = parseNumber(parts[2]);
35
+ const vh = parseNumber(parts[3]);
36
+ if (vw == null || vh == null) return null;
37
+ return { width: vw, height: vh };
38
+ }
39
+
40
+ export async function dimensionsFromSvg(url: string): Promise<Dims | null> {
41
+ if (!isSvgUrl(url)) return null;
42
+ const text = await fetchSvgText(url);
43
+ if (text == null) return null;
44
+ const doc = new DOMParser().parseFromString(text, 'image/svg+xml');
45
+ const root = doc.documentElement;
46
+ if (!root || root.tagName.toLowerCase() !== 'svg') return null;
47
+
48
+ const w = parseNumber(root.getAttribute('width'));
49
+ const h = parseNumber(root.getAttribute('height'));
50
+ if (w != null && h != null) return { width: w, height: h };
51
+
52
+ return dimsFromViewBox(root.getAttribute('viewBox'));
53
+ }
@@ -0,0 +1,87 @@
1
+ type Dims = { width: number; height: number };
2
+
3
+ function valid(w: unknown, h: unknown): Dims | null {
4
+ const width = Number(w);
5
+ const height = Number(h);
6
+ if (!Number.isFinite(width) || !Number.isFinite(height)) return null;
7
+ if (width <= 0 || height <= 0) return null;
8
+ return { width, height };
9
+ }
10
+
11
+ function fromSearchParams(params: URLSearchParams): Dims | null {
12
+ const size = params.get('size') ?? params.get('dim') ?? params.get('dimensions');
13
+ if (size) {
14
+ const match = /^(\d+)[xX](\d+)$/.exec(size);
15
+ if (match) return valid(match[1], match[2]);
16
+ }
17
+ const resize = params.get('resize') ?? params.get('fit');
18
+ if (resize) {
19
+ const match = /^(\d+),(\d+)$/.exec(resize);
20
+ if (match) return valid(match[1], match[2]);
21
+ }
22
+ const w = params.get('w') ?? params.get('width') ?? params.get('imwidth');
23
+ const h = params.get('h') ?? params.get('height') ?? params.get('imheight');
24
+ if (w && h) return valid(w, h);
25
+ return null;
26
+ }
27
+
28
+ function firstMatch(segments: string[], re: RegExp): string | null {
29
+ for (const seg of segments) {
30
+ const m = re.exec(seg);
31
+ if (m) return m[1];
32
+ }
33
+ return null;
34
+ }
35
+
36
+ function fromCloudinary(pathname: string): Dims | null {
37
+ const match = /\/(?:upload|fetch|private|authenticated)\/([^/]+(?:\/[^/]+)*)\//.exec(pathname);
38
+ if (!match) return null;
39
+ const segments = match[1].split('/');
40
+ const w = firstMatch(segments, /(?:^|,)w_(\d+)(?:,|$)/);
41
+ const h = firstMatch(segments, /(?:^|,)h_(\d+)(?:,|$)/);
42
+ return w && h ? valid(w, h) : null;
43
+ }
44
+
45
+ function fromCloudflare(pathname: string): Dims | null {
46
+ const match = /\/cdn-cgi\/image\/([^/]+)\//.exec(pathname);
47
+ if (!match) return null;
48
+ const w = /(?:^|,)width=(\d+)(?:,|$)/.exec(match[1]);
49
+ const h = /(?:^|,)height=(\d+)(?:,|$)/.exec(match[1]);
50
+ return w && h ? valid(w[1], h[1]) : null;
51
+ }
52
+
53
+ function fromImageKit(pathname: string): Dims | null {
54
+ const match = /\/tr:([^/]+)\//.exec(pathname);
55
+ if (!match) return null;
56
+ const w = /(?:^|,)w-(\d+)(?:,|$)/.exec(match[1]);
57
+ const h = /(?:^|,)h-(\d+)(?:,|$)/.exec(match[1]);
58
+ return w && h ? valid(w[1], h[1]) : null;
59
+ }
60
+
61
+ function fromPath(pathname: string): Dims | null {
62
+ return fromCloudinary(pathname) ?? fromCloudflare(pathname) ?? fromImageKit(pathname);
63
+ }
64
+
65
+ function fromFilename(pathname: string): Dims | null {
66
+ const base = pathname.split('/').pop() ?? '';
67
+ const wh = /[-_](\d{2,5})[xX](\d{2,5})(?:[._-]|\.[a-z0-9]+$)/.exec(base);
68
+ if (wh) return valid(wh[1], wh[2]);
69
+ const sep = /[-_]w(\d+)[-_]h(\d+)/.exec(base);
70
+ if (sep) return valid(sep[1], sep[2]);
71
+ return null;
72
+ }
73
+
74
+ function safeParse(url: string): URL | null {
75
+ try {
76
+ return new URL(url, 'https://base.local');
77
+ } catch {
78
+ return null;
79
+ }
80
+ }
81
+
82
+ export function dimensionsFromUrl(url: string): Dims | null {
83
+ if (!url) return null;
84
+ const parsed = safeParse(url);
85
+ if (!parsed) return null;
86
+ return fromSearchParams(parsed.searchParams) ?? fromPath(parsed.pathname) ?? fromFilename(parsed.pathname);
87
+ }
@@ -1,10 +1,13 @@
1
- import { IconImageBroken } from '../../components/icons';
1
+ import { IconImageBroken, IconUploadFailed } from '../../components/icons';
2
2
  import type { I18nInstance } from '../../components/utils/tools';
3
3
  import { tr } from './i18n';
4
4
 
5
+ export type ErrorVariant = 'broken' | 'upload';
6
+
5
7
  export interface ErrorStateOptions {
6
8
  title?: string;
7
9
  message?: string;
10
+ variant?: ErrorVariant;
8
11
  onTryAgain?(): void;
9
12
  onSwap?(): void;
10
13
  i18n?: I18nInstance;
@@ -14,11 +17,13 @@ export function renderErrorState(opts: ErrorStateOptions): HTMLElement {
14
17
  const root = document.createElement('div');
15
18
  root.className = 'blok-image-error';
16
19
  root.setAttribute('data-role', 'error-state');
20
+ const variant: ErrorVariant = opts.variant ?? 'broken';
21
+ root.setAttribute('data-variant', variant);
17
22
 
18
23
  const icon = document.createElement('div');
19
24
  icon.className = 'blok-image-error__icon';
20
25
  icon.setAttribute('aria-hidden', 'true');
21
- icon.innerHTML = IconImageBroken;
26
+ icon.innerHTML = variant === 'upload' ? IconUploadFailed : IconImageBroken;
22
27
 
23
28
  const body = document.createElement('div');
24
29
  body.className = 'blok-image-error__body';