@mieweb/ui 0.10.0-dev.3 → 0.10.0-dev.31

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 (498) hide show
  1. package/README.md +4 -4
  2. package/agent/mieweb-ui.instructions.md +90 -1
  3. package/dist/CsvBlock-FX5YNGNE.cjs +17 -0
  4. package/dist/{CsvBlock-ROJCKJDP.cjs.map → CsvBlock-FX5YNGNE.cjs.map} +1 -1
  5. package/dist/CsvBlock-VLMG7GUO.js +8 -0
  6. package/dist/{CsvBlock-UWPMTLE2.js.map → CsvBlock-VLMG7GUO.js.map} +1 -1
  7. package/dist/HtmlPreviewBlock-5JE7L3GR.js +8 -0
  8. package/dist/{HtmlPreviewBlock-ME5U3XNS.js.map → HtmlPreviewBlock-5JE7L3GR.js.map} +1 -1
  9. package/dist/HtmlPreviewBlock-UO37JQ3K.cjs +17 -0
  10. package/dist/{HtmlPreviewBlock-DWFN6EUB.cjs.map → HtmlPreviewBlock-UO37JQ3K.cjs.map} +1 -1
  11. package/dist/Input-yN516s5_.d.cts +3 -0
  12. package/dist/Input-yN516s5_.d.ts +3 -0
  13. package/dist/MermaidBlock-3XHFBAMV.js +8 -0
  14. package/dist/{MermaidBlock-2B6CPD6Y.js.map → MermaidBlock-3XHFBAMV.js.map} +1 -1
  15. package/dist/MermaidBlock-RZ75RPZA.cjs +17 -0
  16. package/dist/{MermaidBlock-D2UC5M55.cjs.map → MermaidBlock-RZ75RPZA.cjs.map} +1 -1
  17. package/dist/SurveyBlock-MUVJ3JUI.js +8 -0
  18. package/dist/{SurveyBlock-4DO62RBT.js.map → SurveyBlock-MUVJ3JUI.js.map} +1 -1
  19. package/dist/SurveyBlock-VH47YXZC.cjs +17 -0
  20. package/dist/{SurveyBlock-4CD4AYMJ.cjs.map → SurveyBlock-VH47YXZC.cjs.map} +1 -1
  21. package/dist/ag-grid.d.cts +142 -1
  22. package/dist/ag-grid.d.ts +142 -1
  23. package/dist/brands/bluehive.cjs +3 -3
  24. package/dist/brands/bluehive.css +3 -0
  25. package/dist/brands/bluehive.js +1 -1
  26. package/dist/brands/index.cjs +14 -14
  27. package/dist/brands/index.js +4 -4
  28. package/dist/{chunk-JYZW2PZS.cjs → chunk-254QK722.cjs} +7 -7
  29. package/dist/chunk-254QK722.cjs.map +1 -0
  30. package/dist/{chunk-VKELAMAZ.js → chunk-2JICT4A2.js} +27 -11
  31. package/dist/chunk-2JICT4A2.js.map +1 -0
  32. package/dist/{chunk-VPWJCJCX.cjs → chunk-35Y4ILCU.cjs} +7 -7
  33. package/dist/{chunk-VPWJCJCX.cjs.map → chunk-35Y4ILCU.cjs.map} +1 -1
  34. package/dist/{chunk-G3JX3UAU.cjs → chunk-3KPDQG5O.cjs} +5 -5
  35. package/dist/{chunk-G3JX3UAU.cjs.map → chunk-3KPDQG5O.cjs.map} +1 -1
  36. package/dist/{chunk-Y5HFM7LO.js → chunk-3RXZWHCU.js} +4 -4
  37. package/dist/{chunk-Y5HFM7LO.js.map → chunk-3RXZWHCU.js.map} +1 -1
  38. package/dist/chunk-3YBS4WUQ.js +52 -0
  39. package/dist/chunk-3YBS4WUQ.js.map +1 -0
  40. package/dist/{chunk-WNJRS7Y7.cjs → chunk-3ZWCIPFT.cjs} +4 -2
  41. package/dist/chunk-3ZWCIPFT.cjs.map +1 -0
  42. package/dist/chunk-4HC2IBOX.js +258 -0
  43. package/dist/chunk-4HC2IBOX.js.map +1 -0
  44. package/dist/chunk-4IS3QCOQ.cjs +453 -0
  45. package/dist/chunk-4IS3QCOQ.cjs.map +1 -0
  46. package/dist/chunk-4NCDU5IG.cjs +56 -0
  47. package/dist/chunk-4NCDU5IG.cjs.map +1 -0
  48. package/dist/{chunk-E4IBHYJ7.cjs → chunk-6N6LIAUJ.cjs} +9 -9
  49. package/dist/{chunk-E4IBHYJ7.cjs.map → chunk-6N6LIAUJ.cjs.map} +1 -1
  50. package/dist/{chunk-3M7TAXNR.js → chunk-6ZPTZTKN.js} +3 -3
  51. package/dist/{chunk-3M7TAXNR.js.map → chunk-6ZPTZTKN.js.map} +1 -1
  52. package/dist/{chunk-MWVW4APN.cjs → chunk-7UTBDFFL.cjs} +4 -4
  53. package/dist/{chunk-MWVW4APN.cjs.map → chunk-7UTBDFFL.cjs.map} +1 -1
  54. package/dist/{chunk-FJ7YPVKV.js → chunk-7X6R3JIA.js} +3 -3
  55. package/dist/{chunk-FJ7YPVKV.js.map → chunk-7X6R3JIA.js.map} +1 -1
  56. package/dist/{chunk-GOALNQZ2.js → chunk-7YO7DNUV.js} +4 -83
  57. package/dist/chunk-7YO7DNUV.js.map +1 -0
  58. package/dist/{chunk-P2CA3XGI.js → chunk-7ZV67VZE.js} +4 -4
  59. package/dist/{chunk-P2CA3XGI.js.map → chunk-7ZV67VZE.js.map} +1 -1
  60. package/dist/chunk-ADW7ZYCY.cjs +2707 -0
  61. package/dist/chunk-ADW7ZYCY.cjs.map +1 -0
  62. package/dist/{chunk-2G75X6TS.cjs → chunk-AHHFFXJR.cjs} +3 -3
  63. package/dist/{chunk-2G75X6TS.cjs.map → chunk-AHHFFXJR.cjs.map} +1 -1
  64. package/dist/{chunk-VILW53UZ.js → chunk-BIQ7GSO2.js} +3 -3
  65. package/dist/{chunk-VILW53UZ.js.map → chunk-BIQ7GSO2.js.map} +1 -1
  66. package/dist/chunk-BM35CACB.js +148 -0
  67. package/dist/chunk-BM35CACB.js.map +1 -0
  68. package/dist/chunk-BNH4SXJB.js +874 -0
  69. package/dist/chunk-BNH4SXJB.js.map +1 -0
  70. package/dist/{chunk-XEAT7XJG.cjs → chunk-BUT6MF5K.cjs} +29 -13
  71. package/dist/chunk-BUT6MF5K.cjs.map +1 -0
  72. package/dist/{chunk-UAMXCMST.cjs → chunk-CFI3TQMA.cjs} +3 -3
  73. package/dist/{chunk-UAMXCMST.cjs.map → chunk-CFI3TQMA.cjs.map} +1 -1
  74. package/dist/{chunk-J5CSLNCN.cjs → chunk-COM7RNZU.cjs} +2 -2
  75. package/dist/{chunk-J5CSLNCN.cjs.map → chunk-COM7RNZU.cjs.map} +1 -1
  76. package/dist/{chunk-XI34EGK5.cjs → chunk-CPPUT74P.cjs} +9 -9
  77. package/dist/{chunk-XI34EGK5.cjs.map → chunk-CPPUT74P.cjs.map} +1 -1
  78. package/dist/{chunk-ACCAXVOG.js → chunk-CRS2CQWM.js} +134 -56
  79. package/dist/chunk-CRS2CQWM.js.map +1 -0
  80. package/dist/{chunk-OE5CKRUC.js → chunk-D22GE27K.js} +4 -4
  81. package/dist/{chunk-OE5CKRUC.js.map → chunk-D22GE27K.js.map} +1 -1
  82. package/dist/chunk-DXEPYK3I.cjs +92 -0
  83. package/dist/chunk-DXEPYK3I.cjs.map +1 -0
  84. package/dist/{chunk-ZGRCSNPK.js → chunk-E2PBPQGS.js} +4 -4
  85. package/dist/{chunk-ZGRCSNPK.js.map → chunk-E2PBPQGS.js.map} +1 -1
  86. package/dist/{chunk-5JJ2DAE4.js → chunk-ENMXHZNE.js} +3 -3
  87. package/dist/{chunk-5JJ2DAE4.js.map → chunk-ENMXHZNE.js.map} +1 -1
  88. package/dist/{chunk-XCP454Q6.js → chunk-F4N67NAF.js} +12 -3
  89. package/dist/chunk-F4N67NAF.js.map +1 -0
  90. package/dist/chunk-FBCDYTWM.js +385 -0
  91. package/dist/chunk-FBCDYTWM.js.map +1 -0
  92. package/dist/{chunk-VU6UTJRM.js → chunk-FIKO4WR6.js} +3 -3
  93. package/dist/{chunk-VU6UTJRM.js.map → chunk-FIKO4WR6.js.map} +1 -1
  94. package/dist/{chunk-DEDN5HAG.js → chunk-FZURBQJ2.js} +3 -3
  95. package/dist/{chunk-DEDN5HAG.js.map → chunk-FZURBQJ2.js.map} +1 -1
  96. package/dist/{chunk-JHULS3EC.js → chunk-GBUVIGD5.js} +89 -3
  97. package/dist/chunk-GBUVIGD5.js.map +1 -0
  98. package/dist/chunk-GU5OS7JJ.cjs +281 -0
  99. package/dist/chunk-GU5OS7JJ.cjs.map +1 -0
  100. package/dist/{chunk-V7D3YGUV.js → chunk-GVLNXPJX.js} +4 -4
  101. package/dist/{chunk-V7D3YGUV.js.map → chunk-GVLNXPJX.js.map} +1 -1
  102. package/dist/chunk-GVM6DTR5.js +90 -0
  103. package/dist/chunk-GVM6DTR5.js.map +1 -0
  104. package/dist/{chunk-SQHMGT4W.js → chunk-GW4RFJZ5.js} +7 -7
  105. package/dist/chunk-GW4RFJZ5.js.map +1 -0
  106. package/dist/{chunk-3QEVGSFG.cjs → chunk-GYXUS65N.cjs} +5 -5
  107. package/dist/{chunk-3QEVGSFG.cjs.map → chunk-GYXUS65N.cjs.map} +1 -1
  108. package/dist/{chunk-WGPLUCBD.js → chunk-H2IAMSHK.js} +3 -3
  109. package/dist/{chunk-WGPLUCBD.js.map → chunk-H2IAMSHK.js.map} +1 -1
  110. package/dist/{chunk-JID7AZTO.cjs → chunk-H3ROMJYI.cjs} +4 -4
  111. package/dist/{chunk-JID7AZTO.cjs.map → chunk-H3ROMJYI.cjs.map} +1 -1
  112. package/dist/{chunk-GD7EBGC4.cjs → chunk-HC3NAN55.cjs} +19 -19
  113. package/dist/{chunk-GD7EBGC4.cjs.map → chunk-HC3NAN55.cjs.map} +1 -1
  114. package/dist/{chunk-7ZXAQTV4.cjs → chunk-HIZWOAWY.cjs} +8 -8
  115. package/dist/{chunk-7ZXAQTV4.cjs.map → chunk-HIZWOAWY.cjs.map} +1 -1
  116. package/dist/{chunk-NV2CWBI2.cjs → chunk-IEY3ZJIT.cjs} +12 -3
  117. package/dist/chunk-IEY3ZJIT.cjs.map +1 -0
  118. package/dist/chunk-IT775BYG.js +179 -0
  119. package/dist/chunk-IT775BYG.js.map +1 -0
  120. package/dist/chunk-IYWG72DM.js +166 -0
  121. package/dist/chunk-IYWG72DM.js.map +1 -0
  122. package/dist/{chunk-2YCERQWC.js → chunk-JBIGSP2T.js} +6 -6
  123. package/dist/{chunk-2YCERQWC.js.map → chunk-JBIGSP2T.js.map} +1 -1
  124. package/dist/{chunk-IX6KFB3K.cjs → chunk-JELTRRR5.cjs} +9 -9
  125. package/dist/{chunk-IX6KFB3K.cjs.map → chunk-JELTRRR5.cjs.map} +1 -1
  126. package/dist/{chunk-YQDA366U.js → chunk-JHG3ELS2.js} +2 -2
  127. package/dist/{chunk-YQDA366U.js.map → chunk-JHG3ELS2.js.map} +1 -1
  128. package/dist/{chunk-WWJIW2IH.cjs → chunk-JSXIB6EJ.cjs} +4 -4
  129. package/dist/{chunk-WWJIW2IH.cjs.map → chunk-JSXIB6EJ.cjs.map} +1 -1
  130. package/dist/{chunk-WNM7IZJ7.js → chunk-K34DXMLZ.js} +7 -7
  131. package/dist/{chunk-WNM7IZJ7.js.map → chunk-K34DXMLZ.js.map} +1 -1
  132. package/dist/{chunk-FXO5ARBB.cjs → chunk-KDW6BD4O.cjs} +4 -4
  133. package/dist/{chunk-FXO5ARBB.cjs.map → chunk-KDW6BD4O.cjs.map} +1 -1
  134. package/dist/{chunk-Z5V7SAZ4.js → chunk-KFEN2SRZ.js} +3 -3
  135. package/dist/{chunk-Z5V7SAZ4.js.map → chunk-KFEN2SRZ.js.map} +1 -1
  136. package/dist/{chunk-2QKBTPUC.cjs → chunk-KGKBZN3T.cjs} +8 -8
  137. package/dist/{chunk-2QKBTPUC.cjs.map → chunk-KGKBZN3T.cjs.map} +1 -1
  138. package/dist/{chunk-UV2FVNWT.cjs → chunk-LFPJ3OUM.cjs} +5 -5
  139. package/dist/{chunk-UV2FVNWT.cjs.map → chunk-LFPJ3OUM.cjs.map} +1 -1
  140. package/dist/{chunk-WNAA6CLE.cjs → chunk-LHBWRMNC.cjs} +94 -2
  141. package/dist/chunk-LHBWRMNC.cjs.map +1 -0
  142. package/dist/{chunk-JI244Y7C.js → chunk-MLAWXPRY.js} +190 -5
  143. package/dist/chunk-MLAWXPRY.js.map +1 -0
  144. package/dist/chunk-N7C4OEP7.cjs +356 -0
  145. package/dist/chunk-N7C4OEP7.cjs.map +1 -0
  146. package/dist/{chunk-WNZAYBVB.cjs → chunk-NKV76R65.cjs} +48 -48
  147. package/dist/{chunk-WNZAYBVB.cjs.map → chunk-NKV76R65.cjs.map} +1 -1
  148. package/dist/{chunk-PYJDVWXM.js → chunk-NUB5HRKS.js} +3 -3
  149. package/dist/{chunk-PYJDVWXM.js.map → chunk-NUB5HRKS.js.map} +1 -1
  150. package/dist/{chunk-LL6IWKI3.js → chunk-OW3SQJ7P.js} +3 -3
  151. package/dist/{chunk-LL6IWKI3.js.map → chunk-OW3SQJ7P.js.map} +1 -1
  152. package/dist/{chunk-5GUOOLPR.cjs → chunk-P5CMZZRZ.cjs} +5 -5
  153. package/dist/{chunk-5GUOOLPR.cjs.map → chunk-P5CMZZRZ.cjs.map} +1 -1
  154. package/dist/{chunk-3T7QGLNB.js → chunk-PJEL5ZZV.js} +4 -2
  155. package/dist/chunk-PJEL5ZZV.js.map +1 -0
  156. package/dist/{chunk-H4ZXMQQW.js → chunk-QOVJ6Z6R.js} +3 -3
  157. package/dist/{chunk-H4ZXMQQW.js.map → chunk-QOVJ6Z6R.js.map} +1 -1
  158. package/dist/{chunk-U42F3HLE.cjs → chunk-QURJVPRH.cjs} +190 -5
  159. package/dist/chunk-QURJVPRH.cjs.map +1 -0
  160. package/dist/{chunk-X4XPNTCZ.cjs → chunk-R5Z7AOVU.cjs} +136 -58
  161. package/dist/chunk-R5Z7AOVU.cjs.map +1 -0
  162. package/dist/{chunk-TMMVIUUN.js → chunk-R6KPWIGO.js} +4 -4
  163. package/dist/{chunk-TMMVIUUN.js.map → chunk-R6KPWIGO.js.map} +1 -1
  164. package/dist/{chunk-22CYDCXA.js → chunk-RM2HPQIC.js} +105 -14
  165. package/dist/chunk-RM2HPQIC.js.map +1 -0
  166. package/dist/{chunk-ENKFJJZX.js → chunk-SD7ONW6S.js} +6 -6
  167. package/dist/{chunk-ENKFJJZX.js.map → chunk-SD7ONW6S.js.map} +1 -1
  168. package/dist/{chunk-RJ6NTJHC.js → chunk-SRMTRD7F.js} +3 -3
  169. package/dist/{chunk-RJ6NTJHC.js.map → chunk-SRMTRD7F.js.map} +1 -1
  170. package/dist/chunk-T4JYUICS.js +2657 -0
  171. package/dist/chunk-T4JYUICS.js.map +1 -0
  172. package/dist/{chunk-7ZDPD5ZX.cjs → chunk-T4L7Q5FA.cjs} +7 -7
  173. package/dist/{chunk-7ZDPD5ZX.cjs.map → chunk-T4L7Q5FA.cjs.map} +1 -1
  174. package/dist/{chunk-NJ6MY6V5.js → chunk-T5BBZQ66.js} +3 -3
  175. package/dist/{chunk-NJ6MY6V5.js.map → chunk-T5BBZQ66.js.map} +1 -1
  176. package/dist/{chunk-2IZLKPUW.js → chunk-THLIL6PY.js} +3 -3
  177. package/dist/{chunk-2IZLKPUW.js.map → chunk-THLIL6PY.js.map} +1 -1
  178. package/dist/{chunk-SGFYA22I.cjs → chunk-TJCX4OML.cjs} +8 -8
  179. package/dist/{chunk-SGFYA22I.cjs.map → chunk-TJCX4OML.cjs.map} +1 -1
  180. package/dist/{chunk-N6IY47YA.cjs → chunk-TTSSUOEV.cjs} +8 -8
  181. package/dist/{chunk-N6IY47YA.cjs.map → chunk-TTSSUOEV.cjs.map} +1 -1
  182. package/dist/{chunk-5MCBWTIF.cjs → chunk-TYE5K5WV.cjs} +4 -4
  183. package/dist/{chunk-5MCBWTIF.cjs.map → chunk-TYE5K5WV.cjs.map} +1 -1
  184. package/dist/{chunk-VOKVG3ER.js → chunk-UBSH27C2.js} +4 -4
  185. package/dist/{chunk-VOKVG3ER.js.map → chunk-UBSH27C2.js.map} +1 -1
  186. package/dist/{chunk-TAXD5ADA.cjs → chunk-UEDTZYGI.cjs} +3 -3
  187. package/dist/{chunk-TAXD5ADA.cjs.map → chunk-UEDTZYGI.cjs.map} +1 -1
  188. package/dist/{chunk-UQ3VVR6A.cjs → chunk-UPWIJC6I.cjs} +3 -3
  189. package/dist/{chunk-UQ3VVR6A.cjs.map → chunk-UPWIJC6I.cjs.map} +1 -1
  190. package/dist/{chunk-S7WCHDBO.js → chunk-VCI2Y7ST.js} +3 -3
  191. package/dist/{chunk-S7WCHDBO.js.map → chunk-VCI2Y7ST.js.map} +1 -1
  192. package/dist/chunk-VINZZQBD.cjs +323 -0
  193. package/dist/chunk-VINZZQBD.cjs.map +1 -0
  194. package/dist/{chunk-OD47TTAW.cjs → chunk-VOQJHSXN.cjs} +9 -9
  195. package/dist/{chunk-OD47TTAW.cjs.map → chunk-VOQJHSXN.cjs.map} +1 -1
  196. package/dist/chunk-VPTASZ2O.cjs +171 -0
  197. package/dist/chunk-VPTASZ2O.cjs.map +1 -0
  198. package/dist/chunk-WXFGHDTV.cjs +896 -0
  199. package/dist/chunk-WXFGHDTV.cjs.map +1 -0
  200. package/dist/{chunk-VNYW4C4J.cjs → chunk-X6A27RGO.cjs} +4 -84
  201. package/dist/chunk-X6A27RGO.cjs.map +1 -0
  202. package/dist/chunk-XBTKZCZF.js +333 -0
  203. package/dist/chunk-XBTKZCZF.js.map +1 -0
  204. package/dist/chunk-XDIMTPZU.cjs +202 -0
  205. package/dist/chunk-XDIMTPZU.cjs.map +1 -0
  206. package/dist/chunk-XDU65GLW.js +21 -0
  207. package/dist/chunk-XDU65GLW.js.map +1 -0
  208. package/dist/chunk-XI74P5F2.cjs +424 -0
  209. package/dist/chunk-XI74P5F2.cjs.map +1 -0
  210. package/dist/{chunk-WIAQQNFU.cjs → chunk-XRVMYT5G.cjs} +106 -13
  211. package/dist/chunk-XRVMYT5G.cjs.map +1 -0
  212. package/dist/chunk-XVW5DPPP.js +429 -0
  213. package/dist/chunk-XVW5DPPP.js.map +1 -0
  214. package/dist/chunk-Y4E2WRUR.cjs +188 -0
  215. package/dist/chunk-Y4E2WRUR.cjs.map +1 -0
  216. package/dist/chunk-Y4QNLW7W.js +300 -0
  217. package/dist/chunk-Y4QNLW7W.js.map +1 -0
  218. package/dist/{chunk-6EN3IQQI.cjs → chunk-YRHBSSQ3.cjs} +6 -6
  219. package/dist/{chunk-6EN3IQQI.cjs.map → chunk-YRHBSSQ3.cjs.map} +1 -1
  220. package/dist/{chunk-KZFBQ7GY.js → chunk-YU55JD35.js} +3 -3
  221. package/dist/{chunk-KZFBQ7GY.js.map → chunk-YU55JD35.js.map} +1 -1
  222. package/dist/chunk-YW2AKBLS.cjs +23 -0
  223. package/dist/chunk-YW2AKBLS.cjs.map +1 -0
  224. package/dist/{chunk-ELPW32ZI.cjs → chunk-ZTMYKAVU.cjs} +45 -45
  225. package/dist/{chunk-ELPW32ZI.cjs.map → chunk-ZTMYKAVU.cjs.map} +1 -1
  226. package/dist/{chunk-3QGS6CXD.js → chunk-ZYL4SNOR.js} +3 -3
  227. package/dist/{chunk-3QGS6CXD.js.map → chunk-ZYL4SNOR.js.map} +1 -1
  228. package/dist/components/Alert/index.d.cts +1 -1
  229. package/dist/components/Alert/index.d.ts +1 -1
  230. package/dist/components/AlertDialog/index.cjs +6 -5
  231. package/dist/components/AlertDialog/index.d.cts +28 -3
  232. package/dist/components/AlertDialog/index.d.ts +28 -3
  233. package/dist/components/AlertDialog/index.js +5 -4
  234. package/dist/components/AudioRecorder/index.d.cts +2 -2
  235. package/dist/components/AudioRecorder/index.d.ts +2 -2
  236. package/dist/components/Autocomplete/index.d.cts +8 -2
  237. package/dist/components/Autocomplete/index.d.ts +8 -2
  238. package/dist/components/Avatar/index.d.cts +1 -1
  239. package/dist/components/Avatar/index.d.ts +1 -1
  240. package/dist/components/Badge/index.d.cts +1 -1
  241. package/dist/components/Badge/index.d.ts +1 -1
  242. package/dist/components/BoardView/index.cjs +24 -0
  243. package/dist/components/BoardView/index.cjs.map +1 -0
  244. package/dist/components/BoardView/index.d.cts +41 -0
  245. package/dist/components/BoardView/index.d.ts +41 -0
  246. package/dist/components/BoardView/index.js +7 -0
  247. package/dist/components/BoardView/index.js.map +1 -0
  248. package/dist/components/Button/index.cjs +4 -3
  249. package/dist/components/Button/index.d.cts +2 -1
  250. package/dist/components/Button/index.d.ts +2 -1
  251. package/dist/components/Button/index.js +2 -1
  252. package/dist/components/CalendarView/index.cjs +23 -0
  253. package/dist/components/CalendarView/index.cjs.map +1 -0
  254. package/dist/components/CalendarView/index.d.cts +39 -0
  255. package/dist/components/CalendarView/index.d.ts +39 -0
  256. package/dist/components/CalendarView/index.js +10 -0
  257. package/dist/components/CalendarView/index.js.map +1 -0
  258. package/dist/components/Card/index.d.cts +3 -3
  259. package/dist/components/Card/index.d.ts +3 -3
  260. package/dist/components/Collapsible/index.cjs +6 -6
  261. package/dist/components/Collapsible/index.js +3 -3
  262. package/dist/components/CountryCodeDropdown/index.cjs +5 -5
  263. package/dist/components/CountryCodeDropdown/index.js +2 -2
  264. package/dist/components/CustomizableDashboard/index.cjs +10 -9
  265. package/dist/components/CustomizableDashboard/index.js +3 -2
  266. package/dist/components/Dropdown/index.cjs +10 -10
  267. package/dist/components/Dropdown/index.d.cts +2 -1
  268. package/dist/components/Dropdown/index.d.ts +2 -1
  269. package/dist/components/Dropdown/index.js +3 -3
  270. package/dist/components/FloatingWindow/index.cjs +5 -4
  271. package/dist/components/FloatingWindow/index.js +3 -2
  272. package/dist/components/GanttView/index.cjs +20 -0
  273. package/dist/components/GanttView/index.cjs.map +1 -0
  274. package/dist/components/GanttView/index.d.cts +36 -0
  275. package/dist/components/GanttView/index.d.ts +36 -0
  276. package/dist/components/GanttView/index.js +7 -0
  277. package/dist/components/GanttView/index.js.map +1 -0
  278. package/dist/components/GlossaryTooltip/index.cjs +3 -3
  279. package/dist/components/GlossaryTooltip/index.js +2 -2
  280. package/dist/components/KeyboardShortcutsOverlay/index.cjs +5 -5
  281. package/dist/components/KeyboardShortcutsOverlay/index.js +3 -3
  282. package/dist/components/ListView/index.cjs +23 -0
  283. package/dist/components/ListView/index.cjs.map +1 -0
  284. package/dist/components/ListView/index.d.cts +124 -0
  285. package/dist/components/ListView/index.d.ts +124 -0
  286. package/dist/components/ListView/index.js +10 -0
  287. package/dist/components/ListView/index.js.map +1 -0
  288. package/dist/components/Markdown/index.cjs +20 -19
  289. package/dist/components/Markdown/index.js +8 -7
  290. package/dist/components/MediaEditor/index.cjs +15 -14
  291. package/dist/components/MediaEditor/index.d.cts +91 -2
  292. package/dist/components/MediaEditor/index.d.ts +91 -2
  293. package/dist/components/MediaEditor/index.js +10 -9
  294. package/dist/components/MediaFeed/index.cjs +26 -0
  295. package/dist/components/MediaFeed/index.cjs.map +1 -0
  296. package/dist/components/MediaFeed/index.d.cts +104 -0
  297. package/dist/components/MediaFeed/index.d.ts +104 -0
  298. package/dist/components/MediaFeed/index.js +17 -0
  299. package/dist/components/MediaFeed/index.js.map +1 -0
  300. package/dist/components/MediaPlayer/index.cjs +7 -6
  301. package/dist/components/MediaPlayer/index.d.cts +19 -1
  302. package/dist/components/MediaPlayer/index.d.ts +19 -1
  303. package/dist/components/MediaPlayer/index.js +4 -3
  304. package/dist/components/MegaMenu/index.cjs +6 -5
  305. package/dist/components/MegaMenu/index.js +3 -2
  306. package/dist/components/Modal/index.cjs +10 -10
  307. package/dist/components/Modal/index.js +2 -2
  308. package/dist/components/Pagination/index.d.cts +1 -1
  309. package/dist/components/Pagination/index.d.ts +1 -1
  310. package/dist/components/PhoneInput/index.d.cts +36 -3
  311. package/dist/components/PhoneInput/index.d.ts +36 -3
  312. package/dist/components/Progress/index.d.cts +1 -1
  313. package/dist/components/Progress/index.d.ts +1 -1
  314. package/dist/components/Q/index.d.cts +2 -2
  315. package/dist/components/Q/index.d.ts +2 -2
  316. package/dist/components/QuickAction/index.d.cts +1 -1
  317. package/dist/components/QuickAction/index.d.ts +1 -1
  318. package/dist/components/RadialExplorer/index.cjs +5 -4
  319. package/dist/components/RadialExplorer/index.js +4 -3
  320. package/dist/components/RecordButton/index.d.cts +1 -1
  321. package/dist/components/RecordButton/index.d.ts +1 -1
  322. package/dist/components/RichTextEditor/index.cjs +9 -8
  323. package/dist/components/RichTextEditor/index.d.cts +7 -2
  324. package/dist/components/RichTextEditor/index.d.ts +7 -2
  325. package/dist/components/RichTextEditor/index.js +6 -5
  326. package/dist/components/ScrollArea/index.d.cts +1 -1
  327. package/dist/components/ScrollArea/index.d.ts +1 -1
  328. package/dist/components/SectionSpyNav/index.cjs +4 -3
  329. package/dist/components/SectionSpyNav/index.js +3 -2
  330. package/dist/components/Select/index.cjs +4 -4
  331. package/dist/components/Select/index.d.cts +1 -2
  332. package/dist/components/Select/index.d.ts +1 -2
  333. package/dist/components/Select/index.js +2 -2
  334. package/dist/components/Skeleton/index.d.cts +1 -1
  335. package/dist/components/Skeleton/index.d.ts +1 -1
  336. package/dist/components/Slider/index.d.cts +2 -2
  337. package/dist/components/Slider/index.d.ts +2 -2
  338. package/dist/components/SliderCalculator/index.cjs +4 -4
  339. package/dist/components/SliderCalculator/index.js +2 -2
  340. package/dist/components/SourceTip/index.cjs +3 -3
  341. package/dist/components/SourceTip/index.js +2 -2
  342. package/dist/components/Spinner/index.d.cts +2 -2
  343. package/dist/components/Spinner/index.d.ts +2 -2
  344. package/dist/components/SuperChat/index.cjs +1406 -823
  345. package/dist/components/SuperChat/index.cjs.map +1 -1
  346. package/dist/components/SuperChat/index.d.cts +126 -8
  347. package/dist/components/SuperChat/index.d.ts +126 -8
  348. package/dist/components/SuperChat/index.js +1398 -815
  349. package/dist/components/SuperChat/index.js.map +1 -1
  350. package/dist/components/SuperChat/plugins/index.cjs +6 -6
  351. package/dist/components/SuperChat/plugins/index.d.cts +2 -3
  352. package/dist/components/SuperChat/plugins/index.d.ts +2 -3
  353. package/dist/components/SuperChat/plugins/index.js +5 -5
  354. package/dist/components/Text/index.d.cts +3 -3
  355. package/dist/components/Text/index.d.ts +3 -3
  356. package/dist/components/Textarea/index.d.cts +1 -2
  357. package/dist/components/Textarea/index.d.ts +1 -2
  358. package/dist/components/ThemeProvider/index.cjs +9 -9
  359. package/dist/components/ThemeProvider/index.d.cts +3 -1
  360. package/dist/components/ThemeProvider/index.d.ts +3 -1
  361. package/dist/components/ThemeProvider/index.js +3 -3
  362. package/dist/components/Tooltip/index.cjs +3 -3
  363. package/dist/components/Tooltip/index.js +2 -2
  364. package/dist/components/TranscriptView/index.d.cts +85 -4
  365. package/dist/components/TranscriptView/index.d.ts +85 -4
  366. package/dist/components/ViewSet/index.cjs +24 -0
  367. package/dist/components/ViewSet/index.cjs.map +1 -0
  368. package/dist/components/ViewSet/index.d.cts +200 -0
  369. package/dist/components/ViewSet/index.d.ts +200 -0
  370. package/dist/components/ViewSet/index.js +15 -0
  371. package/dist/components/ViewSet/index.js.map +1 -0
  372. package/dist/components/ViewSwitcher/index.cjs +20 -0
  373. package/dist/components/ViewSwitcher/index.cjs.map +1 -0
  374. package/dist/components/ViewSwitcher/index.d.cts +4 -0
  375. package/dist/components/ViewSwitcher/index.d.ts +4 -0
  376. package/dist/components/ViewSwitcher/index.js +7 -0
  377. package/dist/components/ViewSwitcher/index.js.map +1 -0
  378. package/dist/datavis.cjs +3 -2
  379. package/dist/datavis.cjs.map +1 -1
  380. package/dist/datavis.d.cts +167 -13
  381. package/dist/datavis.d.ts +167 -13
  382. package/dist/datavis.js +2 -1
  383. package/dist/datavis.js.map +1 -1
  384. package/dist/deck.cjs +3360 -0
  385. package/dist/deck.cjs.map +1 -0
  386. package/dist/deck.d.cts +712 -0
  387. package/dist/deck.d.ts +712 -0
  388. package/dist/deck.js +3316 -0
  389. package/dist/deck.js.map +1 -0
  390. package/dist/esheet.cjs +14 -13
  391. package/dist/esheet.cjs.map +1 -1
  392. package/dist/esheet.d.cts +183 -1
  393. package/dist/esheet.d.ts +183 -1
  394. package/dist/esheet.js +11 -10
  395. package/dist/esheet.js.map +1 -1
  396. package/dist/globe.cjs +2 -2
  397. package/dist/globe.js +1 -1
  398. package/dist/hooks/index.cjs +60 -27
  399. package/dist/hooks/index.d.cts +590 -31
  400. package/dist/hooks/index.d.ts +590 -31
  401. package/dist/hooks/index.js +6 -5
  402. package/dist/icons-wBacj6BW.d.cts +142 -0
  403. package/dist/icons-wBacj6BW.d.ts +142 -0
  404. package/dist/index-DoYYWsNc.d.cts +127 -0
  405. package/dist/index-DoYYWsNc.d.ts +127 -0
  406. package/dist/index.cjs +1420 -1048
  407. package/dist/index.cjs.map +1 -1
  408. package/dist/index.d.cts +8796 -482
  409. package/dist/index.d.ts +8796 -482
  410. package/dist/index.js +368 -232
  411. package/dist/index.js.map +1 -1
  412. package/dist/kerebron.cjs +58 -19
  413. package/dist/kerebron.cjs.map +1 -1
  414. package/dist/kerebron.css +115 -0
  415. package/dist/kerebron.d.cts +37 -0
  416. package/dist/kerebron.d.ts +37 -0
  417. package/dist/kerebron.js +58 -19
  418. package/dist/kerebron.js.map +1 -1
  419. package/dist/maps.cjs +160 -0
  420. package/dist/maps.cjs.map +1 -0
  421. package/dist/maps.d.cts +42 -0
  422. package/dist/maps.d.ts +42 -0
  423. package/dist/maps.js +138 -0
  424. package/dist/maps.js.map +1 -0
  425. package/dist/motion.cjs +7 -7
  426. package/dist/motion.d.cts +186 -2
  427. package/dist/motion.d.ts +186 -2
  428. package/dist/motion.js +2 -2
  429. package/dist/q.d.cts +25 -3
  430. package/dist/q.d.ts +25 -3
  431. package/dist/styles/effects.css +133 -0
  432. package/dist/styles/init.css +3 -0
  433. package/dist/styles.css +1 -1
  434. package/dist/tailwind-preset.cjs +4 -4
  435. package/dist/tailwind-preset.js +1 -1
  436. package/dist/templates.cjs +156 -0
  437. package/dist/templates.cjs.map +1 -0
  438. package/dist/templates.d.cts +734 -0
  439. package/dist/templates.d.ts +734 -0
  440. package/dist/templates.js +11 -0
  441. package/dist/templates.js.map +1 -0
  442. package/dist/types-Cx1FHLq2.d.cts +548 -0
  443. package/dist/types-Cx1FHLq2.d.ts +548 -0
  444. package/dist/types-DsdZvEI1.d.cts +92 -0
  445. package/dist/types-DsdZvEI1.d.ts +92 -0
  446. package/dist/utils/index.d.cts +13 -2
  447. package/dist/utils/index.d.ts +13 -2
  448. package/package.json +62 -13
  449. package/dist/Animated-XmH6k8pZ.d.cts +0 -188
  450. package/dist/Animated-XmH6k8pZ.d.ts +0 -188
  451. package/dist/CsvBlock-ROJCKJDP.cjs +0 -16
  452. package/dist/CsvBlock-UWPMTLE2.js +0 -7
  453. package/dist/HtmlPreviewBlock-DWFN6EUB.cjs +0 -16
  454. package/dist/HtmlPreviewBlock-ME5U3XNS.js +0 -7
  455. package/dist/MedicationEditor-Bp4NLy7y.d.cts +0 -352
  456. package/dist/MedicationEditor-Bp4NLy7y.d.ts +0 -352
  457. package/dist/MermaidBlock-2B6CPD6Y.js +0 -7
  458. package/dist/MermaidBlock-D2UC5M55.cjs +0 -16
  459. package/dist/SurveyBlock-4CD4AYMJ.cjs +0 -16
  460. package/dist/SurveyBlock-4DO62RBT.js +0 -7
  461. package/dist/chunk-22CYDCXA.js.map +0 -1
  462. package/dist/chunk-3T7QGLNB.js.map +0 -1
  463. package/dist/chunk-6HFFWEM3.cjs +0 -22
  464. package/dist/chunk-6HFFWEM3.cjs.map +0 -1
  465. package/dist/chunk-ACCAXVOG.js.map +0 -1
  466. package/dist/chunk-GOALNQZ2.js.map +0 -1
  467. package/dist/chunk-HB7C7NB5.js +0 -20
  468. package/dist/chunk-HB7C7NB5.js.map +0 -1
  469. package/dist/chunk-JHULS3EC.js.map +0 -1
  470. package/dist/chunk-JI244Y7C.js.map +0 -1
  471. package/dist/chunk-JYZW2PZS.cjs.map +0 -1
  472. package/dist/chunk-NV2CWBI2.cjs.map +0 -1
  473. package/dist/chunk-SQHMGT4W.js.map +0 -1
  474. package/dist/chunk-U42F3HLE.cjs.map +0 -1
  475. package/dist/chunk-VKELAMAZ.js.map +0 -1
  476. package/dist/chunk-VNYW4C4J.cjs.map +0 -1
  477. package/dist/chunk-WIAQQNFU.cjs.map +0 -1
  478. package/dist/chunk-WNAA6CLE.cjs.map +0 -1
  479. package/dist/chunk-WNJRS7Y7.cjs.map +0 -1
  480. package/dist/chunk-X4XPNTCZ.cjs.map +0 -1
  481. package/dist/chunk-XCP454Q6.js.map +0 -1
  482. package/dist/chunk-XEAT7XJG.cjs.map +0 -1
  483. package/dist/html-MdxqSzjD.d.cts +0 -13
  484. package/dist/html-MdxqSzjD.d.ts +0 -13
  485. package/dist/orderRows-BUJYgSc7.d.cts +0 -221
  486. package/dist/orderRows-BUJYgSc7.d.ts +0 -221
  487. package/dist/transcript-Cg7uSW-C.d.cts +0 -84
  488. package/dist/transcript-Cg7uSW-C.d.ts +0 -84
  489. package/dist/types-B97JNRNQ.d.cts +0 -251
  490. package/dist/types-CnPEwzlp.d.cts +0 -254
  491. package/dist/types-CnPEwzlp.d.ts +0 -254
  492. package/dist/types-gZXrfLj6.d.ts +0 -251
  493. package/dist/useAnchoredPosition-CKwLSQW8.d.cts +0 -76
  494. package/dist/useAnchoredPosition-CKwLSQW8.d.ts +0 -76
  495. package/dist/useTheme-B9SWu6ui.d.cts +0 -24
  496. package/dist/useTheme-B9SWu6ui.d.ts +0 -24
  497. package/dist/useTranscriptEdits-CGzlemHT.d.cts +0 -182
  498. package/dist/useTranscriptEdits-D32bLs0l.d.ts +0 -182
