@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.
- package/README.md +1 -0
- package/dist/_chunks/{Agent-Su_LDF9_.js → Agent-tE7ZJPxG.js} +80 -78
- package/dist/_chunks/Agent-tE7ZJPxG.js.map +1 -0
- package/dist/_chunks/{Document-DecVclEe.js → Document-Bmx6774B.js} +33 -21
- package/dist/_chunks/Document-Bmx6774B.js.map +1 -0
- package/dist/_chunks/Media-Cft7Pwrh.js +108 -0
- package/dist/_chunks/Media-Cft7Pwrh.js.map +1 -0
- package/dist/_chunks/{PkLazyImg-ClL4nr95.js → PkLazyImg-Dbj2dDXA.js} +2 -2
- package/dist/_chunks/{PkLazyImg-ClL4nr95.js.map → PkLazyImg-Dbj2dDXA.js.map} +1 -1
- package/dist/_chunks/{PkStreamingMarkdown-CwqsJnJJ.js → PkStreamingMarkdown-CNI8aV8t.js} +636 -427
- package/dist/_chunks/PkStreamingMarkdown-CNI8aV8t.js.map +1 -0
- package/dist/_chunks/{PkToolRequestGeolocation-CEVpl50q.js → PkToolRequestGeolocation-Bzy4IYSp.js} +4 -4
- package/dist/_chunks/PkToolRequestGeolocation-Bzy4IYSp.js.map +1 -0
- package/dist/_chunks/{PkToolRequestOAuthConnection-CncDU-Kl.js → PkToolRequestOAuthConnection-13CQH07t.js} +5 -5
- package/dist/_chunks/PkToolRequestOAuthConnection-13CQH07t.js.map +1 -0
- package/dist/_chunks/{PkToolShowArtifact-M6jlSmyJ.js → PkToolShowArtifact-CGbHDEie.js} +4 -4
- package/dist/_chunks/{PkToolShowArtifact-M6jlSmyJ.js.map → PkToolShowArtifact-CGbHDEie.js.map} +1 -1
- package/dist/_chunks/{PkToolShowCalendarEvent-C41JgOUA.js → PkToolShowCalendarEvent-DIFX_rUz.js} +3 -3
- package/dist/_chunks/{PkToolShowCalendarEvent-C41JgOUA.js.map → PkToolShowCalendarEvent-DIFX_rUz.js.map} +1 -1
- package/dist/_chunks/{PkToolShowComparison-DbbUD9pg.js → PkToolShowComparison-CWLFWT9h.js} +7 -7
- package/dist/_chunks/PkToolShowComparison-CWLFWT9h.js.map +1 -0
- package/dist/_chunks/{PkToolShowContactForm-D_dW59Dl.js → PkToolShowContactForm-CYxgatUA.js} +5 -5
- package/dist/_chunks/PkToolShowContactForm-CYxgatUA.js.map +1 -0
- package/dist/_chunks/{PkToolShowDiagram-Hy9qh68O.js → PkToolShowDiagram-Dx1Ba0PG.js} +4 -4
- package/dist/_chunks/PkToolShowDiagram-Dx1Ba0PG.js.map +1 -0
- package/dist/_chunks/{PkToolShowEmail-Dn3JHYIR.js → PkToolShowEmail-DnFFgzom.js} +3 -3
- package/dist/_chunks/{PkToolShowEmail-Dn3JHYIR.js.map → PkToolShowEmail-DnFFgzom.js.map} +1 -1
- package/dist/_chunks/{PkToolShowForm-DbJHMDbt.js → PkToolShowForm-B6x3Lp2i.js} +7 -8
- package/dist/_chunks/PkToolShowForm-B6x3Lp2i.js.map +1 -0
- package/dist/_chunks/{PkToolShowImageGallery-C1lzlO0y.js → PkToolShowImageGallery-D99N_Plf.js} +2 -2
- package/dist/_chunks/{PkToolShowImageGallery-C1lzlO0y.js.map → PkToolShowImageGallery-D99N_Plf.js.map} +1 -1
- package/dist/_chunks/{PkToolShowLocation-CKhPxKFA.js → PkToolShowLocation-AfnrtFVJ.js} +3 -3
- package/dist/_chunks/{PkToolShowLocation-CKhPxKFA.js.map → PkToolShowLocation-AfnrtFVJ.js.map} +1 -1
- package/dist/_chunks/{PkToolShowMessage-U9CCU7eG.js → PkToolShowMessage-DUo2c-im.js} +3 -3
- package/dist/_chunks/{PkToolShowMessage-U9CCU7eG.js.map → PkToolShowMessage-DUo2c-im.js.map} +1 -1
- package/dist/_chunks/{PkToolShowProductList-UeiRMLHu.js → PkToolShowProductList-BN6Qk1_y.js} +3 -3
- package/dist/_chunks/{PkToolShowProductList-UeiRMLHu.js.map → PkToolShowProductList-BN6Qk1_y.js.map} +1 -1
- package/dist/_chunks/{PkToolShowQrCode-CypLrfh5.js → PkToolShowQrCode-BLqeBecX.js} +3 -3
- package/dist/_chunks/{PkToolShowQrCode-CypLrfh5.js.map → PkToolShowQrCode-BLqeBecX.js.map} +1 -1
- package/dist/_chunks/{PkToolShowSources-B69JmwbZ.js → PkToolShowSources-DpZb5FUP.js} +5 -5
- package/dist/_chunks/PkToolShowSources-DpZb5FUP.js.map +1 -0
- package/dist/_chunks/{PkToolShowSuggestedReply-CKxSH0Y9.js → PkToolShowSuggestedReply-C10nNgBs.js} +3 -3
- package/dist/_chunks/{PkToolShowSuggestedReply-CKxSH0Y9.js.map → PkToolShowSuggestedReply-C10nNgBs.js.map} +1 -1
- package/dist/_chunks/{PkToolShowVideo-BgKxdBcC.js → PkToolShowVideo-S9b4QHUj.js} +2 -2
- package/dist/_chunks/{PkToolShowVideo-BgKxdBcC.js.map → PkToolShowVideo-S9b4QHUj.js.map} +1 -1
- package/dist/_chunks/{PkToolShowWeather-LPd3tC77.js → PkToolShowWeather-CqhG430w.js} +2 -2
- package/dist/_chunks/PkToolShowWeather-CqhG430w.js.map +1 -0
- package/dist/_chunks/{PkToolShowWebPages-ep_erFF0.js → PkToolShowWebPages-txAZi_iG.js} +3 -3
- package/dist/_chunks/{PkToolShowWebPages-ep_erFF0.js.map → PkToolShowWebPages-txAZi_iG.js.map} +1 -1
- package/dist/_chunks/PkUrl-BPbjZJ1A.js.map +1 -1
- package/dist/_chunks/{VvCheckboxGroup.es-Bdu2gFLN.js → VvCheckboxGroup.es-CTrF3pue.js} +2 -2
- package/dist/_chunks/{VvCheckboxGroup.es-Bdu2gFLN.js.map → VvCheckboxGroup.es-CTrF3pue.js.map} +1 -1
- package/dist/_chunks/{VvCombobox.es-C0wpJIr_.js → VvCombobox.es-BWiXmQ_S.js} +10 -10
- package/dist/_chunks/{VvCombobox.es-C0wpJIr_.js.map → VvCombobox.es-BWiXmQ_S.js.map} +1 -1
- package/dist/_chunks/{VvInputText.es-Zgtw2YNw.js → VvInputText.es-Bo9I6g8H.js} +6 -6
- package/dist/_chunks/{VvInputText.es-Zgtw2YNw.js.map → VvInputText.es-Bo9I6g8H.js.map} +1 -1
- package/dist/_chunks/{VvRadioGroup.es-DZLL19SC.js → VvRadioGroup.es-9ooHCuik.js} +2 -2
- package/dist/_chunks/{VvRadioGroup.es-DZLL19SC.js.map → VvRadioGroup.es-9ooHCuik.js.map} +1 -1
- package/dist/_chunks/{VvSelect.es-ovnZRHG5.js → VvSelect.es-DG0VuWtP.js} +2 -2
- package/dist/_chunks/{VvSelect.es-ovnZRHG5.js.map → VvSelect.es-DG0VuWtP.js.map} +1 -1
- package/dist/_chunks/{VvTextarea.es-DbP5Lt2T.js → VvTextarea.es-Dg3pxdZy.js} +6 -6
- package/dist/_chunks/{VvTextarea.es-DbP5Lt2T.js.map → VvTextarea.es-Dg3pxdZy.js.map} +1 -1
- package/dist/_chunks/{browser-NgY6LXg-.js → browser-B0Xnbqi7.js} +726 -751
- package/dist/_chunks/browser-B0Xnbqi7.js.map +1 -0
- package/dist/_chunks/{dist-n5iFNYf-.js → dist-QdjZA6MJ.js} +143 -133
- package/dist/_chunks/{dist-n5iFNYf-.js.map → dist-QdjZA6MJ.js.map} +1 -1
- package/dist/_chunks/{index.es-dtdl3VFG.js → index.es-0YpCa4c5.js} +6 -6
- package/dist/_chunks/{index.es-dtdl3VFG.js.map → index.es-0YpCa4c5.js.map} +1 -1
- package/dist/_chunks/{index.es-BJnUA_36.js → index.es-CHkJ2TMJ.js} +10 -10
- package/dist/_chunks/{index.es-BJnUA_36.js.map → index.es-CHkJ2TMJ.js.map} +1 -1
- package/dist/_chunks/text-DbSEK8si.js.map +1 -1
- package/dist/ai-elements.es.js +3077 -3134
- package/dist/ai-elements.es.js.map +1 -1
- package/dist-vue/PkChatbot.js +1 -1
- package/dist-vue/PkChatbotEmptyState.js +1 -1
- package/dist-vue/PkChatbotError.js +1 -1
- package/dist-vue/PkChatbotFeedbackForm.js +1 -1
- package/dist-vue/PkChatbotFilePreview.js +1 -1
- package/dist-vue/PkChatbotInput.js +1 -1
- package/dist-vue/PkChatbotMessages.js +1 -1
- package/dist-vue/PkChatbotStepPayload.js +1 -1
- package/dist-vue/PkChatbotStepToolDetail.js +1 -1
- package/dist-vue/PkChatbotSteps.js +1 -1
- package/dist-vue/PkChatbotViewChat.js +1 -1
- package/dist-vue/PkChatbotViewConversations.js +1 -1
- package/dist-vue/PkChatbotViewFiles.js +1 -1
- package/dist-vue/PkChatbotViewProfile.js +1 -1
- package/dist-vue/_chunks/{Agent-C8BsTAxk.js → Agent-De2gFNjR.js} +165 -176
- package/dist-vue/_chunks/Agent-De2gFNjR.js.map +1 -0
- package/dist-vue/_chunks/{Document-CaUfI_SZ.js → Document-8umjeTVS.js} +84 -72
- package/dist-vue/_chunks/Document-8umjeTVS.js.map +1 -0
- package/dist-vue/_chunks/Media-_HfFLHGD.js.map +1 -1
- package/dist-vue/_chunks/{PkChatbot-o7k7d-fj.js → PkChatbot-CMajc7tE.js} +61 -61
- package/dist-vue/_chunks/PkChatbot-CMajc7tE.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotEmptyState-BvaeBxhx.js → PkChatbotEmptyState-BtzBYOHJ.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotEmptyState-BvaeBxhx.js.map → PkChatbotEmptyState-BtzBYOHJ.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotError-CBP2mf-n.js → PkChatbotError-gvDpRcEz.js} +21 -19
- package/dist-vue/_chunks/PkChatbotError-gvDpRcEz.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotFeedbackForm-DO1QIgmo.js → PkChatbotFeedbackForm-CxLOdwkm.js} +2 -2
- package/dist-vue/_chunks/PkChatbotFeedbackForm-CxLOdwkm.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotFilePreview-DO1wZPPj.js → PkChatbotFilePreview-CwiVQDF2.js} +3 -3
- package/dist-vue/_chunks/PkChatbotFilePreview-CwiVQDF2.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotInput-D8x52cVm.js → PkChatbotInput-MSpF6SB6.js} +140 -125
- package/dist-vue/_chunks/PkChatbotInput-MSpF6SB6.js.map +1 -0
- package/dist-vue/_chunks/PkChatbotMessages-Bz5q8EtT.js +776 -0
- package/dist-vue/_chunks/PkChatbotMessages-Bz5q8EtT.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotStepPayload-BH6piqOi.js → PkChatbotStepPayload-XW4gT9AZ.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotStepPayload-BH6piqOi.js.map → PkChatbotStepPayload-XW4gT9AZ.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotStepToolDetail-BJ7xUvgi.js → PkChatbotStepToolDetail-C4-K6Glw.js} +3 -3
- package/dist-vue/_chunks/{PkChatbotStepToolDetail-BJ7xUvgi.js.map → PkChatbotStepToolDetail-C4-K6Glw.js.map} +1 -1
- package/dist-vue/_chunks/PkChatbotSteps-CrqjWpv0.js +190 -0
- package/dist-vue/_chunks/PkChatbotSteps-CrqjWpv0.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotViewChat-CNH_glPI.js → PkChatbotViewChat-DXu5ncaU.js} +10 -10
- package/dist-vue/_chunks/{PkChatbotViewChat-CNH_glPI.js.map → PkChatbotViewChat-DXu5ncaU.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewConversations-BENvHLZt.js → PkChatbotViewConversations-3LaZPFyw.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotViewConversations-BENvHLZt.js.map → PkChatbotViewConversations-3LaZPFyw.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewFiles-qmLESi1V.js → PkChatbotViewFiles-CTqnbsCj.js} +3 -3
- package/dist-vue/_chunks/{PkChatbotViewFiles-qmLESi1V.js.map → PkChatbotViewFiles-CTqnbsCj.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewProfile-DzfZnitQ.js → PkChatbotViewProfile-B-Mp1jGQ.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotViewProfile-DzfZnitQ.js.map → PkChatbotViewProfile-B-Mp1jGQ.js.map} +1 -1
- package/dist-vue/_chunks/PkRelativeTime--1cIphlA.js.map +1 -1
- package/dist-vue/_chunks/{PkStreamingMarkdown-D8_LwZMR.js → PkStreamingMarkdown-D0IOaETI.js} +432 -419
- package/dist-vue/_chunks/PkStreamingMarkdown-D0IOaETI.js.map +1 -0
- package/dist-vue/_chunks/{PkSvgViewer-DPpE9fiz.js → PkSvgViewer-D-0M5bqg.js} +2 -2
- package/dist-vue/_chunks/PkSvgViewer-D-0M5bqg.js.map +1 -0
- package/dist-vue/_chunks/{PkToolRequestGeolocation-D1ZPmWiB.js → PkToolRequestGeolocation-Q3N3jlO8.js} +3 -3
- package/dist-vue/_chunks/PkToolRequestGeolocation-Q3N3jlO8.js.map +1 -0
- package/dist-vue/_chunks/{PkToolRequestOAuthConnection-CoJyKEE6.js → PkToolRequestOAuthConnection-lYoTJIF_.js} +4 -4
- package/dist-vue/_chunks/PkToolRequestOAuthConnection-lYoTJIF_.js.map +1 -0
- package/dist-vue/_chunks/{PkToolShowArtifact-CEXdfOGG.js → PkToolShowArtifact-DHdJuzDi.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowArtifact-CEXdfOGG.js.map → PkToolShowArtifact-DHdJuzDi.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowComparison-DMSjIpCR.js → PkToolShowComparison-BLn4pkno.js} +5 -5
- package/dist-vue/_chunks/PkToolShowComparison-BLn4pkno.js.map +1 -0
- package/dist-vue/_chunks/{PkToolShowContactForm-DHmzAIVF.js → PkToolShowContactForm-DceSyuX8.js} +3 -3
- package/dist-vue/_chunks/PkToolShowContactForm-DceSyuX8.js.map +1 -0
- package/dist-vue/_chunks/{PkToolShowDiagram-DuDp5EHd.js → PkToolShowDiagram-pwc0wpNo.js} +4 -4
- package/dist-vue/_chunks/PkToolShowDiagram-pwc0wpNo.js.map +1 -0
- package/dist-vue/_chunks/{PkToolShowEmail-CavhsPvi.js → PkToolShowEmail-DF__nKpR.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowEmail-CavhsPvi.js.map → PkToolShowEmail-DF__nKpR.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowForm-CO5A_j9L.js → PkToolShowForm-Dx10jOXm.js} +7 -7
- package/dist-vue/_chunks/PkToolShowForm-Dx10jOXm.js.map +1 -0
- package/dist-vue/_chunks/{PkToolShowImageGallery-V9U3LJfF.js → PkToolShowImageGallery-DudQzBx4.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowImageGallery-V9U3LJfF.js.map → PkToolShowImageGallery-DudQzBx4.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowMessage-DQojxDiV.js → PkToolShowMessage-Ck6VP-gw.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowMessage-DQojxDiV.js.map → PkToolShowMessage-Ck6VP-gw.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowProductList-Cn0yewM3.js → PkToolShowProductList-zfM8cx-l.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowProductList-Cn0yewM3.js.map → PkToolShowProductList-zfM8cx-l.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowSources-BvWOzVkQ.js → PkToolShowSources-Dlaz2Y77.js} +5 -5
- package/dist-vue/_chunks/PkToolShowSources-Dlaz2Y77.js.map +1 -0
- package/dist-vue/_chunks/{PkToolShowSuggestedReply-DQFOVonE.js → PkToolShowSuggestedReply-DWLkUh2L.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowSuggestedReply-DQFOVonE.js.map → PkToolShowSuggestedReply-DWLkUh2L.js.map} +1 -1
- package/dist-vue/_chunks/PkToolShowWeather-Bzqalzh8.js.map +1 -1
- package/dist-vue/_chunks/{PkToolShowWebPages-Bzkkn9GV.js → PkToolShowWebPages-CosBYLrE.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowWebPages-Bzkkn9GV.js.map → PkToolShowWebPages-CosBYLrE.js.map} +1 -1
- package/dist-vue/_chunks/{PkUrl-xUBKVJCv.js → PkUrl-B5CNTQj9.js} +2 -2
- package/dist-vue/_chunks/PkUrl-B5CNTQj9.js.map +1 -0
- package/dist-vue/_chunks/{createChatbotApiClient-CJ_5_3IT.js → createChatbotApiClient-MkaPbGWB.js} +6 -3
- package/dist-vue/_chunks/createChatbotApiClient-MkaPbGWB.js.map +1 -0
- package/dist-vue/_chunks/{useChatbotStore-CiRAuq7v.js → useChatbotStore-BzfqjiYz.js} +6 -3
- package/dist-vue/_chunks/useChatbotStore-BzfqjiYz.js.map +1 -0
- package/dist-vue/_chunks/useDialogConfirm-KWz0ohCQ.js.map +1 -1
- package/dist-vue/_chunks/{utils-Coqik0XI.js → utils-C1666_6C.js} +58 -43
- package/dist-vue/_chunks/utils-C1666_6C.js.map +1 -0
- package/dist-vue/api.js +1 -1
- package/dist-vue/composables.js +3 -3
- package/dist-vue/index.js +3869 -3490
- package/dist-vue/index.js.map +1 -1
- package/dist-vue/locales.js +36 -8
- package/dist-vue/packages/components/src/chat/PkAgentSettingsPanel.d.ts +20 -3
- package/dist-vue/packages/components/src/chat/PkChatButton.d.ts +3 -2
- package/dist-vue/packages/components/src/chat/PkLanguageModel.d.ts +26 -2
- package/dist-vue/packages/components/src/chat/PkLanguageModelCombobox.d.ts +53 -1
- package/dist-vue/packages/components/src/chat/PkModelOption.d.ts +19 -0
- package/dist-vue/packages/components/src/chat/PkReasoningSettings.d.ts +6 -0
- package/dist-vue/packages/components/src/chat/PkStreamingMarkdown.d.ts +6 -0
- package/dist-vue/packages/components/src/chat/PkStreamingMarkdownAutoscroll.d.ts +1 -0
- package/dist-vue/packages/components/src/chat/constants.d.ts +5 -18
- package/dist-vue/packages/components/src/chat/index.d.ts +3 -1
- package/dist-vue/packages/components/src/chat/modelCatalog.d.ts +46 -0
- package/dist-vue/packages/components/src/chat/utils.d.ts +16 -0
- package/dist-vue/packages/components/src/table/PkTableSortable.d.ts +13 -1
- package/dist-vue/packages/composable/src/chatbot/useChatbotStore.d.ts +18 -0
- package/dist-vue/packages/composable/src/useChatbotError.d.ts +2 -0
- package/dist-vue/packages/models/src/schema/Agent.d.ts +70 -10
- package/dist-vue/packages/models/src/schema/Chat.d.ts +31 -0
- package/dist-vue/packages/models/src/schema/ModelProvider.d.ts +316 -0
- package/dist-vue/packages/models/src/schema/Organization.d.ts +142 -2
- package/dist-vue/packages/models/src/schema/ReasoningChat.d.ts +20 -0
- package/dist-vue/packages/models/src/schema/SubAgent.d.ts +20 -0
- package/dist-vue/packages/models/src/schema/UserOverview.d.ts +41 -0
- package/dist-vue/packages/models/src/schema/constants.d.ts +56 -91
- package/dist-vue/packages/models/src/schema/index.d.ts +1 -0
- package/dist-vue/style.css +1 -1
- package/package.json +1 -1
- package/dist/_chunks/Agent-Su_LDF9_.js.map +0 -1
- package/dist/_chunks/Document-DecVclEe.js.map +0 -1
- package/dist/_chunks/Media-C6SOQfJZ.js +0 -122
- package/dist/_chunks/Media-C6SOQfJZ.js.map +0 -1
- package/dist/_chunks/PkStreamingMarkdown-CwqsJnJJ.js.map +0 -1
- package/dist/_chunks/PkToolRequestGeolocation-CEVpl50q.js.map +0 -1
- package/dist/_chunks/PkToolRequestOAuthConnection-CncDU-Kl.js.map +0 -1
- package/dist/_chunks/PkToolShowComparison-DbbUD9pg.js.map +0 -1
- package/dist/_chunks/PkToolShowContactForm-D_dW59Dl.js.map +0 -1
- package/dist/_chunks/PkToolShowDiagram-Hy9qh68O.js.map +0 -1
- package/dist/_chunks/PkToolShowForm-DbJHMDbt.js.map +0 -1
- package/dist/_chunks/PkToolShowSources-B69JmwbZ.js.map +0 -1
- package/dist/_chunks/PkToolShowWeather-LPd3tC77.js.map +0 -1
- package/dist/_chunks/browser-NgY6LXg-.js.map +0 -1
- package/dist/_chunks/utils-YJ0ZOLDG.js +0 -185
- package/dist/_chunks/utils-YJ0ZOLDG.js.map +0 -1
- package/dist-vue/_chunks/Agent-C8BsTAxk.js.map +0 -1
- package/dist-vue/_chunks/Document-CaUfI_SZ.js.map +0 -1
- package/dist-vue/_chunks/PkChatbot-o7k7d-fj.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotError-CBP2mf-n.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotFeedbackForm-DO1QIgmo.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotFilePreview-DO1wZPPj.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotInput-D8x52cVm.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotMessages-BFlU046I.js +0 -771
- package/dist-vue/_chunks/PkChatbotMessages-BFlU046I.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotSteps-DtV1beDc.js +0 -180
- package/dist-vue/_chunks/PkChatbotSteps-DtV1beDc.js.map +0 -1
- package/dist-vue/_chunks/PkStreamingMarkdown-D8_LwZMR.js.map +0 -1
- package/dist-vue/_chunks/PkSvgViewer-DPpE9fiz.js.map +0 -1
- package/dist-vue/_chunks/PkToolRequestGeolocation-D1ZPmWiB.js.map +0 -1
- package/dist-vue/_chunks/PkToolRequestOAuthConnection-CoJyKEE6.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowComparison-DMSjIpCR.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowContactForm-DHmzAIVF.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowDiagram-DuDp5EHd.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowForm-CO5A_j9L.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowSources-BvWOzVkQ.js.map +0 -1
- package/dist-vue/_chunks/PkUrl-xUBKVJCv.js.map +0 -1
- package/dist-vue/_chunks/createChatbotApiClient-CJ_5_3IT.js.map +0 -1
- package/dist-vue/_chunks/useChatbotStore-CiRAuq7v.js.map +0 -1
- 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-
|
|
2
|
-
import { t } from "./PkChatbotFilePreview-
|
|
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
|
|
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
|
|
8
|
-
function
|
|
9
|
-
var t =
|
|
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
|
|
13
|
-
var t =
|
|
12
|
+
function j(e) {
|
|
13
|
+
var t = k.get(e);
|
|
14
14
|
t && t.update();
|
|
15
15
|
}
|
|
16
|
-
var
|
|
17
|
-
typeof window > "u" ? ((
|
|
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
|
-
},
|
|
21
|
+
}, M.update = function(e) {
|
|
22
22
|
return e;
|
|
23
|
-
}) : ((
|
|
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" && !
|
|
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
|
-
}),
|
|
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",
|
|
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
|
|
80
|
+
var N = M, P = ["type"], F = {
|
|
81
81
|
key: 0,
|
|
82
82
|
class: "pk-chat-button__label"
|
|
83
|
-
},
|
|
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
|
|
95
|
-
class:
|
|
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 ? (
|
|
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
|
-
"
|
|
119
|
-
"
|
|
120
|
-
|
|
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
|
|
147
|
-
|
|
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
|
-
|
|
152
|
-
O.value = R.value, z = null;
|
|
153
|
-
}, 300);
|
|
151
|
+
V(), k.value = z.value;
|
|
154
152
|
}, be = () => {
|
|
155
|
-
|
|
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
|
-
|
|
158
|
-
e !==
|
|
159
|
-
|
|
159
|
+
re(k, (e) => {
|
|
160
|
+
e !== z.value && (z.value = e ?? "", _(() => {
|
|
161
|
+
P.value && N.update(P.value);
|
|
160
162
|
}));
|
|
161
163
|
});
|
|
162
|
-
let
|
|
163
|
-
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
for (let t of e)
|
|
168
|
-
},
|
|
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
|
-
|
|
171
|
-
},
|
|
172
|
-
let t =
|
|
173
|
-
t && URL.revokeObjectURL(t.localUrl),
|
|
174
|
-
},
|
|
175
|
-
dataTypes: s(() =>
|
|
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
|
-
|
|
179
|
+
Oe.value && e && Q(e);
|
|
178
180
|
}
|
|
179
|
-
}),
|
|
180
|
-
|
|
181
|
-
}, $ = s(() =>
|
|
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:
|
|
185
|
-
dismiss: () =>
|
|
186
|
-
} :
|
|
186
|
+
text: M.attachmentNotice,
|
|
187
|
+
dismiss: () => j("dismiss-attachment-notice")
|
|
188
|
+
} : M.dismissableNotice && Ae.value ? {
|
|
187
189
|
id: "dismissable",
|
|
188
|
-
markdown:
|
|
189
|
-
dismiss:
|
|
190
|
-
} : null),
|
|
191
|
-
|
|
192
|
-
|
|
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
|
|
196
|
-
|
|
197
|
-
}),
|
|
198
|
-
|
|
199
|
-
for (let e of
|
|
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
|
|
202
|
-
return
|
|
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 ? (
|
|
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 ? (
|
|
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"])) : (
|
|
217
|
-
$.value.dismiss ? (
|
|
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:
|
|
235
|
+
ref: R,
|
|
228
236
|
class: "pk-chatbot-input__form",
|
|
229
|
-
onSubmit:
|
|
237
|
+
onSubmit: ae(Pe, ["prevent"])
|
|
230
238
|
}, [
|
|
231
|
-
|
|
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,
|
|
235
|
-
|
|
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) =>
|
|
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
|
-
|
|
258
|
-
m.fileUpload && m.fileUpload.enabled && (
|
|
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:
|
|
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:
|
|
276
|
+
disabled: W.value,
|
|
269
277
|
onClick: t
|
|
270
|
-
}), [p(
|
|
278
|
+
}), [p(_, {
|
|
271
279
|
name: "ri:add-line",
|
|
272
280
|
class: "pk-chat-button__icon"
|
|
273
281
|
})], 16, fe)]),
|
|
274
|
-
items:
|
|
275
|
-
|
|
282
|
+
items: O(() => [
|
|
283
|
+
X.value ? (x(), c(b, {
|
|
276
284
|
key: 0,
|
|
277
|
-
disabled:
|
|
278
|
-
onClick:
|
|
285
|
+
disabled: W.value || m.attachmentLimitReached,
|
|
286
|
+
onClick: Te
|
|
279
287
|
}, {
|
|
280
|
-
default:
|
|
288
|
+
default: O(() => [p(_, {
|
|
281
289
|
name: "ri:camera-line",
|
|
282
290
|
class: "pk-chatbot-input__dropdown-icon"
|
|
283
|
-
}), f(" " +
|
|
291
|
+
}), f(" " + w(s.$t("action.takePhoto")), 1)]),
|
|
284
292
|
_: 1
|
|
285
293
|
}, 8, ["disabled"])) : l("", !0),
|
|
286
|
-
p(
|
|
287
|
-
disabled:
|
|
288
|
-
onClick:
|
|
294
|
+
p(b, {
|
|
295
|
+
disabled: W.value || m.attachmentLimitReached,
|
|
296
|
+
onClick: Z
|
|
289
297
|
}, {
|
|
290
|
-
default:
|
|
298
|
+
default: O(() => [p(_, {
|
|
291
299
|
name: "ri:attachment-line",
|
|
292
300
|
class: "pk-chatbot-input__dropdown-icon"
|
|
293
|
-
}), f(" " +
|
|
301
|
+
}), f(" " + w(s.$t("action.attachFile")), 1)]),
|
|
294
302
|
_: 1
|
|
295
303
|
}, 8, ["disabled"]),
|
|
296
|
-
|
|
304
|
+
C(s.$slots, "additional-actions")
|
|
297
305
|
]),
|
|
298
306
|
_: 3
|
|
299
|
-
}, 16)) : m.fileUpload && m.fileUpload.enabled ? (
|
|
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:
|
|
304
|
-
onClick:
|
|
311
|
+
disabled: W.value || m.attachmentLimitReached,
|
|
312
|
+
onClick: Z
|
|
305
313
|
}, null, 8, ["title", "disabled"])) : l("", !0),
|
|
306
|
-
m.fileUpload && m.fileUpload.enabled ? (
|
|
314
|
+
m.fileUpload && m.fileUpload.enabled ? (x(), u("input", {
|
|
307
315
|
key: 2,
|
|
308
316
|
ref_key: "fileInputEl",
|
|
309
|
-
ref:
|
|
317
|
+
ref: F,
|
|
310
318
|
type: "file",
|
|
311
319
|
hidden: "",
|
|
312
320
|
multiple: "",
|
|
313
|
-
accept:
|
|
314
|
-
onChange:
|
|
321
|
+
accept: we.value,
|
|
322
|
+
onChange: Ee
|
|
315
323
|
}, null, 40, pe)) : l("", !0),
|
|
316
|
-
m.fileUpload && m.fileUpload.enabled &&
|
|
324
|
+
m.fileUpload && m.fileUpload.enabled && X.value ? (x(), u("input", {
|
|
317
325
|
key: 3,
|
|
318
326
|
ref_key: "cameraInputEl",
|
|
319
|
-
ref:
|
|
327
|
+
ref: L,
|
|
320
328
|
type: "file",
|
|
321
329
|
capture: "environment",
|
|
322
330
|
hidden: "",
|
|
323
|
-
accept:
|
|
324
|
-
onChange:
|
|
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:
|
|
329
|
-
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:
|
|
335
|
-
onKeydown:
|
|
346
|
+
onInput: xe,
|
|
347
|
+
onKeydown: ie(Fe, ["enter"])
|
|
336
348
|
}, null, 40, ge)]),
|
|
337
|
-
m.maxMessageLength ? (
|
|
349
|
+
m.maxMessageLength ? (x(), u("div", {
|
|
338
350
|
key: 4,
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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:
|
|
346
|
-
onClick: h[1] ||= (e) =>
|
|
358
|
+
disabled: W.value,
|
|
359
|
+
onClick: h[1] ||= (e) => j("voice-start")
|
|
347
360
|
}, null, 8, ["title", "disabled"])) : l("", !0),
|
|
348
|
-
|
|
361
|
+
H.value ? (x(), c(I, {
|
|
349
362
|
key: 6,
|
|
350
|
-
icon: "ri:stop-
|
|
363
|
+
icon: "ri:stop-fill",
|
|
364
|
+
modifiers: "primary",
|
|
351
365
|
title: s.$t("action.stop"),
|
|
352
|
-
onClick:
|
|
353
|
-
}, null, 8, ["title"])) : (
|
|
366
|
+
onClick: Ne
|
|
367
|
+
}, null, 8, ["title"])) : (x(), c(I, {
|
|
354
368
|
key: 7,
|
|
355
369
|
type: "submit",
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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 {
|
|
385
|
+
export { I as n, L as t };
|
|
371
386
|
|
|
372
|
-
//# sourceMappingURL=PkChatbotInput-
|
|
387
|
+
//# sourceMappingURL=PkChatbotInput-MSpF6SB6.js.map
|