@jackuait/blok 0.6.0-beta.9 → 0.6.0

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 (320) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-Bn6Q_o8h.mjs → blok-BAh1rvUC.mjs} +3410 -2927
  3. package/dist/chunks/i18next-B47TKgbU.mjs +1303 -0
  4. package/dist/chunks/{i18next-loader-DjR4d8M7.mjs → i18next-loader-CHtGO6IK.mjs} +2 -2
  5. package/dist/chunks/{index-oe38cp86.mjs → index-DBWWKrDe.mjs} +12 -12
  6. package/dist/chunks/{inline-tool-convert-SRTkyaZn.mjs → inline-tool-convert-DduRc0fF.mjs} +1467 -951
  7. package/dist/chunks/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
  8. package/dist/chunks/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
  9. package/dist/{messages-DnXLrlHh.mjs → chunks/messages-4v4MuVEc.mjs} +6 -0
  10. package/dist/chunks/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
  11. package/dist/chunks/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
  12. package/dist/chunks/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
  13. package/dist/{messages-uKX8WBaD.mjs → chunks/messages-96kNZDll.mjs} +6 -0
  14. package/dist/chunks/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
  15. package/dist/{messages-DBn76jVV.mjs → chunks/messages-B217znr-.mjs} +8 -2
  16. package/dist/{messages-DT4dP5uK.mjs → chunks/messages-B8WNljW3.mjs} +6 -0
  17. package/dist/chunks/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
  18. package/dist/{messages-CZygwLwM.mjs → chunks/messages-BI43k_BD.mjs} +6 -0
  19. package/dist/{messages-CzTufCHu.mjs → chunks/messages-BJ6zrz2j.mjs} +6 -0
  20. package/dist/{messages-BoJc_p1r.mjs → chunks/messages-BUl_Rcnj.mjs} +6 -0
  21. package/dist/chunks/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
  22. package/dist/{messages-C2htQ_3F.mjs → chunks/messages-BcpCubnC.mjs} +6 -0
  23. package/dist/{messages-D5C3J9qr.mjs → chunks/messages-Bm-E4iRC.mjs} +6 -0
  24. package/dist/chunks/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
  25. package/dist/chunks/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
  26. package/dist/chunks/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
  27. package/dist/{messages-Dz9L52ol.mjs → chunks/messages-CRJ_mchV.mjs} +6 -0
  28. package/dist/chunks/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
  29. package/dist/chunks/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
  30. package/dist/{messages-R3hUSvr3.mjs → chunks/messages-CfiyT2Wi.mjs} +6 -0
  31. package/dist/{messages-CJdUsQ-c.mjs → chunks/messages-CgTq3QhU.mjs} +6 -0
  32. package/dist/chunks/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
  33. package/dist/{messages-Q7AO_FLv.mjs → chunks/messages-Cjjo7yHR.mjs} +6 -0
  34. package/dist/{messages-C99mq906.mjs → chunks/messages-Cl6ayUaq.mjs} +6 -0
  35. package/dist/chunks/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
  36. package/dist/chunks/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
  37. package/dist/chunks/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
  38. package/dist/{messages-BWF-zUpY.mjs → chunks/messages-CrCYPCk3.mjs} +6 -0
  39. package/dist/{messages-D-ZtY5v0.mjs → chunks/messages-Cs8zmZ3L.mjs} +6 -0
  40. package/dist/{messages-DprmQg6V.mjs → chunks/messages-CzK0LEhb.mjs} +6 -0
  41. package/dist/chunks/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
  42. package/dist/chunks/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
  43. package/dist/chunks/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
  44. package/dist/{messages-kep5wtm4.mjs → chunks/messages-D4qqwVgQ.mjs} +6 -0
  45. package/dist/chunks/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
  46. package/dist/{messages-CY8_RyFE.mjs → chunks/messages-D7u2bmP2.mjs} +6 -0
  47. package/dist/chunks/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
  48. package/dist/{messages-DLfR5bMd.mjs → chunks/messages-D9ndgBnU.mjs} +6 -0
  49. package/dist/{messages-CVw84KdI.mjs → chunks/messages-DDTQgImT.mjs} +6 -0
  50. package/dist/{messages-_ErNTNhk.mjs → chunks/messages-DH_jBeED.mjs} +6 -0
  51. package/dist/chunks/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
  52. package/dist/chunks/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
  53. package/dist/chunks/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
  54. package/dist/chunks/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
  55. package/dist/chunks/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
  56. package/dist/chunks/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
  57. package/dist/{messages-Z9nEU2xK.mjs → chunks/messages-DviiFSv2.mjs} +6 -0
  58. package/dist/chunks/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
  59. package/dist/{messages-w7v1GNaE.mjs → chunks/messages-Dzzn6XoD.mjs} +6 -0
  60. package/dist/{messages-CqWJcCbY.mjs → chunks/messages-GSByFygY.mjs} +6 -0
  61. package/dist/chunks/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
  62. package/dist/chunks/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
  63. package/dist/{messages-BU2nlrLK.mjs → chunks/messages-RonBBCnh.mjs} +6 -0
  64. package/dist/{messages-Bmu_S7GM.mjs → chunks/messages-VDriF5Qy.mjs} +6 -0
  65. package/dist/{messages-CLhcMlTc.mjs → chunks/messages-ZjUAIWb1.mjs} +6 -0
  66. package/dist/{messages-9SihnaXQ.mjs → chunks/messages-b1EdvUm0.mjs} +6 -0
  67. package/dist/{messages-DvFLX36Q.mjs → chunks/messages-begYOTgC.mjs} +6 -0
  68. package/dist/{messages-BMv4xwIr.mjs → chunks/messages-jrncnb-H.mjs} +6 -0
  69. package/dist/{messages-D5iv1Kox.mjs → chunks/messages-nefz1S71.mjs} +6 -0
  70. package/dist/{messages-CQwpzUFp.mjs → chunks/messages-ucTVgS5G.mjs} +6 -0
  71. package/dist/chunks/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
  72. package/dist/{messages-C9eaarcK.mjs → chunks/messages-wmi-iFkH.mjs} +6 -0
  73. package/dist/chunks/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
  74. package/dist/full.mjs +2 -2
  75. package/dist/locales.mjs +90 -84
  76. package/dist/{messages-BogRq8lt.mjs → messages-0AbcLMLm.mjs} +6 -0
  77. package/dist/{messages-DJDG55Vq.mjs → messages-0E0AkrNu.mjs} +6 -0
  78. package/dist/{chunks/messages-DnXLrlHh.mjs → messages-4v4MuVEc.mjs} +6 -0
  79. package/dist/{messages-DnIhyAJk.mjs → messages-62v-CLC-.mjs} +6 -0
  80. package/dist/{messages-Dzwxv9v1.mjs → messages-8DeO60Oo.mjs} +6 -0
  81. package/dist/{messages-B1Aww8q7.mjs → messages-8IPXkrDl.mjs} +6 -0
  82. package/dist/{chunks/messages-uKX8WBaD.mjs → messages-96kNZDll.mjs} +6 -0
  83. package/dist/{messages-BL0tXcDf.mjs → messages-B1FZ8lxU.mjs} +6 -0
  84. package/dist/{chunks/messages-DBn76jVV.mjs → messages-B217znr-.mjs} +8 -2
  85. package/dist/{chunks/messages-DT4dP5uK.mjs → messages-B8WNljW3.mjs} +6 -0
  86. package/dist/{messages-BdeLo0N9.mjs → messages-BC8IN4Bf.mjs} +6 -0
  87. package/dist/{chunks/messages-CZygwLwM.mjs → messages-BI43k_BD.mjs} +6 -0
  88. package/dist/{chunks/messages-CzTufCHu.mjs → messages-BJ6zrz2j.mjs} +6 -0
  89. package/dist/{chunks/messages-BoJc_p1r.mjs → messages-BUl_Rcnj.mjs} +6 -0
  90. package/dist/{messages-CnwibSvh.mjs → messages-BZlmVRwn.mjs} +6 -0
  91. package/dist/{chunks/messages-C2htQ_3F.mjs → messages-BcpCubnC.mjs} +6 -0
  92. package/dist/{chunks/messages-D5C3J9qr.mjs → messages-Bm-E4iRC.mjs} +6 -0
  93. package/dist/{messages-BELRf6DU.mjs → messages-C4jL-90N.mjs} +6 -0
  94. package/dist/{messages-1fC8IMyX.mjs → messages-CDBLbUOQ.mjs} +6 -0
  95. package/dist/{messages-7QoX8DkW.mjs → messages-CH4hrauY.mjs} +6 -0
  96. package/dist/{chunks/messages-Dz9L52ol.mjs → messages-CRJ_mchV.mjs} +6 -0
  97. package/dist/{messages-JELdtT6E.mjs → messages-CW4c4cRk.mjs} +6 -0
  98. package/dist/{messages-CKI54h6O.mjs → messages-C_4otP7U.mjs} +6 -0
  99. package/dist/{chunks/messages-R3hUSvr3.mjs → messages-CfiyT2Wi.mjs} +6 -0
  100. package/dist/{chunks/messages-CJdUsQ-c.mjs → messages-CgTq3QhU.mjs} +6 -0
  101. package/dist/{messages-D1Hv8XGo.mjs → messages-Chb7k3Rg.mjs} +6 -0
  102. package/dist/{chunks/messages-Q7AO_FLv.mjs → messages-Cjjo7yHR.mjs} +6 -0
  103. package/dist/{chunks/messages-C99mq906.mjs → messages-Cl6ayUaq.mjs} +6 -0
  104. package/dist/{messages-Diu6jAaR.mjs → messages-CmR9ftc_.mjs} +6 -0
  105. package/dist/{messages-LPVfA-8K.mjs → messages-Cr49Nt3U.mjs} +6 -0
  106. package/dist/{messages-DqM1LFg5.mjs → messages-Cr94GzbX.mjs} +6 -0
  107. package/dist/{chunks/messages-BWF-zUpY.mjs → messages-CrCYPCk3.mjs} +6 -0
  108. package/dist/{chunks/messages-D-ZtY5v0.mjs → messages-Cs8zmZ3L.mjs} +6 -0
  109. package/dist/{chunks/messages-DprmQg6V.mjs → messages-CzK0LEhb.mjs} +6 -0
  110. package/dist/{messages-BSbjsyHY.mjs → messages-D00x4S8o.mjs} +6 -0
  111. package/dist/{messages-Xq8UmkVs.mjs → messages-D1mn7Zd5.mjs} +6 -0
  112. package/dist/{messages-BC86qLvI.mjs → messages-D2NOpHn9.mjs} +6 -0
  113. package/dist/{chunks/messages-kep5wtm4.mjs → messages-D4qqwVgQ.mjs} +6 -0
  114. package/dist/{messages-7W4d0DwD.mjs → messages-D5S1Dnpm.mjs} +6 -0
  115. package/dist/{chunks/messages-CY8_RyFE.mjs → messages-D7u2bmP2.mjs} +6 -0
  116. package/dist/{messages-BFG6Wlgy.mjs → messages-D85FqxgY.mjs} +6 -0
  117. package/dist/{chunks/messages-DLfR5bMd.mjs → messages-D9ndgBnU.mjs} +6 -0
  118. package/dist/{chunks/messages-CVw84KdI.mjs → messages-DDTQgImT.mjs} +6 -0
  119. package/dist/{chunks/messages-_ErNTNhk.mjs → messages-DH_jBeED.mjs} +6 -0
  120. package/dist/{messages-CMkNSDTo.mjs → messages-DRXWF0PV.mjs} +6 -0
  121. package/dist/{messages-BYyy6Wqf.mjs → messages-DVQvl8Qj.mjs} +6 -0
  122. package/dist/{messages-CznZadDf.mjs → messages-DXktiao_.mjs} +6 -0
  123. package/dist/{messages-DhLKYm2j.mjs → messages-DdK-nFGm.mjs} +6 -0
  124. package/dist/{messages-BMXCuEKO.mjs → messages-DlJbPF2T.mjs} +6 -0
  125. package/dist/{messages-CvGLfqmV.mjs → messages-DnVlmiNT.mjs} +6 -0
  126. package/dist/{chunks/messages-Z9nEU2xK.mjs → messages-DviiFSv2.mjs} +6 -0
  127. package/dist/{messages-BB5z9Uba.mjs → messages-DzqM3Fel.mjs} +6 -0
  128. package/dist/{chunks/messages-w7v1GNaE.mjs → messages-Dzzn6XoD.mjs} +6 -0
  129. package/dist/{chunks/messages-CqWJcCbY.mjs → messages-GSByFygY.mjs} +6 -0
  130. package/dist/{messages-_ncGrKHh.mjs → messages-L_kl2Qvh.mjs} +6 -0
  131. package/dist/{messages-BrPFGbM-.mjs → messages-Phkd7XmE.mjs} +6 -0
  132. package/dist/{chunks/messages-BU2nlrLK.mjs → messages-RonBBCnh.mjs} +6 -0
  133. package/dist/{chunks/messages-Bmu_S7GM.mjs → messages-VDriF5Qy.mjs} +6 -0
  134. package/dist/{chunks/messages-CLhcMlTc.mjs → messages-ZjUAIWb1.mjs} +6 -0
  135. package/dist/{chunks/messages-9SihnaXQ.mjs → messages-b1EdvUm0.mjs} +6 -0
  136. package/dist/{chunks/messages-DvFLX36Q.mjs → messages-begYOTgC.mjs} +6 -0
  137. package/dist/{chunks/messages-BMv4xwIr.mjs → messages-jrncnb-H.mjs} +6 -0
  138. package/dist/{chunks/messages-D5iv1Kox.mjs → messages-nefz1S71.mjs} +6 -0
  139. package/dist/{chunks/messages-CQwpzUFp.mjs → messages-ucTVgS5G.mjs} +6 -0
  140. package/dist/{messages-DBRw-7Zc.mjs → messages-v3GipbFl.mjs} +6 -0
  141. package/dist/{chunks/messages-C9eaarcK.mjs → messages-wmi-iFkH.mjs} +6 -0
  142. package/dist/{messages-O5tQus_0.mjs → messages-yHcs38yI.mjs} +6 -0
  143. package/dist/tools.mjs +3190 -1690
  144. package/dist/vendor.LICENSE.txt +109 -109
  145. package/package.json +43 -57
  146. package/src/blok.ts +12 -0
  147. package/src/components/__module.ts +21 -0
  148. package/src/components/block/api.ts +17 -0
  149. package/src/components/block/style-manager.ts +6 -2
  150. package/src/components/block/tool-renderer.ts +33 -30
  151. package/src/components/blocks.ts +132 -15
  152. package/src/components/i18n/locales/am/messages.json +6 -0
  153. package/src/components/i18n/locales/ar/messages.json +6 -0
  154. package/src/components/i18n/locales/az/messages.json +6 -0
  155. package/src/components/i18n/locales/bg/messages.json +6 -0
  156. package/src/components/i18n/locales/bn/messages.json +6 -0
  157. package/src/components/i18n/locales/bs/messages.json +6 -0
  158. package/src/components/i18n/locales/cs/messages.json +6 -0
  159. package/src/components/i18n/locales/da/messages.json +6 -0
  160. package/src/components/i18n/locales/de/messages.json +6 -0
  161. package/src/components/i18n/locales/dv/messages.json +6 -0
  162. package/src/components/i18n/locales/el/messages.json +6 -0
  163. package/src/components/i18n/locales/en/messages.json +6 -0
  164. package/src/components/i18n/locales/es/messages.json +6 -0
  165. package/src/components/i18n/locales/et/messages.json +6 -0
  166. package/src/components/i18n/locales/fa/messages.json +6 -0
  167. package/src/components/i18n/locales/fi/messages.json +6 -0
  168. package/src/components/i18n/locales/fil/messages.json +6 -0
  169. package/src/components/i18n/locales/fr/messages.json +6 -0
  170. package/src/components/i18n/locales/gu/messages.json +6 -0
  171. package/src/components/i18n/locales/he/messages.json +6 -0
  172. package/src/components/i18n/locales/hi/messages.json +6 -0
  173. package/src/components/i18n/locales/hr/messages.json +6 -0
  174. package/src/components/i18n/locales/hu/messages.json +6 -0
  175. package/src/components/i18n/locales/hy/messages.json +6 -0
  176. package/src/components/i18n/locales/id/messages.json +6 -0
  177. package/src/components/i18n/locales/it/messages.json +6 -0
  178. package/src/components/i18n/locales/ja/messages.json +6 -0
  179. package/src/components/i18n/locales/ka/messages.json +6 -0
  180. package/src/components/i18n/locales/km/messages.json +6 -0
  181. package/src/components/i18n/locales/kn/messages.json +6 -0
  182. package/src/components/i18n/locales/ko/messages.json +6 -0
  183. package/src/components/i18n/locales/ku/messages.json +6 -0
  184. package/src/components/i18n/locales/lo/messages.json +6 -0
  185. package/src/components/i18n/locales/lt/messages.json +6 -0
  186. package/src/components/i18n/locales/lv/messages.json +6 -0
  187. package/src/components/i18n/locales/mk/messages.json +6 -0
  188. package/src/components/i18n/locales/ml/messages.json +6 -0
  189. package/src/components/i18n/locales/mn/messages.json +6 -0
  190. package/src/components/i18n/locales/mr/messages.json +6 -0
  191. package/src/components/i18n/locales/ms/messages.json +6 -0
  192. package/src/components/i18n/locales/my/messages.json +6 -0
  193. package/src/components/i18n/locales/ne/messages.json +6 -0
  194. package/src/components/i18n/locales/nl/messages.json +6 -0
  195. package/src/components/i18n/locales/no/messages.json +6 -0
  196. package/src/components/i18n/locales/pa/messages.json +6 -0
  197. package/src/components/i18n/locales/pl/messages.json +6 -0
  198. package/src/components/i18n/locales/ps/messages.json +6 -0
  199. package/src/components/i18n/locales/pt/messages.json +6 -0
  200. package/src/components/i18n/locales/ro/messages.json +6 -0
  201. package/src/components/i18n/locales/ru/messages.json +6 -0
  202. package/src/components/i18n/locales/sd/messages.json +6 -0
  203. package/src/components/i18n/locales/si/messages.json +6 -0
  204. package/src/components/i18n/locales/sk/messages.json +6 -0
  205. package/src/components/i18n/locales/sl/messages.json +6 -0
  206. package/src/components/i18n/locales/sq/messages.json +6 -0
  207. package/src/components/i18n/locales/sr/messages.json +6 -0
  208. package/src/components/i18n/locales/sv/messages.json +6 -0
  209. package/src/components/i18n/locales/sw/messages.json +6 -0
  210. package/src/components/i18n/locales/ta/messages.json +6 -0
  211. package/src/components/i18n/locales/te/messages.json +6 -0
  212. package/src/components/i18n/locales/th/messages.json +6 -0
  213. package/src/components/i18n/locales/tr/messages.json +6 -0
  214. package/src/components/i18n/locales/ug/messages.json +6 -0
  215. package/src/components/i18n/locales/uk/messages.json +6 -0
  216. package/src/components/i18n/locales/ur/messages.json +6 -0
  217. package/src/components/i18n/locales/vi/messages.json +6 -0
  218. package/src/components/i18n/locales/yi/messages.json +6 -0
  219. package/src/components/i18n/locales/zh/messages.json +6 -0
  220. package/src/components/icons/index.ts +17 -0
  221. package/src/components/inline-tools/inline-tool-link.ts +1 -1
  222. package/src/components/inline-tools/inline-tool-marker.ts +737 -0
  223. package/src/components/inline-tools/utils/formatting-range-utils.ts +6 -3
  224. package/src/components/inline-tools/utils/marker-dom-utils.ts +17 -0
  225. package/src/components/modules/api/blocks.ts +34 -9
  226. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +75 -29
  227. package/src/components/modules/blockEvents/index.ts +13 -5
  228. package/src/components/modules/blockManager/blockManager.ts +81 -2
  229. package/src/components/modules/blockManager/hierarchy.ts +20 -2
  230. package/src/components/modules/blockManager/operations.ts +70 -35
  231. package/src/components/modules/blockManager/repository.ts +22 -0
  232. package/src/components/modules/blockManager/types.ts +3 -1
  233. package/src/components/modules/blockManager/yjs-sync.ts +173 -39
  234. package/src/components/modules/blockSelection.ts +3 -0
  235. package/src/components/modules/crossBlockSelection.ts +11 -3
  236. package/src/components/modules/drag/preview/DragPreview.ts +10 -2
  237. package/src/components/modules/drag/target/DropTargetDetector.ts +100 -11
  238. package/src/components/modules/drag/utils/drag.constants.ts +1 -1
  239. package/src/components/modules/normalizeInlineImages.ts +263 -0
  240. package/src/components/modules/paste/google-docs-preprocessor.ts +197 -0
  241. package/src/components/modules/paste/handlers/base.ts +43 -2
  242. package/src/components/modules/paste/handlers/html-handler.ts +1 -1
  243. package/src/components/modules/paste/handlers/index.ts +1 -0
  244. package/src/components/modules/paste/handlers/table-cells-handler.ts +104 -0
  245. package/src/components/modules/paste/index.ts +20 -3
  246. package/src/components/modules/readonly.ts +8 -2
  247. package/src/components/modules/rectangleSelection.ts +5 -2
  248. package/src/components/modules/renderer.ts +35 -0
  249. package/src/components/modules/saver.ts +52 -2
  250. package/src/components/modules/toolbar/blockSettings.ts +52 -44
  251. package/src/components/modules/toolbar/index.ts +124 -17
  252. package/src/components/modules/toolbar/inline/index.ts +4 -4
  253. package/src/components/modules/toolbar/plus-button.ts +3 -3
  254. package/src/components/modules/toolbar/settings-toggler.ts +3 -3
  255. package/src/components/modules/toolbar/styles.ts +7 -7
  256. package/src/components/modules/ui.ts +6 -6
  257. package/src/components/modules/uiControllers/controllers/blockHover.ts +16 -2
  258. package/src/components/modules/uiControllers/handlers/touch.ts +83 -10
  259. package/src/components/modules/yjs/block-observer.ts +9 -3
  260. package/src/components/modules/yjs/document-store.ts +10 -7
  261. package/src/components/modules/yjs/types.ts +8 -6
  262. package/src/components/modules/yjs/undo-history.ts +90 -11
  263. package/src/components/selection/fake-background/shadows.ts +1 -1
  264. package/src/components/shared/color-picker.ts +211 -0
  265. package/src/components/shared/color-presets.ts +25 -0
  266. package/src/components/ui/toolbox.ts +19 -11
  267. package/src/components/utils/color-mapping.ts +241 -0
  268. package/src/components/utils/notifier/draw.ts +9 -9
  269. package/src/components/utils/placeholder.ts +24 -8
  270. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -2
  271. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +14 -12
  272. package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
  273. package/src/components/utils/popover/popover-abstract.ts +27 -3
  274. package/src/components/utils/popover/popover-desktop.ts +26 -3
  275. package/src/components/utils/popover/popover-inline.ts +14 -1
  276. package/src/components/utils/popover/popover-mobile.ts +4 -4
  277. package/src/components/utils/popover/popover.const.ts +2 -2
  278. package/src/components/utils/sanitizer.ts +24 -3
  279. package/src/components/utils/tw.ts +17 -5
  280. package/src/stories/Header.stories.ts +106 -0
  281. package/src/stories/MarkerColors.stories.ts +730 -0
  282. package/src/stories/Popover.stories.ts +1 -3
  283. package/src/stories/Table.stories.ts +1662 -0
  284. package/src/styles/main.css +207 -37
  285. package/src/tools/header/index.ts +1 -1
  286. package/src/tools/index.ts +3 -1
  287. package/src/tools/list/caret-manager.ts +28 -10
  288. package/src/tools/list/constants.ts +2 -2
  289. package/src/tools/list/dom-builder.ts +3 -3
  290. package/src/tools/list/static-configs.ts +0 -1
  291. package/src/tools/paragraph/index.ts +9 -5
  292. package/src/tools/table/core/table-commands.ts +99 -0
  293. package/src/tools/table/core/table-controller.ts +231 -0
  294. package/src/tools/table/core/table-events.ts +102 -0
  295. package/src/tools/table/index.ts +1070 -174
  296. package/src/tools/table/ownership/table-event-broker.ts +74 -0
  297. package/src/tools/table/ownership/table-ownership-registry.ts +126 -0
  298. package/src/tools/table/table-add-controls.ts +85 -15
  299. package/src/tools/table/table-cell-blocks.ts +336 -38
  300. package/src/tools/table/table-cell-clipboard.ts +415 -0
  301. package/src/tools/table/table-cell-color-picker.ts +34 -0
  302. package/src/tools/table/table-cell-selection.ts +264 -15
  303. package/src/tools/table/table-core.ts +3 -42
  304. package/src/tools/table/table-heading-toggle.ts +2 -2
  305. package/src/tools/table/table-model.ts +623 -0
  306. package/src/tools/table/table-operations.ts +59 -78
  307. package/src/tools/table/table-resize.ts +15 -11
  308. package/src/tools/table/table-restrictions.ts +69 -3
  309. package/src/tools/table/table-row-col-action-handler.ts +22 -7
  310. package/src/tools/table/table-row-col-controls.ts +129 -12
  311. package/src/tools/table/table-row-col-drag.ts +14 -0
  312. package/src/tools/table/table-scroll-haze.ts +152 -0
  313. package/src/tools/table/types.ts +22 -1
  314. package/src/tools/table/view/table-cell-blocks-adapter.ts +47 -0
  315. package/src/variants/blok-minimum.ts +13 -0
  316. package/types/api/block.d.ts +13 -0
  317. package/types/api/blocks.d.ts +16 -0
  318. package/types/tools/table.d.ts +2 -0
  319. package/dist/chunks/i18next-CugVlwWp.mjs +0 -1292
  320. package/src/tools/table/data-normalizer.ts +0 -32