@@ -1,418 +1,235 @@
1
1
  import { TextRenderContext } from '../../chunk-I6CY5C6A.js';
2
2
  export { TextRenderContext, useTextRenderContext } from '../../chunk-I6CY5C6A.js';
3
- import { ChatBubble, MCPToolCallDisplay, AITypingIndicator, SparklesIcon, CloseIcon } from '../../chunk-22CYDCXA.js';
4
- import { notifyComposerMigrationOnce, ChatComposer } from '../../chunk-ACCAXVOG.js';
5
- import { Dropdown, DropdownSubmenu, DropdownItem } from '../../chunk-ZGRCSNPK.js';
3
+ import { ChatBubble, MCPToolCallDisplay, AITypingIndicator, SparklesIcon, ButtonGroup, CloseIcon, JumpToBottomButton } from '../../chunk-RM2HPQIC.js';
4
+ import { notifyComposerMigrationOnce, ChatComposer } from '../../chunk-CRS2CQWM.js';
5
+ import { MediaFeed } from '../../chunk-BNH4SXJB.js';
6
+ import '../../chunk-RISZWWEQ.js';
7
+ import { MediaPlayer } from '../../chunk-2JICT4A2.js';
8
+ import { Dropdown, DropdownSubmenu, DropdownItem } from '../../chunk-E2PBPQGS.js';
9
+ import '../../chunk-VVDE4CHU.js';
6
10
  import { Avatar } from '../../chunk-HZ4MBUC3.js';
