@8wave/ai-elements 0.111.0-beta.3 → 0.111.0-beta.8
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/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-OokLeTf1.js → PkToolRequestGeolocation-Bzy4IYSp.js} +3 -3
- package/{dist-vue/_chunks/PkToolRequestGeolocation-Bxqz9oSo.js.map → dist/_chunks/PkToolRequestGeolocation-Bzy4IYSp.js.map} +1 -1
- package/dist/_chunks/{PkToolRequestOAuthConnection-CtqKG6Yb.js → PkToolRequestOAuthConnection-CWEKoD71.js} +3 -3
- package/dist/_chunks/{PkToolRequestOAuthConnection-CtqKG6Yb.js.map → PkToolRequestOAuthConnection-CWEKoD71.js.map} +1 -1
- 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-B38hHWq2.js} +3 -3
- package/dist/_chunks/{PkToolShowComparison-DbbUD9pg.js.map → PkToolShowComparison-B38hHWq2.js.map} +1 -1
- package/dist/_chunks/{PkToolShowContactForm-D_dW59Dl.js → PkToolShowContactForm-DUw_bZiJ.js} +4 -4
- package/dist/_chunks/{PkToolShowContactForm-D_dW59Dl.js.map → PkToolShowContactForm-DUw_bZiJ.js.map} +1 -1
- package/dist/_chunks/{PkToolShowDiagram-BdmG9gm8.js → PkToolShowDiagram-Dx1Ba0PG.js} +3 -3
- 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-CKQQltJ6.js} +6 -7
- package/dist/_chunks/PkToolShowForm-CKQQltJ6.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-Dot-W0Mj.js → PkToolShowSources-DpZb5FUP.js} +4 -4
- package/dist/_chunks/{PkToolShowSources-Dot-W0Mj.js.map → PkToolShowSources-DpZb5FUP.js.map} +1 -1
- 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 +3064 -3094
- 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/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-BPKSPIeC.js → PkChatbot-DE1bKmDi.js} +61 -61
- package/dist-vue/_chunks/PkChatbot-DE1bKmDi.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/{PkChatbotInput-JnHaRlfk.js → PkChatbotInput-MSpF6SB6.js} +139 -124
- package/dist-vue/_chunks/PkChatbotInput-MSpF6SB6.js.map +1 -0
- package/dist-vue/_chunks/PkChatbotMessages-B6ONEJnZ.js +776 -0
- package/dist-vue/_chunks/PkChatbotMessages-B6ONEJnZ.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-CEqzF1G9.js → PkChatbotViewChat-BMQtx1Gi.js} +10 -10
- package/dist-vue/_chunks/{PkChatbotViewChat-CEqzF1G9.js.map → PkChatbotViewChat-BMQtx1Gi.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewConversations-C787v5ll.js → PkChatbotViewConversations-3LaZPFyw.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotViewConversations-C787v5ll.js.map → PkChatbotViewConversations-3LaZPFyw.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewFiles-CNFLt8YO.js → PkChatbotViewFiles-CTqnbsCj.js} +3 -3
- package/dist-vue/_chunks/{PkChatbotViewFiles-CNFLt8YO.js.map → PkChatbotViewFiles-CTqnbsCj.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewProfile-7p0ci3qm.js → PkChatbotViewProfile-B-Mp1jGQ.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotViewProfile-7p0ci3qm.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-D-0M5bqg.js.map +1 -1
- package/dist-vue/_chunks/{PkToolRequestGeolocation-Bxqz9oSo.js → PkToolRequestGeolocation-Q3N3jlO8.js} +2 -2
- package/{dist/_chunks/PkToolRequestGeolocation-OokLeTf1.js.map → dist-vue/_chunks/PkToolRequestGeolocation-Q3N3jlO8.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolRequestOAuthConnection-C6rXgb0s.js → PkToolRequestOAuthConnection-C0LW5Evp.js} +2 -2
- package/dist-vue/_chunks/{PkToolRequestOAuthConnection-C6rXgb0s.js.map → PkToolRequestOAuthConnection-C0LW5Evp.js.map} +1 -1
- 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/{PkToolShowContactForm-DHmzAIVF.js → PkToolShowContactForm-BB2X4UdQ.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowContactForm-DHmzAIVF.js.map → PkToolShowContactForm-BB2X4UdQ.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowDiagram-dwCVZ1up.js → PkToolShowDiagram-BH6ihikd.js} +2 -2
- package/dist-vue/_chunks/PkToolShowDiagram-BH6ihikd.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-DUKIyj9V.js} +6 -6
- package/dist-vue/_chunks/PkToolShowForm-DUKIyj9V.js.map +1 -0
- 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-7Q5Iogxi.js → PkToolShowSources-Dlaz2Y77.js} +4 -4
- package/dist-vue/_chunks/{PkToolShowSources-7Q5Iogxi.js.map → PkToolShowSources-Dlaz2Y77.js.map} +1 -1
- 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-D9f69brW.js → createChatbotApiClient-MkaPbGWB.js} +2 -2
- package/dist-vue/_chunks/createChatbotApiClient-MkaPbGWB.js.map +1 -0
- package/dist-vue/_chunks/{useChatbotStore-9Cw_oR6J.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 +3853 -3485
- 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 +5 -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 +10 -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/PkToolShowDiagram-BdmG9gm8.js.map +0 -1
- package/dist/_chunks/PkToolShowForm-DbJHMDbt.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-BPKSPIeC.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotError-CBP2mf-n.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotInput-JnHaRlfk.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotMessages-DAlkoMkY.js +0 -771
- package/dist-vue/_chunks/PkChatbotMessages-DAlkoMkY.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotSteps-rommD48p.js +0 -180
- package/dist-vue/_chunks/PkChatbotSteps-rommD48p.js.map +0 -1
- package/dist-vue/_chunks/PkStreamingMarkdown-D8_LwZMR.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowDiagram-dwCVZ1up.js.map +0 -1
- package/dist-vue/_chunks/PkToolShowForm-CO5A_j9L.js.map +0 -1
- package/dist-vue/_chunks/PkUrl-xUBKVJCv.js.map +0 -1
- package/dist-vue/_chunks/createChatbotApiClient-D9f69brW.js.map +0 -1
- package/dist-vue/_chunks/useChatbotStore-9Cw_oR6J.js.map +0 -1
- package/dist-vue/_chunks/utils-Coqik0XI.js.map +0 -1
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { t as e } from "./PkStreamingMarkdown-
|
|
1
|
+
import { t as e } from "./PkStreamingMarkdown-D0IOaETI.js";
|
|
2
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PkChatbotInput-MSpF6SB6.js","names":["$t","$slots","$n"],"sources":["../../../../node_modules/.pnpm/autosize@6.0.1/node_modules/autosize/dist/autosize.esm.js","../../../../packages/components/src/chat/PkChatButton.vue","../../../../packages/components/src/chat/PkChatButton.vue","../../../../packages/components/src/chat/PkChatbotInput.vue","../../../../packages/components/src/chat/PkChatbotInput.vue"],"sourcesContent":["var e=new Map;function t(t){var o=e.get(t);o&&o.destroy()}function o(t){var o=e.get(t);o&&o.update()}var r=null;\"undefined\"==typeof window?((r=function(e){return e}).destroy=function(e){return e},r.update=function(e){return e}):((r=function(t,o){return t&&Array.prototype.forEach.call(t.length?t:[t],function(t){return function(t){if(t&&t.nodeName&&\"TEXTAREA\"===t.nodeName&&!e.has(t)){var o,r=null,n=window.getComputedStyle(t),i=(o=t.value,function(){a({testForHeightReduction:\"\"===o||!t.value.startsWith(o),restoreTextAlign:null}),o=t.value}),l=function(o){t.removeEventListener(\"autosize:destroy\",l),t.removeEventListener(\"autosize:update\",s),t.removeEventListener(\"input\",i),window.removeEventListener(\"resize\",s),Object.keys(o).forEach(function(e){return t.style[e]=o[e]}),e.delete(t)}.bind(t,{height:t.style.height,resize:t.style.resize,textAlign:t.style.textAlign,overflowY:t.style.overflowY,overflowX:t.style.overflowX,wordWrap:t.style.wordWrap});t.addEventListener(\"autosize:destroy\",l),t.addEventListener(\"autosize:update\",s),t.addEventListener(\"input\",i),window.addEventListener(\"resize\",s),t.style.overflowX=\"hidden\",t.style.wordWrap=\"break-word\",e.set(t,{destroy:l,update:s}),s()}function a(e){var o,i,l=e.restoreTextAlign,s=void 0===l?null:l,d=e.testForHeightReduction,u=void 0===d||d,c=n.overflowY;if(0!==t.scrollHeight&&(\"vertical\"===n.resize?t.style.resize=\"none\":\"both\"===n.resize&&(t.style.resize=\"horizontal\"),u&&(o=function(e){for(var t=[];e&&e.parentNode&&e.parentNode instanceof Element;)e.parentNode.scrollTop&&t.push([e.parentNode,e.parentNode.scrollTop]),e=e.parentNode;return function(){return t.forEach(function(e){var t=e[0],o=e[1];t.style.scrollBehavior=\"auto\",t.scrollTop=o,t.style.scrollBehavior=null})}}(t),t.style.height=\"\"),i=\"content-box\"===n.boxSizing?t.scrollHeight-(parseFloat(n.paddingTop)+parseFloat(n.paddingBottom)):t.scrollHeight+parseFloat(n.borderTopWidth)+parseFloat(n.borderBottomWidth),\"none\"!==n.maxHeight&&i>parseFloat(n.maxHeight)?(\"hidden\"===n.overflowY&&(t.style.overflow=\"scroll\"),i=parseFloat(n.maxHeight)):\"hidden\"!==n.overflowY&&(t.style.overflow=\"hidden\"),t.style.height=i+\"px\",s&&(t.style.textAlign=s),o&&o(),r!==i&&(t.dispatchEvent(new Event(\"autosize:resized\",{bubbles:!0})),r=i),c!==n.overflow&&!s)){var v=n.textAlign;\"hidden\"===n.overflow&&(t.style.textAlign=\"start\"===v?\"end\":\"start\"),a({restoreTextAlign:v,testForHeightReduction:!0})}}function s(){a({testForHeightReduction:!0,restoreTextAlign:null})}}(t)}),t}).destroy=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],t),e},r.update=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],o),e});var n=r;export default n;\n","<script lang=\"ts\" setup>\n /**\n * The icon button of the chat dock: attach, send and stop in the input,\n * mute and hang up in a live call. One component, because the call bar\n * takes the place of the input and the two must not look like two\n * different pieces of software.\n *\n * Native attributes fall through to the button, so `title`, `disabled` and\n * `aria-pressed` are written by the caller as they would be on a `<button>`.\n */\n withDefaults(\n defineProps<{\n icon: string\n /** Written next to the icon, for an action nobody should have to guess from a glyph. */\n label?: string\n type?: 'button' | 'submit'\n /** `primary` is the filled circle of send and stop, the one action the dock is for. */\n modifiers?: 'danger' | 'primary'\n }>(),\n { label: undefined, type: 'button', modifiers: undefined },\n )\n</script>\n\n<template>\n <button\n class=\"pk-chat-button\"\n :class=\"[\n modifiers ? `pk-chat-button--${modifiers}` : undefined,\n { 'pk-chat-button--labelled': label },\n ]\"\n :type=\"type\">\n <VvIcon :name=\"icon\" class=\"pk-chat-button__icon\" />\n <span v-if=\"label\" class=\"pk-chat-button__label\">{{ label }}</span>\n </button>\n</template>\n\n<style lang=\"scss\">\n .pk-chat-button {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n padding: var(--spacing-4);\n border: none;\n border-radius: var(--rounded);\n background-color: transparent;\n color: var(--color-word-1);\n cursor: pointer;\n transition: var(--transition-colors);\n\n &:hover {\n background-color: var(--color-surface-2);\n }\n\n // The fields' focus ring: a 1px surface-5 line measured 1.3:1 on the\n // surface, under the 3:1 a focus indicator needs\n &:focus-visible {\n outline: var(--spacing-2) solid var(--input-focus-color);\n outline-offset: 0;\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n // A toggle has to survive a glance: a crossed-out glyph alone changes\n // too few pixels to notice mid-sentence.\n &[aria-pressed='true'] {\n background-color: var(--color-surface-3);\n color: var(--color-word);\n }\n\n // A wash of the same red rather than a lighter red behind it: the\n // `lighten-5` step lands close enough to the icon to leave it at about\n // 2:1, which is a button that disappears exactly while it is being\n // pointed at. The tint composites over whatever surface is behind, so\n // it holds in the dark theme too.\n &--danger {\n color: var(--color-danger);\n\n &:hover {\n background-color: color-mix(\n in srgb,\n var(--color-danger) 12%,\n transparent\n );\n }\n }\n\n // Same 28px box as the ghost buttons, so the dock keeps its height,\n // with a smaller glyph because a filled shape needs air around it.\n // Its edge is visible, so it sits on the input's padding line just as\n // the text does: a ghost glyph sat 6px further in and made the two\n // sides of the input look unequal. Empty, it turns into a grey pad\n // with the fields' disabled ink: a light arrow on that pad vanished,\n // and with it the circle's edge, which is what squares the sides.\n // The agent's color when the widget has one, like the user's bubble.\n &--primary {\n --pk-chat-button-fill: var(\n --chatbot-main-color,\n var(--color-word-1)\n );\n\n padding: var(--spacing-6);\n border-radius: var(--rounded-full);\n background-color: var(--pk-chat-button-fill);\n color: var(--chatbot-contrast-color, var(--color-surface));\n\n &:hover {\n background-color: color-mix(\n in srgb,\n var(--pk-chat-button-fill) 85%,\n var(--color-surface)\n );\n }\n\n // Off the disc, or a dark ring would sink into a dark fill\n &:focus-visible {\n outline-offset: var(--spacing-2);\n }\n\n &:disabled {\n opacity: 1;\n background-color: var(--color-surface-3);\n color: var(--color-word-3);\n }\n\n .pk-chat-button__icon {\n width: var(--spacing-16);\n height: var(--spacing-16);\n }\n }\n\n &--labelled {\n gap: var(--spacing-4);\n padding-inline: var(--spacing-8);\n font-size: var(--text-12);\n }\n\n &__icon {\n display: block;\n width: var(--spacing-20);\n height: var(--spacing-20);\n }\n }\n</style>\n","<script lang=\"ts\" setup>\n /**\n * The icon button of the chat dock: attach, send and stop in the input,\n * mute and hang up in a live call. One component, because the call bar\n * takes the place of the input and the two must not look like two\n * different pieces of software.\n *\n * Native attributes fall through to the button, so `title`, `disabled` and\n * `aria-pressed` are written by the caller as they would be on a `<button>`.\n */\n withDefaults(\n defineProps<{\n icon: string\n /** Written next to the icon, for an action nobody should have to guess from a glyph. */\n label?: string\n type?: 'button' | 'submit'\n /** `primary` is the filled circle of send and stop, the one action the dock is for. */\n modifiers?: 'danger' | 'primary'\n }>(),\n { label: undefined, type: 'button', modifiers: undefined },\n )\n</script>\n\n<template>\n <button\n class=\"pk-chat-button\"\n :class=\"[\n modifiers ? `pk-chat-button--${modifiers}` : undefined,\n { 'pk-chat-button--labelled': label },\n ]\"\n :type=\"type\">\n <VvIcon :name=\"icon\" class=\"pk-chat-button__icon\" />\n <span v-if=\"label\" class=\"pk-chat-button__label\">{{ label }}</span>\n </button>\n</template>\n\n<style lang=\"scss\">\n .pk-chat-button {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n padding: var(--spacing-4);\n border: none;\n border-radius: var(--rounded);\n background-color: transparent;\n color: var(--color-word-1);\n cursor: pointer;\n transition: var(--transition-colors);\n\n &:hover {\n background-color: var(--color-surface-2);\n }\n\n // The fields' focus ring: a 1px surface-5 line measured 1.3:1 on the\n // surface, under the 3:1 a focus indicator needs\n &:focus-visible {\n outline: var(--spacing-2) solid var(--input-focus-color);\n outline-offset: 0;\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n // A toggle has to survive a glance: a crossed-out glyph alone changes\n // too few pixels to notice mid-sentence.\n &[aria-pressed='true'] {\n background-color: var(--color-surface-3);\n color: var(--color-word);\n }\n\n // A wash of the same red rather than a lighter red behind it: the\n // `lighten-5` step lands close enough to the icon to leave it at about\n // 2:1, which is a button that disappears exactly while it is being\n // pointed at. The tint composites over whatever surface is behind, so\n // it holds in the dark theme too.\n &--danger {\n color: var(--color-danger);\n\n &:hover {\n background-color: color-mix(\n in srgb,\n var(--color-danger) 12%,\n transparent\n );\n }\n }\n\n // Same 28px box as the ghost buttons, so the dock keeps its height,\n // with a smaller glyph because a filled shape needs air around it.\n // Its edge is visible, so it sits on the input's padding line just as\n // the text does: a ghost glyph sat 6px further in and made the two\n // sides of the input look unequal. Empty, it turns into a grey pad\n // with the fields' disabled ink: a light arrow on that pad vanished,\n // and with it the circle's edge, which is what squares the sides.\n // The agent's color when the widget has one, like the user's bubble.\n &--primary {\n --pk-chat-button-fill: var(\n --chatbot-main-color,\n var(--color-word-1)\n );\n\n padding: var(--spacing-6);\n border-radius: var(--rounded-full);\n background-color: var(--pk-chat-button-fill);\n color: var(--chatbot-contrast-color, var(--color-surface));\n\n &:hover {\n background-color: color-mix(\n in srgb,\n var(--pk-chat-button-fill) 85%,\n var(--color-surface)\n );\n }\n\n // Off the disc, or a dark ring would sink into a dark fill\n &:focus-visible {\n outline-offset: var(--spacing-2);\n }\n\n &:disabled {\n opacity: 1;\n background-color: var(--color-surface-3);\n color: var(--color-word-3);\n }\n\n .pk-chat-button__icon {\n width: var(--spacing-16);\n height: var(--spacing-16);\n }\n }\n\n &--labelled {\n gap: var(--spacing-4);\n padding-inline: var(--spacing-8);\n font-size: var(--text-12);\n }\n\n &__icon {\n display: block;\n width: var(--spacing-20);\n height: var(--spacing-20);\n }\n }\n</style>\n","<script setup lang=\"ts\">\n // @ts-expect-error - no types for autosize\n import autosize from 'autosize'\n import {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n useTemplateRef,\n watch,\n } from 'vue'\n import { useDropZone } from '@vueuse/core'\n import type { AgentFileUpload } from 'models'\n import type { PendingAttachment } from 'composables'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkChatbotFilePreview from './PkChatbotFilePreview.vue'\n import PkChatButton from './PkChatButton.vue'\n\n // --- Models & Props ---\n\n const modelValue = defineModel<string | undefined>({ default: undefined })\n const pendingAttachments = defineModel<PendingAttachment[]>(\n 'pendingAttachments',\n { default: () => [] },\n )\n\n const emit = defineEmits<{\n submit: []\n 'stop-generation': []\n 'file-select': [file: File]\n 'dismiss-attachment-notice': []\n 'voice-start': []\n }>()\n\n const props = defineProps<{\n placeholder?: string\n dismissableNotice?: string\n status?: 'submitted' | 'streaming' | 'ready' | 'error'\n maxMessageLength?: number\n fileUpload?: AgentFileUpload\n enableDragDrop?: boolean\n attachmentLimitReached?: boolean\n attachmentNotice?: string\n /** Show the talk button: the agent has voice enabled. */\n voiceEnabled?: boolean\n }>()\n\n // --- Template refs ---\n\n const textareaEl = useTemplateRef<HTMLTextAreaElement>('textareaEl')\n const fileInputEl = useTemplateRef<HTMLInputElement>('fileInputEl')\n const cameraInputEl = useTemplateRef<HTMLInputElement>('cameraInputEl')\n const formEl = useTemplateRef<HTMLFormElement>('formEl')\n\n // --- Input buffering (decouples typing from reactive model propagation) ---\n\n const localValue = ref(modelValue.value ?? '')\n let syncTimer: ReturnType<typeof setTimeout> | null = null\n\n const cancelSync = () => {\n if (syncTimer !== null) {\n clearTimeout(syncTimer)\n syncTimer = null\n }\n }\n\n const flushSync = () => {\n cancelSync()\n modelValue.value = localValue.value\n }\n\n const scheduleSync = () => {\n cancelSync()\n syncTimer = setTimeout(() => {\n modelValue.value = localValue.value\n syncTimer = null\n }, 300)\n }\n\n const onTextareaInput = () => {\n localValue.value = textareaEl.value?.value ?? ''\n scheduleSync()\n }\n\n watch(modelValue, (v) => {\n if (v !== localValue.value) {\n localValue.value = v ?? ''\n nextTick(() => {\n if (textareaEl.value) {\n autosize.update(textareaEl.value)\n }\n })\n }\n })\n\n // --- Status computeds ---\n\n const isStreaming = computed(() => props.status === 'streaming')\n const isSubmitted = computed(() => props.status === 'submitted')\n const isInputDisabled = computed(\n () => isStreaming.value || isSubmitted.value,\n )\n\n // --- Validation ---\n\n const counterId = useId()\n const currentLength = computed(() => localValue.value.length)\n\n const isOverLimit = computed(\n () =>\n props.maxMessageLength !== undefined &&\n currentLength.value > props.maxMessageLength,\n )\n\n const isUploadingAnyFile = computed(() =>\n pendingAttachments.value.some((a) => a.state === 'uploading'),\n )\n\n const isSubmitEnabled = computed(() => {\n if (\n isInputDisabled.value ||\n isUploadingAnyFile.value ||\n isOverLimit.value\n ) {\n return false\n }\n return localValue.value.trim().length > 0\n })\n\n // --- File upload ---\n\n const hasCaptureSupport = 'capture' in document.createElement('input')\n\n const acceptMimeTypes = computed(\n () => props.fileUpload?.allowedMimeTypes?.join(',') ?? '',\n )\n\n const acceptImageMimeTypes = computed(() =>\n (props.fileUpload?.allowedMimeTypes ?? [])\n .filter((m) => m.startsWith('image/'))\n .join(','),\n )\n\n const showCameraOption = computed(\n () => hasCaptureSupport && acceptImageMimeTypes.value.length > 0,\n )\n\n const openFilePicker = () => {\n fileInputEl.value?.click()\n }\n\n const openCameraPicker = () => {\n cameraInputEl.value?.click()\n }\n\n // The store owns the attachment limits and drops any overflow; the input\n // just forwards every picked/dropped file.\n const emitFiles = (files: File[]) => {\n for (const file of files) {\n emit('file-select', file)\n }\n }\n\n const onFileChange = (event: Event) => {\n const input = event.target as HTMLInputElement\n emitFiles(Array.from(input.files ?? []))\n input.value = ''\n }\n\n // --- Attachments ---\n\n const removeAttachment = (id: string) => {\n const att = pendingAttachments.value.find((a) => a.id === id)\n if (att) {\n URL.revokeObjectURL(att.localUrl)\n }\n pendingAttachments.value = pendingAttachments.value.filter(\n (a) => a.id !== id,\n )\n }\n\n // --- Drag & drop ---\n\n const isDragDropEnabled = computed(\n () => (props.enableDragDrop ?? true) && !!props.fileUpload?.enabled,\n )\n\n const handleDrop = (files: File[] | null) => {\n if (!isDragDropEnabled.value || !files) {\n return\n }\n emitFiles(files)\n }\n\n const { isOverDropZone } = useDropZone(formEl, {\n dataTypes: computed(() => props.fileUpload?.allowedMimeTypes ?? []),\n onDrop: handleDrop,\n })\n\n // --- Notice queue (single slot above the input, highest priority wins) ---\n\n type InputNotice = {\n id: string\n text?: string\n markdown?: string\n icon?: string\n dismiss?: () => void\n }\n\n const isDismissableNoticeVisible = ref(true)\n const closeDismissableNotice = () => {\n isDismissableNoticeVisible.value = false\n }\n\n const activeNotice = computed<InputNotice | null>(() => {\n // Order = priority. The alert takes precedence over the notice.\n if (props.attachmentNotice) {\n return {\n id: 'limit',\n icon: 'ri:information-line',\n text: props.attachmentNotice,\n dismiss: () => emit('dismiss-attachment-notice'),\n }\n }\n if (props.dismissableNotice && isDismissableNoticeVisible.value) {\n return {\n id: 'dismissable',\n markdown: props.dismissableNotice,\n dismiss: closeDismissableNotice,\n }\n }\n return null\n })\n\n // --- Submit ---\n\n /**\n * Send turns disabled and then gives way to stop, stop gives way to send:\n * a keyboard user who pressed one would be left on the page body. Hand\n * the focus to the textarea, but only after a keyboard press: a tap has no\n * focus to keep, and focusing would bring the phone keyboard back up over\n * the answer.\n */\n const keepKeyboardFocus = () => {\n if (formEl.value?.querySelector('button:focus-visible')) {\n textareaEl.value?.focus()\n }\n }\n\n const stopGeneration = () => {\n keepKeyboardFocus()\n emit('stop-generation')\n }\n\n const handleSubmit = () => {\n if (!isSubmitEnabled.value) {\n return\n }\n keepKeyboardFocus()\n flushSync()\n emit('submit')\n localValue.value = ''\n modelValue.value = ''\n nextTick(() => {\n if (textareaEl.value) {\n textareaEl.value.value = ''\n autosize.update(textareaEl.value)\n }\n })\n }\n\n /**\n * Enter sends, Shift+Enter goes to a new line. The Enter that confirms an\n * IME composition (Japanese, Chinese, Korean) belongs to the composition:\n * Safari reports it with `isComposing` already false, hence the 229.\n */\n const onTextareaEnter = (event: KeyboardEvent) => {\n if (event.shiftKey || event.isComposing || event.keyCode === 229) {\n return\n }\n event.preventDefault()\n handleSubmit()\n }\n\n // --- Lifecycle ---\n\n onMounted(() => {\n if (textareaEl.value) {\n autosize(textareaEl.value)\n }\n })\n\n onBeforeUnmount(() => {\n cancelSync()\n if (textareaEl.value) {\n autosize.destroy(textareaEl.value)\n }\n for (const att of pendingAttachments.value) {\n URL.revokeObjectURL(att.localUrl)\n }\n })\n</script>\n\n<template>\n <div class=\"pk-chatbot-input\">\n <div\n v-if=\"activeNotice\"\n :key=\"activeNotice.id\"\n class=\"pk-chatbot-input__notice\"\n role=\"status\">\n <VvIcon\n v-if=\"activeNotice.icon\"\n :name=\"activeNotice.icon\"\n class=\"pk-chatbot-input__notice-icon\" />\n <PkStreamingMarkdown\n v-if=\"activeNotice.markdown\"\n :markdown=\"activeNotice.markdown\"\n class=\"wysiwyg pk-chatbot-input__notice-text\" />\n <span v-else class=\"pk-chatbot-input__notice-text\">\n {{ activeNotice.text }}\n </span>\n <VvButton\n v-if=\"activeNotice.dismiss\"\n :title=\"$t('action.close')\"\n modifiers=\"action-quiet\"\n icon=\"ri:close-line\"\n class=\"w-18 h-18\"\n @click=\"activeNotice.dismiss()\" />\n </div>\n <form\n ref=\"formEl\"\n class=\"pk-chatbot-input__form\"\n @submit.prevent=\"handleSubmit\">\n <div\n v-if=\"isOverDropZone && isDragDropEnabled\"\n class=\"pk-chatbot-input__drop-overlay\">\n <VvIcon\n name=\"ri:upload-cloud-2-line\"\n class=\"pk-chatbot-input__drop-overlay-icon\" />\n <span>{{ $t('action.dropFile') }}</span>\n </div>\n <div\n v-if=\"pendingAttachments.length\"\n class=\"pk-chatbot-input__attachments\">\n <PkChatbotFilePreview\n v-for=\"att in pendingAttachments\"\n :key=\"att.id\"\n :media-type=\"att.file.type\"\n :url=\"att.localUrl\"\n :filename=\"att.file.name\"\n :size=\"att.file.size\"\n :loading=\"att.state === 'uploading'\"\n :error=\"att.state === 'error' ? att.error : undefined\"\n :removable=\"att.state !== 'uploading'\"\n compact\n @remove=\"removeAttachment(att.id)\" />\n </div>\n <div class=\"pk-chatbot-input__fieldset\">\n <slot name=\"prepend\" />\n <VvDropdown\n v-if=\"\n fileUpload &&\n fileUpload.enabled &&\n (showCameraOption || $slots['additional-actions'])\n \"\n v-bind=\"{\n placement: 'top-start',\n modifiers: 'menu',\n flip: true,\n offset: 3,\n }\">\n <template #default=\"{ init, toggle, aria }\">\n <!-- The only one still written by hand: the dropdown\n anchors itself to whatever `init` receives, and that\n has to be the element, not a component instance -->\n <button\n :ref=\"(e: any) => init(e)\"\n v-bind=\"aria\"\n class=\"pk-chat-button\"\n type=\"button\"\n :title=\"$t('action.attachFile')\"\n :disabled=\"isInputDisabled\"\n @click=\"toggle\">\n <VvIcon\n name=\"ri:add-line\"\n class=\"pk-chat-button__icon\" />\n </button>\n </template>\n <template #items>\n <VvDropdownAction\n v-if=\"showCameraOption\"\n :disabled=\"\n isInputDisabled || attachmentLimitReached\n \"\n @click=\"openCameraPicker\">\n <VvIcon\n name=\"ri:camera-line\"\n class=\"pk-chatbot-input__dropdown-icon\" />\n {{ $t('action.takePhoto') }}\n </VvDropdownAction>\n <VvDropdownAction\n :disabled=\"\n isInputDisabled || attachmentLimitReached\n \"\n @click=\"openFilePicker\">\n <VvIcon\n name=\"ri:attachment-line\"\n class=\"pk-chatbot-input__dropdown-icon\" />\n {{ $t('action.attachFile') }}\n </VvDropdownAction>\n <slot name=\"additional-actions\" />\n </template>\n </VvDropdown>\n <PkChatButton\n v-else-if=\"fileUpload && fileUpload.enabled\"\n icon=\"ri:add-line\"\n :title=\"$t('action.attachFile')\"\n :disabled=\"isInputDisabled || attachmentLimitReached\"\n @click=\"openFilePicker\" />\n <input\n v-if=\"fileUpload && fileUpload.enabled\"\n ref=\"fileInputEl\"\n type=\"file\"\n hidden\n multiple\n :accept=\"acceptMimeTypes\"\n @change=\"onFileChange\" />\n <input\n v-if=\"fileUpload && fileUpload.enabled && showCameraOption\"\n ref=\"cameraInputEl\"\n type=\"file\"\n capture=\"environment\"\n hidden\n :accept=\"acceptImageMimeTypes\"\n @change=\"onFileChange\" />\n <div class=\"pk-chatbot-input__content\">\n <textarea\n ref=\"textareaEl\"\n :value=\"localValue\"\n class=\"pk-chatbot-input__textarea\"\n name=\"message\"\n rows=\"1\"\n enterkeyhint=\"send\"\n :aria-label=\"$t('label.message')\"\n :aria-describedby=\"\n maxMessageLength ? counterId : undefined\n \"\n :aria-invalid=\"isOverLimit || undefined\"\n :placeholder\n @input=\"onTextareaInput\"\n @keydown.enter=\"onTextareaEnter\"></textarea>\n </div>\n <div\n v-if=\"maxMessageLength\"\n :id=\"counterId\"\n class=\"pk-chatbot-input__counter\"\n :class=\"{ 'pk-chatbot-input__counter--over': isOverLimit }\">\n {{ $n(currentLength, 'integer') }}/<span\n class=\"opacity-60\"\n >{{ $n(maxMessageLength, 'integer') }}</span\n >\n </div>\n <PkChatButton\n v-if=\"voiceEnabled && !isStreaming\"\n icon=\"ri:mic-line\"\n :title=\"$t('action.talk')\"\n :disabled=\"isInputDisabled\"\n @click=\"emit('voice-start')\" />\n <PkChatButton\n v-if=\"isStreaming\"\n icon=\"ri:stop-fill\"\n modifiers=\"primary\"\n :title=\"$t('action.stop')\"\n @click=\"stopGeneration\" />\n <PkChatButton\n v-else\n type=\"submit\"\n modifiers=\"primary\"\n :icon=\"isSubmitted ? 'loading-loop' : 'ri:arrow-up-line'\"\n :title=\"$t('action.submit')\"\n :disabled=\"!isSubmitEnabled\" />\n </div>\n </form>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-chatbot-input {\n position: relative;\n display: flex;\n flex-direction: column;\n margin-inline: var(--spacing-sm);\n margin-bottom: var(--spacing-sm);\n\n &__notice {\n position: relative;\n padding: var(--spacing-10) var(--spacing-sm);\n display: flex;\n align-items: flex-start;\n gap: var(--spacing-sm);\n background-color: var(--color-surface-1);\n border-top-left-radius: var(--rounded-xl);\n border-top-right-radius: var(--rounded-xl);\n transition-property: var(--transition-property-all);\n transition-duration: var(--duration-300);\n transition-timing-function: var(--ease-in-out);\n font-size: var(--text-12);\n color: var(--color-word-4);\n\n &::after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n right: 0;\n bottom: calc(-1 * var(--spacing-12));\n height: var(--spacing-12);\n background-color: var(--color-surface-1);\n z-index: 1;\n }\n\n &-icon {\n flex-shrink: 0;\n width: var(--spacing-18);\n height: var(--spacing-18);\n }\n\n &-text {\n flex: 1;\n min-width: 0;\n }\n }\n\n &__form {\n position: relative;\n display: flex;\n z-index: 1;\n flex-direction: column;\n\n // The composer is a field too: same border and focus ring as the\n // form fields, on top of the shadow and the 12px radius that make\n // it the container (12) of its 8px buttons\n border-radius: var(--rounded-xl);\n border: 1px solid var(--input-border-color);\n background-color: var(--color-surface);\n padding: var(--spacing-14);\n box-shadow: var(--shadow-lg);\n font-size: var(\n --text-16\n ); // prevent ios zoom on input focus by using a font size >= 16px\n gap: var(--spacing-xs);\n transition: var(--input-transition);\n\n @include media-breakpoint-up('sm', $breakpoints) {\n font-size: var(--text-14);\n padding: var(--spacing-10);\n }\n\n &:has(:focus-within) {\n border-color: var(--input-focus-color);\n box-shadow: var(--shadow-lg), var(--input-focus-ring);\n }\n }\n\n &__drop-overlay {\n position: absolute;\n inset: 0;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-xs);\n border-radius: var(--rounded-xl);\n background-color: color-mix(\n in srgb,\n var(--color-surface) 85%,\n transparent\n );\n pointer-events: none;\n }\n\n &__fieldset {\n display: flex;\n align-items: center;\n gap: var(--spacing-xs);\n flex: 1;\n }\n\n &__content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4);\n min-width: 0;\n overflow: hidden;\n }\n\n &__textarea {\n display: block;\n border: none;\n outline: none;\n resize: none;\n width: 100%;\n max-height: 200px;\n color: var(--color-word-1);\n background-color: var(--color-surface);\n\n &::placeholder {\n color: var(--color-word-4);\n }\n }\n\n &__attachments {\n display: flex;\n flex-wrap: wrap;\n // Roomy gap so the uniform-height chips breathe in the row.\n gap: var(--spacing-12);\n padding-bottom: var(--spacing-xs);\n border-bottom: 1px solid var(--color-surface-2);\n }\n\n &__counter {\n background-color: var(--color-surface-1);\n border: 1px solid var(--color-surface-3);\n border-radius: var(--rounded-md);\n font-size: var(--text-12);\n color: var(--color-word-3);\n line-height: 1;\n padding-inline: var(--spacing-6);\n padding-block: var(--spacing-4);\n z-index: 1;\n font-variant-numeric: tabular-nums;\n font-family: var(--font-mono);\n font-weight: var(--font-bold);\n\n &--over {\n color: var(--color-danger);\n border-color: var(--color-danger-lighten-5);\n font-weight: var(--font-bold);\n }\n }\n }\n</style>\n","<script setup lang=\"ts\">\n // @ts-expect-error - no types for autosize\n import autosize from 'autosize'\n import {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n useTemplateRef,\n watch,\n } from 'vue'\n import { useDropZone } from '@vueuse/core'\n import type { AgentFileUpload } from 'models'\n import type { PendingAttachment } from 'composables'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkChatbotFilePreview from './PkChatbotFilePreview.vue'\n import PkChatButton from './PkChatButton.vue'\n\n // --- Models & Props ---\n\n const modelValue = defineModel<string | undefined>({ default: undefined })\n const pendingAttachments = defineModel<PendingAttachment[]>(\n 'pendingAttachments',\n { default: () => [] },\n )\n\n const emit = defineEmits<{\n submit: []\n 'stop-generation': []\n 'file-select': [file: File]\n 'dismiss-attachment-notice': []\n 'voice-start': []\n }>()\n\n const props = defineProps<{\n placeholder?: string\n dismissableNotice?: string\n status?: 'submitted' | 'streaming' | 'ready' | 'error'\n maxMessageLength?: number\n fileUpload?: AgentFileUpload\n enableDragDrop?: boolean\n attachmentLimitReached?: boolean\n attachmentNotice?: string\n /** Show the talk button: the agent has voice enabled. */\n voiceEnabled?: boolean\n }>()\n\n // --- Template refs ---\n\n const textareaEl = useTemplateRef<HTMLTextAreaElement>('textareaEl')\n const fileInputEl = useTemplateRef<HTMLInputElement>('fileInputEl')\n const cameraInputEl = useTemplateRef<HTMLInputElement>('cameraInputEl')\n const formEl = useTemplateRef<HTMLFormElement>('formEl')\n\n // --- Input buffering (decouples typing from reactive model propagation) ---\n\n const localValue = ref(modelValue.value ?? '')\n let syncTimer: ReturnType<typeof setTimeout> | null = null\n\n const cancelSync = () => {\n if (syncTimer !== null) {\n clearTimeout(syncTimer)\n syncTimer = null\n }\n }\n\n const flushSync = () => {\n cancelSync()\n modelValue.value = localValue.value\n }\n\n const scheduleSync = () => {\n cancelSync()\n syncTimer = setTimeout(() => {\n modelValue.value = localValue.value\n syncTimer = null\n }, 300)\n }\n\n const onTextareaInput = () => {\n localValue.value = textareaEl.value?.value ?? ''\n scheduleSync()\n }\n\n watch(modelValue, (v) => {\n if (v !== localValue.value) {\n localValue.value = v ?? ''\n nextTick(() => {\n if (textareaEl.value) {\n autosize.update(textareaEl.value)\n }\n })\n }\n })\n\n // --- Status computeds ---\n\n const isStreaming = computed(() => props.status === 'streaming')\n const isSubmitted = computed(() => props.status === 'submitted')\n const isInputDisabled = computed(\n () => isStreaming.value || isSubmitted.value,\n )\n\n // --- Validation ---\n\n const counterId = useId()\n const currentLength = computed(() => localValue.value.length)\n\n const isOverLimit = computed(\n () =>\n props.maxMessageLength !== undefined &&\n currentLength.value > props.maxMessageLength,\n )\n\n const isUploadingAnyFile = computed(() =>\n pendingAttachments.value.some((a) => a.state === 'uploading'),\n )\n\n const isSubmitEnabled = computed(() => {\n if (\n isInputDisabled.value ||\n isUploadingAnyFile.value ||\n isOverLimit.value\n ) {\n return false\n }\n return localValue.value.trim().length > 0\n })\n\n // --- File upload ---\n\n const hasCaptureSupport = 'capture' in document.createElement('input')\n\n const acceptMimeTypes = computed(\n () => props.fileUpload?.allowedMimeTypes?.join(',') ?? '',\n )\n\n const acceptImageMimeTypes = computed(() =>\n (props.fileUpload?.allowedMimeTypes ?? [])\n .filter((m) => m.startsWith('image/'))\n .join(','),\n )\n\n const showCameraOption = computed(\n () => hasCaptureSupport && acceptImageMimeTypes.value.length > 0,\n )\n\n const openFilePicker = () => {\n fileInputEl.value?.click()\n }\n\n const openCameraPicker = () => {\n cameraInputEl.value?.click()\n }\n\n // The store owns the attachment limits and drops any overflow; the input\n // just forwards every picked/dropped file.\n const emitFiles = (files: File[]) => {\n for (const file of files) {\n emit('file-select', file)\n }\n }\n\n const onFileChange = (event: Event) => {\n const input = event.target as HTMLInputElement\n emitFiles(Array.from(input.files ?? []))\n input.value = ''\n }\n\n // --- Attachments ---\n\n const removeAttachment = (id: string) => {\n const att = pendingAttachments.value.find((a) => a.id === id)\n if (att) {\n URL.revokeObjectURL(att.localUrl)\n }\n pendingAttachments.value = pendingAttachments.value.filter(\n (a) => a.id !== id,\n )\n }\n\n // --- Drag & drop ---\n\n const isDragDropEnabled = computed(\n () => (props.enableDragDrop ?? true) && !!props.fileUpload?.enabled,\n )\n\n const handleDrop = (files: File[] | null) => {\n if (!isDragDropEnabled.value || !files) {\n return\n }\n emitFiles(files)\n }\n\n const { isOverDropZone } = useDropZone(formEl, {\n dataTypes: computed(() => props.fileUpload?.allowedMimeTypes ?? []),\n onDrop: handleDrop,\n })\n\n // --- Notice queue (single slot above the input, highest priority wins) ---\n\n type InputNotice = {\n id: string\n text?: string\n markdown?: string\n icon?: string\n dismiss?: () => void\n }\n\n const isDismissableNoticeVisible = ref(true)\n const closeDismissableNotice = () => {\n isDismissableNoticeVisible.value = false\n }\n\n const activeNotice = computed<InputNotice | null>(() => {\n // Order = priority. The alert takes precedence over the notice.\n if (props.attachmentNotice) {\n return {\n id: 'limit',\n icon: 'ri:information-line',\n text: props.attachmentNotice,\n dismiss: () => emit('dismiss-attachment-notice'),\n }\n }\n if (props.dismissableNotice && isDismissableNoticeVisible.value) {\n return {\n id: 'dismissable',\n markdown: props.dismissableNotice,\n dismiss: closeDismissableNotice,\n }\n }\n return null\n })\n\n // --- Submit ---\n\n /**\n * Send turns disabled and then gives way to stop, stop gives way to send:\n * a keyboard user who pressed one would be left on the page body. Hand\n * the focus to the textarea, but only after a keyboard press: a tap has no\n * focus to keep, and focusing would bring the phone keyboard back up over\n * the answer.\n */\n const keepKeyboardFocus = () => {\n if (formEl.value?.querySelector('button:focus-visible')) {\n textareaEl.value?.focus()\n }\n }\n\n const stopGeneration = () => {\n keepKeyboardFocus()\n emit('stop-generation')\n }\n\n const handleSubmit = () => {\n if (!isSubmitEnabled.value) {\n return\n }\n keepKeyboardFocus()\n flushSync()\n emit('submit')\n localValue.value = ''\n modelValue.value = ''\n nextTick(() => {\n if (textareaEl.value) {\n textareaEl.value.value = ''\n autosize.update(textareaEl.value)\n }\n })\n }\n\n /**\n * Enter sends, Shift+Enter goes to a new line. The Enter that confirms an\n * IME composition (Japanese, Chinese, Korean) belongs to the composition:\n * Safari reports it with `isComposing` already false, hence the 229.\n */\n const onTextareaEnter = (event: KeyboardEvent) => {\n if (event.shiftKey || event.isComposing || event.keyCode === 229) {\n return\n }\n event.preventDefault()\n handleSubmit()\n }\n\n // --- Lifecycle ---\n\n onMounted(() => {\n if (textareaEl.value) {\n autosize(textareaEl.value)\n }\n })\n\n onBeforeUnmount(() => {\n cancelSync()\n if (textareaEl.value) {\n autosize.destroy(textareaEl.value)\n }\n for (const att of pendingAttachments.value) {\n URL.revokeObjectURL(att.localUrl)\n }\n })\n</script>\n\n<template>\n <div class=\"pk-chatbot-input\">\n <div\n v-if=\"activeNotice\"\n :key=\"activeNotice.id\"\n class=\"pk-chatbot-input__notice\"\n role=\"status\">\n <VvIcon\n v-if=\"activeNotice.icon\"\n :name=\"activeNotice.icon\"\n class=\"pk-chatbot-input__notice-icon\" />\n <PkStreamingMarkdown\n v-if=\"activeNotice.markdown\"\n :markdown=\"activeNotice.markdown\"\n class=\"wysiwyg pk-chatbot-input__notice-text\" />\n <span v-else class=\"pk-chatbot-input__notice-text\">\n {{ activeNotice.text }}\n </span>\n <VvButton\n v-if=\"activeNotice.dismiss\"\n :title=\"$t('action.close')\"\n modifiers=\"action-quiet\"\n icon=\"ri:close-line\"\n class=\"w-18 h-18\"\n @click=\"activeNotice.dismiss()\" />\n </div>\n <form\n ref=\"formEl\"\n class=\"pk-chatbot-input__form\"\n @submit.prevent=\"handleSubmit\">\n <div\n v-if=\"isOverDropZone && isDragDropEnabled\"\n class=\"pk-chatbot-input__drop-overlay\">\n <VvIcon\n name=\"ri:upload-cloud-2-line\"\n class=\"pk-chatbot-input__drop-overlay-icon\" />\n <span>{{ $t('action.dropFile') }}</span>\n </div>\n <div\n v-if=\"pendingAttachments.length\"\n class=\"pk-chatbot-input__attachments\">\n <PkChatbotFilePreview\n v-for=\"att in pendingAttachments\"\n :key=\"att.id\"\n :media-type=\"att.file.type\"\n :url=\"att.localUrl\"\n :filename=\"att.file.name\"\n :size=\"att.file.size\"\n :loading=\"att.state === 'uploading'\"\n :error=\"att.state === 'error' ? att.error : undefined\"\n :removable=\"att.state !== 'uploading'\"\n compact\n @remove=\"removeAttachment(att.id)\" />\n </div>\n <div class=\"pk-chatbot-input__fieldset\">\n <slot name=\"prepend\" />\n <VvDropdown\n v-if=\"\n fileUpload &&\n fileUpload.enabled &&\n (showCameraOption || $slots['additional-actions'])\n \"\n v-bind=\"{\n placement: 'top-start',\n modifiers: 'menu',\n flip: true,\n offset: 3,\n }\">\n <template #default=\"{ init, toggle, aria }\">\n <!-- The only one still written by hand: the dropdown\n anchors itself to whatever `init` receives, and that\n has to be the element, not a component instance -->\n <button\n :ref=\"(e: any) => init(e)\"\n v-bind=\"aria\"\n class=\"pk-chat-button\"\n type=\"button\"\n :title=\"$t('action.attachFile')\"\n :disabled=\"isInputDisabled\"\n @click=\"toggle\">\n <VvIcon\n name=\"ri:add-line\"\n class=\"pk-chat-button__icon\" />\n </button>\n </template>\n <template #items>\n <VvDropdownAction\n v-if=\"showCameraOption\"\n :disabled=\"\n isInputDisabled || attachmentLimitReached\n \"\n @click=\"openCameraPicker\">\n <VvIcon\n name=\"ri:camera-line\"\n class=\"pk-chatbot-input__dropdown-icon\" />\n {{ $t('action.takePhoto') }}\n </VvDropdownAction>\n <VvDropdownAction\n :disabled=\"\n isInputDisabled || attachmentLimitReached\n \"\n @click=\"openFilePicker\">\n <VvIcon\n name=\"ri:attachment-line\"\n class=\"pk-chatbot-input__dropdown-icon\" />\n {{ $t('action.attachFile') }}\n </VvDropdownAction>\n <slot name=\"additional-actions\" />\n </template>\n </VvDropdown>\n <PkChatButton\n v-else-if=\"fileUpload && fileUpload.enabled\"\n icon=\"ri:add-line\"\n :title=\"$t('action.attachFile')\"\n :disabled=\"isInputDisabled || attachmentLimitReached\"\n @click=\"openFilePicker\" />\n <input\n v-if=\"fileUpload && fileUpload.enabled\"\n ref=\"fileInputEl\"\n type=\"file\"\n hidden\n multiple\n :accept=\"acceptMimeTypes\"\n @change=\"onFileChange\" />\n <input\n v-if=\"fileUpload && fileUpload.enabled && showCameraOption\"\n ref=\"cameraInputEl\"\n type=\"file\"\n capture=\"environment\"\n hidden\n :accept=\"acceptImageMimeTypes\"\n @change=\"onFileChange\" />\n <div class=\"pk-chatbot-input__content\">\n <textarea\n ref=\"textareaEl\"\n :value=\"localValue\"\n class=\"pk-chatbot-input__textarea\"\n name=\"message\"\n rows=\"1\"\n enterkeyhint=\"send\"\n :aria-label=\"$t('label.message')\"\n :aria-describedby=\"\n maxMessageLength ? counterId : undefined\n \"\n :aria-invalid=\"isOverLimit || undefined\"\n :placeholder\n @input=\"onTextareaInput\"\n @keydown.enter=\"onTextareaEnter\"></textarea>\n </div>\n <div\n v-if=\"maxMessageLength\"\n :id=\"counterId\"\n class=\"pk-chatbot-input__counter\"\n :class=\"{ 'pk-chatbot-input__counter--over': isOverLimit }\">\n {{ $n(currentLength, 'integer') }}/<span\n class=\"opacity-60\"\n >{{ $n(maxMessageLength, 'integer') }}</span\n >\n </div>\n <PkChatButton\n v-if=\"voiceEnabled && !isStreaming\"\n icon=\"ri:mic-line\"\n :title=\"$t('action.talk')\"\n :disabled=\"isInputDisabled\"\n @click=\"emit('voice-start')\" />\n <PkChatButton\n v-if=\"isStreaming\"\n icon=\"ri:stop-fill\"\n modifiers=\"primary\"\n :title=\"$t('action.stop')\"\n @click=\"stopGeneration\" />\n <PkChatButton\n v-else\n type=\"submit\"\n modifiers=\"primary\"\n :icon=\"isSubmitted ? 'loading-loop' : 'ri:arrow-up-line'\"\n :title=\"$t('action.submit')\"\n :disabled=\"!isSubmitEnabled\" />\n </div>\n </form>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-chatbot-input {\n position: relative;\n display: flex;\n flex-direction: column;\n margin-inline: var(--spacing-sm);\n margin-bottom: var(--spacing-sm);\n\n &__notice {\n position: relative;\n padding: var(--spacing-10) var(--spacing-sm);\n display: flex;\n align-items: flex-start;\n gap: var(--spacing-sm);\n background-color: var(--color-surface-1);\n border-top-left-radius: var(--rounded-xl);\n border-top-right-radius: var(--rounded-xl);\n transition-property: var(--transition-property-all);\n transition-duration: var(--duration-300);\n transition-timing-function: var(--ease-in-out);\n font-size: var(--text-12);\n color: var(--color-word-4);\n\n &::after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n right: 0;\n bottom: calc(-1 * var(--spacing-12));\n height: var(--spacing-12);\n background-color: var(--color-surface-1);\n z-index: 1;\n }\n\n &-icon {\n flex-shrink: 0;\n width: var(--spacing-18);\n height: var(--spacing-18);\n }\n\n &-text {\n flex: 1;\n min-width: 0;\n }\n }\n\n &__form {\n position: relative;\n display: flex;\n z-index: 1;\n flex-direction: column;\n\n // The composer is a field too: same border and focus ring as the\n // form fields, on top of the shadow and the 12px radius that make\n // it the container (12) of its 8px buttons\n border-radius: var(--rounded-xl);\n border: 1px solid var(--input-border-color);\n background-color: var(--color-surface);\n padding: var(--spacing-14);\n box-shadow: var(--shadow-lg);\n font-size: var(\n --text-16\n ); // prevent ios zoom on input focus by using a font size >= 16px\n gap: var(--spacing-xs);\n transition: var(--input-transition);\n\n @include media-breakpoint-up('sm', $breakpoints) {\n font-size: var(--text-14);\n padding: var(--spacing-10);\n }\n\n &:has(:focus-within) {\n border-color: var(--input-focus-color);\n box-shadow: var(--shadow-lg), var(--input-focus-ring);\n }\n }\n\n &__drop-overlay {\n position: absolute;\n inset: 0;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-xs);\n border-radius: var(--rounded-xl);\n background-color: color-mix(\n in srgb,\n var(--color-surface) 85%,\n transparent\n );\n pointer-events: none;\n }\n\n &__fieldset {\n display: flex;\n align-items: center;\n gap: var(--spacing-xs);\n flex: 1;\n }\n\n &__content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4);\n min-width: 0;\n overflow: hidden;\n }\n\n &__textarea {\n display: block;\n border: none;\n outline: none;\n resize: none;\n width: 100%;\n max-height: 200px;\n color: var(--color-word-1);\n background-color: var(--color-surface);\n\n &::placeholder {\n color: var(--color-word-4);\n }\n }\n\n &__attachments {\n display: flex;\n flex-wrap: wrap;\n // Roomy gap so the uniform-height chips breathe in the row.\n gap: var(--spacing-12);\n padding-bottom: var(--spacing-xs);\n border-bottom: 1px solid var(--color-surface-2);\n }\n\n &__counter {\n background-color: var(--color-surface-1);\n border: 1px solid var(--color-surface-3);\n border-radius: var(--rounded-md);\n font-size: var(--text-12);\n color: var(--color-word-3);\n line-height: 1;\n padding-inline: var(--spacing-6);\n padding-block: var(--spacing-4);\n z-index: 1;\n font-variant-numeric: tabular-nums;\n font-family: var(--font-mono);\n font-weight: var(--font-bold);\n\n &--over {\n color: var(--color-danger);\n border-color: var(--color-danger-lighten-5);\n font-weight: var(--font-bold);\n }\n }\n }\n</style>\n"],"x_google_ignoreList":[0],"mappings":";;;;;;AAAA,IAAI,oBAAE,IAAI,IAAE;AAAE,SAAS,EAAE,GAAE;CAAC,IAAI,IAAE,EAAE,IAAI,CAAC;CAAE,KAAG,EAAE,QAAQ;AAAC;AAAC,SAAS,EAAE,GAAE;CAAC,IAAI,IAAE,EAAE,IAAI,CAAC;CAAE,KAAG,EAAE,OAAO;AAAC;AAAC,IAAI,IAAE;AAAkB,OAAO,SAApB,OAA4B,CAAC,IAAE,SAAS,GAAE;CAAC,OAAO;AAAC,EAAA,CAAG,UAAQ,SAAS,GAAE;CAAC,OAAO;AAAC,GAAE,EAAE,SAAO,SAAS,GAAE;CAAC,OAAO;AAAC,MAAI,CAAC,IAAE,SAAS,GAAE,GAAE;CAAC,OAAO,KAAG,MAAM,UAAU,QAAQ,KAAK,EAAE,SAAO,IAAE,CAAC,CAAC,GAAE,SAAS,GAAE;EAAC,OAAO,SAAS,GAAE;GAAC,IAAG,KAAG,EAAE,YAAuB,EAAE,aAAf,cAAyB,CAAC,EAAE,IAAI,CAAC,GAAE;IAAC,IAAI,GAAE,IAAE,MAAK,IAAE,OAAO,iBAAiB,CAAC,GAAE,KAAG,IAAE,EAAE,OAAM,WAAU;KAAC,EAAE;MAAC,wBAA4B,MAAL,MAAQ,CAAC,EAAE,MAAM,WAAW,CAAC;MAAE,kBAAiB;KAAI,CAAC,GAAE,IAAE,EAAE;IAAK,IAAG,IAAE,SAAS,GAAE;KAAC,EAAE,oBAAoB,oBAAmB,CAAC,GAAE,EAAE,oBAAoB,mBAAkB,CAAC,GAAE,EAAE,oBAAoB,SAAQ,CAAC,GAAE,OAAO,oBAAoB,UAAS,CAAC,GAAE,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,SAAS,GAAE;MAAC,OAAO,EAAE,MAAM,KAAG,EAAE;KAAE,CAAC,GAAE,EAAE,OAAO,CAAC;IAAC,EAAE,KAAK,GAAE;KAAC,QAAO,EAAE,MAAM;KAAO,QAAO,EAAE,MAAM;KAAO,WAAU,EAAE,MAAM;KAAU,WAAU,EAAE,MAAM;KAAU,WAAU,EAAE,MAAM;KAAU,UAAS,EAAE,MAAM;IAAQ,CAAC;IAAE,EAAE,iBAAiB,oBAAmB,CAAC,GAAE,EAAE,iBAAiB,mBAAkB,CAAC,GAAE,EAAE,iBAAiB,SAAQ,CAAC,GAAE,OAAO,iBAAiB,UAAS,CAAC,GAAE,EAAE,MAAM,YAAU,UAAS,EAAE,MAAM,WAAS,cAAa,EAAE,IAAI,GAAE;KAAC,SAAQ;KAAE,QAAO;IAAC,CAAC,GAAE,EAAE;GAAC;GAAC,SAAS,EAAE,GAAE;IAAC,IAAI,GAAE,GAAE,IAAE,EAAE,kBAAiB,IAAW,MAAT,KAAK,IAAM,OAAK,GAAE,IAAE,EAAE,wBAAuB,IAAW,MAAT,KAAK,KAAO,GAAE,IAAE,EAAE;IAAU,IAAO,EAAE,iBAAN,MAAkC,EAAE,WAAf,aAAsB,EAAE,MAAM,SAAO,SAAgB,EAAE,WAAX,WAAoB,EAAE,MAAM,SAAO,eAAc,MAAI,IAAE,SAAS,GAAE;KAAC,KAAI,IAAI,IAAE,CAAC,GAAE,KAAG,EAAE,cAAY,EAAE,sBAAsB,UAAS,EAAE,WAAW,aAAW,EAAE,KAAK,CAAC,EAAE,YAAW,EAAE,WAAW,SAAS,CAAC,GAAE,IAAE,EAAE;KAAW,OAAO,WAAU;MAAC,OAAO,EAAE,QAAQ,SAAS,GAAE;OAAC,IAAI,IAAE,EAAE,IAAG,IAAE,EAAE;OAAG,EAAE,MAAM,iBAAe,QAAO,EAAE,YAAU,GAAE,EAAE,MAAM,iBAAe;MAAI,CAAC;KAAC;IAAC,EAAE,CAAC,GAAE,EAAE,MAAM,SAAO,KAAI,IAAkB,EAAE,cAAlB,gBAA4B,EAAE,gBAAc,WAAW,EAAE,UAAU,IAAE,WAAW,EAAE,aAAa,KAAG,EAAE,eAAa,WAAW,EAAE,cAAc,IAAE,WAAW,EAAE,iBAAiB,GAAW,EAAE,cAAX,UAAsB,IAAE,WAAW,EAAE,SAAS,KAAc,EAAE,cAAb,aAAyB,EAAE,MAAM,WAAS,WAAU,IAAE,WAAW,EAAE,SAAS,KAAc,EAAE,cAAb,aAAyB,EAAE,MAAM,WAAS,WAAU,EAAE,MAAM,SAAO,IAAE,MAAK,MAAI,EAAE,MAAM,YAAU,IAAG,KAAG,EAAE,GAAE,MAAI,MAAI,EAAE,cAAc,IAAI,MAAM,oBAAmB,EAAC,SAAQ,CAAC,EAAC,CAAC,CAAC,GAAE,IAAE,IAAG,MAAI,EAAE,YAAU,CAAC,IAAG;KAAC,IAAI,IAAE,EAAE;KAAU,AAAW,EAAE,aAAb,aAAwB,EAAE,MAAM,YAAoB,MAAV,UAAY,QAAM,UAAS,EAAE;MAAC,kBAAiB;MAAE,wBAAuB,CAAC;KAAC,CAAC;IAAC;GAAC;GAAC,SAAS,IAAG;IAAC,EAAE;KAAC,wBAAuB,CAAC;KAAE,kBAAiB;IAAI,CAAC;GAAC;EAAC,EAAE,CAAC;CAAC,CAAC,GAAE;AAAC,EAAA,CAAG,UAAQ,SAAS,GAAE;CAAC,OAAO,KAAG,MAAM,UAAU,QAAQ,KAAK,EAAE,SAAO,IAAE,CAAC,CAAC,GAAE,CAAC,GAAE;AAAC,GAAE,EAAE,SAAO,SAAS,GAAE;CAAC,OAAO,KAAG,MAAM,UAAU,QAAQ,KAAK,EAAE,SAAO,IAAE,CAAC,CAAC,GAAE,CAAC,GAAE;AAAC;AAAG,IAAI,IAAE;;;;;;;;;;;;;;GCwBjlF,OAAA,EAAA,GAAA,EASS,UAAA;IARL,OAAK,EAAA,CAAC,kBAAgB,CACA,EAAA,YAAS,mBAAsB,EAAA,cAAc,KAAA,GAAqD,EAAA,4BAAA,EAAA,MAAK,CAAA,CAAA,CAAA;IAI5H,MAAM,EAAA;GACP,GAAA,CAAA,EAAoD,GAAA;IAA3C,MAAM,EAAA;IAAM,OAAM;GACf,GAAA,MAAA,GAAA,CAAA,MAAA,CAAA,GAAA,EAAA,SAAZ,EAAA,GAAA,EAAmE,QAAnE,GAAmE,EAAf,EAAA,KAAK,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEV7D,IAAM,IAAa,EAA+B,GAAA,YAAuB,GACnE,IAAqB,EACxB,GAAC,oBAEJ,GAEM,IAAO,GAQP,IAAQ,GAeR,IAAa,EAAoC,YAAY,GAC7D,IAAc,EAAiC,aAAa,GAC5D,IAAgB,EAAiC,eAAe,GAChE,IAAS,EAAgC,QAAQ,GAIjD,IAAa,EAAI,EAAW,SAAS,EAAE,GACzC,IAAkD,MAEhD,UAAmB;GACrB,AAAI,MAAc,SACd,aAAa,CAAS,GACtB,IAAY;EAEpB,GAEM,WAAkB;GAEpB,AADA,EAAW,GACX,EAAW,QAAQ,EAAW;EAClC,GAEM,WAAqB;GAEvB,AADA,EAAW,GACX,IAAY,iBAAiB;IAEzB,AADA,EAAW,QAAQ,EAAW,OAC9B,IAAY;GAChB,GAAG,GAAG;EACV,GAEM,WAAwB;GAE1B,AADA,EAAW,QAAQ,EAAW,OAAO,SAAS,IAC9C,GAAa;EACjB;EAEA,GAAM,IAAa,MAAM;GACrB,AAAI,MAAM,EAAW,UACjB,EAAW,QAAQ,KAAK,IACxB,QAAe;IACX,AAAI,EAAW,SACX,EAAS,OAAO,EAAW,KAAK;GAExC,CAAC;EAET,CAAC;EAID,IAAM,IAAc,QAAe,EAAM,WAAW,WAAW,GACzD,IAAc,QAAe,EAAM,WAAW,WAAW,GACzD,IAAkB,QACd,EAAY,SAAS,EAAY,KAC3C,GAIM,IAAY,GAAM,GAClB,IAAgB,QAAe,EAAW,MAAM,MAAM,GAEtD,IAAc,QAEZ,EAAM,qBAAqB,KAAA,KAC3B,EAAc,QAAQ,EAAM,gBACpC,GAEM,KAAqB,QACvB,EAAmB,MAAM,MAAM,MAAM,EAAE,UAAU,WAAW,CAChE,GAEM,IAAkB,QAEhB,EAAgB,SAChB,GAAmB,SACnB,EAAY,QAEL,KAEJ,EAAW,MAAM,KAAK,CAAC,CAAC,SAAS,CAC3C,GAIK,KAAoB,aAAa,SAAS,cAAc,OAAO,GAE/D,KAAkB,QACd,EAAM,YAAY,kBAAkB,KAAK,GAAG,KAAK,EAC3D,GAEM,IAAuB,SACxB,EAAM,YAAY,oBAAoB,CAAC,EAAA,CACnC,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,CAAA,CACpC,KAAK,GAAG,CACjB,GAEM,IAAmB,QACf,MAAqB,EAAqB,MAAM,SAAS,CACnE,GAEM,UAAuB;GACzB,EAAY,OAAO,MAAM;EAC7B,GAEM,WAAyB;GAC3B,EAAc,OAAO,MAAM;EAC/B,GAIM,KAAa,MAAkB;GACjC,KAAK,IAAM,KAAQ,GACf,EAAK,eAAe,CAAI;EAEhC,GAEM,MAAgB,MAAiB;GACnC,IAAM,IAAQ,EAAM;GAEpB,AADA,EAAU,MAAM,KAAK,EAAM,SAAS,CAAC,CAAC,CAAC,GACvC,EAAM,QAAQ;EAClB,GAIM,MAAoB,MAAe;GACrC,IAAM,IAAM,EAAmB,MAAM,MAAM,MAAM,EAAE,OAAO,CAAE;GAI5D,AAHI,KACA,IAAI,gBAAgB,EAAI,QAAQ,GAEpC,EAAmB,QAAQ,EAAmB,MAAM,QAC/C,MAAM,EAAE,OAAO,CACpB;EACJ,GAIM,KAAoB,SACf,EAAM,kBAAkB,OAAS,CAAC,CAAC,EAAM,YAAY,OAChE,GASM,EAAE,uBAAmB,GAAY,GAAQ;GAC3C,WAAW,QAAe,EAAM,YAAY,oBAAoB,CAAC,CAAC;GAClE,SATgB,MAAyB;IACrC,AAAC,GAAkB,SAAU,KAGjC,EAAU,CAAK;GACnB;EAKA,CAAC,GAYK,KAA6B,EAAI,EAAI,GACrC,WAA+B;GACjC,GAA2B,QAAQ;EACvC,GAEM,IAAe,QAEb,EAAM,mBACC;GACH,IAAI;GACJ,MAAM;GACN,MAAM,EAAM;GACZ,eAAe,EAAK,2BAA2B;EACnD,IAEA,EAAM,qBAAqB,GAA2B,QAC/C;GACH,IAAI;GACJ,UAAU,EAAM;GAChB,SAAS;EACb,IAEG,IACV,GAWK,WAA0B;GAC5B,AAAI,EAAO,OAAO,cAAc,sBAAsB,KAClD,EAAW,OAAO,MAAM;EAEhC,GAEM,WAAuB;GAEzB,AADA,GAAkB,GAClB,EAAK,iBAAiB;EAC1B,GAEM,WAAqB;GAClB,EAAgB,UAGrB,GAAkB,GAClB,GAAU,GACV,EAAK,QAAQ,GACb,EAAW,QAAQ,IACnB,EAAW,QAAQ,IACnB,QAAe;IACX,AAAI,EAAW,UACX,EAAW,MAAM,QAAQ,IACzB,EAAS,OAAO,EAAW,KAAK;GAExC,CAAC;EACL,GAOM,MAAmB,MAAyB;GAC1C,EAAM,YAAY,EAAM,eAAe,EAAM,YAAY,QAG7D,EAAM,eAAe,GACrB,GAAa;EACjB;SAIA,QAAgB;GACZ,AAAI,EAAW,SACX,EAAS,EAAW,KAAK;EAEjC,CAAC,GAED,QAAsB;GAElB,AADA,EAAW,GACP,EAAW,SACX,EAAS,QAAQ,EAAW,KAAK;GAErC,KAAK,IAAM,KAAO,EAAmB,OACjC,IAAI,gBAAgB,EAAI,QAAQ;EAExC,CAAC;;GAID,OAAA,EAAA,GAAA,EAmLM,OAnLN,IAmLM,CAjLQ,EAAA,SADV,EAAA,GAAA,EAuBM,OAAA;IArBD,KAAK,EAAA,MAAa;IACnB,OAAM;IACN,MAAK;;IAEK,EAAA,MAAa,QADvB,EAAA,GAAA,EAG4C,GAAA;;KADvC,MAAM,EAAA,MAAa;KACpB,OAAM;;IAEA,EAAA,MAAa,YADvB,EAAA,GAAA,EAGoD,GAAA;;KAD/C,UAAU,EAAA,MAAa;KACxB,OAAM;IACV,GAAA,MAAA,GAAA,CAAA,UAAA,CAAA,MAAA,EAAA,GAAA,EAEO,QAFP,IAEO,EADA,EAAA,MAAa,IAAI,GAAA,CAAA;IAGd,EAAA,MAAa,WADvB,EAAA,GAAA,EAMsC,GAAA;;KAJjC,OAAOA,EAAAA,GAAE,cAAA;KACV,WAAU;KACV,MAAK;KACL,OAAM;KACL,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,MAAa,QAAO;;GAEpC,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAyJO,QAAA;IAxJC,SAAA;IAAJ,KAAI;IACJ,OAAM;IACL,UAAM,GAAU,IAAY,CAAA,SAAA,CAAA;;IAEnB,EAAA,EAAA,KAAkB,GAAA,SAD5B,EAAA,GAAA,EAOM,OAPN,IAOM,CAJF,EAEkD,GAAA;KAD9C,MAAK;KACL,OAAM;IACV,CAAA,GAAA,EAAwC,QAAA,MAAA,EAA/BA,EAAAA,GAAE,iBAAA,CAAA,GAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;IAGL,EAAA,MAAmB,UAD7B,EAAA,GAAA,EAeM,OAfN,IAeM,EAZF,EAAA,EAAA,GAAA,EAWyC,GAAA,MAAA,GAVvB,EAAA,QAAP,OADX,EAAA,GAAA,EAWyC,GAAA;KATpC,KAAK,EAAI;KACT,cAAY,EAAI,KAAK;KACrB,KAAK,EAAI;KACT,UAAU,EAAI,KAAK;KACnB,MAAM,EAAI,KAAK;KACf,SAAS,EAAI,UAAK;KAClB,OAAO,EAAI,UAAK,UAAe,EAAI,QAAQ,KAAA;KAC3C,WAAW,EAAI,UAAK;KACrB,SAAA;KACC,WAAM,MAAE,GAAiB,EAAI,EAAE;;;;;;;;;;;IAExC,EA4HM,OA5HN,IA4HM;KA3HF,EAAuB,EAAA,QAAA,SAAA;KAEY,EAAA,cAAsC,EAAA,WAAW,YAAoC,EAAA,SAAoBC,EAAAA,OAAM,0BADlJ,EAAA,GAAA,EAqDa,GAAA,GAAA,EAAA,EAAA,KAAA,EAAA,GA/CD;;;;;KAKP,CAAA,CAAA,GAAA;MACU,SAAO,GAeL,EAfS,SAAM,WAAQ,cAAI,CAIpC,EAWS,UAXT,EAWS,EAVJ,MAAM,MAAW,EAAK,CAAC,EAChB,GAAA,GAAI;OACZ,OAAM;OACN,MAAK;OACJ,OAAOD,EAAAA,GAAE,mBAAA;OACT,UAAU,EAAA;OACV,SAAO;MACR,CAAA,GAAA,CAAA,EAEmC,GAAA;OAD/B,MAAK;OACL,OAAM;;MAGP,OAAK,QAWO;OATT,EAAA,SADV,EAAA,GAAA,EAUmB,GAAA;;QARd,UAA2C,EAAA,SAAmB,EAAA;QAG9D,SAAO;;QACR,SAAA,QAE8C,CAF9C,EAE8C,GAAA;SAD1C,MAAK;SACL,OAAM;QAAoC,CAAA,GAAA,EAAA,MAC9C,EAAGA,EAAAA,GAAE,kBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;OAET,EASmB,GAAA;QARd,UAA2C,EAAA,SAAmB,EAAA;QAG9D,SAAO;;QACR,SAAA,QAE8C,CAF9C,EAE8C,GAAA;SAD1C,MAAK;SACL,OAAM;QAAoC,CAAA,GAAA,EAAA,MAC9C,EAAGA,EAAAA,GAAE,mBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;OAET,EAAkC,EAAA,QAAA,oBAAA;;;KAI3B,GAAA,EAAA,KAAA,EAAA,cAAc,EAAA,WAAW,WADxC,EAAA,GAAA,EAK8B,GAAA;;MAH1B,MAAK;MACJ,OAAOA,EAAAA,GAAE,mBAAA;MACT,UAAU,EAAA,SAAmB,EAAA;MAC7B,SAAO;;KAEF,EAAA,cAAc,EAAA,WAAW,WADnC,EAAA,GAAA,EAO6B,SAAA;;MALrB,SAAA;MAAJ,KAAI;MACJ,MAAK;MACL,QAAA;MACA,UAAA;MACC,QAAQ,GAAA;MACR,UAAQ;;KAEH,EAAA,cAAc,EAAA,WAAW,WAAW,EAAA,SAD9C,EAAA,GAAA,EAO6B,SAAA;;MALrB,SAAA;MAAJ,KAAI;MACJ,MAAK;MACL,SAAQ;MACR,QAAA;MACC,QAAQ,EAAA;MACR,UAAQ;;KACb,EAgBM,OAhBN,IAgBM,CAfF,EAcgD,YAAA;MAbxC,SAAA;MAAJ,KAAI;MACH,OAAO,EAAA;MACR,OAAM;MACN,MAAK;MACL,MAAK;MACL,cAAa;MACZ,cAAYA,EAAAA,GAAE,eAAA;MACd,oBAA+C,EAAA,mBAAmB,EAAA,CAAA,IAAY,KAAA;MAG9E,gBAAc,EAAA,SAAe,KAAA;MAC7B,aAAA,EAAA;MACA,SAAO;MACP,WAAO,GAAQ,IAAe,CAAA,OAAA,CAAA;;KAG7B,EAAA,oBADV,EAAA,GAAA,EASM,OAAA;;MAPD,IAAI,EAAA,CAAA;MACL,OAAK,EAAA,CAAC,6BAA2B,EAAA,mCACY,EAAA,MAAW,CAAA,CAAA;KACrDE,GAAAA,CAAAA,EAAAA,EAAAA,EAAAA,GAAG,EAAA,OAAa,SAAA,CAAA,IAAe,KAAC,CAAA,GAAA,EAGlC,QAHkC,IAGlC,EADOA,EAAAA,GAAG,EAAA,kBAAgB,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,IAAA,EAAA,KAAA,EAAA,IAAA,EAAA;KAIrB,EAAA,gBAAY,CAAK,EAAA,SAD3B,EAAA,GAAA,EAKmC,GAAA;;MAH/B,MAAK;MACJ,OAAOF,EAAAA,GAAE,aAAA;MACT,UAAU,EAAA;MACV,SAAK,AAAA,EAAA,QAAA,MAAE,EAAI,aAAA;;KAEN,EAAA,SADV,EAAA,GAAA,EAK8B,GAAA;;MAH1B,MAAK;MACL,WAAU;MACT,OAAOA,EAAAA,GAAE,aAAA;MACT,SAAO;KACZ,GAAA,MAAA,GAAA,CAAA,OAAA,CAAA,MAAA,EAAA,GAAA,EAMmC,GAAA;;MAJ/B,MAAK;MACL,WAAU;MACT,MAAM,EAAA,QAAW,iBAAA;MACjB,OAAOA,EAAAA,GAAE,eAAA;MACT,UAAQ,CAAG,EAAA"}
|