@jackuait/blok 0.10.0 → 0.10.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 (225) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-BfcBwAfE.mjs → blok-D-T1XZ92.mjs} +1494 -1491
  3. package/dist/chunks/{constants-QNVyXALL.mjs → constants-CaB-mlB5.mjs} +55 -48
  4. package/dist/chunks/{i18next-loader-CwsYu0n6.mjs → i18next-loader-CDnSPae_.mjs} +1 -1
  5. package/dist/chunks/{lightweight-i18n-Cvv8CWh4.mjs → lightweight-i18n-DZmo8dAI.mjs} +1 -0
  6. package/dist/chunks/{messages-DG-4DPmP.mjs → messages-1_6UkKLS.mjs} +1 -0
  7. package/dist/{messages-CqXtJTpU.mjs → chunks/messages-4Ck88DYZ2.mjs} +1 -0
  8. package/dist/{messages-96iaAUds2.mjs → chunks/messages-8Ld7P_9j2.mjs} +1 -0
  9. package/dist/{messages-DLX_iBDJ.mjs → chunks/messages-BAlZjPcl.mjs} +1 -0
  10. package/dist/chunks/{messages-p1mbe__S.mjs → messages-BHMiK51R.mjs} +1 -0
  11. package/dist/chunks/{messages-Cdf0W9H02.mjs → messages-BJ-vT1SU2.mjs} +1 -0
  12. package/dist/{messages-Smt4GBbj.mjs → chunks/messages-BK8Cp2d0.mjs} +1 -0
  13. package/dist/chunks/{messages-Bphq_Bt3.mjs → messages-BKN3YVIj.mjs} +1 -0
  14. package/dist/{messages-DTh9a8mR.mjs → chunks/messages-BMD37y3q2.mjs} +1 -0
  15. package/dist/chunks/{messages-DlonA3wa.mjs → messages-BONyZroH.mjs} +1 -0
  16. package/dist/chunks/{messages-DMVXnAYj.mjs → messages-BRAoJpOu.mjs} +1 -0
  17. package/dist/chunks/{messages-C6Mpiacw.mjs → messages-BRoa9tGl.mjs} +1 -0
  18. package/dist/{messages-aWZH50vu2.mjs → chunks/messages-BbEW9bQz.mjs} +1 -0
  19. package/dist/{messages-BIHc0KHY.mjs → chunks/messages-BeGZqQwz.mjs} +1 -0
  20. package/dist/chunks/{messages-C7VGpihw.mjs → messages-BfAcUavP.mjs} +1 -0
  21. package/dist/chunks/{messages-Cu-Wevxs2.mjs → messages-BgM91Lxm2.mjs} +1 -0
  22. package/dist/{messages-BYNcD6uR.mjs → chunks/messages-BlxwW7M6.mjs} +1 -0
  23. package/dist/chunks/{messages-rCd0Rrw6.mjs → messages-Bz0-KNEB.mjs} +1 -0
  24. package/dist/{messages-7QD-X6XT2.mjs → chunks/messages-C0IFfhnp.mjs} +1 -0
  25. package/dist/chunks/{messages-Dr0Ekmbz.mjs → messages-C15z2r5U.mjs} +1 -0
  26. package/dist/chunks/{messages-MxpWO1db.mjs → messages-C1S9ztpF.mjs} +1 -0
  27. package/dist/chunks/{messages-8IHf7ZP3.mjs → messages-CC_noR8y.mjs} +1 -0
  28. package/dist/chunks/{messages-COO5xmcA.mjs → messages-CD_MnBln.mjs} +1 -0
  29. package/dist/{messages-BiiongNz2.mjs → chunks/messages-CIfUm1Oa.mjs} +1 -0
  30. package/dist/chunks/{messages-B9kmbUWV.mjs → messages-CPBN4zWc.mjs} +1 -0
  31. package/dist/chunks/{messages-DlLXpgWM2.mjs → messages-CQBo3lmL2.mjs} +1 -0
  32. package/dist/{messages-DnGJD4TL.mjs → chunks/messages-CRF7nNrO.mjs} +1 -0
  33. package/dist/{messages-D8FQWulF2.mjs → chunks/messages-CTCe595D2.mjs} +1 -0
  34. package/dist/{messages-BRZX964b2.mjs → chunks/messages-CW35K1pq.mjs} +1 -0
  35. package/dist/chunks/{messages-CVdpweyf2.mjs → messages-CZSlfnkO2.mjs} +1 -0
  36. package/dist/chunks/{messages-iS34FHFB.mjs → messages-ChK7v1PV.mjs} +1 -0
  37. package/dist/chunks/{messages-BjadX8jR2.mjs → messages-Clku7Cf-2.mjs} +1 -0
  38. package/dist/{messages-DIJlIqlQ2.mjs → chunks/messages-CszmHAvQ.mjs} +1 -0
  39. package/dist/{messages-D0aw5_0k2.mjs → chunks/messages-CvANwuht2.mjs} +1 -0
  40. package/dist/chunks/{messages-BQYvBqm2.mjs → messages-CxiURE2X.mjs} +1 -0
  41. package/dist/chunks/{messages-A_MkXDlG.mjs → messages-CxxyR4vY.mjs} +1 -0
  42. package/dist/chunks/{messages-BUVhHx0q2.mjs → messages-D22e9h7V2.mjs} +1 -0
  43. package/dist/{messages-DYTTu0O12.mjs → chunks/messages-D7dx_6k8.mjs} +1 -0
  44. package/dist/chunks/{messages-BA8Iv99Y2.mjs → messages-DBMaLL8b2.mjs} +1 -0
  45. package/dist/{messages-DbySKTKt2.mjs → chunks/messages-DB_-5Xln.mjs} +1 -0
  46. package/dist/chunks/{messages-JyvWu4rf2.mjs → messages-DEBy3nuJ2.mjs} +1 -0
  47. package/dist/chunks/{messages-NEqrrYvE2.mjs → messages-DMoERagV2.mjs} +1 -0
  48. package/dist/{messages-Dy-Y_nEI.mjs → chunks/messages-DPzHD51Y.mjs} +1 -0
  49. package/dist/chunks/{messages-jfVpL9c-2.mjs → messages-DSrdy9Nw2.mjs} +1 -0
  50. package/dist/chunks/{messages-Cmf6NhSC.mjs → messages-DTN1XGll.mjs} +1 -0
  51. package/dist/chunks/{messages-BE6lHKwf.mjs → messages-DUeiPraX.mjs} +1 -0
  52. package/dist/{messages-Ddnj2iTG2.mjs → chunks/messages-DUr9WAkD.mjs} +1 -0
  53. package/dist/chunks/{messages-Ck81cQkn2.mjs → messages-DVr1sqfI2.mjs} +1 -0
  54. package/dist/chunks/{messages-aZcy0JQq2.mjs → messages-DjvaiALg2.mjs} +1 -0
  55. package/dist/{messages-DkLU_rWm.mjs → chunks/messages-DrfRYiM32.mjs} +1 -0
  56. package/dist/{messages-Dw__BcTj.mjs → chunks/messages-DtoId_bw2.mjs} +1 -0
  57. package/dist/{messages-Bq3F2Tp_.mjs → chunks/messages-Du2BffA7.mjs} +1 -0
  58. package/dist/{messages-CjbnogEC.mjs → chunks/messages-DxHh0O8j2.mjs} +1 -0
  59. package/dist/{messages-BECMxmfX.mjs → chunks/messages-EDMC5ukV.mjs} +1 -0
  60. package/dist/{messages-BTQPpoM42.mjs → chunks/messages-ElIGUi0O2.mjs} +1 -0
  61. package/dist/{messages-B1ZUQagA.mjs → chunks/messages-JSQjKQ8I.mjs} +1 -0
  62. package/dist/{messages-CWIXvnDf2.mjs → chunks/messages-Q7-4ZJLB2.mjs} +1 -0
  63. package/dist/{messages-BJeGJksD.mjs → chunks/messages-QMOmwcZb.mjs} +1 -0
  64. package/dist/chunks/{messages-xuqyb6Ff2.mjs → messages-QilfinOn2.mjs} +1 -0
  65. package/dist/{messages-BmAn22OX.mjs → chunks/messages-a07QVz8U.mjs} +1 -0
  66. package/dist/{messages-nlhESX9t.mjs → chunks/messages-eFd4YYzt.mjs} +1 -0
  67. package/dist/{messages-Dnp9N6RU2.mjs → chunks/messages-euM2m3wQ.mjs} +1 -0
  68. package/dist/chunks/{messages-BVjoM7P0.mjs → messages-kGmxkeFH.mjs} +1 -0
  69. package/dist/chunks/{messages-D9N2MvQx2.mjs → messages-oMc7qugU2.mjs} +1 -0
  70. package/dist/{messages-Dvn35ksS.mjs → chunks/messages-sDdNf8O9.mjs} +1 -0
  71. package/dist/{messages-Bm0Feca1.mjs → chunks/messages-wl8YrvGG.mjs} +1 -0
  72. package/dist/{messages-j7o5rT9s.mjs → chunks/messages-zt6zdYWh.mjs} +1 -0
  73. package/dist/chunks/{tools-DHtzbrxy.mjs → tools-BFK2MvVI.mjs} +1024 -895
  74. package/dist/full.mjs +3 -3
  75. package/dist/locales.mjs +68 -67
  76. package/dist/{messages-F2xRoY1w.mjs → messages-2ZWBTerL.mjs} +1 -0
  77. package/dist/{messages-Dl3Sv6Rq2.mjs → messages-53w0fPZS2.mjs} +1 -0
  78. package/dist/{chunks/messages-BDZA10kl2.mjs → messages-98nQiC7t2.mjs} +1 -0
  79. package/dist/{messages-CcF4y-E4.mjs → messages-A96tMxeU.mjs} +1 -0
  80. package/dist/{messages-Ce6KVEbT.mjs → messages-BE_z-zrb.mjs} +1 -0
  81. package/dist/{chunks/messages-CSJ_zb3a2.mjs → messages-BK_LsgY4.mjs} +1 -0
  82. package/dist/{messages-CJTy6JZt.mjs → messages-BbJ7ZXY8.mjs} +1 -0
  83. package/dist/{messages-BwHs4cm1.mjs → messages-BcVB3osF.mjs} +1 -0
  84. package/dist/{chunks/messages-CSL-6xfb2.mjs → messages-BckDk9aq2.mjs} +1 -0
  85. package/dist/{chunks/messages-C0HvoMPb.mjs → messages-Be_2RHZD.mjs} +1 -0
  86. package/dist/{messages-Dl5Y2-Ia.mjs → messages-BesJaI6A.mjs} +1 -0
  87. package/dist/{chunks/messages-D3zojZ94.mjs → messages-BiTMwiKH.mjs} +1 -0
  88. package/dist/{chunks/messages-BhzzNkN-.mjs → messages-BmH2cQHQ.mjs} +1 -0
  89. package/dist/{chunks/messages-Bfnq1xv4.mjs → messages-BrOWqNCu2.mjs} +1 -0
  90. package/dist/{chunks/messages-BSghd0ez.mjs → messages-Brd5R-da2.mjs} +1 -0
  91. package/dist/{chunks/messages-DJoNVjqP.mjs → messages-C0GSBBCo2.mjs} +1 -0
  92. package/dist/{chunks/messages-B2N4fUi72.mjs → messages-C1vc5584.mjs} +1 -0
  93. package/dist/{messages-aMXpHt5X2.mjs → messages-C6ONf71u2.mjs} +1 -0
  94. package/dist/{chunks/messages-BeFqtIrc2.mjs → messages-C7lJg8fy2.mjs} +1 -0
  95. package/dist/{messages-CSUHBs4c2.mjs → messages-CRNogopy2.mjs} +1 -0
  96. package/dist/{messages-DLlc9QPw.mjs → messages-CT-Kdas6.mjs} +1 -0
  97. package/dist/{messages-DPA-mMWC2.mjs → messages-CTTmWn4Y2.mjs} +1 -0
  98. package/dist/{chunks/messages-DWu1r4gc2.mjs → messages-CZbcxlZt2.mjs} +1 -0
  99. package/dist/{chunks/messages-Bp8qin1R.mjs → messages-C_Qn9SbQ.mjs} +1 -0
  100. package/dist/{chunks/messages-DGL1ySqb2.mjs → messages-CdEASHDp2.mjs} +1 -0
  101. package/dist/{chunks/messages-Bxvi1ebN.mjs → messages-CdduYw-q.mjs} +1 -0
  102. package/dist/{chunks/messages-Je5YvxiY.mjs → messages-Che99vKP.mjs} +1 -0
  103. package/dist/{chunks/messages-BYxLFj7y.mjs → messages-CisR4PNV.mjs} +1 -0
  104. package/dist/{messages-5jvKxQNu2.mjs → messages-ClGvlFcH2.mjs} +1 -0
  105. package/dist/{chunks/messages-FWfsxpBz.mjs → messages-CnuH-BZK2.mjs} +1 -0
  106. package/dist/{messages-BYmmMDrN2.mjs → messages-D0005ti32.mjs} +1 -0
  107. package/dist/{messages-B7ieAJBd2.mjs → messages-D05jqBIa2.mjs} +1 -0
  108. package/dist/{chunks/messages-BXM80fdr2.mjs → messages-D0lLw9KM.mjs} +1 -0
  109. package/dist/{chunks/messages-ihCjSFJI2.mjs → messages-D3rwCtKn.mjs} +1 -0
  110. package/dist/{messages-hWwSRF-2.mjs → messages-D6VIFnSW.mjs} +1 -0
  111. package/dist/{chunks/messages-KdawW5Na.mjs → messages-D81w6AmW.mjs} +1 -0
  112. package/dist/{messages-ynAe7ewZ.mjs → messages-DBhvm8NK.mjs} +1 -0
  113. package/dist/{messages-CmB406HW.mjs → messages-DK6dA0O2.mjs} +1 -0
  114. package/dist/{messages-rk-A1Wa42.mjs → messages-DKHbt-7l2.mjs} +1 -0
  115. package/dist/{messages-BIoeoik5.mjs → messages-DM4Gjc9h.mjs} +1 -0
  116. package/dist/{messages-BbYq1pk-.mjs → messages-DODrhcop.mjs} +1 -0
  117. package/dist/{messages-BsycN_JI2.mjs → messages-DOGbHYv-2.mjs} +1 -0
  118. package/dist/{messages-nUVjeh7K.mjs → messages-DQORja0D.mjs} +1 -0
  119. package/dist/{messages-DnG0ef8t2.mjs → messages-DSmxJWju2.mjs} +1 -0
  120. package/dist/{messages-CR_L_UtK.mjs → messages-DVL0KZE5.mjs} +1 -0
  121. package/dist/{chunks/messages-Cs81Z_Bh.mjs → messages-DYuD5-rO.mjs} +1 -0
  122. package/dist/{chunks/messages-CKBhDGI3.mjs → messages-Ddq3Ce3E2.mjs} +1 -0
  123. package/dist/{messages-xh2eOLvs.mjs → messages-DfFZ6Yj5.mjs} +1 -0
  124. package/dist/{messages-DY4IqlhY.mjs → messages-Dnd5YSWv.mjs} +1 -0
  125. package/dist/{chunks/messages-DOuS1Qge.mjs → messages-Do7Xjy0n.mjs} +1 -0
  126. package/dist/{chunks/messages-C3aX3q0H.mjs → messages-DopaMHC42.mjs} +1 -0
  127. package/dist/{messages-dv19AkyJ.mjs → messages-DpJGbx3q.mjs} +1 -0
  128. package/dist/{messages-DBiVgUs2.mjs → messages-DpwMKDV0.mjs} +1 -0
  129. package/dist/{chunks/messages-BAsb5CgZ.mjs → messages-Dqu4aX9s.mjs} +1 -0
  130. package/dist/{messages-BiUGXvYr2.mjs → messages-E8NjqzWq2.mjs} +1 -0
  131. package/dist/{chunks/messages-RInp1ytX.mjs → messages-JNrYldAa2.mjs} +1 -0
  132. package/dist/{chunks/messages-B4UMuyjT.mjs → messages-LMaR2_bE.mjs} +1 -0
  133. package/dist/{messages-E_ZuzGDt.mjs → messages-LYJbLq_F.mjs} +1 -0
  134. package/dist/{messages-DMr62KiO2.mjs → messages-Q5sQeVap2.mjs} +1 -0
  135. package/dist/{messages-Ci0KqX-J.mjs → messages-Xc0KUbYl.mjs} +1 -0
  136. package/dist/{messages-B19o-Teb.mjs → messages-_PLyRfVw.mjs} +1 -0
  137. package/dist/{chunks/messages-TRUuyiFB.mjs → messages-apA6BStA.mjs} +1 -0
  138. package/dist/{chunks/messages-B0vPBsWq.mjs → messages-bkGniiaz.mjs} +1 -0
  139. package/dist/{chunks/messages-D55HRx5O2.mjs → messages-neGD3WGq.mjs} +1 -0
  140. package/dist/{chunks/messages-G416eyjY.mjs → messages-qbKjjvgd2.mjs} +1 -0
  141. package/dist/{chunks/messages-BYlSMRkd.mjs → messages-qfvXgPpu2.mjs} +1 -0
  142. package/dist/{chunks/messages-DzTk8bJ5.mjs → messages-uwK7ktqk.mjs} +1 -0
  143. package/dist/react.mjs +2 -2
  144. package/dist/tools.mjs +2 -2
  145. package/package.json +1 -1
  146. package/src/components/block/index.ts +14 -0
  147. package/src/components/i18n/locales/am/messages.json +1 -0
  148. package/src/components/i18n/locales/ar/messages.json +1 -0
  149. package/src/components/i18n/locales/az/messages.json +1 -0
  150. package/src/components/i18n/locales/bg/messages.json +1 -0
  151. package/src/components/i18n/locales/bn/messages.json +1 -0
  152. package/src/components/i18n/locales/bs/messages.json +1 -0
  153. package/src/components/i18n/locales/cs/messages.json +1 -0
  154. package/src/components/i18n/locales/da/messages.json +1 -0
  155. package/src/components/i18n/locales/de/messages.json +1 -0
  156. package/src/components/i18n/locales/dv/messages.json +1 -0
  157. package/src/components/i18n/locales/el/messages.json +1 -0
  158. package/src/components/i18n/locales/en/messages.json +1 -0
  159. package/src/components/i18n/locales/es/messages.json +1 -0
  160. package/src/components/i18n/locales/et/messages.json +1 -0
  161. package/src/components/i18n/locales/fa/messages.json +1 -0
  162. package/src/components/i18n/locales/fi/messages.json +1 -0
  163. package/src/components/i18n/locales/fil/messages.json +1 -0
  164. package/src/components/i18n/locales/fr/messages.json +1 -0
  165. package/src/components/i18n/locales/gu/messages.json +1 -0
  166. package/src/components/i18n/locales/he/messages.json +1 -0
  167. package/src/components/i18n/locales/hi/messages.json +1 -0
  168. package/src/components/i18n/locales/hr/messages.json +1 -0
  169. package/src/components/i18n/locales/hu/messages.json +1 -0
  170. package/src/components/i18n/locales/hy/messages.json +1 -0
  171. package/src/components/i18n/locales/id/messages.json +1 -0
  172. package/src/components/i18n/locales/it/messages.json +1 -0
  173. package/src/components/i18n/locales/ja/messages.json +1 -0
  174. package/src/components/i18n/locales/ka/messages.json +1 -0
  175. package/src/components/i18n/locales/km/messages.json +1 -0
  176. package/src/components/i18n/locales/kn/messages.json +1 -0
  177. package/src/components/i18n/locales/ko/messages.json +1 -0
  178. package/src/components/i18n/locales/ku/messages.json +1 -0
  179. package/src/components/i18n/locales/lo/messages.json +1 -0
  180. package/src/components/i18n/locales/lt/messages.json +1 -0
  181. package/src/components/i18n/locales/lv/messages.json +1 -0
  182. package/src/components/i18n/locales/mk/messages.json +1 -0
  183. package/src/components/i18n/locales/ml/messages.json +1 -0
  184. package/src/components/i18n/locales/mn/messages.json +1 -0
  185. package/src/components/i18n/locales/mr/messages.json +1 -0
  186. package/src/components/i18n/locales/ms/messages.json +1 -0
  187. package/src/components/i18n/locales/my/messages.json +1 -0
  188. package/src/components/i18n/locales/ne/messages.json +1 -0
  189. package/src/components/i18n/locales/nl/messages.json +1 -0
  190. package/src/components/i18n/locales/no/messages.json +1 -0
  191. package/src/components/i18n/locales/pa/messages.json +1 -0
  192. package/src/components/i18n/locales/pl/messages.json +1 -0
  193. package/src/components/i18n/locales/ps/messages.json +1 -0
  194. package/src/components/i18n/locales/pt/messages.json +1 -0
  195. package/src/components/i18n/locales/ro/messages.json +1 -0
  196. package/src/components/i18n/locales/ru/messages.json +1 -0
  197. package/src/components/i18n/locales/sd/messages.json +1 -0
  198. package/src/components/i18n/locales/si/messages.json +1 -0
  199. package/src/components/i18n/locales/sk/messages.json +1 -0
  200. package/src/components/i18n/locales/sl/messages.json +1 -0
  201. package/src/components/i18n/locales/sq/messages.json +1 -0
  202. package/src/components/i18n/locales/sr/messages.json +1 -0
  203. package/src/components/i18n/locales/sv/messages.json +1 -0
  204. package/src/components/i18n/locales/sw/messages.json +1 -0
  205. package/src/components/i18n/locales/ta/messages.json +1 -0
  206. package/src/components/i18n/locales/te/messages.json +1 -0
  207. package/src/components/i18n/locales/th/messages.json +1 -0
  208. package/src/components/i18n/locales/tr/messages.json +1 -0
  209. package/src/components/i18n/locales/ug/messages.json +1 -0
  210. package/src/components/i18n/locales/uk/messages.json +1 -0
  211. package/src/components/i18n/locales/ur/messages.json +1 -0
  212. package/src/components/i18n/locales/vi/messages.json +1 -0
  213. package/src/components/i18n/locales/yi/messages.json +1 -0
  214. package/src/components/i18n/locales/zh/messages.json +1 -0
  215. package/src/components/icons/index.ts +22 -27
  216. package/src/components/modules/toolbar/index.ts +21 -9
  217. package/src/components/modules/toolbar/positioning.ts +11 -2
  218. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +11 -0
  219. package/src/components/utils/popover/popover-abstract.ts +7 -0
  220. package/src/tools/code/constants.ts +24 -12
  221. package/src/tools/code/dom-builder.ts +122 -89
  222. package/src/tools/code/index.ts +255 -104
  223. package/src/tools/code/language-detector.ts +118 -0
  224. package/types/tools/block-tool.d.ts +10 -0
  225. package/types/utils/popover/popover-item.d.ts +6 -0