7
11
  import '../../chunk-IQ4KQJAO.js';
8
- import '../../chunk-VVDE4CHU.js';
12
+ import { useStickToBottom, useStreamEndedBelowFold } from '../../chunk-BM35CACB.js';
13
+ import '../../chunk-GW4RFJZ5.js';
14
+ import '../../chunk-ENMXHZNE.js';
9
15
  import '../../chunk-6NZXWKUE.js';
10
16
  import '../../chunk-3IMM2PM4.js';
17
+ import '../../chunk-4SMSH4OY.js';
18
+ import '../../chunk-T4ME7QCT.js';
11
19
  import '../../chunk-62ZOA6PX.js';
12
20
  import '../../chunk-WSNMQQ4P.js';
13
- import '../../chunk-T4ME7QCT.js';
21
+ import '../../chunk-VSQF22GL.js';
14
22
  import '../../chunk-BKSPDTX4.js';
23
+ import { usePrefersReducedMotion } from '../../chunk-XDU65GLW.js';
24
+ import { Button } from '../../chunk-7YO7DNUV.js';
15
25
  import { Badge } from '../../chunk-BMSG4NBH.js';
16
- import '../../chunk-XCP454Q6.js';
26
+ import '../../chunk-GVM6DTR5.js';
27
+ import { AnimatedPresence, Animated } from '../../chunk-F4N67NAF.js';
17
28
  import { cn } from '../../chunk-TQONQSJO.js';
18
29
  import '../../chunk-PX6F3LHL.js';
19
- import * as React2 from 'react';
30
+ import * as React3 from 'react';
31
+ import { createElement } from 'react';
32
+ import { Ellipsis, Check, Clipboard, Pencil, Play, ArrowLeft } from 'lucide-react';
33
+ import { cva } from 'class-variance-authority';
34
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
20
35
  import Markdown, { defaultUrlTransform } from 'react-markdown';
21
36
  import remarkGfm from 'remark-gfm';
22
37
  import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
23
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
24
- import { cva } from 'class-variance-authority';
25
- import { Ellipsis, Check, Clipboard, Pencil } from 'lucide-react';
26
38
  import { useVirtualizer } from '@tanstack/react-virtual';
27
39
 
28
- function remarkPreserveLineBreaks() {
29
- const splitNode = (node) => {
30
- if (!node.children) return;
31
- const next = [];
32
- for (const child of node.children) {
33
- if (child.type === "text" && child.value && child.value.includes("\n")) {
34
- const segments = child.value.split("\n");
35
- segments.forEach((segment, i) => {
36
- if (i > 0) next.push({ type: "break" });
37
- if (segment) next.push({ type: "text", value: segment });
38
- });
39
- } else {
40
- splitNode(child);
41
- next.push(child);
42
- }
40
+ function MessageMedia({
41
+ attachment,
42
+ onOpen,
43
+ openLabel,
44
+ playLabel,
45
+ errorLabel,
46
+ retryLabel,
47
+ launchId
48
+ }) {
49
+ const playable = attachment.kind !== "image";
50
+ const actionLabel = playable ? playLabel : openLabel;
51
+ return /* @__PURE__ */ jsxs(
52
+ "div",
53
+ {
54
+ "data-slot": "superchat-message-media",
55
+ className: "mt-3 flex w-72 max-w-full flex-col gap-2",
56
+ children: [
57
+ attachment.title && /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: attachment.title }),
58
+ attachment.kind === "image" && attachment.src ? /* @__PURE__ */ jsx(
59
+ "img",
60
+ {
61
+ src: attachment.src,
62
+ alt: attachment.alt ?? attachment.title ?? "",
63
+ loading: "lazy",
64
+ className: "max-h-72 w-full rounded-lg object-contain"
65
+ }
66
+ ) : (attachment.kind === "video" || attachment.kind === "audio") && attachment.src ? (
67
+ // An opaque themed surface: the player's semi-transparent states
68
+ // (error, loading) must never compose onto a colored chat bubble.
69
+ /* @__PURE__ */ jsx("div", { className: "bg-background overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
70
+ MediaPlayer,
71
+ {
72
+ src: attachment.src,
73
+ kind: attachment.kind,
74
+ poster: attachment.poster,
75
+ "aria-label": attachment.alt ?? attachment.title ?? openLabel,
76
+ controls: !onOpen,
77
+ preload: "metadata",
78
+ labels: { error: errorLabel, retry: retryLabel },
79
+ className: "max-h-72"
80
+ }
81
+ ) })
82
+ ) : attachment.poster ? /* @__PURE__ */ jsx(
83
+ "img",
84
+ {
85
+ src: attachment.poster,
86
+ alt: attachment.alt ?? attachment.title ?? "",
87
+ loading: "lazy",
88
+ className: "max-h-72 w-full rounded-lg object-contain"
89
+ }
90
+ ) : null,
91
+ attachment.caption && /* @__PURE__ */ jsx("p", { className: "text-sm", children: attachment.caption }),
92
+ onOpen && /* @__PURE__ */ jsx(ButtonGroup, { children: /* @__PURE__ */ jsx(
93
+ Button,
94
+ {
95
+ "data-media-launch-id": launchId,
96
+ variant: "secondary",
97
+ size: "sm",
98
+ leftIcon: playable ? /* @__PURE__ */ jsx(Play, { className: "size-4", "aria-hidden": "true" }) : void 0,
99
+ "aria-label": playable && attachment.title ? `${playLabel} ${attachment.title}` : actionLabel,
100
+ onClick: () => onOpen(playable),
101
+ children: actionLabel
102
+ }
103
+ ) })
104
+ ]
43
105
  }
44
- node.children = next;
45
- };
46
- return (tree) => splitNode(tree);
106
+ );
47
107
  }