@@ -1,61 +1,223 @@
1
1
  /* Tailwind CSS - must be first */
2
- @import 'tailwindcss/base';
3
- @import 'tailwindcss/components';
4
- @import 'tailwindcss/utilities';
2
+ @import 'tailwindcss';
5
3
 
6
- /**
7
- * Component classes for the Styles API.
8
- * These single-class names can be safely used with classList.add() by external plugins.
9
- * Each class bundles multiple Tailwind utilities using @apply.
10
- */
11
- @layer components {
12
- /* Base Blok styles - applied to block tool wrappers */
13
- .blok-block {
14
- @apply py-[3px] px-[2px] [&::-webkit-input-placeholder]:!leading-normal;
4
+ /*
5
+ Exclude non-source directories from Tailwind's automatic content detection.
6
+ Without this, Tailwind v4 scans all non-gitignored files (including docs/,
7
+ test/, .claude/) and picks up false class candidates from code examples,
8
+ test fixtures, and markdown — generating dead CSS in the production bundle.
9
+ */
10
+ @source not "../../docs";
11
+ @source not "../../test";
12
+ @source not "../../.claude";
13
+ @source not "../../scripts";
14
+ @source not "../../.storybook";
15
+
16
+ @custom-variant mobile (@media (max-width: 650px));
17
+ @custom-variant not-mobile (@media (min-width: 651px));
18
+ @custom-variant can-hover (@media (hover: hover));
19
+
20
+ @custom-variant dark (&:where(.dark-mode, .dark-mode *));
21
+
22
+ @theme {
23
+ /* Z-index */
24
+ --z-index-overlay: 999;
25
+
26
+ /* Colors */
27
+ --color-selection: #e1f2ff;
28
+ --color-selection-inline: #d4ecff;
29
+ --color-selection-highlight: rgba(46, 170, 220, 0.2);
30
+ --color-bg-light: #eff2f5;
31
+ --color-gray-text: #707684;
32
+ --color-dark: #1d202b;
33
+ --color-active-icon: #388ae5;
34
+ --color-link: #388ae5;
35
+ --color-line-gray: #eff0f1;
36
+ --color-tooltip-bg: #1d202b;
37
+ --color-tooltip-font: #cdd1e0;
38
+ --color-icon-active-bg: rgba(56, 138, 229, 0.1);
39
+ --color-icon-active-text: #388ae5;
40
+ --color-text-primary: black;
41
+ --color-text-secondary: #707684;
42
+ --color-popover-border: #eff0f1;
43
+ --color-popover-shadow: rgba(13, 20, 33, 0.1);
44
+ --color-popover-bg: #ffffff;
45
+ --color-popover-border-icon: rgb(201 201 204 / 48%);
46
+ --color-popover-border-icon-disabled: #eff0f1;
47
+ --color-item-focus-bg: rgba(34, 186, 255, 0.08);
48
+ --color-item-focus-shadow: rgba(7, 161, 227, 0.08);
49
+ --color-item-hover-bg: #f8f8f8;
50
+ --color-item-confirm-bg: #e24a4a;
51
+ --color-item-confirm-hover-bg: #ce4343;
52
+ --color-item-destructive-text: #e24a4a;
53
+ --color-item-destructive-hover-bg: rgba(226, 74, 74, 0.08);
54
+ --color-notify-success-bg: #fafffe;
55
+ --color-notify-success-bar: #41ffb1;
56
+ --color-notify-error-bg: #fffbfb;
57
+ --color-notify-error-bar: #fb5d5d;
58
+ --color-notify-btn-cancel-bg: #f2f5f7;
59
+ --color-notify-btn-cancel-text: #656b7c;
60
+ --color-notify-btn-confirm-bg: #34c992;
61
+
62
+ /* Spacing (also powers w-*, h-*, min-w-*, min-h-*, size-*) */
63
+ --spacing-content-width: 650px;
64
+ --spacing-narrow-mode-right-padding: 50px;
65
+ --spacing-toolbox-btn: 26px;
66
+ --spacing-toolbox-btn-mobile: 36px;
67
+ --spacing-icon: 20px;
68
+ --spacing-icon-mobile: 28px;
69
+ --spacing-block-padding-vertical: 0.4em;
70
+
71
+ /* Max-width */
72
+ --max-width-content: 650px;
73
+
74
+ /* Font family */
75
+ --font-mono: 'PT Mono', 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
76
+
77
+ /* Box shadows */
78
+ --shadow-overlay-pane: 0 3px 15px -3px rgba(13, 20, 33, 0.13);
79
+ --shadow-tool-icon: 0 0 0 1px #eff0f1;
80
+ --shadow-tooltip: 0 8px 12px 0 rgba(29, 32, 43, 0.17), 0 4px 5px -3px rgba(5, 6, 12, 0.49);
81
+ --shadow-notify: 0 11px 17px 0 rgba(23, 32, 61, 0.13);
82
+ --shadow-button-focused: inset 0 0 0 1px rgba(7, 161, 227, 0.08);
83
+ --shadow-input: inset 0 1px 2px 0 rgba(35, 44, 72, 0.06);
84
+ --shadow-button-base: 0 2px 2px 0 rgba(18, 30, 57, 0.04);
85
+ --shadow-button-base-hover: 0 1px 3px 0 rgba(18, 30, 57, 0.08);
86
+ --shadow-demo-btn: 0 22px 18px -4px rgba(137, 207, 255, 0.77);
87
+ --shadow-demo-btn-hover: 0 20px 15px -4px rgba(137, 207, 255, 0.77);
88
+ --shadow-demo-btn-primary: 0 7px 8px -4px rgba(137, 207, 255, 0.77);
89
+ --shadow-demo-dark-btn: 0 24px 18px -14px rgba(4, 154, 255, 0.24);
90
+
91
+ /* Animations */
92
+ --animate-fade-in: fade-in 300ms ease forwards;
93
+ --animate-bounce-in: bounceIn 0.75s cubic-bezier(0.215, 0.61, 0.355, 1) forwards;
94
+ --animate-selection-bounce: selectionBounce 0.75s cubic-bezier(0.215, 0.61, 0.355, 1) forwards;
95
+ --animate-button-clicked: buttonClicked 0.75s cubic-bezier(0.215, 0.61, 0.355, 1) forwards;
96
+ --animate-panel-showing: panelShowing 100ms ease;
97
+ --animate-panel-showing-mobile: panelShowingMobile 250ms ease;
98
+ --animate-wobble: wobble 400ms;
99
+ --animate-rotation: rotation 1.2s infinite linear;
100
+ --animate-notify-bounce-in: notifyBounceIn 600ms 1;
101
+
102
+ /* Keyframes */
103
+ @keyframes fade-in {
104
+ from { opacity: 0; }
105
+ to { opacity: 1; }
15
106
  }
16
107
 
17
- /* Inline Tools styles */
18
- .blok-inline-tool-button {
19
- @apply flex justify-center items-center border-0 rounded h-full p-0 w-7 bg-transparent cursor-pointer leading-normal text-black;
108
+ @keyframes bounceIn {
109
+ 0% { transform: scale3d(0.9, 0.9, 0.9); }
110
+ 20% { transform: scale3d(1.03, 1.03, 1.03); }
111
+ 60%, 100% { transform: scale3d(1, 1, 1); }
20
112
  }
21
113
 
22
- .blok-inline-tool-button--active {
23
- @apply bg-icon-active-bg text-icon-active-text;
114
+ @keyframes selectionBounce {
115
+ 0%, 100% { transform: scale3d(1, 1, 1); }
116
+ 50% { transform: scale3d(1.01, 1.01, 1.01); }
117
+ 70% { transform: scale3d(1, 1, 1); }
24
118
  }
25
119
 
26
- /* Input element styles */
27
- .blok-input {
28
- @apply w-full rounded-[3px] border border-line-gray px-3 py-2.5 outline-none shadow-input [&[data-blok-placeholder]]:before:!static [&[data-blok-placeholder]]:before:inline-block [&[data-blok-placeholder]]:before:w-0 [&[data-blok-placeholder]]:before:whitespace-nowrap [&[data-blok-placeholder]]:before:pointer-events-none;
120
+ @keyframes buttonClicked {
121
+ 0% { transform: scale3d(0.95, 0.95, 0.95); }
122
+ 60% { transform: scale3d(1.02, 1.02, 1.02); }
123
+ 80%, 100% { transform: scale3d(1, 1, 1); }
29
124
  }
30
125
 
31
- /* Loader styles with spinning animation */
32
- .blok-loader {
33
- @apply relative border border-line-gray before:absolute before:left-1/2 before:top-1/2 before:w-[18px] before:h-[18px] before:rounded-full before:content-[''] before:-ml-[11px] before:-mt-[11px] before:border-2 before:border-line-gray before:border-l-active-icon before:animate-rotation;
126
+ @keyframes panelShowing {
127
+ from { opacity: 0; transform: translateY(-8px) scale(0.9); }
128
+ 70% { opacity: 1; transform: translateY(2px); }
129
+ to { transform: translateY(0); }
34
130
  }
35
131
 
36
- /* Button styles */
37
- .blok-button {
38
- @apply p-[13px] rounded-[3px] border border-line-gray text-[14.9px] bg-white text-center cursor-pointer text-gray-text shadow-button-base hover:bg-[#fbfcfe] hover:shadow-button-base-hover [&_svg]:h-5 [&_svg]:mr-[0.2em] [&_svg]:-mt-0.5;
132
+ @keyframes panelShowingMobile {
133
+ from { opacity: 0; transform: translateY(14px) scale(0.98); }
134
+ 70% { opacity: 1; transform: translateY(-4px); }
135
+ to { transform: translateY(0); }
39
136
  }
40
137
 
41
- /* Settings button styles */
42
- .blok-settings-button {
43
- @apply inline-flex items-center justify-center rounded-[3px] cursor-pointer border-0 outline-none bg-transparent align-bottom text-inherit m-0 min-w-toolbox-btn min-h-toolbox-btn [&_svg]:w-auto [&_svg]:h-auto mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile mobile:rounded-lg mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile can-hover:hover:bg-bg-light;
138
+ @keyframes wobble {
139
+ from { transform: translate3d(0, 0, 0); }
140
+ 15% { transform: translate3d(-9%, 0, 0); }
141
+ 30% { transform: translate3d(9%, 0, 0); }
142
+ 45% { transform: translate3d(-4%, 0, 0); }
143
+ 60% { transform: translate3d(4%, 0, 0); }
144
+ 75% { transform: translate3d(-1%, 0, 0); }
145
+ to { transform: translate3d(0, 0, 0); }
44
146
  }
45
147
 
46
- .blok-settings-button--active {
47
- @apply text-active-icon;
148
+ @keyframes rotation {
149
+ 0% { transform: rotate(0deg); }
150
+ 100% { transform: rotate(360deg); }
48
151
  }
49
152
 
50
- .blok-settings-button--focused {
51
- @apply shadow-button-focused bg-item-focus-bg;
153
+ @keyframes notifyBounceIn {
154
+ 0% { opacity: 0; transform: scale(0.3); }
155
+ 50% { opacity: 1; transform: scale(1.05); }
156
+ 70% { transform: scale(0.9); }
157
+ 100% { transform: scale(1); }
52
158
  }
159
+ }
53
160
 
54
- .blok-settings-button--focused-animated {
55
- @apply animate-button-clicked;
161
+ /*
162
+ The default border color has changed to `currentcolor` in Tailwind CSS v4,
163
+ so we've added these compatibility styles to make sure everything still
164
+ looks the same as it did with Tailwind CSS v3.
165
+
166
+ If we ever want to remove these styles, we need to add an explicit border
167
+ color utility to any element that depends on these defaults.
168
+ */
169
+ @layer base {
170
+ *,
171
+ ::after,
172
+ ::before,
173
+ ::backdrop,
174
+ ::file-selector-button {
175
+ border-color: var(--color-gray-200, currentcolor);
56
176
  }
57
177
  }
58
178
 
179
+ /**
180
+ * Component classes for the Styles API.
181
+ * These single-class names can be safely used with classList.add() by external plugins.
182
+ * Each class bundles multiple Tailwind utilities using @apply.
183
+ */
184
+ @utility blok-block {
185
+ /* Base Blok styles - applied to block tool wrappers */
186
+ @apply py-[3px] px-[2px] [&::-webkit-input-placeholder]:leading-normal!;
187
+ }
188
+ @utility blok-inline-tool-button {
189
+ /* Inline Tools styles */
190
+ @apply flex justify-center items-center border-0 rounded-sm h-full p-0 w-7 bg-transparent cursor-pointer leading-normal text-black;
191
+ }
192
+ @utility blok-inline-tool-button--active {
193
+ @apply bg-icon-active-bg text-icon-active-text;
194
+ }
195
+ @utility blok-input {
196
+ /* Input element styles */
197
+ @apply w-full rounded-[3px] border border-line-gray px-3 py-2.5 outline-hidden shadow-input data-blok-placeholder:before:static! data-blok-placeholder:before:inline-block data-blok-placeholder:before:w-0 data-blok-placeholder:before:whitespace-nowrap data-blok-placeholder:before:pointer-events-none;
198
+ }
199
+ @utility blok-loader {
200
+ /* Loader styles with spinning animation */
201
+ @apply relative border border-line-gray before:absolute before:left-1/2 before:top-1/2 before:w-[18px] before:h-[18px] before:rounded-full before:content-[''] before:-ml-[11px] before:-mt-[11px] before:border-2 before:border-line-gray before:border-l-active-icon before:animate-rotation;
202
+ }
203
+ @utility blok-button {
204
+ /* Button styles */
205
+ @apply p-[13px] rounded-[3px] border border-line-gray text-[14.9px] bg-white text-center cursor-pointer text-gray-text shadow-button-base hover:bg-[#fbfcfe] hover:shadow-button-base-hover [&_svg]:h-5 [&_svg]:mr-[0.2em] [&_svg]:-mt-0.5;
206
+ }
207
+ @utility blok-settings-button {
208
+ /* Settings button styles */
209
+ @apply inline-flex items-center justify-center rounded-[3px] cursor-pointer border-0 outline-hidden bg-transparent align-bottom text-inherit m-0 min-w-toolbox-btn min-h-toolbox-btn [&_svg]:w-auto [&_svg]:h-auto mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile mobile:rounded-lg mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile can-hover:hover:bg-bg-light;
210
+ }
211
+ @utility blok-settings-button--active {
212
+ @apply text-active-icon;
213
+ }
214
+ @utility blok-settings-button--focused {
215
+ @apply shadow-button-focused bg-item-focus-bg;
216
+ }
217
+ @utility blok-settings-button--focused-animated {
218
+ @apply animate-button-clicked;
219
+ }
220
+
59
221
  /**
60
222
  * Navigation mode styles
61
223
  * Applied when user enters block navigation mode via Escape key
@@ -84,7 +246,7 @@
84
246
  }
85
247
 
86
248
  [data-drop-indicator]::before {
87
- @apply content-[''] absolute w-full max-w-content h-1.5 rounded-sm bg-[#d4e3fc] pointer-events-none z-10;
249
+ @apply content-[''] absolute w-full max-w-content h-1.5 rounded-xs bg-[#d4e3fc] pointer-events-none z-10;
88
250
  left: 50%;
89
251
  margin-left: calc(var(--drop-indicator-depth, 0) * 12px);
90
252
  max-width: calc(650px - var(--drop-indicator-depth, 0) * 24px);
@@ -135,7 +297,7 @@
135
297
  }
136
298
 
137
299
  [data-blok-table-cell-blocks] .blok-block {
138
- @apply p-0 m-0;
300
+ @apply p-0 m-0 min-h-[1.6em];
139
301
  }
140
302
 
141
303
  /**
@@ -146,3 +308,11 @@
146
308
  [data-blok-table-heading-col] {
147
309
  @apply font-semibold bg-gray-50;
148
310
  }
311
+
312
+ /**
313
+ * Table scroll haze overlays
314
+ * Gradient indicators that show horizontal scroll availability
315
+ */
316
+ [data-blok-table-haze][data-blok-table-haze-visible] {
317
+ @apply opacity-100;
318
+ }
@@ -146,7 +146,7 @@ export class Header implements BlockTool {
146
146
  /**
147
147
  * Base styles for all header levels
148
148
  */
149
- private static readonly BASE_STYLES = 'py-[3px] px-[2px] m-0 !leading-[1.3] outline-none [&_p]:!p-0 [&_p]:!m-0 [&_div]:!p-0 [&_div]:!m-0';
149
+ private static readonly BASE_STYLES = 'py-[3px] px-[2px] m-0 leading-[1.3]! outline-hidden [&_p]:p-0! [&_p]:m-0! [&_div]:p-0! [&_div]:m-0!';
150
150
 
151
151
  /**
152
152
  * Styles
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * @example
6
6
  * // Import specific tools
7
- * import { Paragraph, Header, List, Bold, Italic, Link } from '@jackuait/blok/tools';
7
+ * import { Paragraph, Header, List, Bold, Italic, Link, Marker } from '@jackuait/blok/tools';
8
8
  *
9
9
  * // Use in Blok configuration (flat config style)
10
10
  * new Blok({
@@ -30,6 +30,7 @@ export { BoldInlineTool as Bold } from '../components/inline-tools/inline-tool-b
30
30
  export { ItalicInlineTool as Italic } from '../components/inline-tools/inline-tool-italic';
31
31
  export { LinkInlineTool as Link } from '../components/inline-tools/inline-tool-link';
32
32
  export { ConvertInlineTool as Convert } from '../components/inline-tools/inline-tool-convert';
33
+ export { MarkerInlineTool as Marker } from '../components/inline-tools/inline-tool-marker';
33
34
 
34
35
  // Default tools configuration for convenience
35
36
  // Note: inlineToolbar defaults to true, so it doesn't need to be specified
@@ -44,4 +45,5 @@ export const defaultInlineTools = {
44
45
  bold: {},
45
46
  italic: {},
46
47
  link: {},
48
+ marker: {},
47
49
  } as const;
@@ -7,8 +7,12 @@
7
7
  import type { API } from '../../../types';
8
8
 
9
9
  /**
10
- * Sets caret to the content element of a block after ensuring DOM is ready.
11
- * Uses requestAnimationFrame to wait for the browser to process DOM updates.
10
+ * Sets caret to the content element of a block.
11
+ * Operates synchronously so subsequent keystrokes land in the correct block
12
+ * (deferring via requestAnimationFrame causes a race where characters typed
13
+ * between the block split and the next animation frame go to the wrong element).
14
+ * Falls back to requestAnimationFrame only when the content element is not yet
15
+ * available (e.g. async rendering).
12
16
  *
13
17
  * @param api - The API instance
14
18
  * @param block - BlockAPI to set caret to
@@ -19,8 +23,7 @@ export const setCaretToBlockContent = (
19
23
  block: ReturnType<API['blocks']['insert']>,
20
24
  position: 'start' | 'end' = 'end'
21
25
  ): void => {
22
- // Use requestAnimationFrame to ensure DOM has been updated
23
- requestAnimationFrame(() => {
26
+ const applyFocus = (deferred: boolean): void => {
24
27
  const holder = block.holder;
25
28
  if (!holder) return;
26
29
 
@@ -29,8 +32,10 @@ export const setCaretToBlockContent = (
29
32
  if (!(contentEl instanceof HTMLElement)) {
30
33
  // Fallback to setToBlock if no content element found
31
34
  api.caret.setToBlock(block, position);
32
- // Update the caret "after" position for undo/redo since we're in requestAnimationFrame
33
- api.caret.updateLastCaretAfterPosition();
35
+
36
+ if (deferred) {
37
+ api.caret.updateLastCaretAfterPosition();
38
+ }
34
39
 
35
40
  return;
36
41
  }
@@ -55,8 +60,21 @@ export const setCaretToBlockContent = (
55
60
  selection.removeAllRanges();
56
61
  selection.addRange(range);
57
62
 
58
- // Update the caret "after" position for undo/redo since we moved the caret
59
- // asynchronously via requestAnimationFrame after the Yjs transaction committed
60
- api.caret.updateLastCaretAfterPosition();
61
- });
63
+ if (deferred) {
64
+ // Update the caret "after" position for undo/redo since we moved the caret
65
+ // asynchronously via requestAnimationFrame after the Yjs transaction committed
66
+ api.caret.updateLastCaretAfterPosition();
67
+ }
68
+ };
69
+
70
+ // Try synchronous focus first — the block is already in the DOM after insert()
71
+ const holder = block.holder;
72
+ const contentEl = holder?.querySelector('[contenteditable="true"]');
73
+
74
+ if (contentEl instanceof HTMLElement) {
75
+ applyFocus(false);
76
+ } else {
77
+ // Content element not available yet — fall back to next frame
78
+ requestAnimationFrame(() => applyFocus(true));
79
+ }
62
80
  }
@@ -12,12 +12,12 @@ export const INDENT_PER_LEVEL = 24;
12
12
  *
13
13
  * Matches paragraph spacing: py-[3px] from blok-block + mt-[2px] mb-px
14
14
  */
15
- export const BASE_STYLES = 'outline-none py-[3px] mt-[2px] mb-px';
15
+ export const BASE_STYLES = 'outline-hidden py-[3px] mt-[2px] mb-px';
16
16
 
17
17
  /**
18
18
  * Styles for standard list items (unordered, ordered)
19
19
  */
20
- export const ITEM_STYLES = 'outline-none pl-0.5 leading-[1.6em]';
20
+ export const ITEM_STYLES = 'outline-hidden pl-0.5 leading-[1.6em]';
21
21
 
22
22
  /**
23
23
  * Styles for checklist items
@@ -176,7 +176,7 @@ export const buildStandardContent = (context: DOMBuilderContext): HTMLElement =>
176
176
 
177
177
  // Create content container
178
178
  const contentContainer = document.createElement('div');
179
- contentContainer.className = twMerge('flex-1 min-w-0 outline-none', ...PLACEHOLDER_CLASSES);
179
+ contentContainer.className = twMerge('flex-1 min-w-0 outline-hidden', ...PLACEHOLDER_CLASSES);
180
180
  contentContainer.setAttribute('data-blok-testid', LIST_TEST_IDS.contentContainer);
181
181
  contentContainer.contentEditable = context.readOnly ? 'false' : 'true';
182
182
  contentContainer.innerHTML = data.text;
@@ -224,7 +224,7 @@ export const buildChecklistContent = (context: DOMBuilderContext): HTMLElement =
224
224
 
225
225
  const content = document.createElement('div');
226
226
  content.className = twMerge(
227
- 'flex-1 outline-none leading-[1.6em]',
227
+ 'flex-1 outline-hidden leading-[1.6em]',
228
228
  data.checked ? 'line-through opacity-60' : '',
229
229
  ...PLACEHOLDER_CLASSES
230
230
  );
@@ -251,7 +251,7 @@ export const buildChecklistContent = (context: DOMBuilderContext): HTMLElement =
251
251
  */
252
252
  export const createMarker = (style: ListItemStyle, depth: number): HTMLElement => {
253
253
  const marker = document.createElement('span');
254
- marker.className = 'flex-shrink-0 select-none';
254
+ marker.className = 'shrink-0 select-none';
255
255
  marker.setAttribute('aria-hidden', 'true');
256
256
  marker.contentEditable = 'false';
257
257
 
@@ -21,7 +21,6 @@ export const getListSanitizeConfig = (): ToolSanitizerConfig => ({
21
21
  },
22
22
  b: true,
23
23
  i: true,
24
- mark: true,
25
24
  },
26
25
  });
27
26
 
@@ -19,7 +19,7 @@ import type {
19
19
  import { DATA_ATTR } from '../../components/constants';
20
20
  import { IconText } from '../../components/icons';
21
21
  import { stripFakeBackgroundElements } from '../../components/utils';
22
- import { PLACEHOLDER_FOCUS_ONLY_CLASSES, setupPlaceholder } from '../../components/utils/placeholder';
22
+ import { PLACEHOLDER_EMPTY_EDITOR_CLASSES, PLACEHOLDER_FOCUS_ONLY_CLASSES, setupPlaceholder } from '../../components/utils/placeholder';
23
23
  import { twMerge } from '../../components/utils/tw';
24
24
 
25
25
  /**
@@ -200,7 +200,7 @@ export class Paragraph implements BlockTool {
200
200
  */
201
201
  private static readonly WRAPPER_CLASSES = [
202
202
  'leading-[1.6em]',
203
- 'outline-none',
203
+ 'outline-hidden',
204
204
  'mt-[2px]',
205
205
  'mb-px',
206
206
  '[&>p:first-of-type]:mt-0',
@@ -239,7 +239,8 @@ export class Paragraph implements BlockTool {
239
239
  div.className = twMerge(
240
240
  this.api.styles.block,
241
241
  Paragraph.WRAPPER_CLASSES,
242
- PLACEHOLDER_FOCUS_ONLY_CLASSES
242
+ PLACEHOLDER_FOCUS_ONLY_CLASSES,
243
+ PLACEHOLDER_EMPTY_EDITOR_CLASSES
243
244
  );
244
245
  div.setAttribute(DATA_ATTR.tool, 'paragraph');
245
246
  div.contentEditable = 'false';
@@ -255,14 +256,14 @@ export class Paragraph implements BlockTool {
255
256
 
256
257
  if (this._data.text) {
257
258
  div.innerHTML = this._data.text;
259
+ } else if (this.readOnly) {
260
+ div.innerHTML = '<br>';
258
261
  }
259
262
 
260
263
  if (!this.readOnly) {
261
264
  div.contentEditable = 'true';
262
265
  div.addEventListener('keyup', this.onKeyUp);
263
266
  setupPlaceholder(div, this.api.i18n.t(this._placeholder), 'data-blok-placeholder-active');
264
- } else {
265
- div.setAttribute('data-blok-placeholder-active', this.api.i18n.t(this._placeholder));
266
267
  }
267
268
 
268
269
  return div;
@@ -377,6 +378,9 @@ export class Paragraph implements BlockTool {
377
378
  src: true,
378
379
  style: true,
379
380
  },
381
+ p: true,
382
+ ul: true,
383
+ li: true,
380
384
  },
381
385
  };
382
386
  }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Typed table commands — the sole input vocabulary for table mutations.
3
+ * Every mutation must be expressible as one of these commands.
4
+ */
5
+ import type { TableData } from '../types';
6
+
7
+ export interface InsertRowCommand {
8
+ readonly type: 'insert-row';
9
+ /** Row index to insert at */
10
+ readonly index: number;
11
+ }
12
+
13
+ export interface DeleteRowCommand {
14
+ readonly type: 'delete-row';
15
+ readonly index: number;
16
+ }
17
+
18
+ export interface MoveRowCommand {
19
+ readonly type: 'move-row';
20
+ readonly fromIndex: number;
21
+ readonly toIndex: number;
22
+ }
23
+
24
+ export interface InsertColumnCommand {
25
+ readonly type: 'insert-column';
26
+ readonly index: number;
27
+ readonly width?: number;
28
+ }
29
+
30
+ export interface DeleteColumnCommand {
31
+ readonly type: 'delete-column';
32
+ readonly index: number;
33
+ }
34
+
35
+ export interface MoveColumnCommand {
36
+ readonly type: 'move-column';
37
+ readonly fromIndex: number;
38
+ readonly toIndex: number;
39
+ }
40
+
41
+ export interface ToggleHeadingCommand {
42
+ readonly type: 'toggle-heading';
43
+ }
44
+
45
+ export interface ToggleHeadingColumnCommand {
46
+ readonly type: 'toggle-heading-column';
47
+ }
48
+
49
+ export interface SetStretchedCommand {
50
+ readonly type: 'set-stretched';
51
+ readonly value: boolean;
52
+ }
53
+
54
+ export interface AddBlockToCellCommand {
55
+ readonly type: 'add-block-to-cell';
56
+ readonly row: number;
57
+ readonly col: number;
58
+ readonly blockId: string;
59
+ }
60
+
61
+ export interface RemoveBlockFromCellCommand {
62
+ readonly type: 'remove-block-from-cell';
63
+ readonly row: number;
64
+ readonly col: number;
65
+ readonly blockId: string;
66
+ }
67
+
68
+ export interface SetCellBlocksCommand {
69
+ readonly type: 'set-cell-blocks';
70
+ readonly row: number;
71
+ readonly col: number;
72
+ readonly blockIds: readonly string[];
73
+ }
74
+
75
+ export interface SetColWidthsCommand {
76
+ readonly type: 'set-col-widths';
77
+ readonly widths: readonly number[] | undefined;
78
+ }
79
+
80
+ export interface ReplaceAllCommand {
81
+ readonly type: 'replace-all';
82
+ readonly data: TableData;
83
+ }
84
+
85
+ export type TableCommand =
86
+ | InsertRowCommand
87
+ | DeleteRowCommand
88
+ | MoveRowCommand
89
+ | InsertColumnCommand
90
+ | DeleteColumnCommand
91
+ | MoveColumnCommand
92
+ | ToggleHeadingCommand
93
+ | ToggleHeadingColumnCommand
94
+ | SetStretchedCommand
95
+ | AddBlockToCellCommand
96
+ | RemoveBlockFromCellCommand
97
+ | SetCellBlocksCommand
98
+ | SetColWidthsCommand
99
+ | ReplaceAllCommand;