@@ -2,30 +2,41 @@ import {
2
2
  WRAPPER_STYLES,
3
3
  HEADER_STYLES,
4
4
  LANGUAGE_BUTTON_STYLES,
5
+ HEADER_CONTROLS_STYLES,
5
6
  HEADER_BUTTON_STYLES,
7
+ HEADER_BUTTON_MATCHED_STYLES,
6
8
  CODE_AREA_STYLES,
7
9
  PREVIEW_AREA_STYLES,
8
10
  CODE_BODY_STYLES,
9
11
  GUTTER_STYLES,
10
12
  GUTTER_LINE_STYLES,
11
- MORE_MENU_STYLES,
12
- MORE_MENU_ITEM_STYLES,
13
+ VIEW_MODE_CONTAINER_STYLES,
14
+ VIEW_MODE_BUTTON_STYLES,
15
+ VIEW_MODE_BUTTON_ACTIVE_STYLES,
16
+ VIEW_MODE_PREVIEW_BUTTON_STYLES,
17
+ VIEW_MODE_PREVIEW_BUTTON_ACTIVE_STYLES,
18
+ SPLIT_CONTAINER_STYLES,
19
+ SPLIT_HALF_STYLES,
13
20
  } from './constants';
14
- import { IconCopy, IconCode, IconChevronDown, IconEllipsis, IconWrap, IconLineNumbers } from '../../components/icons';
21
+ import type { CodeViewMode } from './constants';
22
+ import { IconCopy, IconCode, IconPreview, IconSplitView, IconChevronDown } from '../../components/icons';
15
23
 