48
- function baseSanitizeSchema() {
49
- const schema = JSON.parse(JSON.stringify(defaultSchema));
50
- const attributes = schema.attributes ?? {};
51
- const allowClass = (tag) => {
52
- const existing = attributes[tag] ?? [];
53
- const withoutClass = existing.filter(
54
- (a) => !(Array.isArray(a) && a[0] === "className")
55
- );
56
- attributes[tag] = [...withoutClass, "className"];
57
- };
58
- allowClass("code");
59
- allowClass("pre");
60
- allowClass("span");
61
- allowClass("div");
62
- schema.attributes = attributes;
63
- return schema;
108
+ function formatTime(time) {
109
+ return new Date(time).toLocaleTimeString(void 0, {
110
+ hour: "numeric",
111
+ minute: "2-digit"
112
+ });
64
113
  }
65
- function mergeSanitizeSchema(base, extra) {
66
- if (!extra) return base;
67
- const out = { ...base };
68
- if (Array.isArray(extra.tagNames)) {
69
- const a = base.tagNames ?? [];
70
- out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
114
+ function byTime(a, b) {
115
+ return new Date(a.time).getTime() - new Date(b.time).getTime();
116
+ }
117
+ function lastActivityOf(c) {
118
+ if (c.lastActivity) return new Date(c.lastActivity).getTime();
119
+ const last = lastMessageByTime(c.thread);
120
+ return last ? new Date(last.time).getTime() : 0;
121
+ }
122
+ function escapeRegExp(value) {
123
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
124
+ }
125
+ function detectMentions(text, participants) {
126
+ const ids = [];
127
+ for (const p of participants) {
128
+ if (p.kind === "system") continue;
129
+ const token = "@" + p.name.split(" ")[0];
130
+ const pattern = new RegExp(
131
+ `(?<![\\w@])${escapeRegExp(token)}(?![\\w])`,
132
+ "i"
133
+ );
134
+ if (pattern.test(text)) ids.push(p.id);
71
135
  }
72
- if (extra.attributes && typeof extra.attributes === "object") {
73
- const baseAttrs = {
74
- ...base.attributes ?? {}
75
- };
76
- for (const [tag, attrs] of Object.entries(
77
- extra.attributes
78
- )) {
79
- baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
136
+ return ids;
137
+ }
138
+ function lastMessageByTime(thread) {
139
+ let latest;
140
+ let latestTime = -Infinity;
141
+ for (const message of thread) {
142
+ const t = new Date(message.time).getTime();
143
+ if (t >= latestTime) {
144
+ latest = message;
145
+ latestTime = t;
80
146
  }
81
- out.attributes = baseAttrs;
82
147
  }
83
- if (extra.protocols && typeof extra.protocols === "object") {
84
- const baseProtocols = {
85
- ...base.protocols ?? {}
86
- };
87
- for (const [attr, protocols] of Object.entries(
88
- extra.protocols
89
- )) {
90
- baseProtocols[attr] = Array.from(
91
- /* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
92
- );
148
+ return latest;
149
+ }
150
+ function parseHexColor(value) {
151
+ const hex = value.trim();
152
+ if (!/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(hex)) return null;
153
+ const normalized = hex.length === 4 ? "#" + [...hex.slice(1)].map((char) => char + char).join("") : hex;
154
+ return [1, 3, 5].map(
155
+ (start) => parseInt(normalized.slice(start, start + 2), 16)
156
+ );
157
+ }
158
+ function relativeLuminanceChannel(channel) {
159
+ const normalized = channel / 255;
160
+ return normalized <= 0.03928 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;
161
+ }
162
+ function relativeLuminance(value) {
163
+ const rgb = parseHexColor(value);
164
+ if (!rgb) return null;
165
+ const [red, green, blue] = rgb;
166
+ return 0.2126 * relativeLuminanceChannel(red) + 0.7152 * relativeLuminanceChannel(green) + 0.0722 * relativeLuminanceChannel(blue);
167
+ }
168
+ function contrastRatio(foreground, background) {
169
+ const foregroundLuminance = relativeLuminance(foreground);
170
+ const backgroundLuminance = relativeLuminance(background);
171
+ if (foregroundLuminance === null || backgroundLuminance === null) return null;
172
+ const lighter = Math.max(foregroundLuminance, backgroundLuminance);
173
+ const darker = Math.min(foregroundLuminance, backgroundLuminance);
174
+ return (lighter + 0.05) / (darker + 0.05);
175
+ }
176
+ function minimumContrastRatio(value, backgrounds) {
177
+ const contrasts = backgrounds.map((background) => contrastRatio(value, background)).filter((contrast) => contrast !== null);
178
+ if (contrasts.length !== backgrounds.length) return null;
179
+ return Math.min(...contrasts);
180
+ }
181
+ function accessibleAccentTextColor(value) {
182
+ if (!value) return void 0;
183
+ const contrast = minimumContrastRatio(value, ["#f5f5f5", "#262626"]);
184
+ if (contrast === null) return value;
185
+ return contrast < 4.5 ? void 0 : value;
186
+ }
187
+ function ParticipantAvatar({
188
+ participant
189
+ }) {
190
+ const isAgent = participant?.kind === "agent";
191
+ const backgroundColor = participant?.color ?? (isAgent ? "var(--mieweb-primary-700, #1f2937)" : "#64748b");
192
+ return /* @__PURE__ */ jsx(
193
+ Avatar,
194
+ {
195
+ size: "xs",
196
+ src: participant?.avatar,
197
+ alt: "",
198
+ name: participant?.name ?? "?",
199
+ fallback: isAgent ? /* @__PURE__ */ jsx(SparklesIcon, { size: "sm" }) : void 0,
200
+ style: { backgroundColor },
201
+ "aria-hidden": "true",
202
+ className: "shrink-0"
93
203
  }
94
- out.protocols = baseProtocols;
95
- }
96
- for (const [k, v] of Object.entries(extra)) {
97
- if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
98
- out[k] = v;
99
- }
100
- return out;
204
+ );
101
205
  }
102
- function baseComponents() {
103
- return {
104
- a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
105
- "a",
206
+ function ReferenceChip({
207
+ reference,
208
+ linkBuilder,
209
+ onReferenceClick
210
+ }) {
211
+ const href = linkBuilder?.(reference);
212
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
213
+ /* @__PURE__ */ jsx(
214
+ Badge,
106
215
  {
107
- ...props,
108
- className: cn(
109
- "text-primary-800 hover:text-primary-900 dark:text-primary-300 underline underline-offset-2",
110
- props.className
111
- ),
112
- target: props.target ?? "_blank",
113
- rel: props.rel ?? "noopener noreferrer",
114
- children
216
+ variant: "default",
217
+ size: "sm",
218
+ className: "rounded px-1.5 text-[10px] font-semibold tracking-wide uppercase",
219
+ children: reference.refType
115
220
  }
116
221
  ),
117
- pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
118
- "pre",
222
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: reference.title })
223
+ ] });
224
+ const className = "inline-flex max-w-full items-center gap-2 rounded-lg border border-neutral-200 bg-white px-3 py-1.5 text-sm text-neutral-700 hover:border-primary-300 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200";
225
+ if (href) {
226
+ return /* @__PURE__ */ jsx(
227
+ "a",
119
228
  {
120
- ...props,
121
- tabIndex: 0,
122
- className: cn(
123
- "overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
124
- props.className
125
- )
126
- }
127
- ),
128
- code: ({ node: _node, ...props }) => {
129
- const isBlock = typeof props.className === "string" && props.className.includes("language-");
130
- return /* @__PURE__ */ jsx(
131
- "code",
132
- {
133
- ...props,
134
- className: cn(
135
- !isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] text-neutral-800 dark:bg-neutral-700 dark:text-neutral-100",
136
- props.className
137
- )
138
- }
139
- );
140
- },
141
- input: ({ node: _node, ...props }) => {
142
- if (props.type === "checkbox") {
143
- return /* @__PURE__ */ jsx(
144
- "input",
145
- {
146
- ...props,
147
- "aria-label": props["aria-label"] ?? (props["aria-labelledby"] ? void 0 : "Task list item")
148
- }
149
- );
150
- }
151
- return /* @__PURE__ */ jsx("input", { ...props });
152
- },
153
- table: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("div", { className: "my-2 overflow-x-auto", children: /* @__PURE__ */ jsx(
154
- "table",
155
- {
156
- ...props,
157
- className: cn(
158
- "w-full border-collapse text-sm [&_td]:border [&_td]:border-neutral-200 [&_td]:px-2 [&_td]:py-1 dark:[&_td]:border-neutral-700 [&_th]:border [&_th]:border-neutral-200 [&_th]:px-2 [&_th]:py-1 [&_th]:text-start dark:[&_th]:border-neutral-700",
159
- props.className
160
- )
161
- }
162
- ) }),
163
- // Tailwind's preflight resets list markers/padding; restore them explicitly
164
- // so bullets/numbers show without depending on the typography plugin.
165
- ul: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("ul", { ...props, className: cn("list-disc ps-5", props.className) }),
166
- ol: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("ol", { ...props, className: cn("list-decimal ps-5", props.className) }),
167
- li: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("li", { ...props, className: cn("ps-1", props.className) }),
168
- // Preflight also flattens headings to body size/weight; restore a sensible
169
- // hierarchy without depending on the typography plugin.
170
- h1: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
171
- "h1",
172
- {
173
- ...props,
174
- className: cn("mt-3 mb-1 text-xl font-semibold", props.className),
175
- children
176
- }
177
- ),
178
- h2: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
179
- "h2",
180
- {
181
- ...props,
182
- className: cn("mt-3 mb-1 text-lg font-semibold", props.className),
183
- children
184
- }
185
- ),
186
- h3: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
187
- "h3",
188
- {
189
- ...props,
190
- className: cn("mt-2 mb-1 text-base font-semibold", props.className),
191
- children
192
- }
193
- ),
194
- h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
195
- "h4",
196
- {
197
- ...props,
198
- className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
199
- children
200
- }
201
- ),
202
- h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
203
- "h5",
204
- {
205
- ...props,
206
- className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
207
- children
208
- }
209
- ),
210
- h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
211
- "h6",
212
- {
213
- ...props,
214
- className: cn(
215
- "mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
216
- props.className
217
- ),
218
- children
219
- }
220
- ),
221
- hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
222
- "hr",
223
- {
224
- ...props,
225
- className: cn(
226
- "my-2 border-neutral-300 dark:border-neutral-600",
227
- props.className
228
- )
229
- }
230
- )
231
- };
232
- }
233
- function createMarkdownRenderer(options = {}) {
234
- const { plugins = [], trusted = false } = options;
235
- const remarkPlugins = [
236
- remarkGfm,
237
- remarkPreserveLineBreaks,
238
- ...plugins.flatMap((p) => p.remarkPlugins ?? [])
239
- ];
240
- const pluginRehype = plugins.flatMap(
241
- (p) => p.rehypePlugins ?? []
242
- );
243
- const sanitizeSchema = plugins.reduce(
244
- (acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
245
- baseSanitizeSchema()
246
- );
247
- const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize, sanitizeSchema]];
248
- const components = plugins.reduce(
249
- (acc, p) => ({ ...acc, ...p.components }),
250
- baseComponents()
251
- );
252
- const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsx(
253
- MarkdownContent,
254
- {
255
- text,
256
- messageId: ctx.messageId,
257
- streaming: ctx.streaming,
258
- remarkPlugins,
259
- rehypePlugins,
260
- components
261
- },
262
- ctx.messageId
263
- );
264
- return MarkdownRenderer;
265
- }
266
- var transformUrl = (url, key, node) => {
267
- if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
268
- return url;
269
- }
270
- return defaultUrlTransform(url);
271
- };
272
- var MarkdownContent = React2.memo(function MarkdownContent2({
273
- text,
274
- messageId,
275
- streaming,
276
- remarkPlugins,
277
- rehypePlugins,
278
- components
279
- }) {
280
- return /* @__PURE__ */ jsx(TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsx(
281
- Markdown,
282
- {
283
- remarkPlugins,
284
- rehypePlugins,
285
- urlTransform: transformUrl,
286
- components,
287
- children: text
288
- }
289
- ) });
290
- });
291
- function formatTime(time) {
292
- return new Date(time).toLocaleTimeString(void 0, {
293
- hour: "numeric",
294
- minute: "2-digit"
295
- });
296
- }
297
- function byTime(a, b) {
298
- return new Date(a.time).getTime() - new Date(b.time).getTime();
299
- }
300
- function lastActivityOf(c) {
301
- if (c.lastActivity) return new Date(c.lastActivity).getTime();
302
- const last = lastMessageByTime(c.thread);
303
- return last ? new Date(last.time).getTime() : 0;
304
- }
305
- function escapeRegExp(value) {
306
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
307
- }
308
- function detectMentions(text, participants) {
309
- const ids = [];
310
- for (const p of participants) {
311
- if (p.kind === "system") continue;
312
- const token = "@" + p.name.split(" ")[0];
313
- const pattern = new RegExp(
314
- `(?<![\\w@])${escapeRegExp(token)}(?![\\w])`,
315
- "i"
316
- );
317
- if (pattern.test(text)) ids.push(p.id);
318
- }
319
- return ids;
320
- }
321
- function lastMessageByTime(thread) {
322
- let latest;
323
- let latestTime = -Infinity;
324
- for (const message of thread) {
325
- const t = new Date(message.time).getTime();
326
- if (t >= latestTime) {
327
- latest = message;
328
- latestTime = t;
329
- }
330
- }
331
- return latest;
332
- }
333
- function parseHexColor(value) {
334
- const hex = value.trim();
335
- if (!/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(hex)) return null;
336
- const normalized = hex.length === 4 ? "#" + [...hex.slice(1)].map((char) => char + char).join("") : hex;
337
- return [1, 3, 5].map(
338
- (start) => parseInt(normalized.slice(start, start + 2), 16)
339
- );
340
- }
341
- function relativeLuminanceChannel(channel) {
342
- const normalized = channel / 255;
343
- return normalized <= 0.03928 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;
344
- }
345
- function relativeLuminance(value) {
346
- const rgb = parseHexColor(value);
347
- if (!rgb) return null;
348
- const [red, green, blue] = rgb;
349
- return 0.2126 * relativeLuminanceChannel(red) + 0.7152 * relativeLuminanceChannel(green) + 0.0722 * relativeLuminanceChannel(blue);
350
- }
351
- function contrastRatio(foreground, background) {
352
- const foregroundLuminance = relativeLuminance(foreground);
353
- const backgroundLuminance = relativeLuminance(background);
354
- if (foregroundLuminance === null || backgroundLuminance === null) return null;
355
- const lighter = Math.max(foregroundLuminance, backgroundLuminance);
356
- const darker = Math.min(foregroundLuminance, backgroundLuminance);
357
- return (lighter + 0.05) / (darker + 0.05);
358
- }
359
- function minimumContrastRatio(value, backgrounds) {
360
- const contrasts = backgrounds.map((background) => contrastRatio(value, background)).filter((contrast) => contrast !== null);
361
- if (contrasts.length !== backgrounds.length) return null;
362
- return Math.min(...contrasts);
363
- }
364
- function accessibleAccentTextColor(value) {
365
- if (!value) return void 0;
366
- const contrast = minimumContrastRatio(value, ["#f5f5f5", "#262626"]);
367
- if (contrast === null) return value;
368
- return contrast < 4.5 ? void 0 : value;
369
- }
370
- function ParticipantAvatar({
371
- participant
372
- }) {
373
- const isAgent = participant?.kind === "agent";
374
- const backgroundColor = participant?.color ?? (isAgent ? "var(--mieweb-primary-700, #1f2937)" : "#64748b");
375
- return /* @__PURE__ */ jsx(
376
- Avatar,
377
- {
378
- size: "xs",
379
- src: participant?.avatar,
380
- alt: "",
381
- name: participant?.name ?? "?",
382
- fallback: isAgent ? /* @__PURE__ */ jsx(SparklesIcon, { size: "sm" }) : void 0,
383
- style: { backgroundColor },
384
- "aria-hidden": "true",
385
- className: "shrink-0"
386
- }
387
- );
388
- }
389
- function ReferenceChip({
390
- reference,
391
- linkBuilder,
392
- onReferenceClick
393
- }) {
394
- const href = linkBuilder?.(reference);
395
- const content = /* @__PURE__ */ jsxs(Fragment, { children: [
396
- /* @__PURE__ */ jsx(
397
- Badge,
398
- {
399
- variant: "default",
400
- size: "sm",
401
- className: "rounded px-1.5 text-[10px] font-semibold tracking-wide uppercase",
402
- children: reference.refType
403
- }
404
- ),
405
- /* @__PURE__ */ jsx("span", { className: "truncate", children: reference.title })
406
- ] });
407
- const className = "inline-flex max-w-full items-center gap-2 rounded-lg border border-neutral-200 bg-white px-3 py-1.5 text-sm text-neutral-700 hover:border-primary-300 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200";
408
- if (href) {
409
- return /* @__PURE__ */ jsx(
410
- "a",
411
- {
412
- href,
413
- className,
414
- onClick: () => onReferenceClick?.(reference),
415
- children: content
229
+ href,
230
+ className,
231
+ onClick: () => onReferenceClick?.(reference),
232
+ children: content
416
233
  }
417
234
  );
418
235
  }
@@ -472,11 +289,11 @@ function useMessageCopy({
472
289
  getText,
473
290
  defaultFormat
474
291
  }) {
475
- const [copied, setCopied] = React2.useState(false);
476
- const copiedTimer = React2.useRef(
292
+ const [copied, setCopied] = React3.useState(false);
293
+ const copiedTimer = React3.useRef(
477
294
  void 0
478
295
  );
479
- React2.useEffect(() => () => window.clearTimeout(copiedTimer.current), []);
296
+ React3.useEffect(() => () => window.clearTimeout(copiedTimer.current), []);
480
297
  const flash = () => {
481
298
  setCopied(true);
482
299
  window.clearTimeout(copiedTimer.current);
@@ -529,7 +346,7 @@ function FooterActionButton({
529
346
  action,
530
347
  isSelf
531
348
  }) {
532
- const [open, setOpen] = React2.useState(false);
349
+ const [open, setOpen] = React3.useState(false);
533
350
  const onClickCapture = action.submenu ? (e) => {
534
351
  if (e.metaKey || e.ctrlKey) {
535
352
  e.preventDefault();
@@ -572,17 +389,13 @@ function FooterActionButton({
572
389
  }
573
390
  );
574
391
  }
575
- var MessageActionsBar = React2.forwardRef(function MessageActionsBar2({ actions, isSelf }, ref) {
392
+ var MessageActionsBar = React3.forwardRef(function MessageActionsBar2({ actions, isSelf }, ref) {
576
393
  return /* @__PURE__ */ jsx(
577
394
  "div",
578
395
  {
579
396
  ref,
580
397
  "data-slot": "superchat-message-actions",
581
- className: cn(
582
- "flex items-center gap-0.5",
583
- isSelf && "justify-end",
584
- actionRevealClass
585
- ),
398
+ className: cn("flex flex-col items-center gap-0.5", actionRevealClass),
586
399
  children: actions.map((action) => /* @__PURE__ */ jsx(FooterActionButton, { action, isSelf }, action.id))
587
400
  }
588
401
  );
@@ -592,7 +405,7 @@ function MessageOverflowMenu({
592
405
  actions,
593
406
  footerVisible
594
407
  }) {
595
- const [open, setOpen] = React2.useState(false);
408
+ const [open, setOpen] = React3.useState(false);
596
409
  const select = (fn) => {
597
410
  setOpen(false);
598
411
  fn();
@@ -601,7 +414,7 @@ function MessageOverflowMenu({
601
414
  "div",
602
415
  {
603
416
  className: cn(
604
- "sticky bottom-2 shrink-0 self-end transition-opacity",
417
+ "sticky bottom-2 mt-auto shrink-0 transition-opacity",
605
418
  // Rich content (e.g. NITRO tables) layers internals up to z-50, so the
606
419
  // open menu's stacking context must clear that.
607
420
  open ? "z-[60]" : "z-10",
@@ -645,7 +458,7 @@ function MessageOverflowMenu({
645
458
  }
646
459
  );
647
460
  }
648
- var MessageRow = React2.memo(function MessageRow2({
461
+ var MessageRow = React3.memo(function MessageRow2({
649
462
  message,
650
463
  participant,
651
464
  isSelf,
@@ -654,21 +467,27 @@ var MessageRow = React2.memo(function MessageRow2({
654
467
  onReferenceClick,
655
468
  editable,
656
469
  onMessageEdited,
657
- defaultCopyFormat = "rich"
470
+ defaultCopyFormat = "rich",
471
+ onOpenMedia,
472
+ openMediaLabel = "Open in media feed",
473
+ playMediaLabel = "Play",
474
+ mediaErrorLabel,
475
+ mediaRetryLabel
658
476
  }) {
659
477
  const streaming = message.status === "streaming";
660
- const hasBody = !!message.text || (message.content?.length ?? 0) > 0;
661
- const [isEditing, setIsEditing] = React2.useState(false);
662
- const [draft, setDraft] = React2.useState(message.text ?? "");
663
- const editRef = React2.useRef(null);
664
- const bubbleRef = React2.useRef(null);
665
- const autosize = React2.useCallback(() => {
478
+ const hasBody = !!message.text || (message.content?.length ?? 0) > 0 || (message.media?.length ?? 0) > 0;
479
+ const [isEditing, setIsEditing] = React3.useState(false);
480
+ const [draft, setDraft] = React3.useState(message.text ?? "");
481
+ const [editMinWidth, setEditMinWidth] = React3.useState();
482
+ const editRef = React3.useRef(null);
483
+ const bubbleRef = React3.useRef(null);
484
+ const autosize = React3.useCallback(() => {
666
485
  const el = editRef.current;
667
486
  if (!el) return;
668
487
  el.style.height = "auto";
669
488
  el.style.height = `${el.scrollHeight}px`;
670
489
  }, []);
671
- React2.useEffect(() => {
490
+ React3.useEffect(() => {
672
491
  if (!isEditing) return;
673
492
  const el = editRef.current;
674
493
  if (!el) return;
@@ -683,337 +502,662 @@ var MessageRow = React2.memo(function MessageRow2({
683
502
  ${block.text}
684
503
  \`\`\``;
685
504
  }
686
- if ((block.type === "text" || block.type === "thinking") && block.text) {
687
- return block.text;
505
+ if ((block.type === "text" || block.type === "thinking") && block.text) {
506
+ return block.text;
507
+ }
508
+ return "";
509
+ }).filter(Boolean).join("\n\n") ?? "";
510
+ const canCopy = !isEditing && (!!message.content?.length || typeof message.text === "string" && message.text.length > 0);
511
+ const showEditAction = canEdit && !isEditing;
512
+ const actionCount = (canCopy ? 1 : 0) + (showEditAction ? 1 : 0);
513
+ const hasActions = actionCount > 0;
514
+ const collapseToMenu = actionCount > 1;
515
+ const copy = useMessageCopy({
516
+ markdown: markdownSource,
517
+ getHtml: () => bubbleRef.current?.innerHTML ?? "",
518
+ getText: () => bubbleRef.current?.textContent ?? "",
519
+ defaultFormat: defaultCopyFormat
520
+ });
521
+ const actionsBarRef = React3.useRef(null);
522
+ const [footerVisible, setFooterVisible] = React3.useState(true);
523
+ React3.useEffect(() => {
524
+ const el = actionsBarRef.current;
525
+ if (!el || typeof globalThis.IntersectionObserver === "undefined") return;
526
+ const observer = new globalThis.IntersectionObserver(([entry]) => {
527
+ setFooterVisible(entry?.isIntersecting ?? false);
528
+ });
529
+ observer.observe(el);
530
+ return () => observer.disconnect();
531
+ }, [hasActions, collapseToMenu]);
532
+ if (message.type === "system") {
533
+ return /* @__PURE__ */ jsx(
534
+ "div",
535
+ {
536
+ "data-slot": "superchat-system-message",
537
+ role: "status",
538
+ className: "my-1 text-center text-xs text-neutral-500 dark:text-neutral-400",
539
+ children: message.text
540
+ }
541
+ );
542
+ }
543
+ if (message.type === "ref" && message.ref) {
544
+ return /* @__PURE__ */ jsx(
545
+ "div",
546
+ {
547
+ "data-slot": "superchat-reference",
548
+ className: cn("flex", isSelf && "justify-end"),
549
+ children: /* @__PURE__ */ jsx(
550
+ ReferenceChip,
551
+ {
552
+ reference: message.ref,
553
+ linkBuilder,
554
+ onReferenceClick
555
+ }
556
+ )
557
+ }
558
+ );
559
+ }
560
+ const accent = participant?.color;
561
+ const accentTextColor = accessibleAccentTextColor(accent);
562
+ const authorName = participant?.name ?? "Unknown";
563
+ const startEdit = () => {
564
+ const el = bubbleRef.current;
565
+ if (el) {
566
+ const cs = getComputedStyle(el);
567
+ const contentWidth = el.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight);
568
+ setEditMinWidth(contentWidth > 0 ? contentWidth : void 0);
569
+ }
570
+ setDraft(message.text ?? "");
571
+ setIsEditing(true);
572
+ };
573
+ const cancelEdit = () => setIsEditing(false);
574
+ const saveEdit = () => {
575
+ const next = draft.trim();
576
+ if (next && next !== message.text) onMessageEdited?.(message.id, next);
577
+ setIsEditing(false);
578
+ };
579
+ const handleEditPaste = (e) => {
580
+ const files = Array.from(e.clipboardData.items).filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((f) => f !== null);
581
+ if (files.length === 0) return;
582
+ e.preventDefault();
583
+ const el = e.currentTarget;
584
+ const start = el.selectionStart ?? draft.length;
585
+ const end = el.selectionEnd ?? draft.length;
586
+ Promise.all(
587
+ files.map(
588
+ (file, i) => new Promise((resolve) => {
589
+ const reader = new window.FileReader();
590
+ reader.onload = () => {
591
+ const dataUrl = typeof reader.result === "string" ? reader.result : "";
592
+ const name = file.name || `pasted-image-${i + 1}.png`;
593
+ resolve(dataUrl ? `![${name}](${dataUrl})` : "");
594
+ };
595
+ reader.readAsDataURL(file);
596
+ })
597
+ )
598
+ ).then((snippets) => {
599
+ const insert = snippets.filter(Boolean).join("\n");
600
+ if (!insert) return;
601
+ el.focus();
602
+ el.setSelectionRange(start, end);
603
+ const text = `${insert}
604
+ `;
605
+ const inserted = typeof document !== "undefined" && typeof document.execCommand === "function" && document.execCommand("insertText", false, text);
606
+ if (!inserted) {
607
+ setDraft((prev) => `${prev.slice(0, start)}${text}${prev.slice(end)}`);
608
+ }
609
+ requestAnimationFrame(autosize);
610
+ });
611
+ };
612
+ const actions = [
613
+ ...canCopy ? [
614
+ {
615
+ id: "copy",
616
+ label: "Copy message",
617
+ title: "Copy message (\u2318/Ctrl-click: default format)",
618
+ icon: copy.copied ? /* @__PURE__ */ jsx(Check, { size: 14, "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Clipboard, { size: 14, "aria-hidden": "true" }),
619
+ onSelect: copy.copyDefault,
620
+ submenu: {
621
+ label: "Copy as",
622
+ items: [
623
+ {
624
+ id: "copy-rich",
625
+ label: "Copy as rich text",
626
+ description: "Rich text + Markdown",
627
+ onSelect: copy.copyRich
628
+ },
629
+ {
630
+ id: "copy-markdown",
631
+ label: "Copy as Markdown",
632
+ onSelect: copy.copyMarkdown
633
+ },
634
+ {
635
+ id: "copy-plain",
636
+ label: "Copy as plain text",
637
+ onSelect: copy.copyPlain
638
+ }
639
+ ]
640
+ }
641
+ }
642
+ ] : [],
643
+ ...showEditAction ? [
644
+ {
645
+ id: "edit",
646
+ label: "Edit message",
647
+ icon: /* @__PURE__ */ jsx(Pencil, { size: 14, "aria-hidden": "true" }),
648
+ onSelect: startEdit
649
+ }
650
+ ] : []
651
+ ];
652
+ return /* @__PURE__ */ jsxs(
653
+ "div",
654
+ {
655
+ "data-slot": "superchat-message",
656
+ role: "article",
657
+ "aria-label": `${authorName}, ${formatTime(message.time)}`,
658
+ className: cn(
659
+ "group flex gap-2",
660
+ isSelf ? "flex-row-reverse" : "flex-row"
661
+ ),
662
+ children: [
663
+ /* @__PURE__ */ jsxs(
664
+ "div",
665
+ {
666
+ "data-slot": "superchat-message-gutter",
667
+ className: "flex shrink-0 flex-col items-center gap-1",
668
+ children: [
669
+ /* @__PURE__ */ jsx(ParticipantAvatar, { participant }),
670
+ hasActions && /* @__PURE__ */ jsxs(Fragment, { children: [
671
+ /* @__PURE__ */ jsx(
672
+ MessageOverflowMenu,
673
+ {
674
+ isSelf,
675
+ actions,
676
+ footerVisible: collapseToMenu ? false : footerVisible
677
+ }
678
+ ),
679
+ !collapseToMenu && /* @__PURE__ */ jsx(
680
+ MessageActionsBar,
681
+ {
682
+ ref: actionsBarRef,
683
+ actions,
684
+ isSelf
685
+ }
686
+ )
687
+ ] })
688
+ ]
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsxs(
692
+ "div",
693
+ {
694
+ className: cn(
695
+ "flex min-w-0 flex-1 flex-col gap-1",
696
+ isSelf && "items-end"
697
+ ),
698
+ children: [
699
+ /* @__PURE__ */ jsxs(
700
+ "div",
701
+ {
702
+ "data-slot": "superchat-message-meta",
703
+ className: "flex items-baseline gap-2",
704
+ children: [
705
+ /* @__PURE__ */ jsx(
706
+ "span",
707
+ {
708
+ className: "text-xs font-medium",
709
+ style: accentTextColor ? { color: accentTextColor } : void 0,
710
+ children: authorName
711
+ }
712
+ ),
713
+ participant?.role && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: participant.role }),
714
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: formatTime(message.time) }),
715
+ message.editedAt && /* @__PURE__ */ jsx(
716
+ "span",
717
+ {
718
+ "data-slot": "superchat-edited-indicator",
719
+ className: "text-[10px] text-neutral-500 dark:text-neutral-400",
720
+ title: `Edited ${formatTime(message.editedAt)}`,
721
+ children: "(edited)"
722
+ }
723
+ )
724
+ ]
725
+ }
726
+ ),
727
+ /* @__PURE__ */ jsx(
728
+ "div",
729
+ {
730
+ className: cn(
731
+ "flex w-full items-center gap-1",
732
+ isSelf ? "flex-row-reverse" : "flex-row"
733
+ ),
734
+ children: /* @__PURE__ */ jsx(
735
+ ChatBubble,
736
+ {
737
+ ref: bubbleRef,
738
+ "data-slot": "superchat-bubble",
739
+ variant: isSelf ? "user" : "assistant",
740
+ hasError: message.status === "error",
741
+ className: "text-sm has-[[data-slot=superchat-nitro-table]]:w-full has-[[data-slot=superchat-nitro-table]]:max-w-full",
742
+ children: isEditing ? /* @__PURE__ */ jsxs(
743
+ "div",
744
+ {
745
+ "data-slot": "superchat-message-editor",
746
+ className: "flex w-80 max-w-full flex-col gap-2",
747
+ style: editMinWidth ? { minWidth: editMinWidth } : void 0,
748
+ children: [
749
+ /* @__PURE__ */ jsx(
750
+ "textarea",
751
+ {
752
+ value: draft,
753
+ ref: editRef,
754
+ rows: 2,
755
+ onChange: (e) => {
756
+ setDraft(e.target.value);
757
+ autosize();
758
+ },
759
+ onPaste: handleEditPaste,
760
+ onKeyDown: (e) => {
761
+ if (e.key === "Enter" && !e.shiftKey) {
762
+ e.preventDefault();
763
+ saveEdit();
764
+ } else if (e.key === "Escape") {
765
+ e.preventDefault();
766
+ cancelEdit();
767
+ }
768
+ },
769
+ "aria-label": "Edit message",
770
+ className: "focus:ring-primary-500 max-h-60 min-h-16 w-full resize-none rounded-lg border border-neutral-300 bg-white px-3 py-2 text-sm text-neutral-900 focus:ring-1 focus:outline-none dark:border-neutral-600 dark:bg-neutral-900 dark:text-white"
771
+ }
772
+ ),
773
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
774
+ /* @__PURE__ */ jsx(
775
+ "button",
776
+ {
777
+ type: "button",
778
+ onClick: cancelEdit,
779
+ className: "rounded-md px-2.5 py-1 text-xs font-medium text-neutral-200 hover:bg-white/10",
780
+ children: "Cancel"
781
+ }
782
+ ),
783
+ /* @__PURE__ */ jsx(
784
+ "button",
785
+ {
786
+ type: "button",
787
+ onClick: saveEdit,
788
+ disabled: !draft.trim() || draft.trim() === message.text,
789
+ className: "rounded-md bg-white px-2.5 py-1 text-xs font-medium text-neutral-900 hover:bg-neutral-100 disabled:opacity-40",
790
+ children: "Save"
791
+ }
792
+ )
793
+ ] })
794
+ ]
795
+ }
796
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
797
+ message.content?.map((block, i) => {
798
+ if (block.type === "tool_use" && block.toolCall) {
799
+ return /* @__PURE__ */ jsx(MCPToolCallDisplay, { toolCall: block.toolCall }, i);
800
+ }
801
+ if ((block.type === "text" || block.type === "thinking") && block.text) {
802
+ return /* @__PURE__ */ jsx(
803
+ "div",
804
+ {
805
+ className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
806
+ children: renderText(block.text, {
807
+ messageId: message.id,
808
+ streaming,
809
+ role: participant?.kind === "human" ? "user" : "assistant"
810
+ })
811
+ },
812
+ i
813
+ );
814
+ }
815
+ if (block.type === "code" && block.text) {
816
+ const fenced = `\`\`\`${block.language ?? ""}
817
+ ${block.text}
818
+ \`\`\``;
819
+ return /* @__PURE__ */ jsx(
820
+ "div",
821
+ {
822
+ className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
823
+ children: renderText(fenced, {
824
+ messageId: message.id,
825
+ streaming,
826
+ role: participant?.kind === "human" ? "user" : "assistant"
827
+ })
828
+ },
829
+ i
830
+ );
831
+ }
832
+ return null;
833
+ }),
834
+ message.text && /* @__PURE__ */ jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word", children: renderText(message.text, {
835
+ messageId: message.id,
836
+ streaming,
837
+ role: participant?.kind === "human" ? "user" : "assistant"
838
+ }) }),
839
+ message.media?.map((attachment) => /* @__PURE__ */ jsx(
840
+ MessageMedia,
841
+ {
842
+ attachment,
843
+ openLabel: openMediaLabel,
844
+ playLabel: playMediaLabel,
845
+ errorLabel: mediaErrorLabel,
846
+ retryLabel: mediaRetryLabel,
847
+ launchId: JSON.stringify([message.id, attachment.id]),
848
+ onOpen: onOpenMedia ? (play) => onOpenMedia(message.id, attachment.id, play) : void 0
849
+ },
850
+ attachment.id
851
+ )),
852
+ streaming && !hasBody && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(AITypingIndicator, {}) })
853
+ ] })
854
+ }
855
+ )
856
+ }
857
+ )
858
+ ]
859
+ }
860
+ )
861
+ ]
862
+ }
863
+ );
864
+ });
865
+ var sidebarItem = cva(
866
+ "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors",
867
+ {
868
+ variants: {
869
+ active: {
870
+ true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
871
+ false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
872
+ }
873
+ },
874
+ defaultVariants: { active: false }
875
+ }
876
+ );
877
+
878
+ // src/components/SuperChat/media.ts
879
+ function getConversationMediaItems(conversation) {
880
+ const participants = new Map(
881
+ conversation.participants.map((participant) => [
882
+ participant.id,
883
+ participant
884
+ ])
885
+ );
886
+ return [...conversation.thread].sort(byTime).flatMap(
887
+ (message) => (message.media ?? []).map((attachment) => ({
888
+ // Tuple encoding prevents collisions when ids themselves contain a
889
+ // delimiter. Including the conversation keeps selection scoped to it.
890
+ id: JSON.stringify([conversation.id, message.id, attachment.id]),
891
+ conversationId: conversation.id,
892
+ message,
893
+ attachment,
894
+ participant: participants.get(message.participantId)
895
+ }))
896
+ );
897
+ }
898
+ function remarkPreserveLineBreaks() {
899
+ const splitNode = (node) => {
900
+ if (!node.children) return;
901
+ const next = [];
902
+ for (const child of node.children) {
903
+ if (child.type === "text" && child.value && child.value.includes("\n")) {
904
+ const segments = child.value.split("\n");
905
+ segments.forEach((segment, i) => {
906
+ if (i > 0) next.push({ type: "break" });
907
+ if (segment) next.push({ type: "text", value: segment });
908
+ });
909
+ } else {
910
+ splitNode(child);
911
+ next.push(child);
912
+ }
913
+ }
914
+ node.children = next;
915
+ };
916
+ return (tree) => splitNode(tree);
917
+ }
918
+ function baseSanitizeSchema() {
919
+ const schema = JSON.parse(JSON.stringify(defaultSchema));
920
+ const attributes = schema.attributes ?? {};
921
+ const allowClass = (tag) => {
922
+ const existing = attributes[tag] ?? [];
923
+ const withoutClass = existing.filter(
924
+ (a) => !(Array.isArray(a) && a[0] === "className")
925
+ );
926
+ attributes[tag] = [...withoutClass, "className"];
927
+ };
928
+ allowClass("code");
929
+ allowClass("pre");
930
+ allowClass("span");
931
+ allowClass("div");
932
+ schema.attributes = attributes;
933
+ return schema;
934
+ }
935
+ function mergeSanitizeSchema(base, extra) {
936
+ if (!extra) return base;
937
+ const out = { ...base };
938
+ if (Array.isArray(extra.tagNames)) {
939
+ const a = base.tagNames ?? [];
940
+ out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
941
+ }
942
+ if (extra.attributes && typeof extra.attributes === "object") {
943
+ const baseAttrs = {
944
+ ...base.attributes ?? {}
945
+ };
946
+ for (const [tag, attrs] of Object.entries(
947
+ extra.attributes
948
+ )) {
949
+ baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
950
+ }
951
+ out.attributes = baseAttrs;
952
+ }
953
+ if (extra.protocols && typeof extra.protocols === "object") {
954
+ const baseProtocols = {
955
+ ...base.protocols ?? {}
956
+ };
957
+ for (const [attr, protocols] of Object.entries(
958
+ extra.protocols
959
+ )) {
960
+ baseProtocols[attr] = Array.from(
961
+ /* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
962
+ );
688
963
  }
689
- return "";
690
- }).filter(Boolean).join("\n\n") ?? "";
691
- const canCopy = !isEditing && (!!message.content?.length || typeof message.text === "string" && message.text.length > 0);
692
- const hasActions = canCopy || canEdit && !isEditing;
693
- const copy = useMessageCopy({
694
- markdown: markdownSource,
695
- getHtml: () => bubbleRef.current?.innerHTML ?? "",
696
- getText: () => bubbleRef.current?.textContent ?? "",
697
- defaultFormat: defaultCopyFormat
698
- });
699
- const actionsBarRef = React2.useRef(null);
700
- const [footerVisible, setFooterVisible] = React2.useState(true);
701
- React2.useEffect(() => {
702
- const el = actionsBarRef.current;
703
- if (!el || typeof globalThis.IntersectionObserver === "undefined") return;
704
- const observer = new globalThis.IntersectionObserver(([entry]) => {
705
- setFooterVisible(entry?.isIntersecting ?? false);
706
- });
707
- observer.observe(el);
708
- return () => observer.disconnect();
709
- }, [hasActions]);
710
- if (message.type === "system") {
711
- return /* @__PURE__ */ jsx(
712
- "div",
964
+ out.protocols = baseProtocols;
965
+ }
966
+ for (const [k, v] of Object.entries(extra)) {
967
+ if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
968
+ out[k] = v;
969
+ }
970
+ return out;
971
+ }
972
+ function baseComponents() {
973
+ return {
974
+ a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
975
+ "a",
713
976
  {
714
- "data-slot": "superchat-system-message",
715
- role: "status",
716
- className: "my-1 text-center text-xs text-neutral-500 dark:text-neutral-400",
717
- children: message.text
977
+ ...props,
978
+ className: cn(
979
+ "text-primary-800 hover:text-primary-900 dark:text-primary-300 underline underline-offset-2",
980
+ props.className
981
+ ),
982
+ target: props.target ?? "_blank",
983
+ rel: props.rel ?? "noopener noreferrer",
984
+ children
718
985
  }
719
- );
720
- }
721
- if (message.type === "ref" && message.ref) {
722
- return /* @__PURE__ */ jsx(
723
- "div",
986
+ ),
987
+ pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
988
+ "pre",
724
989
  {
725
- "data-slot": "superchat-reference",
726
- className: cn("flex", isSelf && "justify-end"),
727
- children: /* @__PURE__ */ jsx(
728
- ReferenceChip,
990
+ ...props,
991
+ tabIndex: 0,
992
+ className: cn(
993
+ "overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
994
+ props.className
995
+ )
996
+ }
997
+ ),
998
+ code: ({ node: _node, ...props }) => {
999
+ const isBlock = typeof props.className === "string" && props.className.includes("language-");
1000
+ return /* @__PURE__ */ jsx(
1001
+ "code",
1002
+ {
1003
+ ...props,
1004
+ className: cn(
1005
+ !isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] text-neutral-800 dark:bg-neutral-700 dark:text-neutral-100",
1006
+ props.className
1007
+ )
1008
+ }
1009
+ );
1010
+ },
1011
+ input: ({ node: _node, ...props }) => {
1012
+ if (props.type === "checkbox") {
1013
+ return /* @__PURE__ */ jsx(
1014
+ "input",
729
1015
  {
730
- reference: message.ref,
731
- linkBuilder,
732
- onReferenceClick
1016
+ ...props,
1017
+ "aria-label": props["aria-label"] ?? (props["aria-labelledby"] ? void 0 : "Task list item")
733
1018
  }
1019
+ );
1020
+ }
1021
+ return /* @__PURE__ */ jsx("input", { ...props });
1022
+ },
1023
+ table: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("div", { className: "my-2 overflow-x-auto", children: /* @__PURE__ */ jsx(
1024
+ "table",
1025
+ {
1026
+ ...props,
1027
+ className: cn(
1028
+ "w-full border-collapse text-sm [&_td]:border [&_td]:border-neutral-200 [&_td]:px-2 [&_td]:py-1 dark:[&_td]:border-neutral-700 [&_th]:border [&_th]:border-neutral-200 [&_th]:px-2 [&_th]:py-1 [&_th]:text-start dark:[&_th]:border-neutral-700",
1029
+ props.className
734
1030
  )
735
1031
  }
736
- );
737
- }
738
- const accent = participant?.color;
739
- const accentTextColor = accessibleAccentTextColor(accent);
740
- const authorName = participant?.name ?? "Unknown";
741
- const startEdit = () => {
742
- setDraft(message.text ?? "");
743
- setIsEditing(true);
744
- };
745
- const cancelEdit = () => setIsEditing(false);
746
- const saveEdit = () => {
747
- const next = draft.trim();
748
- if (next && next !== message.text) onMessageEdited?.(message.id, next);
749
- setIsEditing(false);
750
- };
751
- const handleEditPaste = (e) => {
752
- const files = Array.from(e.clipboardData.items).filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((f) => f !== null);
753
- if (files.length === 0) return;
754
- e.preventDefault();
755
- const el = e.currentTarget;
756
- const start = el.selectionStart ?? draft.length;
757
- const end = el.selectionEnd ?? draft.length;
758
- Promise.all(
759
- files.map(
760
- (file, i) => new Promise((resolve) => {
761
- const reader = new window.FileReader();
762
- reader.onload = () => {
763
- const dataUrl = typeof reader.result === "string" ? reader.result : "";
764
- const name = file.name || `pasted-image-${i + 1}.png`;
765
- resolve(dataUrl ? `![${name}](${dataUrl})` : "");
766
- };
767
- reader.readAsDataURL(file);
768
- })
769
- )
770
- ).then((snippets) => {
771
- const insert = snippets.filter(Boolean).join("\n");
772
- if (!insert) return;
773
- el.focus();
774
- el.setSelectionRange(start, end);
775
- const text = `${insert}
776
- `;
777
- const inserted = typeof document !== "undefined" && typeof document.execCommand === "function" && document.execCommand("insertText", false, text);
778
- if (!inserted) {
779
- setDraft((prev) => `${prev.slice(0, start)}${text}${prev.slice(end)}`);
1032
+ ) }),
1033
+ // Tailwind's preflight resets list markers/padding; restore them explicitly
1034
+ // so bullets/numbers show without depending on the typography plugin.
1035
+ ul: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("ul", { ...props, className: cn("list-disc ps-5", props.className) }),
1036
+ ol: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("ol", { ...props, className: cn("list-decimal ps-5", props.className) }),
1037
+ li: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("li", { ...props, className: cn("ps-1", props.className) }),
1038
+ // Preflight also flattens headings to body size/weight; restore a sensible
1039
+ // hierarchy without depending on the typography plugin.
1040
+ h1: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
1041
+ "h1",
1042
+ {
1043
+ ...props,
1044
+ className: cn("mt-3 mb-1 text-xl font-semibold", props.className),
1045
+ children
780
1046
  }
781
- requestAnimationFrame(autosize);
782
- });
783
- };
784
- const actions = [
785
- ...canCopy ? [
1047
+ ),
1048
+ h2: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
1049
+ "h2",
786
1050
  {
787
- id: "copy",
788
- label: "Copy message",
789
- title: "Copy message (\u2318/Ctrl-click: default format)",
790
- icon: copy.copied ? /* @__PURE__ */ jsx(Check, { size: 14, "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Clipboard, { size: 14, "aria-hidden": "true" }),
791
- onSelect: copy.copyDefault,
792
- submenu: {
793
- label: "Copy as",
794
- items: [
795
- {
796
- id: "copy-rich",
797
- label: "Copy as rich text",
798
- description: "Rich text + Markdown",
799
- onSelect: copy.copyRich
800
- },
801
- {
802
- id: "copy-markdown",
803
- label: "Copy as Markdown",
804
- onSelect: copy.copyMarkdown
805
- },
806
- {
807
- id: "copy-plain",
808
- label: "Copy as plain text",
809
- onSelect: copy.copyPlain
810
- }
811
- ]
812
- }
1051
+ ...props,
1052
+ className: cn("mt-3 mb-1 text-lg font-semibold", props.className),
1053
+ children
1054
+ }
1055
+ ),
1056
+ h3: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
1057
+ "h3",
1058
+ {
1059
+ ...props,
1060
+ className: cn("mt-2 mb-1 text-base font-semibold", props.className),
1061
+ children
1062
+ }
1063
+ ),
1064
+ h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
1065
+ "h4",
1066
+ {
1067
+ ...props,
1068
+ className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
1069
+ children
813
1070
  }
814
- ] : [],
815
- ...canEdit && !isEditing ? [
1071
+ ),
1072
+ h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
1073
+ "h5",
816
1074
  {
817
- id: "edit",
818
- label: "Edit message",
819
- icon: /* @__PURE__ */ jsx(Pencil, { size: 14, "aria-hidden": "true" }),
820
- onSelect: startEdit
1075
+ ...props,
1076
+ className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
1077
+ children
821
1078
  }
822
- ] : []
1079
+ ),
1080
+ h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
1081
+ "h6",
1082
+ {
1083
+ ...props,
1084
+ className: cn(
1085
+ "mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
1086
+ props.className
1087
+ ),
1088
+ children
1089
+ }
1090
+ ),
1091
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
1092
+ "hr",
1093
+ {
1094
+ ...props,
1095
+ className: cn(
1096
+ "my-2 border-neutral-300 dark:border-neutral-600",
1097
+ props.className
1098
+ )
1099
+ }
1100
+ )
1101
+ };
1102
+ }
1103
+ function createMarkdownRenderer(options = {}) {
1104
+ const { plugins = [], trusted = false } = options;
1105
+ const remarkPlugins = [
1106
+ remarkGfm,
1107
+ remarkPreserveLineBreaks,
1108
+ ...plugins.flatMap((p) => p.remarkPlugins ?? [])
823
1109
  ];
824
- return /* @__PURE__ */ jsxs(
825
- "div",
826
- {
827
- "data-slot": "superchat-message",
828
- role: "article",
829
- "aria-label": `${authorName}, ${formatTime(message.time)}`,
830
- className: cn(
831
- "group flex gap-2",
832
- isSelf ? "flex-row-reverse" : "flex-row"
833
- ),
834
- children: [
835
- /* @__PURE__ */ jsx(ParticipantAvatar, { participant }),
836
- /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 flex-col gap-1", isSelf && "items-end"), children: [
837
- /* @__PURE__ */ jsxs(
838
- "div",
839
- {
840
- "data-slot": "superchat-message-meta",
841
- className: "flex items-baseline gap-2",
842
- children: [
843
- /* @__PURE__ */ jsx(
844
- "span",
845
- {
846
- className: "text-xs font-medium",
847
- style: accentTextColor ? { color: accentTextColor } : void 0,
848
- children: authorName
849
- }
850
- ),
851
- participant?.role && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: participant.role }),
852
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: formatTime(message.time) }),
853
- message.editedAt && /* @__PURE__ */ jsx(
854
- "span",
855
- {
856
- "data-slot": "superchat-edited-indicator",
857
- className: "text-[10px] text-neutral-500 dark:text-neutral-400",
858
- title: `Edited ${formatTime(message.editedAt)}`,
859
- children: "(edited)"
860
- }
861
- )
862
- ]
863
- }
864
- ),
865
- /* @__PURE__ */ jsxs(
866
- "div",
867
- {
868
- className: cn(
869
- "flex items-center gap-1",
870
- isSelf ? "flex-row-reverse" : "flex-row"
871
- ),
872
- children: [
873
- hasActions && /* @__PURE__ */ jsx(
874
- MessageOverflowMenu,
875
- {
876
- isSelf,
877
- actions,
878
- footerVisible
879
- }
880
- ),
881
- /* @__PURE__ */ jsx(
882
- ChatBubble,
883
- {
884
- ref: bubbleRef,
885
- "data-slot": "superchat-bubble",
886
- variant: isSelf ? "user" : "assistant",
887
- hasError: message.status === "error",
888
- className: "text-sm has-[[data-slot=superchat-nitro-table]]:w-full has-[[data-slot=superchat-nitro-table]]:max-w-full",
889
- children: isEditing ? /* @__PURE__ */ jsxs(
890
- "div",
891
- {
892
- "data-slot": "superchat-message-editor",
893
- className: "flex w-80 max-w-full flex-col gap-2",
894
- children: [
895
- /* @__PURE__ */ jsx(
896
- "textarea",
897
- {
898
- value: draft,
899
- ref: editRef,
900
- rows: 2,
901
- onChange: (e) => {
902
- setDraft(e.target.value);
903
- autosize();
904
- },
905
- onPaste: handleEditPaste,
906
- onKeyDown: (e) => {
907
- if (e.key === "Enter" && !e.shiftKey) {
908
- e.preventDefault();
909
- saveEdit();
910
- } else if (e.key === "Escape") {
911
- e.preventDefault();
912
- cancelEdit();
913
- }
914
- },
915
- "aria-label": "Edit message",
916
- className: "focus:ring-primary-500 max-h-60 min-h-16 w-full resize-none rounded-lg border border-neutral-300 bg-white px-3 py-2 text-sm text-neutral-900 focus:ring-1 focus:outline-none dark:border-neutral-600 dark:bg-neutral-900 dark:text-white"
917
- }
918
- ),
919
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
920
- /* @__PURE__ */ jsx(
921
- "button",
922
- {
923
- type: "button",
924
- onClick: cancelEdit,
925
- className: "rounded-md px-2.5 py-1 text-xs font-medium text-neutral-200 hover:bg-white/10",
926
- children: "Cancel"
927
- }
928
- ),
929
- /* @__PURE__ */ jsx(
930
- "button",
931
- {
932
- type: "button",
933
- onClick: saveEdit,
934
- disabled: !draft.trim() || draft.trim() === message.text,
935
- className: "rounded-md bg-white px-2.5 py-1 text-xs font-medium text-neutral-900 hover:bg-neutral-100 disabled:opacity-40",
936
- children: "Save"
937
- }
938
- )
939
- ] })
940
- ]
941
- }
942
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
943
- message.content?.map((block, i) => {
944
- if (block.type === "tool_use" && block.toolCall) {
945
- return /* @__PURE__ */ jsx(MCPToolCallDisplay, { toolCall: block.toolCall }, i);
946
- }
947
- if ((block.type === "text" || block.type === "thinking") && block.text) {
948
- return /* @__PURE__ */ jsx(
949
- "div",
950
- {
951
- className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
952
- children: renderText(block.text, {
953
- messageId: message.id,
954
- streaming,
955
- role: participant?.kind === "human" ? "user" : "assistant"
956
- })
957
- },
958
- i
959
- );
960
- }
961
- if (block.type === "code" && block.text) {
962
- const fenced = `\`\`\`${block.language ?? ""}
963
- ${block.text}
964
- \`\`\``;
965
- return /* @__PURE__ */ jsx(
966
- "div",
967
- {
968
- className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
969
- children: renderText(fenced, {
970
- messageId: message.id,
971
- streaming,
972
- role: participant?.kind === "human" ? "user" : "assistant"
973
- })
974
- },
975
- i
976
- );
977
- }
978
- return null;
979
- }),
980
- message.text && /* @__PURE__ */ jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word", children: renderText(message.text, {
981
- messageId: message.id,
982
- streaming,
983
- role: participant?.kind === "human" ? "user" : "assistant"
984
- }) }),
985
- streaming && !hasBody && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(AITypingIndicator, {}) })
986
- ] })
987
- }
988
- )
989
- ]
990
- }
991
- ),
992
- hasActions && /* @__PURE__ */ jsx(
993
- MessageActionsBar,
994
- {
995
- ref: actionsBarRef,
996
- actions,
997
- isSelf
998
- }
999
- )
1000
- ] })
1001
- ]
1002
- }
1110
+ const pluginRehype = plugins.flatMap(
1111
+ (p) => p.rehypePlugins ?? []
1003
1112
  );
