@8wave/ai-elements 0.110.0 → 0.111.0-beta.11

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 (234) hide show
  1. package/README.md +1 -0
  2. package/dist/_chunks/{Agent-Su_LDF9_.js → Agent-tE7ZJPxG.js} +80 -78
  3. package/dist/_chunks/Agent-tE7ZJPxG.js.map +1 -0
  4. package/dist/_chunks/{Document-DecVclEe.js → Document-Bmx6774B.js} +33 -21
  5. package/dist/_chunks/Document-Bmx6774B.js.map +1 -0
  6. package/dist/_chunks/Media-Cft7Pwrh.js +108 -0
  7. package/dist/_chunks/Media-Cft7Pwrh.js.map +1 -0
  8. package/dist/_chunks/{PkLazyImg-ClL4nr95.js → PkLazyImg-Dbj2dDXA.js} +2 -2
  9. package/dist/_chunks/{PkLazyImg-ClL4nr95.js.map → PkLazyImg-Dbj2dDXA.js.map} +1 -1
  10. package/dist/_chunks/{PkStreamingMarkdown-CwqsJnJJ.js → PkStreamingMarkdown-CNI8aV8t.js} +636 -427
  11. package/dist/_chunks/PkStreamingMarkdown-CNI8aV8t.js.map +1 -0
  12. package/dist/_chunks/{PkToolRequestGeolocation-CEVpl50q.js → PkToolRequestGeolocation-Bzy4IYSp.js} +4 -4
  13. package/dist/_chunks/PkToolRequestGeolocation-Bzy4IYSp.js.map +1 -0
  14. package/dist/_chunks/{PkToolRequestOAuthConnection-CncDU-Kl.js → PkToolRequestOAuthConnection-13CQH07t.js} +5 -5
  15. package/dist/_chunks/PkToolRequestOAuthConnection-13CQH07t.js.map +1 -0
  16. package/dist/_chunks/{PkToolShowArtifact-M6jlSmyJ.js → PkToolShowArtifact-CGbHDEie.js} +4 -4
  17. package/dist/_chunks/{PkToolShowArtifact-M6jlSmyJ.js.map → PkToolShowArtifact-CGbHDEie.js.map} +1 -1
  18. package/dist/_chunks/{PkToolShowCalendarEvent-C41JgOUA.js → PkToolShowCalendarEvent-DIFX_rUz.js} +3 -3
  19. package/dist/_chunks/{PkToolShowCalendarEvent-C41JgOUA.js.map → PkToolShowCalendarEvent-DIFX_rUz.js.map} +1 -1
  20. package/dist/_chunks/{PkToolShowComparison-DbbUD9pg.js → PkToolShowComparison-CWLFWT9h.js} +7 -7
  21. package/dist/_chunks/PkToolShowComparison-CWLFWT9h.js.map +1 -0
  22. package/dist/_chunks/{PkToolShowContactForm-D_dW59Dl.js → PkToolShowContactForm-CYxgatUA.js} +5 -5
  23. package/dist/_chunks/PkToolShowContactForm-CYxgatUA.js.map +1 -0
  24. package/dist/_chunks/{PkToolShowDiagram-Hy9qh68O.js → PkToolShowDiagram-Dx1Ba0PG.js} +4 -4
  25. package/dist/_chunks/PkToolShowDiagram-Dx1Ba0PG.js.map +1 -0
  26. package/dist/_chunks/{PkToolShowEmail-Dn3JHYIR.js → PkToolShowEmail-DnFFgzom.js} +3 -3
  27. package/dist/_chunks/{PkToolShowEmail-Dn3JHYIR.js.map → PkToolShowEmail-DnFFgzom.js.map} +1 -1
  28. package/dist/_chunks/{PkToolShowForm-DbJHMDbt.js → PkToolShowForm-B6x3Lp2i.js} +7 -8
  29. package/dist/_chunks/PkToolShowForm-B6x3Lp2i.js.map +1 -0
  30. package/dist/_chunks/{PkToolShowImageGallery-C1lzlO0y.js → PkToolShowImageGallery-D99N_Plf.js} +2 -2
  31. package/dist/_chunks/{PkToolShowImageGallery-C1lzlO0y.js.map → PkToolShowImageGallery-D99N_Plf.js.map} +1 -1
  32. package/dist/_chunks/{PkToolShowLocation-CKhPxKFA.js → PkToolShowLocation-AfnrtFVJ.js} +3 -3
  33. package/dist/_chunks/{PkToolShowLocation-CKhPxKFA.js.map → PkToolShowLocation-AfnrtFVJ.js.map} +1 -1
  34. package/dist/_chunks/{PkToolShowMessage-U9CCU7eG.js → PkToolShowMessage-DUo2c-im.js} +3 -3
  35. package/dist/_chunks/{PkToolShowMessage-U9CCU7eG.js.map → PkToolShowMessage-DUo2c-im.js.map} +1 -1
  36. package/dist/_chunks/{PkToolShowProductList-UeiRMLHu.js → PkToolShowProductList-BN6Qk1_y.js} +3 -3
  37. package/dist/_chunks/{PkToolShowProductList-UeiRMLHu.js.map → PkToolShowProductList-BN6Qk1_y.js.map} +1 -1
  38. package/dist/_chunks/{PkToolShowQrCode-CypLrfh5.js → PkToolShowQrCode-BLqeBecX.js} +3 -3
  39. package/dist/_chunks/{PkToolShowQrCode-CypLrfh5.js.map → PkToolShowQrCode-BLqeBecX.js.map} +1 -1
  40. package/dist/_chunks/{PkToolShowSources-B69JmwbZ.js → PkToolShowSources-DpZb5FUP.js} +5 -5
  41. package/dist/_chunks/PkToolShowSources-DpZb5FUP.js.map +1 -0
  42. package/dist/_chunks/{PkToolShowSuggestedReply-CKxSH0Y9.js → PkToolShowSuggestedReply-C10nNgBs.js} +3 -3
  43. package/dist/_chunks/{PkToolShowSuggestedReply-CKxSH0Y9.js.map → PkToolShowSuggestedReply-C10nNgBs.js.map} +1 -1
  44. package/dist/_chunks/{PkToolShowVideo-BgKxdBcC.js → PkToolShowVideo-S9b4QHUj.js} +2 -2
  45. package/dist/_chunks/{PkToolShowVideo-BgKxdBcC.js.map → PkToolShowVideo-S9b4QHUj.js.map} +1 -1
  46. package/dist/_chunks/{PkToolShowWeather-LPd3tC77.js → PkToolShowWeather-CqhG430w.js} +2 -2
  47. package/dist/_chunks/PkToolShowWeather-CqhG430w.js.map +1 -0
  48. package/dist/_chunks/{PkToolShowWebPages-ep_erFF0.js → PkToolShowWebPages-txAZi_iG.js} +3 -3
  49. package/dist/_chunks/{PkToolShowWebPages-ep_erFF0.js.map → PkToolShowWebPages-txAZi_iG.js.map} +1 -1
  50. package/dist/_chunks/PkUrl-BPbjZJ1A.js.map +1 -1
  51. package/dist/_chunks/{VvCheckboxGroup.es-Bdu2gFLN.js → VvCheckboxGroup.es-CTrF3pue.js} +2 -2
  52. package/dist/_chunks/{VvCheckboxGroup.es-Bdu2gFLN.js.map → VvCheckboxGroup.es-CTrF3pue.js.map} +1 -1
  53. package/dist/_chunks/{VvCombobox.es-C0wpJIr_.js → VvCombobox.es-BWiXmQ_S.js} +10 -10
  54. package/dist/_chunks/{VvCombobox.es-C0wpJIr_.js.map → VvCombobox.es-BWiXmQ_S.js.map} +1 -1
  55. package/dist/_chunks/{VvInputText.es-Zgtw2YNw.js → VvInputText.es-Bo9I6g8H.js} +6 -6
  56. package/dist/_chunks/{VvInputText.es-Zgtw2YNw.js.map → VvInputText.es-Bo9I6g8H.js.map} +1 -1
  57. package/dist/_chunks/{VvRadioGroup.es-DZLL19SC.js → VvRadioGroup.es-9ooHCuik.js} +2 -2
  58. package/dist/_chunks/{VvRadioGroup.es-DZLL19SC.js.map → VvRadioGroup.es-9ooHCuik.js.map} +1 -1
  59. package/dist/_chunks/{VvSelect.es-ovnZRHG5.js → VvSelect.es-DG0VuWtP.js} +2 -2
  60. package/dist/_chunks/{VvSelect.es-ovnZRHG5.js.map → VvSelect.es-DG0VuWtP.js.map} +1 -1
  61. package/dist/_chunks/{VvTextarea.es-DbP5Lt2T.js → VvTextarea.es-Dg3pxdZy.js} +6 -6
  62. package/dist/_chunks/{VvTextarea.es-DbP5Lt2T.js.map → VvTextarea.es-Dg3pxdZy.js.map} +1 -1
  63. package/dist/_chunks/{browser-NgY6LXg-.js → browser-B0Xnbqi7.js} +726 -751
  64. package/dist/_chunks/browser-B0Xnbqi7.js.map +1 -0
  65. package/dist/_chunks/{dist-n5iFNYf-.js → dist-QdjZA6MJ.js} +143 -133
  66. package/dist/_chunks/{dist-n5iFNYf-.js.map → dist-QdjZA6MJ.js.map} +1 -1
  67. package/dist/_chunks/{index.es-dtdl3VFG.js → index.es-0YpCa4c5.js} +6 -6
  68. package/dist/_chunks/{index.es-dtdl3VFG.js.map → index.es-0YpCa4c5.js.map} +1 -1
  69. package/dist/_chunks/{index.es-BJnUA_36.js → index.es-CHkJ2TMJ.js} +10 -10
  70. package/dist/_chunks/{index.es-BJnUA_36.js.map → index.es-CHkJ2TMJ.js.map} +1 -1
  71. package/dist/_chunks/text-DbSEK8si.js.map +1 -1
  72. package/dist/ai-elements.es.js +3077 -3134
  73. package/dist/ai-elements.es.js.map +1 -1
  74. package/dist-vue/PkChatbot.js +1 -1
  75. package/dist-vue/PkChatbotEmptyState.js +1 -1
  76. package/dist-vue/PkChatbotError.js +1 -1
  77. package/dist-vue/PkChatbotFeedbackForm.js +1 -1
  78. package/dist-vue/PkChatbotFilePreview.js +1 -1
  79. package/dist-vue/PkChatbotInput.js +1 -1
  80. package/dist-vue/PkChatbotMessages.js +1 -1
  81. package/dist-vue/PkChatbotStepPayload.js +1 -1
  82. package/dist-vue/PkChatbotStepToolDetail.js +1 -1
  83. package/dist-vue/PkChatbotSteps.js +1 -1
  84. package/dist-vue/PkChatbotViewChat.js +1 -1
  85. package/dist-vue/PkChatbotViewConversations.js +1 -1
  86. package/dist-vue/PkChatbotViewFiles.js +1 -1
  87. package/dist-vue/PkChatbotViewProfile.js +1 -1
  88. package/dist-vue/_chunks/{Agent-C8BsTAxk.js → Agent-De2gFNjR.js} +165 -176
  89. package/dist-vue/_chunks/Agent-De2gFNjR.js.map +1 -0
  90. package/dist-vue/_chunks/{Document-CaUfI_SZ.js → Document-8umjeTVS.js} +84 -72
  91. package/dist-vue/_chunks/Document-8umjeTVS.js.map +1 -0
  92. package/dist-vue/_chunks/Media-_HfFLHGD.js.map +1 -1
  93. package/dist-vue/_chunks/{PkChatbot-o7k7d-fj.js → PkChatbot-CMajc7tE.js} +61 -61
  94. package/dist-vue/_chunks/PkChatbot-CMajc7tE.js.map +1 -0
  95. package/dist-vue/_chunks/{PkChatbotEmptyState-BvaeBxhx.js → PkChatbotEmptyState-BtzBYOHJ.js} +2 -2
  96. package/dist-vue/_chunks/{PkChatbotEmptyState-BvaeBxhx.js.map → PkChatbotEmptyState-BtzBYOHJ.js.map} +1 -1
  97. package/dist-vue/_chunks/{PkChatbotError-CBP2mf-n.js → PkChatbotError-gvDpRcEz.js} +21 -19
  98. package/dist-vue/_chunks/PkChatbotError-gvDpRcEz.js.map +1 -0
  99. package/dist-vue/_chunks/{PkChatbotFeedbackForm-DO1QIgmo.js → PkChatbotFeedbackForm-CxLOdwkm.js} +2 -2
  100. package/dist-vue/_chunks/PkChatbotFeedbackForm-CxLOdwkm.js.map +1 -0
  101. package/dist-vue/_chunks/{PkChatbotFilePreview-DO1wZPPj.js → PkChatbotFilePreview-CwiVQDF2.js} +3 -3
  102. package/dist-vue/_chunks/PkChatbotFilePreview-CwiVQDF2.js.map +1 -0
  103. package/dist-vue/_chunks/{PkChatbotInput-D8x52cVm.js → PkChatbotInput-MSpF6SB6.js} +140 -125
  104. package/dist-vue/_chunks/PkChatbotInput-MSpF6SB6.js.map +1 -0
  105. package/dist-vue/_chunks/PkChatbotMessages-Bz5q8EtT.js +776 -0
  106. package/dist-vue/_chunks/PkChatbotMessages-Bz5q8EtT.js.map +1 -0
  107. package/dist-vue/_chunks/{PkChatbotStepPayload-BH6piqOi.js → PkChatbotStepPayload-XW4gT9AZ.js} +2 -2
  108. package/dist-vue/_chunks/{PkChatbotStepPayload-BH6piqOi.js.map → PkChatbotStepPayload-XW4gT9AZ.js.map} +1 -1
  109. package/dist-vue/_chunks/{PkChatbotStepToolDetail-BJ7xUvgi.js → PkChatbotStepToolDetail-C4-K6Glw.js} +3 -3
  110. package/dist-vue/_chunks/{PkChatbotStepToolDetail-BJ7xUvgi.js.map → PkChatbotStepToolDetail-C4-K6Glw.js.map} +1 -1
  111. package/dist-vue/_chunks/PkChatbotSteps-CrqjWpv0.js +190 -0
  112. package/dist-vue/_chunks/PkChatbotSteps-CrqjWpv0.js.map +1 -0
  113. package/dist-vue/_chunks/{PkChatbotViewChat-CNH_glPI.js → PkChatbotViewChat-DXu5ncaU.js} +10 -10
  114. package/dist-vue/_chunks/{PkChatbotViewChat-CNH_glPI.js.map → PkChatbotViewChat-DXu5ncaU.js.map} +1 -1
  115. package/dist-vue/_chunks/{PkChatbotViewConversations-BENvHLZt.js → PkChatbotViewConversations-3LaZPFyw.js} +2 -2
  116. package/dist-vue/_chunks/{PkChatbotViewConversations-BENvHLZt.js.map → PkChatbotViewConversations-3LaZPFyw.js.map} +1 -1
  117. package/dist-vue/_chunks/{PkChatbotViewFiles-qmLESi1V.js → PkChatbotViewFiles-CTqnbsCj.js} +3 -3
  118. package/dist-vue/_chunks/{PkChatbotViewFiles-qmLESi1V.js.map → PkChatbotViewFiles-CTqnbsCj.js.map} +1 -1
  119. package/dist-vue/_chunks/{PkChatbotViewProfile-DzfZnitQ.js → PkChatbotViewProfile-B-Mp1jGQ.js} +2 -2
  120. package/dist-vue/_chunks/{PkChatbotViewProfile-DzfZnitQ.js.map → PkChatbotViewProfile-B-Mp1jGQ.js.map} +1 -1
  121. package/dist-vue/_chunks/PkRelativeTime--1cIphlA.js.map +1 -1
  122. package/dist-vue/_chunks/{PkStreamingMarkdown-D8_LwZMR.js → PkStreamingMarkdown-D0IOaETI.js} +432 -419
  123. package/dist-vue/_chunks/PkStreamingMarkdown-D0IOaETI.js.map +1 -0
  124. package/dist-vue/_chunks/{PkSvgViewer-DPpE9fiz.js → PkSvgViewer-D-0M5bqg.js} +2 -2
  125. package/dist-vue/_chunks/PkSvgViewer-D-0M5bqg.js.map +1 -0
  126. package/dist-vue/_chunks/{PkToolRequestGeolocation-D1ZPmWiB.js → PkToolRequestGeolocation-Q3N3jlO8.js} +3 -3
  127. package/dist-vue/_chunks/PkToolRequestGeolocation-Q3N3jlO8.js.map +1 -0
  128. package/dist-vue/_chunks/{PkToolRequestOAuthConnection-CoJyKEE6.js → PkToolRequestOAuthConnection-lYoTJIF_.js} +4 -4
  129. package/dist-vue/_chunks/PkToolRequestOAuthConnection-lYoTJIF_.js.map +1 -0
  130. package/dist-vue/_chunks/{PkToolShowArtifact-CEXdfOGG.js → PkToolShowArtifact-DHdJuzDi.js} +2 -2
  131. package/dist-vue/_chunks/{PkToolShowArtifact-CEXdfOGG.js.map → PkToolShowArtifact-DHdJuzDi.js.map} +1 -1
  132. package/dist-vue/_chunks/{PkToolShowComparison-DMSjIpCR.js → PkToolShowComparison-BLn4pkno.js} +5 -5
  133. package/dist-vue/_chunks/PkToolShowComparison-BLn4pkno.js.map +1 -0
  134. package/dist-vue/_chunks/{PkToolShowContactForm-DHmzAIVF.js → PkToolShowContactForm-DceSyuX8.js} +3 -3
  135. package/dist-vue/_chunks/PkToolShowContactForm-DceSyuX8.js.map +1 -0
  136. package/dist-vue/_chunks/{PkToolShowDiagram-DuDp5EHd.js → PkToolShowDiagram-pwc0wpNo.js} +4 -4
  137. package/dist-vue/_chunks/PkToolShowDiagram-pwc0wpNo.js.map +1 -0
  138. package/dist-vue/_chunks/{PkToolShowEmail-CavhsPvi.js → PkToolShowEmail-DF__nKpR.js} +2 -2
  139. package/dist-vue/_chunks/{PkToolShowEmail-CavhsPvi.js.map → PkToolShowEmail-DF__nKpR.js.map} +1 -1
  140. package/dist-vue/_chunks/{PkToolShowForm-CO5A_j9L.js → PkToolShowForm-Dx10jOXm.js} +7 -7
  141. package/dist-vue/_chunks/PkToolShowForm-Dx10jOXm.js.map +1 -0
  142. package/dist-vue/_chunks/{PkToolShowImageGallery-V9U3LJfF.js → PkToolShowImageGallery-DudQzBx4.js} +2 -2
  143. package/dist-vue/_chunks/{PkToolShowImageGallery-V9U3LJfF.js.map → PkToolShowImageGallery-DudQzBx4.js.map} +1 -1
  144. package/dist-vue/_chunks/{PkToolShowMessage-DQojxDiV.js → PkToolShowMessage-Ck6VP-gw.js} +2 -2
  145. package/dist-vue/_chunks/{PkToolShowMessage-DQojxDiV.js.map → PkToolShowMessage-Ck6VP-gw.js.map} +1 -1
  146. package/dist-vue/_chunks/{PkToolShowProductList-Cn0yewM3.js → PkToolShowProductList-zfM8cx-l.js} +2 -2
  147. package/dist-vue/_chunks/{PkToolShowProductList-Cn0yewM3.js.map → PkToolShowProductList-zfM8cx-l.js.map} +1 -1
  148. package/dist-vue/_chunks/{PkToolShowSources-BvWOzVkQ.js → PkToolShowSources-Dlaz2Y77.js} +5 -5
  149. package/dist-vue/_chunks/PkToolShowSources-Dlaz2Y77.js.map +1 -0
  150. package/dist-vue/_chunks/{PkToolShowSuggestedReply-DQFOVonE.js → PkToolShowSuggestedReply-DWLkUh2L.js} +2 -2
  151. package/dist-vue/_chunks/{PkToolShowSuggestedReply-DQFOVonE.js.map → PkToolShowSuggestedReply-DWLkUh2L.js.map} +1 -1
  152. package/dist-vue/_chunks/PkToolShowWeather-Bzqalzh8.js.map +1 -1
  153. package/dist-vue/_chunks/{PkToolShowWebPages-Bzkkn9GV.js → PkToolShowWebPages-CosBYLrE.js} +2 -2
  154. package/dist-vue/_chunks/{PkToolShowWebPages-Bzkkn9GV.js.map → PkToolShowWebPages-CosBYLrE.js.map} +1 -1
  155. package/dist-vue/_chunks/{PkUrl-xUBKVJCv.js → PkUrl-B5CNTQj9.js} +2 -2
  156. package/dist-vue/_chunks/PkUrl-B5CNTQj9.js.map +1 -0
  157. package/dist-vue/_chunks/{createChatbotApiClient-CJ_5_3IT.js → createChatbotApiClient-MkaPbGWB.js} +6 -3
  158. package/dist-vue/_chunks/createChatbotApiClient-MkaPbGWB.js.map +1 -0
  159. package/dist-vue/_chunks/{useChatbotStore-CiRAuq7v.js → useChatbotStore-BzfqjiYz.js} +6 -3
  160. package/dist-vue/_chunks/useChatbotStore-BzfqjiYz.js.map +1 -0
  161. package/dist-vue/_chunks/useDialogConfirm-KWz0ohCQ.js.map +1 -1
  162. package/dist-vue/_chunks/{utils-Coqik0XI.js → utils-C1666_6C.js} +58 -43
  163. package/dist-vue/_chunks/utils-C1666_6C.js.map +1 -0
  164. package/dist-vue/api.js +1 -1
  165. package/dist-vue/composables.js +3 -3
  166. package/dist-vue/index.js +3869 -3490
  167. package/dist-vue/index.js.map +1 -1
  168. package/dist-vue/locales.js +36 -8
  169. package/dist-vue/packages/components/src/chat/PkAgentSettingsPanel.d.ts +20 -3
  170. package/dist-vue/packages/components/src/chat/PkChatButton.d.ts +3 -2
  171. package/dist-vue/packages/components/src/chat/PkLanguageModel.d.ts +26 -2
  172. package/dist-vue/packages/components/src/chat/PkLanguageModelCombobox.d.ts +53 -1
  173. package/dist-vue/packages/components/src/chat/PkModelOption.d.ts +19 -0
  174. package/dist-vue/packages/components/src/chat/PkReasoningSettings.d.ts +6 -0
  175. package/dist-vue/packages/components/src/chat/PkStreamingMarkdown.d.ts +6 -0
  176. package/dist-vue/packages/components/src/chat/PkStreamingMarkdownAutoscroll.d.ts +1 -0
  177. package/dist-vue/packages/components/src/chat/constants.d.ts +5 -18
  178. package/dist-vue/packages/components/src/chat/index.d.ts +3 -1
  179. package/dist-vue/packages/components/src/chat/modelCatalog.d.ts +46 -0
  180. package/dist-vue/packages/components/src/chat/utils.d.ts +16 -0
  181. package/dist-vue/packages/components/src/table/PkTableSortable.d.ts +13 -1
  182. package/dist-vue/packages/composable/src/chatbot/useChatbotStore.d.ts +18 -0
  183. package/dist-vue/packages/composable/src/useChatbotError.d.ts +2 -0
  184. package/dist-vue/packages/models/src/schema/Agent.d.ts +70 -10
  185. package/dist-vue/packages/models/src/schema/Chat.d.ts +31 -0
  186. package/dist-vue/packages/models/src/schema/ModelProvider.d.ts +316 -0
  187. package/dist-vue/packages/models/src/schema/Organization.d.ts +142 -2
  188. package/dist-vue/packages/models/src/schema/ReasoningChat.d.ts +20 -0
  189. package/dist-vue/packages/models/src/schema/SubAgent.d.ts +20 -0
  190. package/dist-vue/packages/models/src/schema/UserOverview.d.ts +41 -0
  191. package/dist-vue/packages/models/src/schema/constants.d.ts +56 -91
  192. package/dist-vue/packages/models/src/schema/index.d.ts +1 -0
  193. package/dist-vue/style.css +1 -1
  194. package/package.json +1 -1
  195. package/dist/_chunks/Agent-Su_LDF9_.js.map +0 -1
  196. package/dist/_chunks/Document-DecVclEe.js.map +0 -1
  197. package/dist/_chunks/Media-C6SOQfJZ.js +0 -122
  198. package/dist/_chunks/Media-C6SOQfJZ.js.map +0 -1
  199. package/dist/_chunks/PkStreamingMarkdown-CwqsJnJJ.js.map +0 -1
  200. package/dist/_chunks/PkToolRequestGeolocation-CEVpl50q.js.map +0 -1
  201. package/dist/_chunks/PkToolRequestOAuthConnection-CncDU-Kl.js.map +0 -1
  202. package/dist/_chunks/PkToolShowComparison-DbbUD9pg.js.map +0 -1
  203. package/dist/_chunks/PkToolShowContactForm-D_dW59Dl.js.map +0 -1
  204. package/dist/_chunks/PkToolShowDiagram-Hy9qh68O.js.map +0 -1
  205. package/dist/_chunks/PkToolShowForm-DbJHMDbt.js.map +0 -1
  206. package/dist/_chunks/PkToolShowSources-B69JmwbZ.js.map +0 -1
  207. package/dist/_chunks/PkToolShowWeather-LPd3tC77.js.map +0 -1
  208. package/dist/_chunks/browser-NgY6LXg-.js.map +0 -1
  209. package/dist/_chunks/utils-YJ0ZOLDG.js +0 -185
  210. package/dist/_chunks/utils-YJ0ZOLDG.js.map +0 -1
  211. package/dist-vue/_chunks/Agent-C8BsTAxk.js.map +0 -1
  212. package/dist-vue/_chunks/Document-CaUfI_SZ.js.map +0 -1
  213. package/dist-vue/_chunks/PkChatbot-o7k7d-fj.js.map +0 -1
  214. package/dist-vue/_chunks/PkChatbotError-CBP2mf-n.js.map +0 -1
  215. package/dist-vue/_chunks/PkChatbotFeedbackForm-DO1QIgmo.js.map +0 -1
  216. package/dist-vue/_chunks/PkChatbotFilePreview-DO1wZPPj.js.map +0 -1
  217. package/dist-vue/_chunks/PkChatbotInput-D8x52cVm.js.map +0 -1
  218. package/dist-vue/_chunks/PkChatbotMessages-BFlU046I.js +0 -771
  219. package/dist-vue/_chunks/PkChatbotMessages-BFlU046I.js.map +0 -1
  220. package/dist-vue/_chunks/PkChatbotSteps-DtV1beDc.js +0 -180
  221. package/dist-vue/_chunks/PkChatbotSteps-DtV1beDc.js.map +0 -1
  222. package/dist-vue/_chunks/PkStreamingMarkdown-D8_LwZMR.js.map +0 -1
  223. package/dist-vue/_chunks/PkSvgViewer-DPpE9fiz.js.map +0 -1
  224. package/dist-vue/_chunks/PkToolRequestGeolocation-D1ZPmWiB.js.map +0 -1
  225. package/dist-vue/_chunks/PkToolRequestOAuthConnection-CoJyKEE6.js.map +0 -1
  226. package/dist-vue/_chunks/PkToolShowComparison-DMSjIpCR.js.map +0 -1
  227. package/dist-vue/_chunks/PkToolShowContactForm-DHmzAIVF.js.map +0 -1
  228. package/dist-vue/_chunks/PkToolShowDiagram-DuDp5EHd.js.map +0 -1
  229. package/dist-vue/_chunks/PkToolShowForm-CO5A_j9L.js.map +0 -1
  230. package/dist-vue/_chunks/PkToolShowSources-BvWOzVkQ.js.map +0 -1
  231. package/dist-vue/_chunks/PkUrl-xUBKVJCv.js.map +0 -1
  232. package/dist-vue/_chunks/createChatbotApiClient-CJ_5_3IT.js.map +0 -1
  233. package/dist-vue/_chunks/useChatbotStore-CiRAuq7v.js.map +0 -1
  234. package/dist-vue/_chunks/utils-Coqik0XI.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PkChatbotFilePreview-CwiVQDF2.js","names":["$t","$emit"],"sources":["../../../../packages/components/src/composables/useLightbox.ts","../../../../packages/components/src/chat/PkChatbotFilePreview.vue","../../../../packages/components/src/chat/PkChatbotFilePreview.vue"],"sourcesContent":["import {\n onBeforeUnmount,\n ref,\n shallowRef,\n type Ref,\n type ShallowRef,\n} from 'vue'\nimport type PhotoSwipeLightbox from 'photoswipe/lightbox'\nimport type PhotoSwipe from 'photoswipe'\nimport { loadCdnCss } from 'utils'\n\nconst PHOTOSWIPE_CSS =\n 'https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.css'\n\nconst DEFAULT_IMAGE_SIZE = { width: 1200, height: 800 }\n\nexport interface LightboxImage {\n url: string\n caption?: string\n alt?: string\n /** Natural width in px — used by PhotoSwipe for proper sizing. */\n width?: number\n /** Natural height in px — used by PhotoSwipe for proper sizing. */\n height?: number\n}\n\nexport interface LightboxOptions {\n /** Container element whose child anchors are the gallery items */\n gallery: Ref<HTMLElement | undefined>\n /** CSS selector for gallery items inside the container (default: `'a[data-pswp-src]'`) */\n children?: string\n loop?: boolean\n /** Show a download button in the lightbox toolbar */\n downloadable?: boolean\n /** Show an open-in-new-tab button in the lightbox toolbar */\n openInNewTab?: boolean\n}\n\nexport interface UseLightboxReturn {\n lightbox: ShallowRef<PhotoSwipeLightbox | null>\n /** Initialises PhotoSwipe. Call this inside `onMounted`. */\n init: () => Promise<void>\n}\n\n/**\n * Encapsulates PhotoSwipe 5 initialisation, toolbar customisation, and lifecycle cleanup.\n * CSS is injected into `document.head` so the overlay works in both regular DOM and Shadow DOM.\n *\n * Usage:\n * ```ts\n * const { init } = useLightbox({ gallery: galleryRef, downloadable: true })\n * onMounted(init)\n * ```\n */\nexport function useLightbox(options: LightboxOptions): UseLightboxReturn {\n const {\n gallery,\n children = 'a[data-pswp-src]',\n loop = true,\n downloadable = true,\n openInNewTab = true,\n } = options\n\n const lightbox = shallowRef<PhotoSwipeLightbox | null>(null)\n\n const init = async () => {\n if (!gallery.value) {\n return\n }\n\n // PhotoSwipe renders its overlay into document.body, so CSS must be in\n // document.head — not inside a shadow root.\n loadCdnCss(PHOTOSWIPE_CSS)\n injectPhotoSwipeOverrides()\n\n const { default: PhotoSwipeLightbox } =\n await import('photoswipe/lightbox')\n\n lightbox.value = new PhotoSwipeLightbox({\n gallery: gallery.value,\n children,\n pswpModule: () => import('photoswipe'),\n loop,\n arrowPrevSVG:\n '<svg aria-hidden=\"true\" class=\"pswp__icn\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#ffffff\" d=\"m10.828 12l4.95 4.95l-1.414 1.415L8 12l6.364-6.364l1.414 1.414z\"/></svg>',\n arrowNextSVG:\n '<svg aria-hidden=\"true\" class=\"pswp__icn\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#ffffff\" d=\"m13.172 12l-4.95-4.95l1.414-1.413L16 12l-6.364 6.364l-1.414-1.415z\"/></svg>',\n closeSVG:\n '<svg aria-hidden=\"true\" class=\"pswp__icn\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#ffffff\" d=\"m12 10.587l4.95-4.95l1.414 1.414l-4.95 4.95l4.95 4.95l-1.415 1.414l-4.95-4.95l-4.949 4.95l-1.414-1.415l4.95-4.95l-4.95-4.95L7.05 5.638z\"/></svg>',\n zoomSVG:\n '<svg aria-hidden=\"true\" class=\"pswp__icn\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g class=\"pswp__icn--zoom-in\"><path fill=\"#ffffff\" d=\"m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975zM10 10V7h2v3h3v2h-3v3h-2v-3H7v-2z\"/></g><g class=\"pswp__icn--zoom-out\"><path fill=\"#ffffff\" d=\"m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975zM7 10h8v2H7z\"/></g></svg>',\n })\n\n if (openInNewTab || downloadable) {\n lightbox.value.on('uiRegister', () => {\n const ui = lightbox.value!.pswp?.ui\n if (!ui) {\n return\n }\n\n if (openInNewTab) {\n ui.registerElement({\n name: 'open-in-new-tab-button',\n order: 8,\n isButton: true,\n html: '<svg aria-hidden=\"true\" class=\"pswp__icn\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#ffffff\" d=\"M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm11-3v8h-2V6.413l-7.793 7.794l-1.414-1.414L17.585 5H13V3z\"/></svg>',\n title: 'Open in new tab',\n onClick: (_, __, pswp) => {\n const url = getCurrentSlideUrl(pswp)\n if (url) {\n window.open(\n url,\n '_blank',\n 'noopener,noreferrer',\n )\n }\n },\n })\n }\n\n if (downloadable) {\n ui.registerElement({\n name: 'download-button',\n order: 9,\n isButton: true,\n html: '<svg aria-hidden=\"true\" class=\"pswp__icn\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#ffffff\" d=\"M3 19h18v2H3zm10-5.828L19.071 7.1l1.414 1.414L12 17L3.515 8.515L4.929 7.1L11 13.173V2h2z\"/></svg>',\n title: 'Download',\n onClick: (_, __, pswp) => {\n const url = getCurrentSlideUrl(pswp)\n if (url) {\n downloadImage(url)\n }\n },\n })\n }\n })\n }\n\n lightbox.value.init()\n }\n\n onBeforeUnmount(() => {\n lightbox.value?.destroy()\n lightbox.value = null\n })\n\n return { lightbox, init }\n}\n\n// ---------------------------------------------------------------------------\n// Image size preloading\n// ---------------------------------------------------------------------------\n\nexport interface UseImageSizesReturn {\n preload: (\n images: Array<{ url: string; width?: number; height?: number }>,\n ) => void\n getSize: (url: string) => { width: number; height: number }\n}\n\n/**\n * Preloads natural image dimensions so PhotoSwipe can size its slides correctly.\n * When `width`/`height` are already provided they are used as-is;\n * otherwise the image is loaded in the background to read `naturalWidth`/`naturalHeight`.\n */\nexport function useImageSizes(): UseImageSizesReturn {\n const sizes = ref(new Map<string, { width: number; height: number }>())\n\n const preload = (\n images: Array<{ url: string; width?: number; height?: number }>,\n ) => {\n for (const image of images) {\n if (image.width && image.height) {\n sizes.value.set(image.url, {\n width: image.width,\n height: image.height,\n })\n continue\n }\n const img = new Image()\n img.onload = () => {\n sizes.value.set(image.url, {\n width: img.naturalWidth,\n height: img.naturalHeight,\n })\n }\n img.src = image.url\n }\n }\n\n const getSize = (url: string) => sizes.value.get(url) ?? DEFAULT_IMAGE_SIZE\n\n return { preload, getSize }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getCurrentSlideUrl(pswp: PhotoSwipe): string | undefined {\n return (\n pswp.currSlide?.data?.src ??\n pswp.currSlide?.data?.element\n ?.querySelector('img')\n ?.getAttribute('src') ??\n pswp.currSlide?.data?.element\n ?.querySelector('source')\n ?.getAttribute('srcset') ??\n pswp.currSlide?.data?.element?.getAttribute('src') ??\n undefined\n )\n}\n\n/**\n * Triggers a client-side download for an image URL.\n *\n * For backend media URLs (.../media/:file/view), navigates to the\n * corresponding /download endpoint which redirects to an Azure SAS URL\n * with `Content-Disposition: attachment` — no CORS issues.\n *\n * For blob: URLs (in-session uploads), uses the fetch → blob approach.\n *\n * For data: URLs (inline SVGs, etc.), use the download attribute.\n *\n * Falls back to opening in a new tab for all other cases.\n */\nfunction downloadImage(url: string): void {\n const downloadUrl = toDownloadUrl(url)\n\n const anchor = document.createElement('a')\n anchor.href = downloadUrl\n anchor.target = '_blank'\n anchor.rel = 'noopener noreferrer'\n // `download` attribute works for same-origin, data: and blob: URLs; for\n // cross-origin it is ignored but the browser still follows Content-Disposition.\n anchor.download = getFilenameFromUrl(url)\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n}\n\n/**\n * Converts a `/view` media URL to its `/download` counterpart.\n * Leaves blob:, data: and all other URLs untouched.\n */\nfunction toDownloadUrl(url: string): string {\n return url.replace(/\\/view(\\?|$)/, '/download$1')\n}\n\nfunction getFilenameFromUrl(url: string): string {\n if (url.startsWith('data:image/svg+xml')) {\n return 'diagram.svg'\n }\n if (url.startsWith('data:')) {\n const mime = url.split(':')[1].split(';')[0]\n const ext = mime.split('/')[1] || 'bin'\n return `image.${ext}`\n }\n try {\n const pathname = new URL(url).pathname\n const name = pathname.split('/').pop()\n return name && name.includes('.') ? name : 'image'\n } catch {\n return 'image'\n }\n}\n\nlet overridesInjected = false\n\n/**\n * Injects a one-time `<style>` into `document.head` that raises\n * PhotoSwipe's z-index above any host UI (e.g. floating chat widgets\n * that use `z-index: 2147483647`).\n */\nfunction injectPhotoSwipeOverrides(): void {\n if (overridesInjected) {\n return\n }\n overridesInjected = true\n const style = document.createElement('style')\n style.textContent = [\n '.pswp__counter { font-family: sans-serif; }',\n '.pswp { z-index: 2147483647 !important; }',\n '.pswp__icn { width: 20px; height: 20px; }',\n '.pswp__button { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; }',\n '.pswp__icn--zoom-out { display: none; }',\n '.pswp--zoomed-in .pswp__icn--zoom-in { display: none; }',\n '.pswp--zoomed-in .pswp__icn--zoom-out { display: block; }',\n '.pswp__button--arrow .pswp__icn {left: auto; right: auto; width: 40px; height: 40px; transform: none; margin-top: -20px; }',\n ].join(' ')\n document.head.appendChild(style)\n}\n","<script lang=\"ts\" setup>\n import { computed, ref, onMounted } from 'vue'\n import { useLightbox } from '../composables/useLightbox'\n\n const props = defineProps<{\n mediaType: string\n url: string\n filename?: string\n /** Size in bytes, when known (e.g. local uploads). */\n size?: number\n loading?: boolean\n error?: string\n removable?: boolean\n /**\n * Dense layout for the composer: a small square thumbnail / slim row,\n * without the metadata caption. The full card is reserved for the\n * message log where the details matter.\n */\n compact?: boolean\n }>()\n\n defineEmits<{\n remove: []\n }>()\n\n const isImage = computed(() => props.mediaType.startsWith('image/'))\n\n // --- File-type identity (icon + accent + human kind label) ---\n\n const extension = computed(() => {\n const name = props.filename ?? ''\n const dot = name.lastIndexOf('.')\n return dot > 0 ? name.slice(dot + 1).toLowerCase() : ''\n })\n\n // mediaType subtype, e.g. \"pdf\" from \"application/pdf\"\n const subtype = computed(\n () => props.mediaType.split('/')[1]?.split(';')[0] ?? '',\n )\n\n type FileKind = {\n icon: string\n // CSS color driving the icon glyph + tile tint\n accent: string\n label: string\n }\n\n const KINDS: Array<{ test: RegExp; kind: FileKind }> = [\n {\n test: /pdf/,\n kind: {\n icon: 'ri:file-pdf-2-line',\n accent: '#e2483d',\n label: 'PDF',\n },\n },\n {\n // Match Word specifically: the generic `document` substring also\n // appears in the XLSX/PPTX OOXML mime types (…officedocument…), so\n // matching it here would mis-label spreadsheets/decks as Word.\n test: /msword|wordprocessingml/,\n kind: {\n icon: 'ri:file-word-2-line',\n accent: '#2b7de9',\n label: 'Word',\n },\n },\n {\n test: /sheet|excel|csv/,\n kind: {\n icon: 'ri:file-excel-2-line',\n accent: '#1f9d57',\n label: 'Spreadsheet',\n },\n },\n {\n test: /presentation|powerpoint/,\n kind: {\n icon: 'ri:file-ppt-2-line',\n accent: '#d98324',\n label: 'Presentation',\n },\n },\n {\n test: /zip|compressed|x-7z|x-rar|x-tar|gzip/,\n kind: {\n icon: 'ri:file-zip-line',\n accent: '#c08a1e',\n label: 'Archive',\n },\n },\n {\n test: /^audio\\//,\n kind: {\n icon: 'ri:file-music-line',\n accent: '#8b5cf6',\n label: 'Audio',\n },\n },\n {\n test: /^video\\//,\n kind: {\n icon: 'ri:film-line',\n accent: '#6366f1',\n label: 'Video',\n },\n },\n {\n test: /json|javascript|typescript|xml|html|x-sh|x-python/,\n kind: {\n icon: 'ri:file-code-line',\n accent: '#0d9488',\n label: 'Code',\n },\n },\n {\n test: /^text\\//,\n kind: {\n icon: 'ri:file-text-line',\n accent: '#64748b',\n label: 'Text',\n },\n },\n ]\n\n const fileKind = computed<FileKind>(() => {\n const haystack = `${props.mediaType} ${extension.value}`\n for (const { test, kind } of KINDS) {\n if (test.test(haystack)) {\n return kind\n }\n }\n return {\n icon: 'ri:file-line',\n accent: '#64748b',\n label: 'File',\n }\n })\n\n // Short type tag shown in the meta line: prefer the real extension, fall\n // back to the mime subtype, then the generic kind label.\n const typeTag = computed(() =>\n (\n extension.value ||\n subtype.value ||\n fileKind.value.label\n ).toUpperCase(),\n )\n\n // --- Size & dimensions ---\n\n const formattedSize = computed(() => {\n const bytes = props.size\n if (bytes === undefined || bytes < 0) {\n return undefined\n }\n if (bytes < 1024) {\n return `${bytes} B`\n }\n const units = ['KB', 'MB', 'GB', 'TB']\n let value = bytes / 1024\n let unitIndex = 0\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024\n unitIndex += 1\n }\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${units[unitIndex]}`\n })\n\n // Thumbnail load lifecycle. Driving the spinner and the error fallback\n // off the real <img> events (not a second background fetch) means the\n // image is requested exactly once and reuses the browser cache on any\n // later re-render, instead of re-downloading every time the message list\n // repaints.\n // Not `useImageFallback`: this tile also needs `loading` vs `loaded` and the\n // decoded dimensions, cached across remounts, so the error flag is one field\n // of a richer per-url entry rather than a standalone broken-url set.\n type ThumbStatus = 'loading' | 'loaded' | 'error'\n\n // Module-level, keyed by URL: survives component recreation. In polled\n // views (e.g. admin chat-logs, refreshed every few seconds) the whole\n // message array is replaced on each poll, so this component can be torn\n // down and rebuilt. Seeding from the cache means a URL that already\n // decoded starts in `loaded` (no spinner flash, no re-decode) instead of\n // flickering back through `loading`. This is a client-side, per-session\n // cache (no server/Redis involved); bounded to a max size so a long-lived\n // session browsing many images can't grow it without limit — the oldest\n // entry is evicted first (Map preserves insertion order).\n type ThumbEntry = {\n status: ThumbStatus\n dimensions?: { width: number; height: number }\n }\n const THUMB_CACHE_MAX = 300\n const thumbCache = new Map<string, ThumbEntry>()\n const setThumbCache = (url: string, entry: ThumbEntry) => {\n // Re-insert to mark as most-recently used, then trim from the front.\n thumbCache.delete(url)\n thumbCache.set(url, entry)\n if (thumbCache.size > THUMB_CACHE_MAX) {\n thumbCache.delete(thumbCache.keys().next().value as string)\n }\n }\n\n const cached = thumbCache.get(props.url)\n const thumbStatus = ref<ThumbStatus>(cached?.status ?? 'loading')\n\n // Natural pixel dimensions, captured once the thumbnail decodes. Doubles\n // as the size hint PhotoSwipe needs for its slide (falls back until known).\n const dimensions = ref<{ width: number; height: number } | undefined>(\n cached?.dimensions,\n )\n const onImageLoad = (event: Event) => {\n const img = event.target as HTMLImageElement\n if (img.naturalWidth && img.naturalHeight) {\n dimensions.value = {\n width: img.naturalWidth,\n height: img.naturalHeight,\n }\n }\n thumbStatus.value = 'loaded'\n setThumbCache(props.url, {\n status: 'loaded',\n dimensions: dimensions.value,\n })\n }\n const onImageError = () => {\n thumbStatus.value = 'error'\n setThumbCache(props.url, { status: 'error' })\n }\n\n const pswpSize = computed(() => dimensions.value ?? DEFAULT_PSWP_SIZE)\n\n // Meta fragments joined with \" · \" for the caption / doc subtitle.\n const imageMeta = computed(() =>\n [\n dimensions.value &&\n `${dimensions.value.width}×${dimensions.value.height}`,\n formattedSize.value,\n ].filter(Boolean),\n )\n const docMeta = computed(() =>\n [typeTag.value, formattedSize.value].filter(Boolean),\n )\n\n // --- Lightbox ---\n\n // Slide size PhotoSwipe assumes before the real dimensions are known.\n const DEFAULT_PSWP_SIZE = { width: 1200, height: 800 }\n\n const galleryRef = ref<HTMLElement>()\n const { init } = useLightbox({ gallery: galleryRef, loop: false })\n\n onMounted(async () => {\n if (!isImage.value) {\n return\n }\n await init()\n })\n</script>\n\n<template>\n <!-- Image attachment: a thumbnail tile with a metadata caption -->\n <figure\n v-if=\"isImage\"\n class=\"pk-chatbot-file-preview pk-chatbot-file-preview--image\"\n :class=\"{ 'pk-chatbot-file-preview--compact': compact }\">\n <div ref=\"galleryRef\" class=\"pk-chatbot-file-preview__thumb-wrap\">\n <a\n :href=\"url\"\n :data-pswp-src=\"url\"\n :data-pswp-width=\"pswpSize.width\"\n :data-pswp-height=\"pswpSize.height\"\n :data-pswp-caption=\"filename ?? ''\"\n class=\"pk-chatbot-file-preview__thumb-link\"\n :aria-label=\"filename ?? $t('label.file')\">\n <img\n v-show=\"thumbStatus === 'loaded'\"\n :src=\"url\"\n :alt=\"filename\"\n decoding=\"async\"\n class=\"pk-chatbot-file-preview__thumb\"\n @load=\"onImageLoad\"\n @error=\"onImageError\" />\n </a>\n <!-- Spinner until the thumbnail decodes (or while an upload is in\n flight); a fixed box keeps this from shifting the layout. -->\n <span\n v-if=\"loading || thumbStatus === 'loading'\"\n class=\"pk-chatbot-file-preview__status pk-chatbot-file-preview__status--overlay\">\n <VvIcon name=\"loading-loop\" />\n </span>\n <!-- Failed to load: a quiet icon instead of the browser's broken\n image glyph. -->\n <span\n v-else-if=\"thumbStatus === 'error'\"\n class=\"pk-chatbot-file-preview__status pk-chatbot-file-preview__status--overlay pk-chatbot-file-preview__status--error\">\n <VvIcon name=\"ri:image-2-line\" />\n </span>\n </div>\n <figcaption v-if=\"!compact\" class=\"pk-chatbot-file-preview__caption\">\n <span\n v-if=\"filename\"\n class=\"pk-chatbot-file-preview__name\"\n :title=\"filename\"\n >{{ filename }}</span\n >\n <span class=\"pk-chatbot-file-preview__meta\">\n <span\n v-if=\"error\"\n class=\"pk-chatbot-file-preview__error\"\n :title=\"error\">\n <VvIcon name=\"ri:error-warning-line\" />\n {{ error }}\n </span>\n <template v-else>{{ imageMeta.join(' · ') }}</template>\n </span>\n </figcaption>\n <button\n v-if=\"removable && !loading\"\n type=\"button\"\n class=\"pk-chatbot-file-preview__remove\"\n :title=\"$t('action.remove')\"\n :aria-label=\"$t('action.remove')\"\n @click.prevent=\"$emit('remove')\">\n <VvIcon name=\"ri:close-line\" />\n </button>\n </figure>\n\n <!-- Document attachment: an icon tile + name + type · size -->\n <div\n v-else\n class=\"pk-chatbot-file-preview pk-chatbot-file-preview--doc\"\n :class=\"{\n 'pk-chatbot-file-preview--error': error,\n 'pk-chatbot-file-preview--compact': compact,\n }\">\n <span\n class=\"pk-chatbot-file-preview__icon-tile\"\n :style=\"{ '--file-accent': fileKind.accent }\">\n <VvIcon\n v-if=\"loading\"\n name=\"loading-loop\"\n class=\"pk-chatbot-file-preview__icon\" />\n <VvIcon\n v-else\n :name=\"fileKind.icon\"\n class=\"pk-chatbot-file-preview__icon\" />\n </span>\n <span class=\"pk-chatbot-file-preview__body\">\n <span\n v-if=\"filename\"\n class=\"pk-chatbot-file-preview__name\"\n :title=\"filename\"\n >{{ filename }}</span\n >\n <span class=\"pk-chatbot-file-preview__meta\">\n <span\n v-if=\"error\"\n class=\"pk-chatbot-file-preview__error\"\n :title=\"error\">\n <VvIcon name=\"ri:error-warning-line\" />\n {{ error }}\n </span>\n <template v-else>{{ docMeta.join(' · ') }}</template>\n </span>\n </span>\n <a\n v-if=\"!loading && !error && !compact\"\n :href=\"url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"pk-chatbot-file-preview__open\"\n :title=\"$t('action.download')\"\n :aria-label=\"`${$t('action.download')}${filename ? ` — ${filename}` : ''}`\">\n <VvIcon name=\"ri:download-2-line\" />\n </a>\n <button\n v-if=\"removable && !loading\"\n type=\"button\"\n class=\"pk-chatbot-file-preview__remove\"\n :class=\"{ 'pk-chatbot-file-preview__remove--inline': !compact }\"\n :title=\"$t('action.remove')\"\n :aria-label=\"$t('action.remove')\"\n @click=\"$emit('remove')\">\n <VvIcon name=\"ri:close-line\" />\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-chatbot-file-preview {\n // Concentric radii: outer card and inner tiles share an 8px step.\n --file-radius: var(--rounded-lg, 12px);\n position: relative;\n max-width: 280px;\n background-color: var(--color-surface-1);\n border: 1px solid var(--color-surface-3);\n border-radius: var(--file-radius);\n color: var(--color-word-2);\n font-size: var(--text-12);\n\n &--error {\n border-color: var(--color-danger);\n }\n\n // --- Document card ---\n &--doc {\n display: flex;\n align-items: center;\n gap: var(--spacing-8);\n padding: var(--spacing-8);\n min-width: 0;\n transition:\n border-color 0.18s var(--ease-out),\n background-color 0.18s var(--ease-out),\n box-shadow 0.18s var(--ease-out);\n\n &:hover {\n border-color: var(--color-surface-4);\n background-color: var(--color-surface-2);\n box-shadow: var(--shadow-sm);\n }\n }\n\n &__icon-tile {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--spacing-36);\n height: var(--spacing-36);\n // One step down from the card radius keeps the nested tile concentric.\n border-radius: var(--rounded-md, 6px);\n // Tint derived from the file-type accent; glyph sits at full accent.\n background-color: color-mix(\n in srgb,\n var(--file-accent) 14%,\n transparent\n );\n color: var(--file-accent);\n }\n\n &__icon {\n width: var(--spacing-20);\n height: var(--spacing-20);\n }\n\n &__body {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n flex: 1;\n }\n\n &__open {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--spacing-28);\n height: var(--spacing-28);\n margin-inline-start: var(--spacing-4);\n border-radius: var(--rounded);\n color: var(--color-word-3);\n text-decoration: none;\n opacity: 0;\n transition:\n opacity 0.18s var(--ease-out),\n color 0.18s var(--ease-out),\n background-color 0.18s var(--ease-out);\n\n &:hover {\n background-color: var(--color-surface-3);\n color: var(--color-word-1);\n }\n }\n\n &--doc:hover &__open,\n &--doc:focus-within &__open {\n opacity: 1;\n }\n\n // Touch devices have no hover: keep the open affordance visible.\n @media (hover: none) {\n &--doc &__open {\n opacity: 1;\n }\n }\n\n // --- Image card ---\n &--image {\n display: inline-flex;\n flex-direction: column;\n margin: 0;\n }\n\n &__thumb-wrap {\n position: relative;\n display: flex;\n // Fixed box: the card claims its final footprint before the\n // image decodes, so the message log never shifts on load.\n width: 280px;\n max-width: 100%;\n height: 200px;\n background-color: var(--color-surface);\n border-radius: var(--file-radius);\n overflow: hidden;\n }\n\n &__thumb-link {\n display: flex;\n width: 100%;\n height: 100%;\n cursor: pointer;\n }\n\n &__thumb {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n &__caption {\n display: flex;\n flex-direction: column;\n gap: 1px;\n padding: var(--spacing-8);\n min-width: 0;\n }\n\n &__name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: var(--font-medium, 500);\n color: var(--color-word-1);\n }\n\n &__meta {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-10);\n line-height: var(--leading-normal);\n // Reserve the line even while empty: image dimensions arrive\n // only after decode and must not grow the caption.\n min-height: 1.4em;\n color: var(--color-word-4);\n // Stable column for the dimensions/size figures.\n font-variant-numeric: tabular-nums;\n }\n\n &__error {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n color: var(--color-danger);\n\n .vv-icon {\n flex-shrink: 0;\n }\n }\n\n &__status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n .vv-icon {\n width: var(--spacing-32);\n height: var(--spacing-32);\n }\n\n &--overlay {\n position: absolute;\n inset: 0;\n background-color: color-mix(\n in srgb,\n var(--color-surface-1) 70%,\n transparent\n );\n color: var(--color-word-1);\n }\n\n &--error {\n color: var(--color-word-4);\n }\n }\n\n // --- Remove button (input context) ---\n &__remove {\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n display: flex;\n align-items: center;\n justify-content: center;\n // Visible glyph is 18px but the hit area stays a comfortable 28px.\n width: var(--spacing-28);\n height: var(--spacing-28);\n padding: 0;\n border: none;\n border-radius: var(--rounded-full, 9999px);\n background-color: color-mix(\n in srgb,\n var(--color-surface-1) 85%,\n transparent\n );\n color: var(--color-word-2);\n cursor: pointer;\n line-height: 1;\n box-shadow: var(--shadow-sm);\n transition:\n background-color 0.18s var(--ease-out),\n color 0.18s var(--ease-out),\n scale 0.12s var(--ease-out);\n\n &:hover {\n background-color: var(--color-surface-2);\n color: var(--color-word-1);\n }\n\n &:active {\n scale: 0.96;\n }\n\n // Inside the document row the button rides inline, not overlaid\n // (size is inherited from the base).\n &--inline {\n position: static;\n flex-shrink: 0;\n box-shadow: none;\n background-color: transparent;\n color: var(--color-word-4);\n\n &:hover {\n background-color: var(--color-surface-3);\n color: var(--color-word-1);\n }\n }\n }\n\n // --- Compact (composer) chips ---\n // ChatGPT/Gemini-style: every attachment is the SAME height and carries\n // an always-visible round remove control in the top-right corner — no\n // hover-revealed actions, no size mismatch between image and file chips.\n &--compact {\n // Shared chip height so image and file chips align in the row.\n --chip-size: var(--spacing-56);\n max-width: 240px;\n\n &.pk-chatbot-file-preview--image {\n width: var(--chip-size);\n height: var(--chip-size);\n border-radius: var(--rounded-md, 6px);\n }\n\n // Fill the square; the root's `overflow: hidden` rounds the corners.\n .pk-chatbot-file-preview__thumb-wrap,\n .pk-chatbot-file-preview__thumb-link {\n width: 100%;\n height: 100%;\n }\n\n &.pk-chatbot-file-preview--doc {\n height: var(--chip-size);\n gap: var(--spacing-8);\n padding: var(--spacing-8);\n // Reserve room so the corner remove button never overlaps the\n // name/meta text.\n padding-inline-end: var(--spacing-28);\n }\n\n // Square icon tile that fills the chip height, so file chips read at\n // the same scale as image thumbnails.\n .pk-chatbot-file-preview__icon-tile {\n align-self: stretch;\n width: auto;\n height: auto;\n aspect-ratio: 1;\n }\n\n .pk-chatbot-file-preview__icon {\n width: var(--spacing-20);\n height: var(--spacing-20);\n }\n }\n\n // Always-visible round remove control in the top-right corner. Sits\n // just inside the chip (an ancestor clips overflow), bigger than before,\n // with an extended hit area for easy tapping.\n &--compact &__remove {\n top: var(--spacing-4);\n right: var(--spacing-4);\n width: var(--spacing-24);\n height: var(--spacing-24);\n border: 1px solid var(--color-surface-4);\n background-color: var(--color-surface);\n color: var(--color-word-1);\n font-size: var(--text-16);\n box-shadow: var(--shadow-sm);\n\n // Comfortable touch/click target beyond the small visible glyph.\n &::after {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--spacing-4));\n }\n\n &:hover {\n background-color: var(--color-surface-2);\n color: var(--color-word-1);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n &--doc,\n &__open,\n &__remove {\n transition: none;\n }\n }\n }\n</style>\n","<script lang=\"ts\" setup>\n import { computed, ref, onMounted } from 'vue'\n import { useLightbox } from '../composables/useLightbox'\n\n const props = defineProps<{\n mediaType: string\n url: string\n filename?: string\n /** Size in bytes, when known (e.g. local uploads). */\n size?: number\n loading?: boolean\n error?: string\n removable?: boolean\n /**\n * Dense layout for the composer: a small square thumbnail / slim row,\n * without the metadata caption. The full card is reserved for the\n * message log where the details matter.\n */\n compact?: boolean\n }>()\n\n defineEmits<{\n remove: []\n }>()\n\n const isImage = computed(() => props.mediaType.startsWith('image/'))\n\n // --- File-type identity (icon + accent + human kind label) ---\n\n const extension = computed(() => {\n const name = props.filename ?? ''\n const dot = name.lastIndexOf('.')\n return dot > 0 ? name.slice(dot + 1).toLowerCase() : ''\n })\n\n // mediaType subtype, e.g. \"pdf\" from \"application/pdf\"\n const subtype = computed(\n () => props.mediaType.split('/')[1]?.split(';')[0] ?? '',\n )\n\n type FileKind = {\n icon: string\n // CSS color driving the icon glyph + tile tint\n accent: string\n label: string\n }\n\n const KINDS: Array<{ test: RegExp; kind: FileKind }> = [\n {\n test: /pdf/,\n kind: {\n icon: 'ri:file-pdf-2-line',\n accent: '#e2483d',\n label: 'PDF',\n },\n },\n {\n // Match Word specifically: the generic `document` substring also\n // appears in the XLSX/PPTX OOXML mime types (…officedocument…), so\n // matching it here would mis-label spreadsheets/decks as Word.\n test: /msword|wordprocessingml/,\n kind: {\n icon: 'ri:file-word-2-line',\n accent: '#2b7de9',\n label: 'Word',\n },\n },\n {\n test: /sheet|excel|csv/,\n kind: {\n icon: 'ri:file-excel-2-line',\n accent: '#1f9d57',\n label: 'Spreadsheet',\n },\n },\n {\n test: /presentation|powerpoint/,\n kind: {\n icon: 'ri:file-ppt-2-line',\n accent: '#d98324',\n label: 'Presentation',\n },\n },\n {\n test: /zip|compressed|x-7z|x-rar|x-tar|gzip/,\n kind: {\n icon: 'ri:file-zip-line',\n accent: '#c08a1e',\n label: 'Archive',\n },\n },\n {\n test: /^audio\\//,\n kind: {\n icon: 'ri:file-music-line',\n accent: '#8b5cf6',\n label: 'Audio',\n },\n },\n {\n test: /^video\\//,\n kind: {\n icon: 'ri:film-line',\n accent: '#6366f1',\n label: 'Video',\n },\n },\n {\n test: /json|javascript|typescript|xml|html|x-sh|x-python/,\n kind: {\n icon: 'ri:file-code-line',\n accent: '#0d9488',\n label: 'Code',\n },\n },\n {\n test: /^text\\//,\n kind: {\n icon: 'ri:file-text-line',\n accent: '#64748b',\n label: 'Text',\n },\n },\n ]\n\n const fileKind = computed<FileKind>(() => {\n const haystack = `${props.mediaType} ${extension.value}`\n for (const { test, kind } of KINDS) {\n if (test.test(haystack)) {\n return kind\n }\n }\n return {\n icon: 'ri:file-line',\n accent: '#64748b',\n label: 'File',\n }\n })\n\n // Short type tag shown in the meta line: prefer the real extension, fall\n // back to the mime subtype, then the generic kind label.\n const typeTag = computed(() =>\n (\n extension.value ||\n subtype.value ||\n fileKind.value.label\n ).toUpperCase(),\n )\n\n // --- Size & dimensions ---\n\n const formattedSize = computed(() => {\n const bytes = props.size\n if (bytes === undefined || bytes < 0) {\n return undefined\n }\n if (bytes < 1024) {\n return `${bytes} B`\n }\n const units = ['KB', 'MB', 'GB', 'TB']\n let value = bytes / 1024\n let unitIndex = 0\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024\n unitIndex += 1\n }\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${units[unitIndex]}`\n })\n\n // Thumbnail load lifecycle. Driving the spinner and the error fallback\n // off the real <img> events (not a second background fetch) means the\n // image is requested exactly once and reuses the browser cache on any\n // later re-render, instead of re-downloading every time the message list\n // repaints.\n // Not `useImageFallback`: this tile also needs `loading` vs `loaded` and the\n // decoded dimensions, cached across remounts, so the error flag is one field\n // of a richer per-url entry rather than a standalone broken-url set.\n type ThumbStatus = 'loading' | 'loaded' | 'error'\n\n // Module-level, keyed by URL: survives component recreation. In polled\n // views (e.g. admin chat-logs, refreshed every few seconds) the whole\n // message array is replaced on each poll, so this component can be torn\n // down and rebuilt. Seeding from the cache means a URL that already\n // decoded starts in `loaded` (no spinner flash, no re-decode) instead of\n // flickering back through `loading`. This is a client-side, per-session\n // cache (no server/Redis involved); bounded to a max size so a long-lived\n // session browsing many images can't grow it without limit — the oldest\n // entry is evicted first (Map preserves insertion order).\n type ThumbEntry = {\n status: ThumbStatus\n dimensions?: { width: number; height: number }\n }\n const THUMB_CACHE_MAX = 300\n const thumbCache = new Map<string, ThumbEntry>()\n const setThumbCache = (url: string, entry: ThumbEntry) => {\n // Re-insert to mark as most-recently used, then trim from the front.\n thumbCache.delete(url)\n thumbCache.set(url, entry)\n if (thumbCache.size > THUMB_CACHE_MAX) {\n thumbCache.delete(thumbCache.keys().next().value as string)\n }\n }\n\n const cached = thumbCache.get(props.url)\n const thumbStatus = ref<ThumbStatus>(cached?.status ?? 'loading')\n\n // Natural pixel dimensions, captured once the thumbnail decodes. Doubles\n // as the size hint PhotoSwipe needs for its slide (falls back until known).\n const dimensions = ref<{ width: number; height: number } | undefined>(\n cached?.dimensions,\n )\n const onImageLoad = (event: Event) => {\n const img = event.target as HTMLImageElement\n if (img.naturalWidth && img.naturalHeight) {\n dimensions.value = {\n width: img.naturalWidth,\n height: img.naturalHeight,\n }\n }\n thumbStatus.value = 'loaded'\n setThumbCache(props.url, {\n status: 'loaded',\n dimensions: dimensions.value,\n })\n }\n const onImageError = () => {\n thumbStatus.value = 'error'\n setThumbCache(props.url, { status: 'error' })\n }\n\n const pswpSize = computed(() => dimensions.value ?? DEFAULT_PSWP_SIZE)\n\n // Meta fragments joined with \" · \" for the caption / doc subtitle.\n const imageMeta = computed(() =>\n [\n dimensions.value &&\n `${dimensions.value.width}×${dimensions.value.height}`,\n formattedSize.value,\n ].filter(Boolean),\n )\n const docMeta = computed(() =>\n [typeTag.value, formattedSize.value].filter(Boolean),\n )\n\n // --- Lightbox ---\n\n // Slide size PhotoSwipe assumes before the real dimensions are known.\n const DEFAULT_PSWP_SIZE = { width: 1200, height: 800 }\n\n const galleryRef = ref<HTMLElement>()\n const { init } = useLightbox({ gallery: galleryRef, loop: false })\n\n onMounted(async () => {\n if (!isImage.value) {\n return\n }\n await init()\n })\n</script>\n\n<template>\n <!-- Image attachment: a thumbnail tile with a metadata caption -->\n <figure\n v-if=\"isImage\"\n class=\"pk-chatbot-file-preview pk-chatbot-file-preview--image\"\n :class=\"{ 'pk-chatbot-file-preview--compact': compact }\">\n <div ref=\"galleryRef\" class=\"pk-chatbot-file-preview__thumb-wrap\">\n <a\n :href=\"url\"\n :data-pswp-src=\"url\"\n :data-pswp-width=\"pswpSize.width\"\n :data-pswp-height=\"pswpSize.height\"\n :data-pswp-caption=\"filename ?? ''\"\n class=\"pk-chatbot-file-preview__thumb-link\"\n :aria-label=\"filename ?? $t('label.file')\">\n <img\n v-show=\"thumbStatus === 'loaded'\"\n :src=\"url\"\n :alt=\"filename\"\n decoding=\"async\"\n class=\"pk-chatbot-file-preview__thumb\"\n @load=\"onImageLoad\"\n @error=\"onImageError\" />\n </a>\n <!-- Spinner until the thumbnail decodes (or while an upload is in\n flight); a fixed box keeps this from shifting the layout. -->\n <span\n v-if=\"loading || thumbStatus === 'loading'\"\n class=\"pk-chatbot-file-preview__status pk-chatbot-file-preview__status--overlay\">\n <VvIcon name=\"loading-loop\" />\n </span>\n <!-- Failed to load: a quiet icon instead of the browser's broken\n image glyph. -->\n <span\n v-else-if=\"thumbStatus === 'error'\"\n class=\"pk-chatbot-file-preview__status pk-chatbot-file-preview__status--overlay pk-chatbot-file-preview__status--error\">\n <VvIcon name=\"ri:image-2-line\" />\n </span>\n </div>\n <figcaption v-if=\"!compact\" class=\"pk-chatbot-file-preview__caption\">\n <span\n v-if=\"filename\"\n class=\"pk-chatbot-file-preview__name\"\n :title=\"filename\"\n >{{ filename }}</span\n >\n <span class=\"pk-chatbot-file-preview__meta\">\n <span\n v-if=\"error\"\n class=\"pk-chatbot-file-preview__error\"\n :title=\"error\">\n <VvIcon name=\"ri:error-warning-line\" />\n {{ error }}\n </span>\n <template v-else>{{ imageMeta.join(' · ') }}</template>\n </span>\n </figcaption>\n <button\n v-if=\"removable && !loading\"\n type=\"button\"\n class=\"pk-chatbot-file-preview__remove\"\n :title=\"$t('action.remove')\"\n :aria-label=\"$t('action.remove')\"\n @click.prevent=\"$emit('remove')\">\n <VvIcon name=\"ri:close-line\" />\n </button>\n </figure>\n\n <!-- Document attachment: an icon tile + name + type · size -->\n <div\n v-else\n class=\"pk-chatbot-file-preview pk-chatbot-file-preview--doc\"\n :class=\"{\n 'pk-chatbot-file-preview--error': error,\n 'pk-chatbot-file-preview--compact': compact,\n }\">\n <span\n class=\"pk-chatbot-file-preview__icon-tile\"\n :style=\"{ '--file-accent': fileKind.accent }\">\n <VvIcon\n v-if=\"loading\"\n name=\"loading-loop\"\n class=\"pk-chatbot-file-preview__icon\" />\n <VvIcon\n v-else\n :name=\"fileKind.icon\"\n class=\"pk-chatbot-file-preview__icon\" />\n </span>\n <span class=\"pk-chatbot-file-preview__body\">\n <span\n v-if=\"filename\"\n class=\"pk-chatbot-file-preview__name\"\n :title=\"filename\"\n >{{ filename }}</span\n >\n <span class=\"pk-chatbot-file-preview__meta\">\n <span\n v-if=\"error\"\n class=\"pk-chatbot-file-preview__error\"\n :title=\"error\">\n <VvIcon name=\"ri:error-warning-line\" />\n {{ error }}\n </span>\n <template v-else>{{ docMeta.join(' · ') }}</template>\n </span>\n </span>\n <a\n v-if=\"!loading && !error && !compact\"\n :href=\"url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"pk-chatbot-file-preview__open\"\n :title=\"$t('action.download')\"\n :aria-label=\"`${$t('action.download')}${filename ? ` — ${filename}` : ''}`\">\n <VvIcon name=\"ri:download-2-line\" />\n </a>\n <button\n v-if=\"removable && !loading\"\n type=\"button\"\n class=\"pk-chatbot-file-preview__remove\"\n :class=\"{ 'pk-chatbot-file-preview__remove--inline': !compact }\"\n :title=\"$t('action.remove')\"\n :aria-label=\"$t('action.remove')\"\n @click=\"$emit('remove')\">\n <VvIcon name=\"ri:close-line\" />\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-chatbot-file-preview {\n // Concentric radii: outer card and inner tiles share an 8px step.\n --file-radius: var(--rounded-lg, 12px);\n position: relative;\n max-width: 280px;\n background-color: var(--color-surface-1);\n border: 1px solid var(--color-surface-3);\n border-radius: var(--file-radius);\n color: var(--color-word-2);\n font-size: var(--text-12);\n\n &--error {\n border-color: var(--color-danger);\n }\n\n // --- Document card ---\n &--doc {\n display: flex;\n align-items: center;\n gap: var(--spacing-8);\n padding: var(--spacing-8);\n min-width: 0;\n transition:\n border-color 0.18s var(--ease-out),\n background-color 0.18s var(--ease-out),\n box-shadow 0.18s var(--ease-out);\n\n &:hover {\n border-color: var(--color-surface-4);\n background-color: var(--color-surface-2);\n box-shadow: var(--shadow-sm);\n }\n }\n\n &__icon-tile {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--spacing-36);\n height: var(--spacing-36);\n // One step down from the card radius keeps the nested tile concentric.\n border-radius: var(--rounded-md, 6px);\n // Tint derived from the file-type accent; glyph sits at full accent.\n background-color: color-mix(\n in srgb,\n var(--file-accent) 14%,\n transparent\n );\n color: var(--file-accent);\n }\n\n &__icon {\n width: var(--spacing-20);\n height: var(--spacing-20);\n }\n\n &__body {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n flex: 1;\n }\n\n &__open {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--spacing-28);\n height: var(--spacing-28);\n margin-inline-start: var(--spacing-4);\n border-radius: var(--rounded);\n color: var(--color-word-3);\n text-decoration: none;\n opacity: 0;\n transition:\n opacity 0.18s var(--ease-out),\n color 0.18s var(--ease-out),\n background-color 0.18s var(--ease-out);\n\n &:hover {\n background-color: var(--color-surface-3);\n color: var(--color-word-1);\n }\n }\n\n &--doc:hover &__open,\n &--doc:focus-within &__open {\n opacity: 1;\n }\n\n // Touch devices have no hover: keep the open affordance visible.\n @media (hover: none) {\n &--doc &__open {\n opacity: 1;\n }\n }\n\n // --- Image card ---\n &--image {\n display: inline-flex;\n flex-direction: column;\n margin: 0;\n }\n\n &__thumb-wrap {\n position: relative;\n display: flex;\n // Fixed box: the card claims its final footprint before the\n // image decodes, so the message log never shifts on load.\n width: 280px;\n max-width: 100%;\n height: 200px;\n background-color: var(--color-surface);\n border-radius: var(--file-radius);\n overflow: hidden;\n }\n\n &__thumb-link {\n display: flex;\n width: 100%;\n height: 100%;\n cursor: pointer;\n }\n\n &__thumb {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n &__caption {\n display: flex;\n flex-direction: column;\n gap: 1px;\n padding: var(--spacing-8);\n min-width: 0;\n }\n\n &__name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: var(--font-medium, 500);\n color: var(--color-word-1);\n }\n\n &__meta {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-10);\n line-height: var(--leading-normal);\n // Reserve the line even while empty: image dimensions arrive\n // only after decode and must not grow the caption.\n min-height: 1.4em;\n color: var(--color-word-4);\n // Stable column for the dimensions/size figures.\n font-variant-numeric: tabular-nums;\n }\n\n &__error {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n color: var(--color-danger);\n\n .vv-icon {\n flex-shrink: 0;\n }\n }\n\n &__status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n .vv-icon {\n width: var(--spacing-32);\n height: var(--spacing-32);\n }\n\n &--overlay {\n position: absolute;\n inset: 0;\n background-color: color-mix(\n in srgb,\n var(--color-surface-1) 70%,\n transparent\n );\n color: var(--color-word-1);\n }\n\n &--error {\n color: var(--color-word-4);\n }\n }\n\n // --- Remove button (input context) ---\n &__remove {\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n display: flex;\n align-items: center;\n justify-content: center;\n // Visible glyph is 18px but the hit area stays a comfortable 28px.\n width: var(--spacing-28);\n height: var(--spacing-28);\n padding: 0;\n border: none;\n border-radius: var(--rounded-full, 9999px);\n background-color: color-mix(\n in srgb,\n var(--color-surface-1) 85%,\n transparent\n );\n color: var(--color-word-2);\n cursor: pointer;\n line-height: 1;\n box-shadow: var(--shadow-sm);\n transition:\n background-color 0.18s var(--ease-out),\n color 0.18s var(--ease-out),\n scale 0.12s var(--ease-out);\n\n &:hover {\n background-color: var(--color-surface-2);\n color: var(--color-word-1);\n }\n\n &:active {\n scale: 0.96;\n }\n\n // Inside the document row the button rides inline, not overlaid\n // (size is inherited from the base).\n &--inline {\n position: static;\n flex-shrink: 0;\n box-shadow: none;\n background-color: transparent;\n color: var(--color-word-4);\n\n &:hover {\n background-color: var(--color-surface-3);\n color: var(--color-word-1);\n }\n }\n }\n\n // --- Compact (composer) chips ---\n // ChatGPT/Gemini-style: every attachment is the SAME height and carries\n // an always-visible round remove control in the top-right corner — no\n // hover-revealed actions, no size mismatch between image and file chips.\n &--compact {\n // Shared chip height so image and file chips align in the row.\n --chip-size: var(--spacing-56);\n max-width: 240px;\n\n &.pk-chatbot-file-preview--image {\n width: var(--chip-size);\n height: var(--chip-size);\n border-radius: var(--rounded-md, 6px);\n }\n\n // Fill the square; the root's `overflow: hidden` rounds the corners.\n .pk-chatbot-file-preview__thumb-wrap,\n .pk-chatbot-file-preview__thumb-link {\n width: 100%;\n height: 100%;\n }\n\n &.pk-chatbot-file-preview--doc {\n height: var(--chip-size);\n gap: var(--spacing-8);\n padding: var(--spacing-8);\n // Reserve room so the corner remove button never overlaps the\n // name/meta text.\n padding-inline-end: var(--spacing-28);\n }\n\n // Square icon tile that fills the chip height, so file chips read at\n // the same scale as image thumbnails.\n .pk-chatbot-file-preview__icon-tile {\n align-self: stretch;\n width: auto;\n height: auto;\n aspect-ratio: 1;\n }\n\n .pk-chatbot-file-preview__icon {\n width: var(--spacing-20);\n height: var(--spacing-20);\n }\n }\n\n // Always-visible round remove control in the top-right corner. Sits\n // just inside the chip (an ancestor clips overflow), bigger than before,\n // with an extended hit area for easy tapping.\n &--compact &__remove {\n top: var(--spacing-4);\n right: var(--spacing-4);\n width: var(--spacing-24);\n height: var(--spacing-24);\n border: 1px solid var(--color-surface-4);\n background-color: var(--color-surface);\n color: var(--color-word-1);\n font-size: var(--text-16);\n box-shadow: var(--shadow-sm);\n\n // Comfortable touch/click target beyond the small visible glyph.\n &::after {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--spacing-4));\n }\n\n &:hover {\n background-color: var(--color-surface-2);\n color: var(--color-word-1);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n &--doc,\n &__open,\n &__remove {\n transition: none;\n }\n }\n }\n</style>\n"],"mappings":"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"}
@@ -1,29 +1,29 @@
1
- import { t as e } from "./PkStreamingMarkdown-D8_LwZMR.js";
2
- import { t } from "./PkChatbotFilePreview-DO1wZPPj.js";
1
+ import { t as e } from "./PkStreamingMarkdown-D0IOaETI.js";
2
+ import { t } from "./PkChatbotFilePreview-CwiVQDF2.js";
3
3
  import { VvButton as n, VvDropdown as r, VvDropdownAction as i, VvIcon as a } from "@volverjs/ui-vue/components";
4
- import { Fragment as o, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, createVNode as p, defineComponent as m, mergeModels as h, mergeProps as ee, nextTick as g, normalizeClass as _, normalizeProps as te, onBeforeUnmount as v, onMounted as y, openBlock as b, ref as x, renderList as ne, renderSlot as S, toDisplayString as C, unref as re, useModel as w, useTemplateRef as T, watch as ie, withCtx as E, withKeys as ae, withModifiers as D } from "vue";
4
+ import { Fragment as o, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, createVNode as p, defineComponent as m, mergeModels as h, mergeProps as g, nextTick as _, normalizeClass as v, normalizeProps as ee, onBeforeUnmount as y, onMounted as b, openBlock as x, ref as S, renderList as te, renderSlot as C, toDisplayString as w, unref as T, useId as ne, useModel as E, useTemplateRef as D, watch as re, withCtx as O, withKeys as ie, withModifiers as ae } from "vue";
5
5
  import { useDropZone as oe } from "@vueuse/core";
6
6
  //#region ../../node_modules/.pnpm/autosize@6.0.1/node_modules/autosize/dist/autosize.esm.js
7
- var O = /* @__PURE__ */ new Map();
8
- function k(e) {
9
- var t = O.get(e);
7
+ var k = /* @__PURE__ */ new Map();
8
+ function A(e) {
9
+ var t = k.get(e);
10
10
  t && t.destroy();
11
11
  }
12
- function A(e) {
13
- var t = O.get(e);
12
+ function j(e) {
13
+ var t = k.get(e);
14
14
  t && t.update();
15
15
  }
16
- var j = null;
17
- typeof window > "u" ? ((j = function(e) {
16
+ var M = null;
17
+ typeof window > "u" ? ((M = function(e) {
18
18
  return e;
19
19
  }).destroy = function(e) {
20
20
  return e;
21
- }, j.update = function(e) {
21
+ }, M.update = function(e) {
22
22
  return e;
23
- }) : ((j = function(e, t) {
23
+ }) : ((M = function(e, t) {
24
24
  return e && Array.prototype.forEach.call(e.length ? e : [e], function(e) {
25
25
  return function(e) {
26
- if (e && e.nodeName && e.nodeName === "TEXTAREA" && !O.has(e)) {
26
+ if (e && e.nodeName && e.nodeName === "TEXTAREA" && !k.has(e)) {
27
27
  var t, n = null, r = window.getComputedStyle(e), i = (t = e.value, function() {
28
28
  o({
29
29
  testForHeightReduction: t === "" || !e.value.startsWith(t),
@@ -32,7 +32,7 @@ typeof window > "u" ? ((j = function(e) {
32
32
  }), a = function(t) {
33
33
  e.removeEventListener("autosize:destroy", a), e.removeEventListener("autosize:update", s), e.removeEventListener("input", i), window.removeEventListener("resize", s), Object.keys(t).forEach(function(n) {
34
34
  return e.style[n] = t[n];
35
- }), O.delete(e);
35
+ }), k.delete(e);
36
36
  }.bind(e, {
37
37
  height: e.style.height,
38
38
  resize: e.style.resize,
@@ -41,7 +41,7 @@ typeof window > "u" ? ((j = function(e) {
41
41
  overflowX: e.style.overflowX,
42
42
  wordWrap: e.style.wordWrap
43
43
  });
44
- e.addEventListener("autosize:destroy", a), e.addEventListener("autosize:update", s), e.addEventListener("input", i), window.addEventListener("resize", s), e.style.overflowX = "hidden", e.style.wordWrap = "break-word", O.set(e, {
44
+ e.addEventListener("autosize:destroy", a), e.addEventListener("autosize:update", s), e.addEventListener("input", i), window.addEventListener("resize", s), e.style.overflowX = "hidden", e.style.wordWrap = "break-word", k.set(e, {
45
45
  destroy: a,
46
46
  update: s
47
47
  }), s();
@@ -73,14 +73,14 @@ typeof window > "u" ? ((j = function(e) {
73
73
  }(e);
74
74
  }), e;
75
75
  }).destroy = function(e) {
76
- return e && Array.prototype.forEach.call(e.length ? e : [e], k), e;
77
- }, j.update = function(e) {
78
76
  return e && Array.prototype.forEach.call(e.length ? e : [e], A), e;
77
+ }, M.update = function(e) {
78
+ return e && Array.prototype.forEach.call(e.length ? e : [e], j), e;
79
79
  });
80
- var M = j, N = ["type"], P = {
80
+ var N = M, P = ["type"], F = {
81
81
  key: 0,
82
82
  class: "pk-chat-button__label"
83
- }, F = /* @__PURE__ */ m({
83
+ }, I = /* @__PURE__ */ m({
84
84
  __name: "PkChatButton",
85
85
  props: {
86
86
  icon: {},
@@ -91,13 +91,13 @@ var M = j, N = ["type"], P = {
91
91
  setup(e) {
92
92
  return (t, n) => {
93
93
  let r = a;
94
- return b(), u("button", {
95
- class: _(["pk-chat-button", [e.modifiers ? `pk-chat-button--${e.modifiers}` : void 0, { "pk-chat-button--labelled": e.label }]]),
94
+ return x(), u("button", {
95
+ class: v(["pk-chat-button", [e.modifiers ? `pk-chat-button--${e.modifiers}` : void 0, { "pk-chat-button--labelled": e.label }]]),
96
96
  type: e.type
97
97
  }, [p(r, {
98
98
  name: e.icon,
99
99
  class: "pk-chat-button__icon"
100
- }, null, 8, ["name"]), e.label ? (b(), u("span", P, C(e.label), 1)) : l("", !0)], 10, N);
100
+ }, null, 8, ["name"]), e.label ? (x(), u("span", F, w(e.label), 1)) : l("", !0)], 10, P);
101
101
  };
102
102
  }
103
103
  }), se = { class: "pk-chatbot-input" }, ce = {
@@ -115,9 +115,11 @@ var M = j, N = ["type"], P = {
115
115
  "onClick"
116
116
  ], pe = ["accept"], me = ["accept"], he = { class: "pk-chatbot-input__content" }, ge = [
117
117
  "value",
118
- "placeholder",
119
- "onKeydown"
120
- ], _e = { class: "opacity-60" }, I = /* @__PURE__ */ m({
118
+ "aria-label",
119
+ "aria-describedby",
120
+ "aria-invalid",
121
+ "placeholder"
122
+ ], _e = ["id"], ve = { class: "opacity-60" }, L = /* @__PURE__ */ m({
121
123
  __name: "PkChatbotInput",
122
124
  props: /*@__PURE__*/ h({
123
125
  placeholder: {},
@@ -143,78 +145,84 @@ var M = j, N = ["type"], P = {
143
145
  "voice-start"
144
146
  ], ["update:modelValue", "update:pendingAttachments"]),
145
147
  setup(m, { emit: h }) {
146
- let O = w(m, "modelValue"), k = w(m, "pendingAttachments"), A = h, j = m, N = T("textareaEl"), P = T("fileInputEl"), I = T("cameraInputEl"), L = T("formEl"), R = x(O.value ?? ""), z = null, B = () => {
147
- z !== null && (clearTimeout(z), z = null);
148
- }, ve = () => {
149
- B(), O.value = R.value;
148
+ let k = E(m, "modelValue"), A = E(m, "pendingAttachments"), j = h, M = m, P = D("textareaEl"), F = D("fileInputEl"), L = D("cameraInputEl"), R = D("formEl"), z = S(k.value ?? ""), B = null, V = () => {
149
+ B !== null && (clearTimeout(B), B = null);
150
150
  }, ye = () => {
151
- B(), z = setTimeout(() => {
152
- O.value = R.value, z = null;
153
- }, 300);
151
+ V(), k.value = z.value;
154
152
  }, be = () => {
155
- R.value = N.value?.value ?? "", ye();
153
+ V(), B = setTimeout(() => {
154
+ k.value = z.value, B = null;
155
+ }, 300);
156
+ }, xe = () => {
157
+ z.value = P.value?.value ?? "", be();
156
158
  };
157
- ie(O, (e) => {
158
- e !== R.value && (R.value = e ?? "", g(() => {
159
- N.value && M.update(N.value);
159
+ re(k, (e) => {
160
+ e !== z.value && (z.value = e ?? "", _(() => {
161
+ P.value && N.update(P.value);
160
162
  }));
161
163
  });
162
- let V = s(() => j.status === "streaming"), H = s(() => j.status === "submitted"), U = s(() => V.value || H.value), W = s(() => R.value.length), G = s(() => j.maxMessageLength !== void 0 && W.value > j.maxMessageLength), xe = s(() => k.value.some((e) => e.state === "uploading")), K = s(() => U.value || xe.value || G.value ? !1 : R.value.trim().length > 0), Se = "capture" in document.createElement("input"), Ce = s(() => j.fileUpload?.allowedMimeTypes?.join(",") ?? ""), q = s(() => (j.fileUpload?.allowedMimeTypes ?? []).filter((e) => e.startsWith("image/")).join(",")), J = s(() => Se && q.value.length > 0), Y = () => {
163
- P.value?.click();
164
- }, we = () => {
165
- I.value?.click();
166
- }, X = (e) => {
167
- for (let t of e) A("file-select", t);
168
- }, Z = (e) => {
164
+ let H = s(() => M.status === "streaming"), U = s(() => M.status === "submitted"), W = s(() => H.value || U.value), G = ne(), K = s(() => z.value.length), q = s(() => M.maxMessageLength !== void 0 && K.value > M.maxMessageLength), Se = s(() => A.value.some((e) => e.state === "uploading")), J = s(() => W.value || Se.value || q.value ? !1 : z.value.trim().length > 0), Ce = "capture" in document.createElement("input"), we = s(() => M.fileUpload?.allowedMimeTypes?.join(",") ?? ""), Y = s(() => (M.fileUpload?.allowedMimeTypes ?? []).filter((e) => e.startsWith("image/")).join(",")), X = s(() => Ce && Y.value.length > 0), Z = () => {
165
+ F.value?.click();
166
+ }, Te = () => {
167
+ L.value?.click();
168
+ }, Q = (e) => {
169
+ for (let t of e) j("file-select", t);
170
+ }, Ee = (e) => {
169
171
  let t = e.target;
170
- X(Array.from(t.files ?? [])), t.value = "";
171
- }, Te = (e) => {
172
- let t = k.value.find((t) => t.id === e);
173
- t && URL.revokeObjectURL(t.localUrl), k.value = k.value.filter((t) => t.id !== e);
174
- }, Q = s(() => (j.enableDragDrop ?? !0) && !!j.fileUpload?.enabled), { isOverDropZone: Ee } = oe(L, {
175
- dataTypes: s(() => j.fileUpload?.allowedMimeTypes ?? []),
172
+ Q(Array.from(t.files ?? [])), t.value = "";
173
+ }, De = (e) => {
174
+ let t = A.value.find((t) => t.id === e);
175
+ t && URL.revokeObjectURL(t.localUrl), A.value = A.value.filter((t) => t.id !== e);
176
+ }, Oe = s(() => (M.enableDragDrop ?? !0) && !!M.fileUpload?.enabled), { isOverDropZone: ke } = oe(R, {
177
+ dataTypes: s(() => M.fileUpload?.allowedMimeTypes ?? []),
176
178
  onDrop: (e) => {
177
- Q.value && e && X(e);
179
+ Oe.value && e && Q(e);
178
180
  }
179
- }), De = x(!0), Oe = () => {
180
- De.value = !1;
181
- }, $ = s(() => j.attachmentNotice ? {
181
+ }), Ae = S(!0), je = () => {
182
+ Ae.value = !1;
183
+ }, $ = s(() => M.attachmentNotice ? {
182
184
  id: "limit",
183
185
  icon: "ri:information-line",
184
- text: j.attachmentNotice,
185
- dismiss: () => A("dismiss-attachment-notice")
186
- } : j.dismissableNotice && De.value ? {
186
+ text: M.attachmentNotice,
187
+ dismiss: () => j("dismiss-attachment-notice")
188
+ } : M.dismissableNotice && Ae.value ? {
187
189
  id: "dismissable",
188
- markdown: j.dismissableNotice,
189
- dismiss: Oe
190
- } : null), ke = () => {
191
- K.value && (ve(), A("submit"), R.value = "", O.value = "", g(() => {
192
- N.value && (N.value.value = "", M.update(N.value));
190
+ markdown: M.dismissableNotice,
191
+ dismiss: je
192
+ } : null), Me = () => {
193
+ R.value?.querySelector("button:focus-visible") && P.value?.focus();
194
+ }, Ne = () => {
195
+ Me(), j("stop-generation");
196
+ }, Pe = () => {
197
+ J.value && (Me(), ye(), j("submit"), z.value = "", k.value = "", _(() => {
198
+ P.value && (P.value.value = "", N.update(P.value));
193
199
  }));
200
+ }, Fe = (e) => {
201
+ e.shiftKey || e.isComposing || e.keyCode === 229 || (e.preventDefault(), Pe());
194
202
  };
195
- return y(() => {
196
- N.value && M(N.value);
197
- }), v(() => {
198
- B(), N.value && M.destroy(N.value);
199
- for (let e of k.value) URL.revokeObjectURL(e.localUrl);
203
+ return b(() => {
204
+ P.value && N(P.value);
205
+ }), y(() => {
206
+ V(), P.value && N.destroy(P.value);
207
+ for (let e of A.value) URL.revokeObjectURL(e.localUrl);
200
208
  }), (s, h) => {
201
- let g = a, v = n, y = i, x = r;
202
- return b(), u("div", se, [$.value ? (b(), u("div", {
209
+ let _ = a, y = n, b = i, S = r;
210
+ return x(), u("div", se, [$.value ? (x(), u("div", {
203
211
  key: $.value.id,
204
212
  class: "pk-chatbot-input__notice",
205
213
  role: "status"
206
214
  }, [
207
- $.value.icon ? (b(), c(g, {
215
+ $.value.icon ? (x(), c(_, {
208
216
  key: 0,
209
217
  name: $.value.icon,
210
218
  class: "pk-chatbot-input__notice-icon"
211
219
  }, null, 8, ["name"])) : l("", !0),
212
- $.value.markdown ? (b(), c(e, {
220
+ $.value.markdown ? (x(), c(e, {
213
221
  key: 1,
214
222
  markdown: $.value.markdown,
215
223
  class: "wysiwyg pk-chatbot-input__notice-text"
216
- }, null, 8, ["markdown"])) : (b(), u("span", ce, C($.value.text), 1)),
217
- $.value.dismiss ? (b(), c(v, {
224
+ }, null, 8, ["markdown"])) : (x(), u("span", ce, w($.value.text), 1)),
225
+ $.value.dismiss ? (x(), c(y, {
218
226
  key: 3,
219
227
  title: s.$t("action.close"),
220
228
  modifiers: "action-quiet",
@@ -224,15 +232,15 @@ var M = j, N = ["type"], P = {
224
232
  }, null, 8, ["title"])) : l("", !0)
225
233
  ])) : l("", !0), d("form", {
226
234
  ref_key: "formEl",
227
- ref: L,
235
+ ref: R,
228
236
  class: "pk-chatbot-input__form",
229
- onSubmit: D(ke, ["prevent"])
237
+ onSubmit: ae(Pe, ["prevent"])
230
238
  }, [
231
- re(Ee) && Q.value ? (b(), u("div", le, [p(g, {
239
+ T(ke) && Oe.value ? (x(), u("div", le, [p(_, {
232
240
  name: "ri:upload-cloud-2-line",
233
241
  class: "pk-chatbot-input__drop-overlay-icon"
234
- }), d("span", null, C(s.$t("action.dropFile")), 1)])) : l("", !0),
235
- k.value.length ? (b(), u("div", ue, [(b(!0), u(o, null, ne(k.value, (e) => (b(), c(t, {
242
+ }), d("span", null, w(s.$t("action.dropFile")), 1)])) : l("", !0),
243
+ A.value.length ? (x(), u("div", ue, [(x(!0), u(o, null, te(A.value, (e) => (x(), c(t, {
236
244
  key: e.id,
237
245
  "media-type": e.file.type,
238
246
  url: e.localUrl,
@@ -242,7 +250,7 @@ var M = j, N = ["type"], P = {
242
250
  error: e.state === "error" ? e.error : void 0,
243
251
  removable: e.state !== "uploading",
244
252
  compact: "",
245
- onRemove: (t) => Te(e.id)
253
+ onRemove: (t) => De(e.id)
246
254
  }, null, 8, [
247
255
  "media-type",
248
256
  "url",
@@ -254,108 +262,115 @@ var M = j, N = ["type"], P = {
254
262
  "onRemove"
255
263
  ]))), 128))])) : l("", !0),
256
264
  d("div", de, [
257
- S(s.$slots, "prepend"),
258
- m.fileUpload && m.fileUpload.enabled && (J.value || s.$slots["additional-actions"]) ? (b(), c(x, te(ee({ key: 0 }, {
265
+ C(s.$slots, "prepend"),
266
+ m.fileUpload && m.fileUpload.enabled && (X.value || s.$slots["additional-actions"]) ? (x(), c(S, ee(g({ key: 0 }, {
259
267
  placement: "top-start",
260
268
  modifiers: "menu",
261
269
  flip: !0,
262
270
  offset: 3
263
271
  })), {
264
- default: E(({ init: e, toggle: t, aria: n }) => [d("button", ee({ ref: (t) => e(t) }, n, {
272
+ default: O(({ init: e, toggle: t, aria: n }) => [d("button", g({ ref: (t) => e(t) }, n, {
265
273
  class: "pk-chat-button",
266
274
  type: "button",
267
275
  title: s.$t("action.attachFile"),
268
- disabled: U.value,
276
+ disabled: W.value,
269
277
  onClick: t
270
- }), [p(g, {
278
+ }), [p(_, {
271
279
  name: "ri:add-line",
272
280
  class: "pk-chat-button__icon"
273
281
  })], 16, fe)]),
274
- items: E(() => [
275
- J.value ? (b(), c(y, {
282
+ items: O(() => [
283
+ X.value ? (x(), c(b, {
276
284
  key: 0,
277
- disabled: U.value || m.attachmentLimitReached,
278
- onClick: we
285
+ disabled: W.value || m.attachmentLimitReached,
286
+ onClick: Te
279
287
  }, {
280
- default: E(() => [p(g, {
288
+ default: O(() => [p(_, {
281
289
  name: "ri:camera-line",
282
290
  class: "pk-chatbot-input__dropdown-icon"
283
- }), f(" " + C(s.$t("action.takePhoto")), 1)]),
291
+ }), f(" " + w(s.$t("action.takePhoto")), 1)]),
284
292
  _: 1
285
293
  }, 8, ["disabled"])) : l("", !0),
286
- p(y, {
287
- disabled: U.value || m.attachmentLimitReached,
288
- onClick: Y
294
+ p(b, {
295
+ disabled: W.value || m.attachmentLimitReached,
296
+ onClick: Z
289
297
  }, {
290
- default: E(() => [p(g, {
298
+ default: O(() => [p(_, {
291
299
  name: "ri:attachment-line",
292
300
  class: "pk-chatbot-input__dropdown-icon"
293
- }), f(" " + C(s.$t("action.attachFile")), 1)]),
301
+ }), f(" " + w(s.$t("action.attachFile")), 1)]),
294
302
  _: 1
295
303
  }, 8, ["disabled"]),
296
- S(s.$slots, "additional-actions")
304
+ C(s.$slots, "additional-actions")
297
305
  ]),
298
306
  _: 3
299
- }, 16)) : m.fileUpload && m.fileUpload.enabled ? (b(), c(F, {
307
+ }, 16)) : m.fileUpload && m.fileUpload.enabled ? (x(), c(I, {
300
308
  key: 1,
301
309
  icon: "ri:add-line",
302
310
  title: s.$t("action.attachFile"),
303
- disabled: U.value || m.attachmentLimitReached,
304
- onClick: Y
311
+ disabled: W.value || m.attachmentLimitReached,
312
+ onClick: Z
305
313
  }, null, 8, ["title", "disabled"])) : l("", !0),
306
- m.fileUpload && m.fileUpload.enabled ? (b(), u("input", {
314
+ m.fileUpload && m.fileUpload.enabled ? (x(), u("input", {
307
315
  key: 2,
308
316
  ref_key: "fileInputEl",
309
- ref: P,
317
+ ref: F,
310
318
  type: "file",
311
319
  hidden: "",
312
320
  multiple: "",
313
- accept: Ce.value,
314
- onChange: Z
321
+ accept: we.value,
322
+ onChange: Ee
315
323
  }, null, 40, pe)) : l("", !0),
316
- m.fileUpload && m.fileUpload.enabled && J.value ? (b(), u("input", {
324
+ m.fileUpload && m.fileUpload.enabled && X.value ? (x(), u("input", {
317
325
  key: 3,
318
326
  ref_key: "cameraInputEl",
319
- ref: I,
327
+ ref: L,
320
328
  type: "file",
321
329
  capture: "environment",
322
330
  hidden: "",
323
- accept: q.value,
324
- onChange: Z
331
+ accept: Y.value,
332
+ onChange: Ee
325
333
  }, null, 40, me)) : l("", !0),
326
334
  d("div", he, [d("textarea", {
327
335
  ref_key: "textareaEl",
328
- ref: N,
329
- value: R.value,
336
+ ref: P,
337
+ value: z.value,
330
338
  class: "pk-chatbot-input__textarea",
331
339
  name: "message",
332
340
  rows: "1",
341
+ enterkeyhint: "send",
342
+ "aria-label": s.$t("label.message"),
343
+ "aria-describedby": m.maxMessageLength ? T(G) : void 0,
344
+ "aria-invalid": q.value || void 0,
333
345
  placeholder: m.placeholder,
334
- onInput: be,
335
- onKeydown: ae(D(ke, ["prevent"]), ["enter"])
346
+ onInput: xe,
347
+ onKeydown: ie(Fe, ["enter"])
336
348
  }, null, 40, ge)]),
337
- m.maxMessageLength ? (b(), u("div", {
349
+ m.maxMessageLength ? (x(), u("div", {
338
350
  key: 4,
339
- class: _(["pk-chatbot-input__counter", { "pk-chatbot-input__counter--over": G.value }])
340
- }, [f(C(s.$n(W.value, "integer")) + "/", 1), d("span", _e, C(s.$n(m.maxMessageLength, "integer")), 1)], 2)) : l("", !0),
341
- m.voiceEnabled && !V.value ? (b(), c(F, {
351
+ id: T(G),
352
+ class: v(["pk-chatbot-input__counter", { "pk-chatbot-input__counter--over": q.value }])
353
+ }, [f(w(s.$n(K.value, "integer")) + "/", 1), d("span", ve, w(s.$n(m.maxMessageLength, "integer")), 1)], 10, _e)) : l("", !0),
354
+ m.voiceEnabled && !H.value ? (x(), c(I, {
342
355
  key: 5,
343
356
  icon: "ri:mic-line",
344
357
  title: s.$t("action.talk"),
345
- disabled: U.value,
346
- onClick: h[1] ||= (e) => A("voice-start")
358
+ disabled: W.value,
359
+ onClick: h[1] ||= (e) => j("voice-start")
347
360
  }, null, 8, ["title", "disabled"])) : l("", !0),
348
- V.value ? (b(), c(F, {
361
+ H.value ? (x(), c(I, {
349
362
  key: 6,
350
- icon: "ri:stop-circle-line",
363
+ icon: "ri:stop-fill",
364
+ modifiers: "primary",
351
365
  title: s.$t("action.stop"),
352
- onClick: h[2] ||= (e) => A("stop-generation")
353
- }, null, 8, ["title"])) : (b(), c(F, {
366
+ onClick: Ne
367
+ }, null, 8, ["title"])) : (x(), c(I, {
354
368
  key: 7,
355
369
  type: "submit",
356
- icon: H.value ? "line-md:loading-loop" : K.value ? "ri:send-ins-fill" : "ri:send-ins-line",
357
- title: K.value ? s.$t("action.submit") : s.$t("label.disabled"),
358
- disabled: !K.value
370
+ modifiers: "primary",
371
+ icon: U.value ? "loading-loop" : "ri:arrow-up-line",
372
+ title: s.$t("action.submit"),
373
+ disabled: !J.value
359
374
  }, null, 8, [
360
375
  "icon",
361
376
  "title",
@@ -367,6 +382,6 @@ var M = j, N = ["type"], P = {
367
382
  }
368
383
  });
369
384
  //#endregion
370
- export { F as n, I as t };
385
+ export { I as n, L as t };
371
386
 
372
- //# sourceMappingURL=PkChatbotInput-D8x52cVm.js.map
387
+ //# sourceMappingURL=PkChatbotInput-MSpF6SB6.js.map