16
24
  export interface CodeDOMRefs {
17
25
  wrapper: HTMLElement;
18
26
  languageButton: HTMLButtonElement;
19
- lineNumbersButton: HTMLButtonElement;
20
27
  copyButton: HTMLButtonElement;
21
- wrapButton: HTMLButtonElement;
22
28
  preElement: HTMLPreElement;
23
29
  codeElement: HTMLElement;
24
30
  gutterElement: HTMLElement;
25
- previewToggleButton: HTMLButtonElement | null;
31
+ viewModeContainer: HTMLElement | null;
26
32
  previewElement: HTMLDivElement | null;
27
- moreButton: HTMLButtonElement;
28
- moreMenu: HTMLElement;
33
+ splitContainer: HTMLElement | null;
34
+ }
35
+
36
+ export interface ViewModeLabels {
37
+ code: string;
38
+ preview: string;
39
+ split: string;
29
40
  }
30
41
 
31
42
  export interface BuildCodeDOMOptions {
@@ -33,33 +44,83 @@ export interface BuildCodeDOMOptions {
33
44
  languageName: string;
34
45
  readOnly: boolean;
35
46
  copyLabel: string;
36
- wrapLabel: string;
37
- lineNumbersLabel?: string;
38
47
  previewable?: boolean;
39
- previewToggleLabel?: string;
48
+ viewModeLabels?: ViewModeLabels;
40
49
  }
41
50
 
42
- function buildPreviewElements(
43
- previewToggleLabel?: string,
44
- ): { previewToggleButton: HTMLButtonElement; previewElement: HTMLDivElement } {
45
- const previewToggleButton = document.createElement('button');
51
+ interface ViewModeElements {
52
+ viewModeContainer: HTMLElement;
53
+ previewElement: HTMLDivElement;
54
+ splitContainer: HTMLElement;
55
+ }
46
56
 
47
- previewToggleButton.type = 'button';
48
- previewToggleButton.className = HEADER_BUTTON_STYLES;
49
- previewToggleButton.innerHTML = IconCode;
50
- previewToggleButton.setAttribute('aria-label', previewToggleLabel ?? 'Preview');
51
- previewToggleButton.setAttribute('data-blok-testid', 'code-preview-toggle-btn');
57
+ function buildViewModeElements(
58
+ labels: ViewModeLabels,
59
+ ): ViewModeElements {
60
+ // Segmented control container
61
+ const viewModeContainer = document.createElement('div');
62
+
63
+ viewModeContainer.className = VIEW_MODE_CONTAINER_STYLES;
64
+ viewModeContainer.setAttribute('role', 'group');
65
+ viewModeContainer.setAttribute('data-blok-testid', 'code-view-mode');
66
+
67
+ const modes: Array<{ mode: CodeViewMode; icon: string; label: string }> = [
68
+ { mode: 'code', icon: IconCode, label: labels.code },
69
+ { mode: 'preview', icon: IconPreview, label: labels.preview },
70
+ { mode: 'split', icon: IconSplitView, label: labels.split },
71
+ ];
72
+
73
+ for (const { mode, icon, label } of modes) {
74
+ const button = document.createElement('button');
75
+ const isPreview = mode === 'preview';
76
+
77
+ button.type = 'button';
78
+ button.className = isPreview ? VIEW_MODE_PREVIEW_BUTTON_STYLES : VIEW_MODE_BUTTON_STYLES;
79
+ button.innerHTML = icon;
80
+ button.setAttribute('aria-label', label);
81
+ button.setAttribute('aria-pressed', 'false');
82
+ button.setAttribute('data-blok-testid', `code-mode-${mode}`);
83
+ button.setAttribute('data-mode', mode);
84
+ viewModeContainer.appendChild(button);
85
+ }
52
86
 
87
+ // Preview container
53
88
  const previewElement = document.createElement('div');
54
89
 
55
90
  previewElement.className = PREVIEW_AREA_STYLES;
56
91
  previewElement.setAttribute('data-blok-testid', 'code-preview');
57
92
 
58
- return { previewToggleButton, previewElement };
93
+ // Split container wraps code body + preview
94
+ const splitContainer = document.createElement('div');
95
+
96
+ splitContainer.className = SPLIT_CONTAINER_STYLES;
97
+ splitContainer.setAttribute('data-blok-testid', 'code-split-container');
98
+
99
+ return { viewModeContainer, previewElement, splitContainer };
100
+ }
101
+
102
+ /**
103
+ * Set the active view mode button styling and aria-pressed state.
104
+ */
105
+ export function setActiveViewMode(viewModeContainer: HTMLElement, mode: CodeViewMode): void {
106
+ const buttons = Array.from(viewModeContainer.querySelectorAll<HTMLButtonElement>('[data-mode]'));
107
+
108
+ for (const btn of buttons) {
109
+ const isActive = btn.getAttribute('data-mode') === mode;
110
+ const isPreview = btn.getAttribute('data-mode') === 'preview';
111
+
112
+ btn.setAttribute('aria-pressed', String(isActive));
113
+
114
+ if (isPreview) {
115
+ btn.className = isActive ? VIEW_MODE_PREVIEW_BUTTON_ACTIVE_STYLES : VIEW_MODE_PREVIEW_BUTTON_STYLES;
116
+ } else {
117
+ btn.className = isActive ? VIEW_MODE_BUTTON_ACTIVE_STYLES : VIEW_MODE_BUTTON_STYLES;
118
+ }
119
+ }
59
120
  }
60
121
 
61
122
  export function buildCodeDOM(options: BuildCodeDOMOptions): CodeDOMRefs {
62
- const { code, languageName, readOnly, copyLabel, wrapLabel, lineNumbersLabel, previewable, previewToggleLabel } = options;
123
+ const { code, languageName, readOnly, copyLabel, previewable, viewModeLabels } = options;
63
124
 
64
125
  // Wrapper
65
126
  const wrapper = document.createElement('div');
@@ -89,67 +150,27 @@ export function buildCodeDOM(options: BuildCodeDOMOptions): CodeDOMRefs {
89
150
  const spacer = document.createElement('div');
90
151
  spacer.className = 'flex-1';
91
152
 
92
- // Preview toggle button (only when previewable and not read-only)
93
- const { previewToggleButton, previewElement } = previewable
94
- ? buildPreviewElements(previewToggleLabel)
95
- : { previewToggleButton: null, previewElement: null };
153
+ // View mode segmented control always built in edit mode, hidden for non-previewable languages
154
+ const viewModeResult = !readOnly && viewModeLabels
155
+ ? buildViewModeElements(viewModeLabels)
156
+ : null;
157
+
158
+ const viewModeContainer = viewModeResult?.viewModeContainer ?? null;
159
+ const previewElement = viewModeResult?.previewElement ?? null;
160
+ const splitContainer = viewModeResult?.splitContainer ?? null;
161
+
162
+ if (viewModeContainer) {
163
+ viewModeContainer.hidden = !previewable;
164
+ }
96
165
 
97
166
  // Copy button
98
167
  const copyButton = document.createElement('button');
99
168
  copyButton.type = 'button';
100
- copyButton.className = HEADER_BUTTON_STYLES;
169
+ copyButton.className = previewable ? HEADER_BUTTON_MATCHED_STYLES : HEADER_BUTTON_STYLES;
101
170
  copyButton.innerHTML = IconCopy;
102
171
  copyButton.setAttribute('aria-label', copyLabel);
103
172
  copyButton.setAttribute('data-blok-testid', 'code-copy-btn');
104
173
 
105
- // More button (ellipsis)
106
- const moreButton = document.createElement('button');
107
- moreButton.type = 'button';
108
- moreButton.className = HEADER_BUTTON_STYLES;
109
- moreButton.innerHTML = IconEllipsis;
110
- moreButton.setAttribute('aria-label', 'More');
111
- moreButton.setAttribute('aria-haspopup', 'true');
112
- moreButton.setAttribute('data-blok-testid', 'code-more-btn');
113
-
114
- // More menu dropdown
115
- const moreMenu = document.createElement('div');
116
- moreMenu.className = MORE_MENU_STYLES;
117
- moreMenu.hidden = true;
118
- moreMenu.setAttribute('data-blok-testid', 'code-more-menu');
119
-
120
- // Line numbers toggle (inside more menu)
121
- const lineNumbersButton = document.createElement('button');
122
- lineNumbersButton.type = 'button';
123
- lineNumbersButton.className = MORE_MENU_ITEM_STYLES;
124
- lineNumbersButton.setAttribute('data-blok-testid', 'code-line-numbers-btn');
125
-
126
- const lineNumIconSpan = document.createElement('span');
127
- lineNumIconSpan.className = 'flex items-center justify-center w-5 h-5';
128
- lineNumIconSpan.innerHTML = IconLineNumbers;
129
- lineNumbersButton.appendChild(lineNumIconSpan);
130
-
131
- const lineNumText = document.createElement('span');
132
- lineNumText.textContent = lineNumbersLabel ?? 'Line numbers';
133
- lineNumbersButton.appendChild(lineNumText);
134
-
135
- // Wrap toggle (inside more menu)
136
- const wrapButton = document.createElement('button');
137
- wrapButton.type = 'button';
138
- wrapButton.className = MORE_MENU_ITEM_STYLES;
139
- wrapButton.setAttribute('data-blok-testid', 'code-wrap-btn');
140
-
141
- const wrapIconSpan = document.createElement('span');
142
- wrapIconSpan.className = 'flex items-center justify-center w-5 h-5';
143
- wrapIconSpan.innerHTML = IconWrap;
144
- wrapButton.appendChild(wrapIconSpan);
145
-
146
- const wrapText = document.createElement('span');
147
- wrapText.textContent = wrapLabel;
148
- wrapButton.appendChild(wrapText);
149
-
150
- moreMenu.appendChild(lineNumbersButton);
151
- moreMenu.appendChild(wrapButton);
152
-
153
174
  // Code area
154
175
  const codeElement = document.createElement('code');
155
176
  codeElement.className = CODE_AREA_STYLES;
@@ -178,22 +199,21 @@ export function buildCodeDOM(options: BuildCodeDOMOptions): CodeDOMRefs {
178
199
  gutterElement.appendChild(lineEl);
179
200
  });
180
201
 
181
- // Assemble header: [language] [spacer] [preview toggle?] [copy] [more ▸ menu]
202
+ // Assemble header: [language] [spacer] [controls: view mode? | copy]
182
203
  header.appendChild(languageButton);
183
204
  header.appendChild(spacer);
184
205
 
185
- if (previewToggleButton) {
186
- header.appendChild(previewToggleButton);
206
+ // Controls container — hidden by default, visible on wrapper hover
207
+ const controls = document.createElement('div');
208
+ controls.className = HEADER_CONTROLS_STYLES;
209
+
210
+ if (viewModeContainer) {
211
+ controls.appendChild(viewModeContainer);
187
212
  }
188
213
 
189
- header.appendChild(copyButton);
214
+ controls.appendChild(copyButton);
190
215
 
191
- // More wrapper (relative position anchor for absolute dropdown)
192
- const moreWrapper = document.createElement('div');
193
- moreWrapper.className = 'relative';
194
- moreWrapper.appendChild(moreButton);
195
- moreWrapper.appendChild(moreMenu);
196
- header.appendChild(moreWrapper);
216
+ header.appendChild(controls);
197
217
 
198
218
  // Pre wrapper for semantic HTML
199
219
  const preElement = document.createElement('pre');
@@ -207,11 +227,24 @@ export function buildCodeDOM(options: BuildCodeDOMOptions): CodeDOMRefs {
207
227
 
208
228
  // Assemble wrapper
209
229
  wrapper.appendChild(header);
210
- wrapper.appendChild(codeBody);
211
230
 
212
- if (previewElement) {
213
- wrapper.appendChild(previewElement);
231
+ if (splitContainer && previewElement) {
232
+ // Edit mode: always wrap code body + preview in split container.
233
+ // previewElement is hidden initially; shown when a previewable language is active.
234
+ const codeHalf = document.createElement('div');
235
+ codeHalf.className = SPLIT_HALF_STYLES;
236
+ codeHalf.appendChild(codeBody);
237
+
238
+ const previewHalf = document.createElement('div');
239
+ previewHalf.className = SPLIT_HALF_STYLES;
240
+ previewHalf.appendChild(previewElement);
241
+
242
+ splitContainer.appendChild(codeHalf);
243
+ splitContainer.appendChild(previewHalf);
244
+ wrapper.appendChild(splitContainer);
245
+ } else {
246
+ wrapper.appendChild(codeBody);
214
247
  }
215
248
 
216
- return { wrapper, languageButton, lineNumbersButton, copyButton, wrapButton, preElement, codeElement, gutterElement, previewToggleButton, previewElement, moreButton, moreMenu };
249
+ return { wrapper, languageButton, copyButton, preElement, codeElement, gutterElement, viewModeContainer, previewElement, splitContainer };
217
250
  }