1004
- });
1005
- var sidebarItem = cva(
1006
- "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors",
1007
- {
1008
- variants: {
1009
- active: {
1010
- true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
1011
- false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
1012
- }
1113
+ const sanitizeSchema = plugins.reduce(
1114
+ (acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
1115
+ baseSanitizeSchema()
1116
+ );
1117
+ const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize, sanitizeSchema]];
1118
+ const components = plugins.reduce(
1119
+ (acc, p) => ({ ...acc, ...p.components }),
1120
+ baseComponents()
1121
+ );
1122
+ const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsx(
1123
+ MarkdownContent,
1124
+ {
1125
+ text,
1126
+ messageId: ctx.messageId,
1127
+ streaming: ctx.streaming,
1128
+ remarkPlugins,
1129
+ rehypePlugins,
1130
+ components
1013
1131
  },
1014
- defaultVariants: { active: false }
1132
+ ctx.messageId
1133
+ );
1134
+ return MarkdownRenderer;
1135
+ }
1136
+ var transformUrl = (url, key, node) => {
1137
+ if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
1138
+ return url;
1015
1139
  }
1016
- );
1140
+ return defaultUrlTransform(url);
1141
+ };
1142
+ var MarkdownContent = React3.memo(function MarkdownContent2({
1143
+ text,
1144
+ messageId,
1145
+ streaming,
1146
+ remarkPlugins,
1147
+ rehypePlugins,
1148
+ components
1149
+ }) {
1150
+ return /* @__PURE__ */ jsx(TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsx(
1151
+ Markdown,
1152
+ {
1153
+ remarkPlugins,
1154
+ rehypePlugins,
1155
+ urlTransform: transformUrl,
1156
+ components,
1157
+ children: text
1158
+ }
1159
+ ) });
1160
+ });
1017
1161
  function VirtualThread({
1018
1162
  items,
1019
1163
  participantById,
@@ -1024,32 +1168,28 @@ function VirtualThread({
1024
1168
  editable,
1025
1169
  onMessageEdited,
1026
1170
  defaultCopyFormat,
1027
- order,
1028
- conversationId,
1171
+ onOpenMedia,
1172
+ openMediaLabel,
1173
+ playMediaLabel,
1174
+ mediaErrorLabel,
1175
+ mediaRetryLabel,
1176
+ scrollRef,
1177
+ contentRef,
1029
1178
  containerProps
1030
1179
  }) {
1031
- const parentRef = React2.useRef(null);
1032
1180
  const virtualizer = useVirtualizer({
1033
1181
  count: items.length,
1034
- getScrollElement: () => parentRef.current,
1182
+ getScrollElement: () => scrollRef.current,
1035
1183
  // Rough first guess; real heights are measured via measureElement.
1036
1184
  estimateSize: () => 88,
1037
1185
  overscan: 10,
1038
1186
  getItemKey: (index) => items[index]?.id ?? index
1039
1187
  });
1040
- const count = items.length;
1041
- React2.useEffect(() => {
1042
- if (count === 0) return;
1043
- if (order === "desc") {
1044
- virtualizer.scrollToIndex(0, { align: "start" });
1045
- } else {
1046
- virtualizer.scrollToIndex(count - 1, { align: "end" });
1047
- }
1048
- }, [count, conversationId, order]);
1049
1188
  const virtualItems = virtualizer.getVirtualItems();
1050
- return /* @__PURE__ */ jsx("div", { ...containerProps, ref: parentRef, children: /* @__PURE__ */ jsx(
1189
+ return /* @__PURE__ */ jsx("div", { ...containerProps, ref: scrollRef, children: /* @__PURE__ */ jsx(
1051
1190
  "div",
1052
1191
  {
1192
+ ref: contentRef,
1053
1193
  style: {
1054
1194
  height: virtualizer.getTotalSize(),
1055
1195
  position: "relative",
@@ -1081,7 +1221,12 @@ function VirtualThread({
1081
1221
  onReferenceClick,
1082
1222
  editable,
1083
1223
  onMessageEdited,
1084
- defaultCopyFormat
1224
+ defaultCopyFormat,
1225
+ onOpenMedia,
1226
+ openMediaLabel,
1227
+ playMediaLabel,
1228
+ mediaErrorLabel,
1229
+ mediaRetryLabel
1085
1230
  }
1086
1231
  ) })
1087
1232
  },
@@ -1093,6 +1238,11 @@ function VirtualThread({
1093
1238
  }
1094
1239
  function SuperChat({
1095
1240
  conversation,
1241
+ view,
1242
+ defaultView = "thread",
1243
+ onViewChange,
1244
+ mediaFeedProps,
1245
+ mediaLabels,
1096
1246
  currentParticipantId,
1097
1247
  renderPlugins,
1098
1248
  renderTextContent,
@@ -1104,44 +1254,366 @@ function SuperChat({
1104
1254
  linkBuilder,
1105
1255
  defaultCopyFormat,
1106
1256
  className,
1257
+ showHeader = true,
1258
+ placeholder,
1259
+ allowAttachments,
1260
+ agents,
1261
+ selectedAgent,
1262
+ onAgentChange,
1263
+ agentSelectorLabel,
1264
+ modelSelectorProps,
1265
+ isStreaming,
1266
+ onStop,
1267
+ stopLabel,
1107
1268
  onMessageSent,
1108
1269
  onMessageEdited,
1109
1270
  onConversationClosed,
1110
1271
  onReferenceClick,
1111
1272
  onBack
1112
1273
  }) {
1113
- const headingId = React2.useId();
1114
- React2.useEffect(() => {
1274
+ const headingId = React3.useId();
1275
+ const [internalView, setInternalView] = React3.useState({
1276
+ conversationId: conversation.id,
1277
+ view: defaultView
1278
+ });
1279
+ const activeView = view ?? (internalView.conversationId === conversation.id ? internalView.view : "thread");
1280
+ const labels = {
1281
+ backToConversation: "Back to conversation",
1282
+ openMedia: "Open in media feed",
1283
+ playMedia: "Play",
1284
+ unknownAuthor: "Unknown",
1285
+ ...mediaLabels
1286
+ };
1287
+ const mediaItems = React3.useMemo(() => {
1288
+ const items = getConversationMediaItems(conversation);
1289
+ return order === "desc" ? items.reverse() : items;
1290
+ }, [conversation, order]);
1291
+ const [mediaSelection, setMediaSelection] = React3.useState();
1292
+ const [manualPlaybackRequest, setManualPlaybackRequest] = React3.useState();
1293
+ const playbackRequestCounter = React3.useRef(0);
1294
+ const mediaFeedRef = React3.useRef(null);
1295
+ const backToConversationRef = React3.useRef(null);
1296
+ const focusMediaOnOpenRef = React3.useRef(false);
1297
+ const focusThreadOnBackRef = React3.useRef(false);
1298
+ const mediaReturnTargetRef = React3.useRef(void 0);
1299
+ const mediaContextRef = React3.useRef({
1300
+ conversation,
1301
+ view,
1302
+ onViewChange,
1303
+ mediaFeedProps,
1304
+ mediaItems
1305
+ });
1306
+ mediaContextRef.current = {
1307
+ conversation,
1308
+ view,
1309
+ onViewChange,
1310
+ mediaFeedProps,
1311
+ mediaItems
1312
+ };
1313
+ const setView = React3.useCallback((next) => {
1314
+ const context = mediaContextRef.current;
1315
+ if (context.view === void 0)
1316
+ setInternalView({ conversationId: context.conversation.id, view: next });
1317
+ context.onViewChange?.(next, { conversation: context.conversation });
1318
+ }, []);
1319
+ const handleMediaSelection = React3.useCallback((item) => {
1320
+ setMediaSelection({ conversationId: item.conversationId, itemId: item.id });
1321
+ mediaContextRef.current.mediaFeedProps?.onActiveItemChange?.(item);
1322
+ }, []);
1323
+ const handleOpenMedia = React3.useCallback(
1324
+ (messageId, attachmentId, play = false) => {
1325
+ const item = mediaContextRef.current.mediaItems.find(
1326
+ (candidate) => candidate.message.id === messageId && candidate.attachment.id === attachmentId
1327
+ );
1328
+ if (!item) return;
1329
+ handleMediaSelection(item);
1330
+ mediaReturnTargetRef.current = {
1331
+ conversationId: item.conversationId,
1332
+ messageId,
1333
+ attachmentId
1334
+ };
1335
+ focusMediaOnOpenRef.current = true;
1336
+ setManualPlaybackRequest(
1337
+ play ? {
1338
+ conversationId: item.conversationId,
1339
+ itemId: item.id,
1340
+ requestId: ++playbackRequestCounter.current
1341
+ } : void 0
1342
+ );
1343
+ setView("media");
1344
+ },
1345
+ [handleMediaSelection, setView]
1346
+ );
1347
+ const handleBackToConversation = React3.useCallback(() => {
1348
+ focusMediaOnOpenRef.current = false;
1349
+ focusThreadOnBackRef.current = true;
1350
+ setManualPlaybackRequest(void 0);
1351
+ setView("thread");
1352
+ }, [setView]);
1353
+ const hostPlaybackRequest = mediaFeedProps?.playbackRequest;
1354
+ const hostPlaybackKey = hostPlaybackRequest ? `${hostPlaybackRequest.itemId}\0${hostPlaybackRequest.requestId}` : void 0;
1355
+ React3.useEffect(() => {
1356
+ if (hostPlaybackKey === void 0) return;
1357
+ setManualPlaybackRequest(void 0);
1358
+ }, [hostPlaybackKey]);
1359
+ React3.useEffect(() => {
1360
+ if (internalView.conversationId !== conversation.id) {
1361
+ setInternalView({ conversationId: conversation.id, view: "thread" });
1362
+ }
1363
+ if (mediaReturnTargetRef.current?.conversationId !== conversation.id) {
1364
+ mediaReturnTargetRef.current = void 0;
1365
+ focusMediaOnOpenRef.current = false;
1366
+ focusThreadOnBackRef.current = false;
1367
+ setManualPlaybackRequest(void 0);
1368
+ }
1369
+ }, [conversation.id, internalView.conversationId]);
1370
+ React3.useEffect(() => {
1371
+ if (activeView !== "media" || !focusMediaOnOpenRef.current) return;
1372
+ const target = mediaFeedRef.current?.querySelector(
1373
+ 'article[tabindex="0"]'
1374
+ ) ?? mediaFeedRef.current?.querySelector('[role="feed"]');
1375
+ if (target) focusMediaOnOpenRef.current = false;
1376
+ (target ?? backToConversationRef.current)?.focus({ preventScroll: true });
1377
+ }, [
1378
+ activeView,
1379
+ mediaFeedProps?.loading,
1380
+ mediaFeedProps?.error,
1381
+ mediaItems.length
1382
+ ]);
1383
+ React3.useEffect(() => {
1115
1384
  notifyComposerMigrationOnce("SuperChat");
1116
1385
  }, []);
1117
- const renderText = React2.useMemo(
1386
+ const renderText = React3.useMemo(
1118
1387
  () => renderTextContent ?? createMarkdownRenderer({
1119
1388
  plugins: renderPlugins,
1120
1389
  trusted: trustedContent
1121
1390
  }),
1122
1391
  [renderTextContent, renderPlugins, trustedContent]
1123
1392
  );
1124
- const threadRef = React2.useRef(null);
1125
- React2.useEffect(() => {
1126
- if (virtualized) return;
1127
- const el = threadRef.current;
1128
- if (!el) return;
1129
- el.scrollTop = order === "desc" ? 0 : el.scrollHeight;
1130
- }, [conversation.thread.length, conversation.id, order, virtualized]);
1131
- const participantById = React2.useMemo(() => {
1393
+ const prefersReducedMotion = usePrefersReducedMotion();
1394
+ const {
1395
+ containerRef: threadRef,
1396
+ contentRef: threadContentRef,
1397
+ isAtBottom,
1398
+ scrollToBottom,
1399
+ anchorToTurnStart,
1400
+ followIfPinned,
1401
+ stopFollowing
1402
+ } = useStickToBottom({
1403
+ disabled: order === "desc" || activeView === "media"
1404
+ });
1405
+ React3.useEffect(() => {
1406
+ if (activeView !== "thread") return;
1407
+ setManualPlaybackRequest(void 0);
1408
+ if (!focusThreadOnBackRef.current) return;
1409
+ focusThreadOnBackRef.current = false;
1410
+ const source = mediaReturnTargetRef.current;
1411
+ const launchId = source ? JSON.stringify([source.messageId, source.attachmentId]) : void 0;
1412
+ const launcher = source?.conversationId === conversation.id ? Array.from(
1413
+ threadRef.current?.querySelectorAll(
1414
+ "[data-media-launch-id]"
1415
+ ) ?? []
1416
+ ).find((button) => button.dataset.mediaLaunchId === launchId) : void 0;
1417
+ (launcher ?? threadRef.current)?.focus({ preventScroll: true });
1418
+ }, [activeView, conversation.id, threadRef]);
1419
+ const [hasNewBelow, setHasNewBelow] = React3.useState(false);
1420
+ const [turnStartId, setTurnStartId] = React3.useState(null);
1421
+ const [turnMinHeight, setTurnMinHeight] = React3.useState();
1422
+ const anchoredTurnRef = React3.useRef(null);
1423
+ const threadSnapshotRef = React3.useRef(void 0);
1424
+ const atBottomRef = React3.useRef(isAtBottom);
1425
+ atBottomRef.current = isAtBottom;
1426
+ const pendingMediaOwnSendRef = React3.useRef(false);
1427
+ const pendingMediaAppendRef = React3.useRef(false);
1428
+ React3.useEffect(() => {
1429
+ threadSnapshotRef.current = void 0;
1430
+ pendingMediaOwnSendRef.current = false;
1431
+ pendingMediaAppendRef.current = false;
1432
+ setTurnStartId(null);
1433
+ anchoredTurnRef.current = null;
1434
+ if (order === "desc") {
1435
+ const el = threadRef.current;
1436
+ if (el) el.scrollTop = 0;
1437
+ } else {
1438
+ scrollToBottom("auto");
1439
+ }
1440
+ setHasNewBelow(false);
1441
+ }, [conversation.id, order]);
1442
+ const threadLength = conversation.thread.length;
1443
+ const prevThreadLengthRef = React3.useRef(threadLength);
1444
+ const prevMessageIdsRef = React3.useRef(
1445
+ new Set(conversation.thread.map((message) => message.id))
1446
+ );
1447
+ const policyConversationRef = React3.useRef(conversation.id);
1448
+ const policyBaselinedRef = React3.useRef(false);
1449
+ React3.useEffect(() => {
1450
+ if (!policyBaselinedRef.current || policyConversationRef.current !== conversation.id) {
1451
+ policyBaselinedRef.current = true;
1452
+ policyConversationRef.current = conversation.id;
1453
+ prevThreadLengthRef.current = threadLength;
1454
+ prevMessageIdsRef.current = new Set(
1455
+ conversation.thread.map((message) => message.id)
1456
+ );
1457
+ if (order !== "desc" && [...conversation.thread].sort(byTime).at(-1)?.status === "streaming") {
1458
+ stopFollowing();
1459
+ }
1460
+ return;
1461
+ }
1462
+ if (threadLength === prevThreadLengthRef.current) return;
1463
+ const grew = threadLength > prevThreadLengthRef.current;
1464
+ prevThreadLengthRef.current = threadLength;
1465
+ if (grew && activeView === "media") pendingMediaAppendRef.current = true;
1466
+ if (order === "desc") {
1467
+ const el = threadRef.current;
1468
+ if (el) el.scrollTop = 0;
1469
+ return;
1470
+ }
1471
+ const prevIds = prevMessageIdsRef.current;
1472
+ let turnStart;
1473
+ if (grew && currentParticipantId) {
1474
+ for (const message of [...conversation.thread].sort(byTime)) {
1475
+ if (!prevIds.has(message.id) && message.participantId === currentParticipantId) {
1476
+ turnStart = message.id;
1477
+ }
1478
+ }
1479
+ }
1480
+ if (turnStart) {
1481
+ if (activeView === "media") pendingMediaOwnSendRef.current = true;
1482
+ if (virtualized) {
1483
+ scrollToBottom("auto");
1484
+ } else {
1485
+ setTurnStartId(turnStart);
1486
+ }
1487
+ } else if (grew) {
1488
+ const newest = [...conversation.thread].sort(byTime).at(-1);
1489
+ if (newest?.status === "streaming") {
1490
+ followIfPinned("auto");
1491
+ stopFollowing();
1492
+ } else if (!followIfPinned("auto")) {
1493
+ setHasNewBelow(true);
1494
+ }
1495
+ } else {
1496
+ followIfPinned("auto");
1497
+ }
1498
+ }, [threadLength, order, isAtBottom, conversation.id, activeView]);
1499
+ React3.useLayoutEffect(() => {
1500
+ if (activeView !== "thread") return;
1501
+ const container = threadRef.current;
1502
+ if (!container) return;
1503
+ const snapshot = threadSnapshotRef.current;
1504
+ const sameThread = snapshot?.conversationId === conversation.id && snapshot.order === order;
1505
+ const ownSend = pendingMediaOwnSendRef.current;
1506
+ const appended = pendingMediaAppendRef.current;
1507
+ pendingMediaOwnSendRef.current = false;
1508
+ pendingMediaAppendRef.current = false;
1509
+ if (order === "desc") {
1510
+ container.scrollTop = sameThread && !appended ? snapshot.scrollTop : 0;
1511
+ } else if (ownSend && !virtualized) ; else if (sameThread && !ownSend && (!snapshot.atBottom || !appended)) {
1512
+ container.scrollTop = snapshot.scrollTop;
1513
+ if (!snapshot.atBottom) stopFollowing();
1514
+ } else {
1515
+ scrollToBottom("auto");
1516
+ if ([...conversation.thread].sort(byTime).at(-1)?.status === "streaming")
1517
+ stopFollowing();
1518
+ }
1519
+ return () => {
1520
+ threadSnapshotRef.current = {
1521
+ conversationId: conversation.id,
1522
+ order,
1523
+ scrollTop: container.scrollTop,
1524
+ atBottom: atBottomRef.current
1525
+ };
1526
+ };
1527
+ }, [conversation.id, order, activeView, virtualized]);
1528
+ React3.useLayoutEffect(() => {
1529
+ if (!turnStartId || anchoredTurnRef.current === turnStartId) return;
1530
+ const container = threadRef.current;
1531
+ if (!container) return;
1532
+ const reserve = Math.max(0, container.clientHeight - 32);
1533
+ if (turnMinHeight !== reserve) {
1534
+ setTurnMinHeight(reserve);
1535
+ return;
1536
+ }
1537
+ const target = container.querySelector(
1538
+ '[data-slot="superchat-turn"]'
1539
+ );
1540
+ if (target) {
1541
+ anchorToTurnStart(target, prefersReducedMotion ? "auto" : "smooth");
1542
+ anchoredTurnRef.current = turnStartId;
1543
+ }
1544
+ }, [
1545
+ turnStartId,
1546
+ turnMinHeight,
1547
+ anchorToTurnStart,
1548
+ prefersReducedMotion,
1549
+ threadRef,
1550
+ activeView
1551
+ ]);
1552
+ React3.useEffect(() => {
1553
+ prevMessageIdsRef.current = new Set(
1554
+ conversation.thread.map((message) => message.id)
1555
+ );
1556
+ });
1557
+ React3.useEffect(() => {
1558
+ if (isAtBottom) setHasNewBelow(false);
1559
+ }, [isAtBottom]);
1560
+ const newestMessage = React3.useMemo(
1561
+ () => [...conversation.thread].sort(byTime).at(-1),
1562
+ [conversation]
1563
+ );
1564
+ const raiseNewBelow = React3.useCallback(() => {
1565
+ if (order !== "desc") setHasNewBelow(true);
1566
+ }, [order]);
1567
+ const resumeFollowing = React3.useCallback(() => {
1568
+ if (order !== "desc") scrollToBottom("auto");
1569
+ }, [order, scrollToBottom]);
1570
+ useStreamEndedBelowFold(
1571
+ newestMessage,
1572
+ isAtBottom,
1573
+ raiseNewBelow,
1574
+ resumeFollowing
1575
+ );
1576
+ const handleJumpToBottom = React3.useCallback(() => {
1577
+ scrollToBottom(prefersReducedMotion ? "auto" : "smooth");
1578
+ }, [scrollToBottom, prefersReducedMotion]);
1579
+ const participantById = React3.useMemo(() => {
1132
1580
  const map = /* @__PURE__ */ new Map();
1133
1581
  conversation.participants.forEach((p) => map.set(p.id, p));
1134
1582
  return map;
1135
1583
  }, [conversation]);
1136
- const orderedThread = React2.useMemo(() => {
1584
+ const orderedThread = React3.useMemo(() => {
1137
1585
  const sorted = [...conversation.thread].sort(byTime);
1138
1586
  return order === "desc" ? sorted.reverse() : sorted;
1139
1587
  }, [conversation, order]);
1140
- const onMessageEditedRef = React2.useRef(onMessageEdited);
1588
+ const turnIndex = React3.useMemo(
1589
+ () => turnStartId && order !== "desc" ? orderedThread.findIndex((message) => message.id === turnStartId) : -1,
1590
+ [orderedThread, turnStartId, order]
1591
+ );
1592
+ const renderMessageRow = (m) => /* @__PURE__ */ jsx(
1593
+ MessageRow,
1594
+ {
1595
+ message: m,
1596
+ participant: participantById.get(m.participantId),
1597
+ isSelf: !!currentParticipantId && m.participantId === currentParticipantId,
1598
+ renderText,
1599
+ linkBuilder,
1600
+ onReferenceClick,
1601
+ editable,
1602
+ onMessageEdited: handleMessageEdited,
1603
+ defaultCopyFormat,
1604
+ onOpenMedia: handleOpenMedia,
1605
+ openMediaLabel: labels.openMedia,
1606
+ playMediaLabel: labels.playMedia,
1607
+ mediaErrorLabel: mediaFeedProps?.labels?.mediaError,
1608
+ mediaRetryLabel: mediaFeedProps?.labels?.retry
1609
+ },
1610
+ m.id
1611
+ );
1612
+ const onMessageEditedRef = React3.useRef(onMessageEdited);
1141
1613
  onMessageEditedRef.current = onMessageEdited;
1142
- const conversationRef = React2.useRef(conversation);
1614
+ const conversationRef = React3.useRef(conversation);
1143
1615
  conversationRef.current = conversation;
1144
- const handleMessageEdited = React2.useCallback(
1616
+ const handleMessageEdited = React3.useCallback(
1145
1617
  (messageId, text) => {
1146
1618
  onMessageEditedRef.current?.(messageId, text, {
1147
1619
  conversation: conversationRef.current
@@ -1150,7 +1622,7 @@ function SuperChat({
1150
1622
  []
1151
1623
  );
1152
1624
  const editable = !readOnly && !!onMessageEdited;
1153
- const mentionOptions = React2.useMemo(
1625
+ const mentionOptions = React3.useMemo(
1154
1626
  () => conversation.participants.filter((p) => p.kind !== "system").map((p) => ({
1155
1627
  id: p.id,
1156
1628
  label: p.name,
@@ -1160,17 +1632,17 @@ function SuperChat({
1160
1632
  })),
1161
1633
  [conversation.participants]
1162
1634
  );
1163
- const composerAccept = React2.useMemo(
1635
+ const composerAccept = React3.useMemo(
1164
1636
  () => acceptTokensFor(acceptedFileTypes),
1165
1637
  [acceptedFileTypes]
1166
1638
  );
1167
- const [draft, setDraft] = React2.useState("");
1168
- const draftEpochRef = React2.useRef(0);
1169
- const handleDraftChange = React2.useCallback((value) => {
1639
+ const [draft, setDraft] = React3.useState("");
1640
+ const draftEpochRef = React3.useRef(0);
1641
+ const handleDraftChange = React3.useCallback((value) => {
1170
1642
  draftEpochRef.current += 1;
1171
1643
  setDraft(value);
1172
1644
  }, []);
1173
- const handleComposerSend = React2.useCallback(
1645
+ const handleComposerSend = React3.useCallback(
1174
1646
  async (message) => {
1175
1647
  const epoch = draftEpochRef.current;
1176
1648
  try {
@@ -1201,7 +1673,7 @@ function SuperChat({
1201
1673
  className
1202
1674
  ),
1203
1675
  children: [
1204
- /* @__PURE__ */ jsxs(
1676
+ showHeader ? /* @__PURE__ */ jsxs(
1205
1677
  "header",
1206
1678
  {
1207
1679
  "data-slot": "superchat-header",
@@ -1265,56 +1737,133 @@ function SuperChat({
1265
1737
  )
1266
1738
  ]
1267
1739
  }
1740
+ ) : (
1741
+ // Keeps the panel's aria-labelledby reference valid without a visible header.
1742
+ /* @__PURE__ */ jsx("h2", { id: headingId, className: "sr-only", children: conversation.title })
1268
1743
  ),
1269
- virtualized ? /* @__PURE__ */ jsx(
1270
- VirtualThread,
1744
+ activeView === "media" ? /* @__PURE__ */ jsxs(
1745
+ "div",
1271
1746
  {
1272
- items: orderedThread,
1273
- participantById,
1274
- currentParticipantId,
1275
- renderText,
1276
- linkBuilder,
1277
- onReferenceClick,
1278
- editable,
1279
- onMessageEdited: handleMessageEdited,
1280
- defaultCopyFormat,
1281
- order,
1282
- conversationId: conversation.id,
1283
- containerProps: {
1284
- "data-slot": "superchat-thread",
1285
- role: "log",
1286
- "aria-label": "Messages",
1287
- "aria-live": "polite",
1288
- // Focusable so keyboard-only users can scroll the message history.
1289
- tabIndex: 0,
1290
- className: "flex-1 overflow-y-auto p-4"
1291
- }
1747
+ "data-slot": "superchat-media-view",
1748
+ className: "flex min-h-0 flex-1 flex-col",
1749
+ children: [
1750
+ /* @__PURE__ */ jsx("div", { className: "px-4 pt-2", children: /* @__PURE__ */ jsx(ButtonGroup, { className: "justify-start", children: /* @__PURE__ */ jsx(
1751
+ Button,
1752
+ {
1753
+ ref: backToConversationRef,
1754
+ variant: "ghost",
1755
+ size: "sm",
1756
+ leftIcon: /* @__PURE__ */ jsx(
1757
+ ArrowLeft,
1758
+ {
1759
+ className: "size-4 rtl:rotate-180",
1760
+ "aria-hidden": "true"
1761
+ }
1762
+ ),
1763
+ onClick: handleBackToConversation,
1764
+ children: labels.backToConversation
1765
+ }
1766
+ ) }) }),
1767
+ /* @__PURE__ */ createElement(
1768
+ MediaFeed,
1769
+ {
1770
+ ...mediaFeedProps,
1771
+ ref: mediaFeedRef,
1772
+ key: conversation.id,
1773
+ items: mediaItems,
1774
+ getId: (item) => item.id,
1775
+ getMedia: (item) => item.attachment,
1776
+ getTitle: (item) => item.attachment.title ?? "",
1777
+ getCaption: (item) => item.attachment.caption ?? item.message.text,
1778
+ getAuthor: (item) => ({
1779
+ name: item.participant?.name ?? labels.unknownAuthor,
1780
+ avatar: item.participant?.avatar
1781
+ }),
1782
+ activeItemId: mediaFeedProps?.activeItemId ?? (mediaSelection?.conversationId === conversation.id ? mediaSelection.itemId : void 0),
1783
+ onActiveItemChange: handleMediaSelection,
1784
+ playbackRequest: manualPlaybackRequest?.conversationId === conversation.id ? manualPlaybackRequest : mediaFeedProps?.playbackRequest,
1785
+ className: cn("min-h-0 flex-1", mediaFeedProps?.className)
1786
+ }
1787
+ )
1788
+ ]
1292
1789
  }
1293
- ) : /* @__PURE__ */ jsx(
1790
+ ) : /* @__PURE__ */ jsxs(
1294
1791
  "div",
1295
1792
  {
1296
- "data-slot": "superchat-thread",
1297
- ref: threadRef,
1298
- role: "log",
1299
- "aria-label": "Messages",
1300
- "aria-live": "polite",
1301
- tabIndex: 0,
1302
- className: "flex-1 space-y-4 overflow-y-auto p-4",
1303
- children: orderedThread.map((m) => /* @__PURE__ */ jsx(
1304
- MessageRow,
1305
- {
1306
- message: m,
1307
- participant: participantById.get(m.participantId),
1308
- isSelf: !!currentParticipantId && m.participantId === currentParticipantId,
1309
- renderText,
1310
- linkBuilder,
1311
- onReferenceClick,
1312
- editable,
1313
- onMessageEdited: handleMessageEdited,
1314
- defaultCopyFormat
1315
- },
1316
- m.id
1317
- ))
1793
+ "data-slot": "superchat-thread-viewport",
1794
+ className: "relative flex min-h-0 flex-1 flex-col",
1795
+ children: [
1796
+ virtualized ? /* @__PURE__ */ jsx(
1797
+ VirtualThread,
1798
+ {
1799
+ items: orderedThread,
1800
+ participantById,
1801
+ currentParticipantId,
1802
+ renderText,
1803
+ linkBuilder,
1804
+ onReferenceClick,
1805
+ editable,
1806
+ onMessageEdited: handleMessageEdited,
1807
+ defaultCopyFormat,
1808
+ onOpenMedia: handleOpenMedia,
1809
+ openMediaLabel: labels.openMedia,
1810
+ playMediaLabel: labels.playMedia,
1811
+ mediaErrorLabel: mediaFeedProps?.labels?.mediaError,
1812
+ mediaRetryLabel: mediaFeedProps?.labels?.retry,
1813
+ scrollRef: threadRef,
1814
+ contentRef: threadContentRef,
1815
+ containerProps: {
1816
+ "data-slot": "superchat-thread",
1817
+ role: "log",
1818
+ "aria-label": "Messages",
1819
+ "aria-live": "polite",
1820
+ // Focusable so keyboard-only users can scroll the message history.
1821
+ tabIndex: 0,
1822
+ className: "flex-1 overflow-y-auto p-4"
1823
+ }
1824
+ }
1825
+ ) : /* @__PURE__ */ jsx(
1826
+ "div",
1827
+ {
1828
+ "data-slot": "superchat-thread",
1829
+ ref: threadRef,
1830
+ role: "log",
1831
+ "aria-label": "Messages",
1832
+ "aria-live": "polite",
1833
+ tabIndex: 0,
1834
+ className: "flex-1 overflow-y-auto p-4",
1835
+ children: /* @__PURE__ */ jsxs("div", { ref: threadContentRef, className: "space-y-4", children: [
1836
+ (turnIndex === -1 ? orderedThread : orderedThread.slice(0, turnIndex)).map(renderMessageRow),
1837
+ turnIndex !== -1 && /* @__PURE__ */ jsx(
1838
+ "div",
1839
+ {
1840
+ "data-slot": "superchat-turn",
1841
+ className: "space-y-4",
1842
+ style: { minHeight: turnMinHeight },
1843
+ children: orderedThread.slice(turnIndex).map(renderMessageRow)
1844
+ }
1845
+ )
1846
+ ] })
1847
+ }
1848
+ ),
1849
+ /* @__PURE__ */ jsx(AnimatedPresence, { children: order !== "desc" && !isAtBottom && /* @__PURE__ */ jsx(
1850
+ Animated,
1851
+ {
1852
+ preset: "fade",
1853
+ mode: "presence",
1854
+ className: "absolute inset-x-0 bottom-0 z-20",
1855
+ children: /* @__PURE__ */ jsx(
1856
+ JumpToBottomButton,
1857
+ {
1858
+ dataSlot: "superchat-jump-to-bottom",
1859
+ hasNewMessages: hasNewBelow,
1860
+ onClick: handleJumpToBottom
1861
+ }
1862
+ )
1863
+ },
1864
+ "jump-to-bottom"
1865
+ ) })
1866
+ ]
1318
1867
  }
1319
1868
  ),
1320
1869
  /* @__PURE__ */ jsx(
@@ -1324,13 +1873,24 @@ function SuperChat({
1324
1873
  onValueChange: handleDraftChange,
1325
1874
  onSend: handleComposerSend,
1326
1875
  disabled: readOnly,
1327
- placeholder: readOnly ? "Read-only conversation" : "Type a message\u2026 use @ to address an agent",
1876
+ className: "px-4 pb-4",
1877
+ placeholder: readOnly ? "Read-only conversation" : placeholder ?? "Type a message\u2026 use @ to address an agent",
1328
1878
  mentionOptions,
1329
- allowAttachments: !readOnly,
1879
+ allowAttachments: !readOnly && (allowAttachments ?? true),
1330
1880
  acceptedFileTypes: composerAccept,
1331
1881
  maxFileSize: 25 * 1024 * 1024,
1332
1882
  maxLength: 1e5,
1333
- inputLabel: "Message"
1883
+ inputLabel: "Message",
1884
+ showAgentSelector: !!agents?.length,
1885
+ agents,
1886
+ selectedAgent,
1887
+ onAgentChange,
1888
+ agentSelectorLabel,
1889
+ showModelSelector: !!modelSelectorProps,
1890
+ modelSelectorProps,
1891
+ isStreaming,
1892
+ onStop,
1893
+ stopLabel
1334
1894
  }
1335
1895
  )
1336
1896
  ]
@@ -1345,12 +1905,14 @@ function SuperChatConversations({
1345
1905
  onConversationOpened,
1346
1906
  onNewConversation
1347
1907
  }) {
1348
- const [internalActive, setInternalActive] = React2.useState(
1908
+ const [internalActive, setInternalActive] = React3.useState(
1349
1909
  defaultActiveConversationId ?? conversations[0]?.id
1350
1910
  );
1911
+ const [hasMounted, setHasMounted] = React3.useState(false);
1912
+ React3.useEffect(() => setHasMounted(true), []);
1351
1913
  const requestedId = activeConversationId ?? internalActive;
1352
1914
  const activeId = conversations.some((c) => c.id === requestedId) ? requestedId : conversations[0]?.id;
1353
- const sortedConversations = React2.useMemo(
1915
+ const sortedConversations = React3.useMemo(
1354
1916
  () => [...conversations].sort((a, b) => lastActivityOf(b) - lastActivityOf(a)),
1355
1917
  [conversations]
1356
1918
  );
@@ -1402,10 +1964,21 @@ function SuperChatConversations({
1402
1964
  /* @__PURE__ */ jsx("span", { className: "block truncate font-medium", children: c.title }),
1403
1965
  last?.text && /* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-neutral-600 dark:text-neutral-400", children: last.text })
1404
1966
  ] }),
1405
- !!c.unread && /* @__PURE__ */ jsxs("span", { className: "bg-primary-600 ms-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[10px] font-semibold text-white", children: [
1406
- c.unread,
1407
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: " unread messages" })
1408
- ] })
1967
+ /* @__PURE__ */ jsx(AnimatedPresence, { initial: hasMounted, children: !!c.unread && /* @__PURE__ */ jsxs(
1968
+ Animated,
1969
+ {
1970
+ as: "span",
1971
+ preset: "pop",
1972
+ mode: "presence",
1973
+ "data-slot": "superchat-unread-badge",
1974
+ className: "bg-primary-600 ms-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[10px] font-semibold text-white",
1975
+ children: [
1976
+ c.unread,
1977
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " unread messages" })
1978
+ ]
1979
+ },
1980
+ "unread"
1981
+ ) })
1409
1982
  ]
1410
1983
  }
1411
1984
  ) }, c.id);
@@ -1418,6 +1991,11 @@ function SuperChatConversations({
1418
1991
  }
1419
1992
  function SuperChatInbox({
1420
1993
  conversations,
1994
+ view,
1995
+ defaultView,
1996
+ onViewChange,
1997
+ mediaFeedProps,
1998
+ mediaLabels,
1421
1999
  activeConversationId,
1422
2000
  defaultActiveConversationId,
1423
2001
  currentParticipantId,
@@ -1439,13 +2017,13 @@ function SuperChatInbox({
1439
2017
  onNewConversation,
1440
2018
  onReferenceClick
1441
2019
  }) {
1442
- const [internalActive, setInternalActive] = React2.useState(
2020
+ const [internalActive, setInternalActive] = React3.useState(
1443
2021
  defaultActiveConversationId ?? conversations[0]?.id
1444
2022
  );
1445
2023
  const requestedId = activeConversationId ?? internalActive;
1446
2024
  const active = conversations.find((c) => c.id === requestedId) ?? conversations[0];
1447
2025
  const activeId = active?.id;
1448
- const [mobileView, setMobileView] = React2.useState("list");
2026
+ const [mobileView, setMobileView] = React3.useState("list");
1449
2027
  const handleOpen = (c) => {
1450
2028
  if (activeConversationId === void 0) setInternalActive(c.id);
1451
2029
  setMobileView("chat");
@@ -1479,6 +2057,11 @@ function SuperChatInbox({
1479
2057
  SuperChat,
1480
2058
  {
1481
2059
  conversation: active,
2060
+ view,
2061
+ defaultView,
2062
+ onViewChange,
2063
+ mediaFeedProps,
2064
+ mediaLabels,
1482
2065
  currentParticipantId,
1483
2066
  renderPlugins,
1484
2067
  renderTextContent,
@@ -1514,6 +2097,6 @@ function SuperChatInbox({
1514
2097
  );
1515
2098
  }
1516
2099
 
1517
- export { SuperChat, SuperChatConversations, SuperChatInbox, createMarkdownRenderer };
2100
+ export { SuperChat, SuperChatConversations, SuperChatInbox, createMarkdownRenderer, getConversationMediaItems };
1518
2101
  //# sourceMappingURL=index.js.map
1519
2102
  //# sourceMappingURL=index.js.map