@om_patel_26/chat-widget 1.0.4 → 1.0.6

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 CHANGED
@@ -77,6 +77,55 @@ import serviceAccountKey from './service-account-key.json';
77
77
 
78
78
  **📚 For detailed Vue.js setup guide, see [VUE_INSTALLATION_GUIDE.md](./VUE_INSTALLATION_GUIDE.md)**
79
79
 
80
+ ### Nuxt 3 Usage (Important: Use ClientOnly!)
81
+
82
+ ```bash
83
+ # Install
84
+ npm install @om_patel_26/chat-widget
85
+ ```
86
+
87
+ **⚠️ CRITICAL: The component MUST be wrapped in `<ClientOnly>` for Nuxt SSR!**
88
+
89
+ ```vue
90
+ <template>
91
+ <div>
92
+ <ClientOnly>
93
+ <ChatWidget
94
+ :df-project-id="'your-project-id'"
95
+ :df-agent-id="'your-agent-id'"
96
+ :service-account-key="serviceAccountKey"
97
+ />
98
+ <template #fallback>
99
+ <div>Loading chat...</div>
100
+ </template>
101
+ </ClientOnly>
102
+ </div>
103
+ </template>
104
+
105
+ <script setup>
106
+ import ChatWidget from '@om_patel_26/chat-widget/nuxt';
107
+ import '@om_patel_26/chat-widget/dist/styles.css';
108
+ import serviceAccountKey from './service-account-key.json';
109
+ </script>
110
+ ```
111
+
112
+ **In `nuxt.config.ts`:**
113
+ ```typescript
114
+ export default defineNuxtConfig({
115
+ css: ['@om_patel_26/chat-widget/dist/styles.css'],
116
+
117
+ vite: {
118
+ optimizeDeps: {
119
+ exclude: ['@om_patel_26/chat-widget'],
120
+ },
121
+ },
122
+ });
123
+ ```
124
+
125
+ **Why ClientOnly?** The widget uses browser APIs (`localStorage`, `window`, `WebSocket`) that don't exist during SSR.
126
+
127
+ **📚 For detailed Nuxt 3 setup guide, see [NUXT_USAGE.md](./NUXT_USAGE.md)**
128
+
80
129
  ---
81
130
 
82
131
  ### React/Next.js Usage
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./ChatWidget.vue.cjs2.js");;/* empty css */const t=require("../_virtual/_plugin-vue_export-helper.cjs.js").default(e.default,[["__scopeId","data-v-0ea40880"]]);exports.default=t;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./ChatWidget.vue.cjs2.js");;/* empty css */const t=require("../_virtual/_plugin-vue_export-helper.cjs.js").default(e.default,[["__scopeId","data-v-0d32fcf4"]]);exports.default=t;
2
2
  //# sourceMappingURL=ChatWidget.vue.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),t=require("../composables/useChatWidget.cjs.js"),o=require("../utils/sanitize.cjs.js"),a={class:"blockspark-welcome-header"},l={class:"blockspark-welcome-title"},n={class:"blockspark-welcome-message"},c={class:"blockspark-welcome-cta"},s={key:2,class:"blockspark-chat-window"},r={class:"blockspark-chat-header"},i={class:"blockspark-chat-header-content"},p={class:"blockspark-chat-title"},k={class:"blockspark-chat-subtitle"},d={key:0,class:"blockspark-mode-indicator"},m={key:0,class:"blockspark-mode-badge"},u={key:1,class:"blockspark-agent-info"},g={class:"blockspark-agent-name"},b={key:2,class:"blockspark-mode-badge"},h={key:0,class:"blockspark-chat-empty"},y=["innerHTML"],E={key:0,class:"blockspark-chips-container"},f={key:0,class:"blockspark-chips-group"},B=["onClick"],v={key:0,class:"blockspark-chips-group"},V=["onClick"],N={class:"blockspark-message-time"},C={key:1,class:"blockspark-message blockspark-message-bot"},w={key:2,class:"blockspark-agent-typing-indicator"},M=["value","placeholder","disabled"],S=["disabled"],x=e.defineComponent({inheritAttrs:!1,__name:"ChatWidget",props:{dfProjectId:{},dfLocation:{},dfAgentId:{},serviceAccountKey:{},accessToken:{},languageCode:{},backendBaseUrl:{},backendWsUrl:{},title:{default:"💬 BlockSpark AI Assistant"},subtitle:{default:"We're here to help"},welcomeTitle:{default:"👋 Welcome to BlockSpark"},welcomeMessage:{default:"My name is BlockSpark AI Assistant and I'll guide you."},welcomeCta:{default:"💬 Click here to start chatting!"},showWelcomePopup:{type:Boolean,default:!0},welcomePopupDelay:{default:1500},fallbackWelcomeMessage:{default:"Hello! I'm BlockSpark AI Assistant. How can I help you today?"},inputPlaceholder:{default:"Type your message..."},emptyStateMessage:{default:"Hi! I'm BlockSpark AI Assistant. How can I help you today?"},debug:{type:Boolean,default:!1}},setup(x){const A=x,{state:I,isOpen:L,messages:D,isLoading:W,error:P,chatMode:T,wsConnected:j,agentTyping:F,currentAgent:H,openChat:O,closeChat:_,sendMessage:z,toggleChat:$,setInputValue:q,clearError:U,manager:K}=t.useChatWidget(A),R=e.ref(null),G=e.ref(null),J=e.computed(()=>A);e.watch(()=>D.value.length,()=>{e.nextTick(()=>{R.value?.scrollIntoView({behavior:"smooth"})})});const Q=async()=>{I.value.isOpen||(I.value.isOpen=!0,I.value.showWelcomePopup=!1),await O()},X=()=>{_()},Y=()=>{K.closeWelcomePopup()},Z=e=>{const t=e.target;q(t.value)},ee=async e=>{e.preventDefault(),I.value.inputValue.trim()&&await z(I.value.inputValue)},te=async(e,t)=>{const o=e||t||"";await z(o)},oe=e=>e.includes("👤")||e.includes("being connected")||e.includes("live support agent")||e.includes("transfer your conversation");return e.onMounted(()=>{J.value.showWelcomePopup&&"undefined"!=typeof window&&K.initializeWelcomePopup()}),(t,x)=>(e.openBlock(),e.createElementBlock("div",e.mergeProps({class:"blockspark-chat-widget"},t.$attrs),[e.unref(I).showWelcomePopup&&!e.unref(I).isOpen?(e.openBlock(),e.createElementBlock("div",{key:0,class:"blockspark-welcome-popup",onClick:Q},[e.createElementVNode("div",a,[e.createElementVNode("div",l,e.toDisplayString(J.value.welcomeTitle),1),e.createElementVNode("button",{class:"blockspark-close-popup",onClick:e.withModifiers(Y,["stop"]),"aria-label":"Close welcome popup"}," × ")]),e.createElementVNode("div",n,e.toDisplayString(J.value.welcomeMessage),1),e.createElementVNode("div",c,e.toDisplayString(J.value.welcomeCta),1)])):e.createCommentVNode("",!0),e.unref(I).isOpen?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:1,class:"blockspark-chat-toggle-btn",onClick:Q,"aria-label":"Open chat"},[...x[0]||(x[0]=[e.createElementVNode("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})],-1)])])),e.unref(I).isOpen?(e.openBlock(),e.createElementBlock("div",s,[e.createElementVNode("div",r,[e.createElementVNode("div",i,[e.createElementVNode("div",p,e.toDisplayString(J.value.title),1),e.createElementVNode("div",k,[e.createTextVNode(e.toDisplayString(J.value.subtitle)+" ",1),"human"===e.unref(I).chatMode?(e.openBlock(),e.createElementBlock("span",d," • "+e.toDisplayString(e.unref(j)?"🟢 Connected":"🟡 Connecting..."),1)):e.createCommentVNode("",!0)]),"human"===e.unref(I).chatMode?(e.openBlock(),e.createElementBlock("div",m," Human Support Mode ")):e.createCommentVNode("",!0),"human"===e.unref(I).chatMode?(e.openBlock(),e.createElementBlock("div",u,[x[1]||(x[1]=e.createElementVNode("span",{class:"blockspark-agent-label"},"Agent:",-1)),e.createElementVNode("span",g,e.toDisplayString(e.unref(H).name),1)])):e.createCommentVNode("",!0),"ai"===e.unref(I).chatMode?(e.openBlock(),e.createElementBlock("div",b," Bot Mode ")):e.createCommentVNode("",!0)]),e.createElementVNode("button",{class:"blockspark-chat-close-btn",onClick:X,"aria-label":"Close chat"}," × ")]),e.createElementVNode("div",{class:"blockspark-chat-messages",ref_key:"messagesContainer",ref:G},[0===e.unref(I).messages.length?(e.openBlock(),e.createElementBlock("div",h,[x[2]||(x[2]=e.createElementVNode("div",{class:"blockspark-chat-empty-icon"},"👋",-1)),e.createElementVNode("p",null,e.toDisplayString(J.value.emptyStateMessage),1)])):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(I).messages,t=>{return e.openBlock(),e.createElementBlock("div",{key:t.id,class:e.normalizeClass(["blockspark-message",`blockspark-message-${t.sender}`,{"blockspark-handoff-message":oe(t.text)}])},[e.createElementVNode("div",{class:e.normalizeClass(["blockspark-message-content",{"blockspark-handoff-content":oe(t.text)}])},[e.createElementVNode("span",{innerHTML:e.unref(o.safeLinkifyText)(t.text).replace(/\n/g,"<br>")},null,8,y)],2),t.richContent&&Array.isArray(t.richContent)&&t.richContent.length>0?(e.openBlock(),e.createElementBlock("div",E,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.richContent,(t,o)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:o},[Array.isArray(t)?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(t,(t,a)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:`${o}-${a}`},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",v,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,o)=>(e.openBlock(),e.createElementBlock("button",{key:o,class:"blockspark-chip-button",type:"button",onClick:e=>te(t.text,t.payload)},e.toDisplayString(t.text),9,V))),128))])):e.createCommentVNode("",!0)],64))),128)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",f,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,o)=>(e.openBlock(),e.createElementBlock("button",{key:o,class:"blockspark-chip-button",type:"button",onClick:e=>te(t.text,t.payload)},e.toDisplayString(t.text),9,B))),128))])):e.createCommentVNode("",!0)],64))],64))),128))])):e.createCommentVNode("",!0),e.createElementVNode("div",N,e.toDisplayString((a=t.timestamp,a.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}))),1)],2);var a}),128)),e.unref(I).isLoading?(e.openBlock(),e.createElementBlock("div",C,[...x[3]||(x[3]=[e.createElementVNode("div",{class:"blockspark-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1)])])):e.createCommentVNode("",!0),"human"===e.unref(I).chatMode&&e.unref(F)?(e.openBlock(),e.createElementBlock("div",w,[...x[4]||(x[4]=[e.createElementVNode("span",{class:"blockspark-typing-dots"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("span",{class:"blockspark-typing-text"},"Agent is typing...",-1)])])):e.createCommentVNode("",!0),e.createElementVNode("div",{ref_key:"messagesEndRef",ref:R},null,512)],512),e.createElementVNode("form",{class:"blockspark-chat-input-form",onSubmit:e.withModifiers(ee,["prevent"])},[e.createElementVNode("input",{type:"text",class:"blockspark-chat-input",value:e.unref(I).inputValue,onInput:Z,placeholder:J.value.inputPlaceholder,disabled:e.unref(I).isLoading},null,40,M),e.createElementVNode("button",{type:"submit",class:"blockspark-chat-send-btn",disabled:!e.unref(I).inputValue.trim()||e.unref(I).isLoading},[...x[5]||(x[5]=[e.createElementVNode("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),e.createElementVNode("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})],-1)])],8,S)],32)])):e.createCommentVNode("",!0)],16))}});exports.default=x;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),t=require("../composables/useChatWidget.cjs.js"),o=require("../utils/sanitize.cjs.js"),n={class:"custom-welcome-header"},a={class:"custom-welcome-title"},l={class:"custom-welcome-message"},c={class:"custom-welcome-cta"},s={key:2,class:"custom-chat-window"},r={class:"custom-chat-header"},i={class:"custom-chat-header-content"},m={class:"custom-chat-title"},u={class:"custom-chat-subtitle"},d={key:0,class:"custom-mode-indicator"},p={key:0,class:"custom-mode-badge"},g={key:1,class:"custom-agent-info"},k={class:"custom-agent-name"},h={key:2,class:"custom-mode-badge"},y={key:0,class:"custom-chat-empty"},E={key:1,class:"custom-chat-empty"},v=["innerHTML"],V={key:0,class:"custom-chips-container"},B={key:0,class:"custom-chips-group"},f=["onClick"],N={key:0,class:"custom-chips-group"},C=["onClick"],b={class:"custom-message-time"},w={key:2,class:"custom-message custom-message-bot"},M={key:3,class:"custom-message custom-message-bot"},S={key:4,class:"custom-agent-typing-indicator"},A=["value","placeholder","disabled"],x=["disabled"],I=e.defineComponent({inheritAttrs:!1,__name:"ChatWidget",props:{dfProjectId:{},dfLocation:{},dfAgentId:{},serviceAccountKey:{},accessToken:{},languageCode:{},backendBaseUrl:{},backendWsUrl:{},title:{default:"💬 BlockSpark AI Assistant"},subtitle:{default:"We're here to help"},welcomeTitle:{default:"👋 Welcome to BlockSpark"},welcomeMessage:{default:"My name is BlockSpark AI Assistant and I'll guide you."},welcomeCta:{default:"💬 Click here to start chatting!"},showWelcomePopup:{type:Boolean,default:!0},welcomePopupDelay:{default:1500},fallbackWelcomeMessage:{default:"Hello! I'm BlockSpark AI Assistant. How can I help you today?"},inputPlaceholder:{default:"Type your message..."},emptyStateMessage:{default:"Hi! I'm BlockSpark AI Assistant. How can I help you today?"},debug:{type:Boolean,default:!1}},setup(I){const L=I,{state:D,isOpen:T,messages:W,isLoading:P,error:j,chatMode:F,wsConnected:H,agentTyping:O,currentAgent:z,isConnectingToAgent:_,openChat:$,closeChat:q,sendMessage:U,toggleChat:K,setInputValue:R,clearError:G,manager:J}=t.useChatWidget(L),Q=e.ref(null),X=e.ref(null),Y=e.computed(()=>L),Z=e.computed(()=>D.value.isLoading&&0===D.value.messages.length&&!D.value.sessionId),ee=e.computed(()=>!1),te=_;e.watch(()=>W.value.length,()=>{e.nextTick(()=>{Q.value?.scrollIntoView({behavior:"smooth"})})});const oe=async()=>{D.value.isOpen||(D.value.isOpen=!0,D.value.showWelcomePopup=!1),await $()},ne=()=>{q()},ae=()=>{J.closeWelcomePopup()},le=e=>{const t=e.target;R(t.value)},ce=async e=>{e.preventDefault(),D.value.inputValue.trim()&&await U(D.value.inputValue)},se=async(e,t)=>{const o=e||t||"";await U(o)},re=e=>e.includes("👤")||e.includes("being connected")||e.includes("live support agent")||e.includes("transfer your conversation");return e.onMounted(()=>{Y.value.showWelcomePopup&&"undefined"!=typeof window&&J.initializeWelcomePopup()}),(t,I)=>(e.openBlock(),e.createElementBlock("div",e.mergeProps({class:"custom-chat-widget"},t.$attrs),[e.unref(D).showWelcomePopup&&!e.unref(D).isOpen?(e.openBlock(),e.createElementBlock("div",{key:0,class:"custom-welcome-popup",onClick:oe},[e.createElementVNode("div",n,[e.createElementVNode("div",a,e.toDisplayString(Y.value.welcomeTitle),1),e.createElementVNode("button",{class:"custom-close-popup",onClick:e.withModifiers(ae,["stop"]),"aria-label":"Close welcome popup"}," × ")]),e.createElementVNode("div",l,e.toDisplayString(Y.value.welcomeMessage),1),e.createElementVNode("div",c,e.toDisplayString(Y.value.welcomeCta),1)])):e.createCommentVNode("",!0),e.unref(D).isOpen?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:1,class:"custom-chat-toggle-btn",onClick:oe,"aria-label":"Open chat"},[...I[0]||(I[0]=[e.createElementVNode("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})],-1)])])),e.unref(D).isOpen?(e.openBlock(),e.createElementBlock("div",s,[e.createElementVNode("div",r,[e.createElementVNode("div",i,[e.createElementVNode("div",m,e.toDisplayString(Y.value.title),1),e.createElementVNode("div",u,[e.createTextVNode(e.toDisplayString(Y.value.subtitle)+" ",1),"human"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("span",d," • "+e.toDisplayString(e.unref(H)?"🟢 Connected":"🟡 Connecting..."),1)):e.createCommentVNode("",!0)]),"human"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("div",p," Human Support Mode ")):e.createCommentVNode("",!0),"human"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("div",g,[I[1]||(I[1]=e.createElementVNode("span",{class:"custom-agent-label"},"Agent:",-1)),e.createElementVNode("span",k,e.toDisplayString(e.unref(z).name),1)])):e.createCommentVNode("",!0),"ai"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("div",h," Bot Mode ")):e.createCommentVNode("",!0)]),e.createElementVNode("button",{class:"custom-chat-close-btn",onClick:ne,"aria-label":"Close chat"}," × ")]),e.createElementVNode("div",{class:"custom-chat-messages",ref_key:"messagesContainer",ref:X},[Z.value&&0===e.unref(D).messages.length?(e.openBlock(),e.createElementBlock("div",y,[...I[2]||(I[2]=[e.createElementVNode("div",{class:"custom-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("p",null,"Initializing chat...",-1)])])):Z.value||0!==e.unref(D).messages.length?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",E,[I[3]||(I[3]=e.createElementVNode("div",{class:"custom-chat-empty-icon"},"👋",-1)),e.createElementVNode("p",null,e.toDisplayString(Y.value.emptyStateMessage),1)])),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(D).messages,t=>{return e.openBlock(),e.createElementBlock("div",{key:t.id,class:e.normalizeClass(["custom-message",`custom-message-${t.sender}`,{"custom-handoff-message":re(t.text)}])},[e.createElementVNode("div",{class:e.normalizeClass(["custom-message-content",{"custom-handoff-content":re(t.text)}]),innerHTML:e.unref(o.safeLinkifyText)(t.text).replace(/\n/g,"<br>")},null,10,v),t.richContent&&Array.isArray(t.richContent)&&t.richContent.length>0?(e.openBlock(),e.createElementBlock("div",V,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.richContent,(t,o)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:o},[Array.isArray(t)?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(t,(t,n)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:`${o}-${n}`},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",N,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,o)=>(e.openBlock(),e.createElementBlock("button",{key:o,class:"custom-chip-button",type:"button",onClick:e=>se(t.text,t.payload)},e.toDisplayString(t.text),9,C))),128))])):e.createCommentVNode("",!0)],64))),128)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",B,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,o)=>(e.openBlock(),e.createElementBlock("button",{key:o,class:"custom-chip-button",type:"button",onClick:e=>se(t.text,t.payload)},e.toDisplayString(t.text),9,f))),128))])):e.createCommentVNode("",!0)],64))],64))),128))])):e.createCommentVNode("",!0),e.createElementVNode("div",b,e.toDisplayString((n=t.timestamp,n.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}))),1)],2);var n}),128)),e.unref(D).isLoading?(e.openBlock(),e.createElementBlock("div",w,[...I[4]||(I[4]=[e.createElementVNode("div",{class:"custom-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1)])])):e.createCommentVNode("",!0),e.unref(te)?(e.openBlock(),e.createElementBlock("div",M,[...I[5]||(I[5]=[e.createElementVNode("div",{class:"custom-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("div",{class:"custom-message-content"}," Connecting to agent... ",-1)])])):e.createCommentVNode("",!0),"human"===e.unref(D).chatMode&&e.unref(O)?(e.openBlock(),e.createElementBlock("div",S,[...I[6]||(I[6]=[e.createElementVNode("span",{class:"custom-typing-dots"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("span",{class:"custom-typing-text"},"Agent is typing...",-1)])])):e.createCommentVNode("",!0),e.createElementVNode("div",{ref_key:"messagesEndRef",ref:Q},null,512)],512),e.createElementVNode("form",{class:"custom-chat-input-form",onSubmit:e.withModifiers(ce,["prevent"])},[e.createElementVNode("input",{type:"text",class:"custom-chat-input",value:e.unref(D).inputValue,onInput:le,placeholder:Y.value.inputPlaceholder,disabled:e.unref(D).isLoading||Z.value||ee.value},null,40,A),e.createElementVNode("button",{type:"submit",class:"custom-chat-send-btn",disabled:!e.unref(D).inputValue.trim()||e.unref(D).isLoading||Z.value||ee.value},[...I[7]||(I[7]=[e.createElementVNode("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),e.createElementVNode("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})],-1)])],8,x)],32)])):e.createCommentVNode("",!0)],16))}});exports.default=I;
2
2
  //# sourceMappingURL=ChatWidget.vue.cjs2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.vue.cjs2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"blockspark-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"blockspark-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"blockspark-welcome-header\">\n <div class=\"blockspark-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"blockspark-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"blockspark-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"blockspark-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"blockspark-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"blockspark-chat-window\">\n <div class=\"blockspark-chat-header\">\n <div class=\"blockspark-chat-header-content\">\n <div class=\"blockspark-chat-title\">{{ config.title }}</div>\n <div class=\"blockspark-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"blockspark-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"blockspark-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"blockspark-agent-info\">\n <span class=\"blockspark-agent-label\">Agent:</span>\n <span class=\"blockspark-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"blockspark-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"blockspark-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"blockspark-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"state.messages.length === 0\" class=\"blockspark-chat-empty\">\n <div class=\"blockspark-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'blockspark-message', \n `blockspark-message-${message.sender}`,\n { 'blockspark-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"blockspark-message-content\"\n :class=\"{ 'blockspark-handoff-content': isHandoffMessage(message.text) }\"\n >\n <!-- Safe HTML rendering with sanitization -->\n <!-- Preserve line breaks for better formatting -->\n <span v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"></span>\n </div>\n\n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"blockspark-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"blockspark-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"blockspark-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"blockspark-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"blockspark-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"blockspark-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"blockspark-message blockspark-message-bot\">\n <div class=\"blockspark-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"blockspark-agent-typing-indicator\">\n <span class=\"blockspark-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"blockspark-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"blockspark-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"blockspark-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading\"\n />\n <button\n type=\"submit\"\n class=\"blockspark-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 BlockSpark AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to BlockSpark',\n welcomeMessage: \"My name is BlockSpark AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm BlockSpark AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["props","__props","state","isOpen","messages","isLoading","error","chatMode","wsConnected","agentTyping","currentAgent","openChat","closeChat","sendMessage","toggleChat","setInputValue","clearError","manager","useChatWidget","messagesEndRef","ref","messagesContainer","config","computed","watch","value","length","nextTick","scrollIntoView","behavior","handleOpenChat","async","showWelcomePopup","handleCloseChat","handleCloseWelcomePopup","closeWelcomePopup","handleInput","event","target","handleSubmit","preventDefault","inputValue","trim","handleChipClick","chipText","payload","messageToSend","isHandoffMessage","text","includes","onMounted","window","initializeWelcomePopup","_openBlock","_createElementBlock","_mergeProps","class","$attrs","_unref","onClick","_createElementVNode","_hoisted_1","_hoisted_2","_toDisplayString","welcomeTitle","_hoisted_3","welcomeMessage","_hoisted_4","welcomeCta","width","height","viewBox","fill","stroke","d","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","title","_hoisted_9","subtitle","_hoisted_10","_hoisted_11","_hoisted_12","_cache","_hoisted_13","name","_hoisted_14","_hoisted_15","emptyStateMessage","_Fragment","_renderList","message","key","id","_normalizeClass","sender","innerHTML","safeLinkifyText","replace","richContent","Array","isArray","_hoisted_17","contentGroup","groupIndex","content","contentIndex","type","options","_hoisted_20","chip","chipIndex","$event","_hoisted_21","_hoisted_18","_hoisted_19","_hoisted_22","date","timestamp","toLocaleTimeString","hour","minute","_hoisted_23","_hoisted_24","onSubmit","onInput","placeholder","inputPlaceholder","disabled","x1","y1","x2","y2","points"],"mappings":"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"}
1
+ {"version":3,"file":"ChatWidget.vue.cjs2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"custom-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"custom-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"custom-welcome-header\">\n <div class=\"custom-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"custom-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"custom-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"custom-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"custom-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"custom-chat-window\">\n <div class=\"custom-chat-header\">\n <div class=\"custom-chat-header-content\">\n <div class=\"custom-chat-title\">{{ config.title }}</div>\n <div class=\"custom-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"custom-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-agent-info\">\n <span class=\"custom-agent-label\">Agent:</span>\n <span class=\"custom-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"custom-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"custom-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"custom-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <p>Initializing chat...</p>\n </div>\n <div v-else-if=\"!isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'custom-message', \n `custom-message-${message.sender}`,\n { 'custom-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"custom-message-content\"\n :class=\"{ 'custom-handoff-content': isHandoffMessage(message.text) }\"\n v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"\n ></div>\n \n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"custom-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"custom-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Connecting to Agent Indicator -->\n <div v-if=\"isConnectingToAgent\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <div class=\"custom-message-content\">\n Connecting to agent...\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"custom-agent-typing-indicator\">\n <span class=\"custom-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"custom-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"custom-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"custom-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading || isInitializing || isStartingNewChat\"\n />\n <button\n type=\"submit\"\n class=\"custom-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading || isInitializing || isStartingNewChat\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 BlockSpark AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to BlockSpark',\n welcomeMessage: \"My name is BlockSpark AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm BlockSpark AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n isConnectingToAgent: isConnectingToAgentFromComposable,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Computed state for initialization and connection (matching React component)\nconst isInitializing = computed(() => {\n return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;\n});\n\nconst isStartingNewChat = computed(() => {\n // This would be tracked in manager if needed, for now return false\n return false;\n});\n\n// Use isConnectingToAgent from composable (already computed in manager)\nconst isConnectingToAgent = isConnectingToAgentFromComposable;\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["props","__props","state","isOpen","messages","isLoading","error","chatMode","wsConnected","agentTyping","currentAgent","isConnectingToAgent","isConnectingToAgentFromComposable","openChat","closeChat","sendMessage","toggleChat","setInputValue","clearError","manager","useChatWidget","messagesEndRef","ref","messagesContainer","config","computed","isInitializing","value","length","sessionId","isStartingNewChat","watch","nextTick","scrollIntoView","behavior","handleOpenChat","async","showWelcomePopup","handleCloseChat","handleCloseWelcomePopup","closeWelcomePopup","handleInput","event","target","handleSubmit","preventDefault","inputValue","trim","handleChipClick","chipText","payload","messageToSend","isHandoffMessage","text","includes","onMounted","window","initializeWelcomePopup","_openBlock","_createElementBlock","_mergeProps","class","$attrs","_unref","onClick","_createElementVNode","_hoisted_1","_hoisted_2","_toDisplayString","welcomeTitle","_hoisted_3","welcomeMessage","_hoisted_4","welcomeCta","width","height","viewBox","fill","stroke","d","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","title","_hoisted_9","subtitle","_hoisted_10","_hoisted_11","_hoisted_12","_cache","_hoisted_13","name","_hoisted_14","_hoisted_15","_hoisted_16","emptyStateMessage","_Fragment","_renderList","message","key","id","_normalizeClass","sender","innerHTML","safeLinkifyText","replace","richContent","Array","isArray","_hoisted_18","contentGroup","groupIndex","content","contentIndex","type","options","_hoisted_21","chip","chipIndex","$event","_hoisted_22","_hoisted_19","_hoisted_20","_hoisted_23","date","timestamp","toLocaleTimeString","hour","minute","_hoisted_24","_hoisted_25","_hoisted_26","onSubmit","onInput","placeholder","inputPlaceholder","disabled","x1","y1","x2","y2","points"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import _sfc_main from "./ChatWidget.vue.esm2.js";
2
2
  /* empty css */
3
3
  import _export_sfc from "../_virtual/_plugin-vue_export-helper.esm.js";
4
- const ChatWidget = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0ea40880"]]);
4
+ const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0d32fcf4"]]);
5
5
  export {
6
- ChatWidget as default
6
+ ChatWidgetComponent as default
7
7
  };
8
8
  //# sourceMappingURL=ChatWidget.vue.esm.js.map
@@ -1,65 +1,73 @@
1
1
  import { defineComponent, ref, computed, watch, nextTick, onMounted, openBlock, createElementBlock, mergeProps, unref, createElementVNode, toDisplayString, withModifiers, createCommentVNode, createTextVNode, Fragment, renderList, normalizeClass } from "vue";
2
2
  import { useChatWidget } from "../composables/useChatWidget.esm.js";
3
3
  import { safeLinkifyText } from "../utils/sanitize.esm.js";
4
- const _hoisted_1 = { class: "blockspark-welcome-header" };
5
- const _hoisted_2 = { class: "blockspark-welcome-title" };
6
- const _hoisted_3 = { class: "blockspark-welcome-message" };
7
- const _hoisted_4 = { class: "blockspark-welcome-cta" };
4
+ const _hoisted_1 = { class: "custom-welcome-header" };
5
+ const _hoisted_2 = { class: "custom-welcome-title" };
6
+ const _hoisted_3 = { class: "custom-welcome-message" };
7
+ const _hoisted_4 = { class: "custom-welcome-cta" };
8
8
  const _hoisted_5 = {
9
9
  key: 2,
10
- class: "blockspark-chat-window"
10
+ class: "custom-chat-window"
11
11
  };
12
- const _hoisted_6 = { class: "blockspark-chat-header" };
13
- const _hoisted_7 = { class: "blockspark-chat-header-content" };
14
- const _hoisted_8 = { class: "blockspark-chat-title" };
15
- const _hoisted_9 = { class: "blockspark-chat-subtitle" };
12
+ const _hoisted_6 = { class: "custom-chat-header" };
13
+ const _hoisted_7 = { class: "custom-chat-header-content" };
14
+ const _hoisted_8 = { class: "custom-chat-title" };
15
+ const _hoisted_9 = { class: "custom-chat-subtitle" };
16
16
  const _hoisted_10 = {
17
17
  key: 0,
18
- class: "blockspark-mode-indicator"
18
+ class: "custom-mode-indicator"
19
19
  };
20
20
  const _hoisted_11 = {
21
21
  key: 0,
22
- class: "blockspark-mode-badge"
22
+ class: "custom-mode-badge"
23
23
  };
24
24
  const _hoisted_12 = {
25
25
  key: 1,
26
- class: "blockspark-agent-info"
26
+ class: "custom-agent-info"
27
27
  };
28
- const _hoisted_13 = { class: "blockspark-agent-name" };
28
+ const _hoisted_13 = { class: "custom-agent-name" };
29
29
  const _hoisted_14 = {
30
30
  key: 2,
31
- class: "blockspark-mode-badge"
31
+ class: "custom-mode-badge"
32
32
  };
33
33
  const _hoisted_15 = {
34
34
  key: 0,
35
- class: "blockspark-chat-empty"
35
+ class: "custom-chat-empty"
36
36
  };
37
- const _hoisted_16 = ["innerHTML"];
38
- const _hoisted_17 = {
39
- key: 0,
40
- class: "blockspark-chips-container"
37
+ const _hoisted_16 = {
38
+ key: 1,
39
+ class: "custom-chat-empty"
41
40
  };
41
+ const _hoisted_17 = ["innerHTML"];
42
42
  const _hoisted_18 = {
43
43
  key: 0,
44
- class: "blockspark-chips-group"
44
+ class: "custom-chips-container"
45
45
  };
46
- const _hoisted_19 = ["onClick"];
47
- const _hoisted_20 = {
46
+ const _hoisted_19 = {
48
47
  key: 0,
49
- class: "blockspark-chips-group"
48
+ class: "custom-chips-group"
50
49
  };
51
- const _hoisted_21 = ["onClick"];
52
- const _hoisted_22 = { class: "blockspark-message-time" };
53
- const _hoisted_23 = {
54
- key: 1,
55
- class: "blockspark-message blockspark-message-bot"
50
+ const _hoisted_20 = ["onClick"];
51
+ const _hoisted_21 = {
52
+ key: 0,
53
+ class: "custom-chips-group"
56
54
  };
55
+ const _hoisted_22 = ["onClick"];
56
+ const _hoisted_23 = { class: "custom-message-time" };
57
57
  const _hoisted_24 = {
58
58
  key: 2,
59
- class: "blockspark-agent-typing-indicator"
59
+ class: "custom-message custom-message-bot"
60
+ };
61
+ const _hoisted_25 = {
62
+ key: 3,
63
+ class: "custom-message custom-message-bot"
60
64
  };
61
- const _hoisted_25 = ["value", "placeholder", "disabled"];
62
- const _hoisted_26 = ["disabled"];
65
+ const _hoisted_26 = {
66
+ key: 4,
67
+ class: "custom-agent-typing-indicator"
68
+ };
69
+ const _hoisted_27 = ["value", "placeholder", "disabled"];
70
+ const _hoisted_28 = ["disabled"];
63
71
  const _sfc_main = /* @__PURE__ */ defineComponent({
64
72
  ...{
65
73
  inheritAttrs: false
@@ -99,6 +107,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
99
107
  wsConnected,
100
108
  agentTyping,
101
109
  currentAgent,
110
+ isConnectingToAgent: isConnectingToAgentFromComposable,
102
111
  openChat,
103
112
  closeChat,
104
113
  sendMessage,
@@ -110,6 +119,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
110
119
  const messagesEndRef = ref(null);
111
120
  const messagesContainer = ref(null);
112
121
  const config = computed(() => props);
122
+ const isInitializing = computed(() => {
123
+ return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;
124
+ });
125
+ const isStartingNewChat = computed(() => {
126
+ return false;
127
+ });
128
+ const isConnectingToAgent = isConnectingToAgentFromComposable;
113
129
  watch(
114
130
  () => messages.value.length,
115
131
  () => {
@@ -160,16 +176,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
160
176
  }
161
177
  });
162
178
  return (_ctx, _cache) => {
163
- return openBlock(), createElementBlock("div", mergeProps({ class: "blockspark-chat-widget" }, _ctx.$attrs), [
179
+ return openBlock(), createElementBlock("div", mergeProps({ class: "custom-chat-widget" }, _ctx.$attrs), [
164
180
  unref(state).showWelcomePopup && !unref(state).isOpen ? (openBlock(), createElementBlock("div", {
165
181
  key: 0,
166
- class: "blockspark-welcome-popup",
182
+ class: "custom-welcome-popup",
167
183
  onClick: handleOpenChat
168
184
  }, [
169
185
  createElementVNode("div", _hoisted_1, [
170
186
  createElementVNode("div", _hoisted_2, toDisplayString(config.value.welcomeTitle), 1),
171
187
  createElementVNode("button", {
172
- class: "blockspark-close-popup",
188
+ class: "custom-close-popup",
173
189
  onClick: withModifiers(handleCloseWelcomePopup, ["stop"]),
174
190
  "aria-label": "Close welcome popup"
175
191
  }, " × ")
@@ -179,7 +195,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
179
195
  ])) : createCommentVNode("", true),
180
196
  !unref(state).isOpen ? (openBlock(), createElementBlock("button", {
181
197
  key: 1,
182
- class: "blockspark-chat-toggle-btn",
198
+ class: "custom-chat-toggle-btn",
183
199
  onClick: handleOpenChat,
184
200
  "aria-label": "Open chat"
185
201
  }, [..._cache[0] || (_cache[0] = [
@@ -206,68 +222,72 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
206
222
  ]),
207
223
  unref(state).chatMode === "human" ? (openBlock(), createElementBlock("div", _hoisted_11, " Human Support Mode ")) : createCommentVNode("", true),
208
224
  unref(state).chatMode === "human" ? (openBlock(), createElementBlock("div", _hoisted_12, [
209
- _cache[1] || (_cache[1] = createElementVNode("span", { class: "blockspark-agent-label" }, "Agent:", -1)),
225
+ _cache[1] || (_cache[1] = createElementVNode("span", { class: "custom-agent-label" }, "Agent:", -1)),
210
226
  createElementVNode("span", _hoisted_13, toDisplayString(unref(currentAgent).name), 1)
211
227
  ])) : createCommentVNode("", true),
212
228
  unref(state).chatMode === "ai" ? (openBlock(), createElementBlock("div", _hoisted_14, " Bot Mode ")) : createCommentVNode("", true)
213
229
  ]),
214
230
  createElementVNode("button", {
215
- class: "blockspark-chat-close-btn",
231
+ class: "custom-chat-close-btn",
216
232
  onClick: handleCloseChat,
217
233
  "aria-label": "Close chat"
218
234
  }, " × ")
219
235
  ]),
220
236
  createElementVNode("div", {
221
- class: "blockspark-chat-messages",
237
+ class: "custom-chat-messages",
222
238
  ref_key: "messagesContainer",
223
239
  ref: messagesContainer
224
240
  }, [
225
- unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_15, [
226
- _cache[2] || (_cache[2] = createElementVNode("div", { class: "blockspark-chat-empty-icon" }, "👋", -1)),
241
+ isInitializing.value && unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_15, [..._cache[2] || (_cache[2] = [
242
+ createElementVNode("div", { class: "custom-typing-indicator" }, [
243
+ createElementVNode("span"),
244
+ createElementVNode("span"),
245
+ createElementVNode("span")
246
+ ], -1),
247
+ createElementVNode("p", null, "Initializing chat...", -1)
248
+ ])])) : !isInitializing.value && unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_16, [
249
+ _cache[3] || (_cache[3] = createElementVNode("div", { class: "custom-chat-empty-icon" }, "👋", -1)),
227
250
  createElementVNode("p", null, toDisplayString(config.value.emptyStateMessage), 1)
228
251
  ])) : createCommentVNode("", true),
229
252
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(state).messages, (message) => {
230
253
  return openBlock(), createElementBlock("div", {
231
254
  key: message.id,
232
255
  class: normalizeClass([
233
- "blockspark-message",
234
- `blockspark-message-${message.sender}`,
235
- { "blockspark-handoff-message": isHandoffMessage(message.text) }
256
+ "custom-message",
257
+ `custom-message-${message.sender}`,
258
+ { "custom-handoff-message": isHandoffMessage(message.text) }
236
259
  ])
237
260
  }, [
238
261
  createElementVNode("div", {
239
- class: normalizeClass(["blockspark-message-content", { "blockspark-handoff-content": isHandoffMessage(message.text) }])
240
- }, [
241
- createElementVNode("span", {
242
- innerHTML: unref(safeLinkifyText)(message.text).replace(/\n/g, "<br>")
243
- }, null, 8, _hoisted_16)
244
- ], 2),
245
- message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_17, [
262
+ class: normalizeClass(["custom-message-content", { "custom-handoff-content": isHandoffMessage(message.text) }]),
263
+ innerHTML: unref(safeLinkifyText)(message.text).replace(/\n/g, "<br>")
264
+ }, null, 10, _hoisted_17),
265
+ message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_18, [
246
266
  (openBlock(true), createElementBlock(Fragment, null, renderList(message.richContent, (contentGroup, groupIndex) => {
247
267
  return openBlock(), createElementBlock(Fragment, { key: groupIndex }, [
248
268
  !Array.isArray(contentGroup) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
249
- contentGroup.type === "chips" && contentGroup.options ? (openBlock(), createElementBlock("div", _hoisted_18, [
269
+ contentGroup.type === "chips" && contentGroup.options ? (openBlock(), createElementBlock("div", _hoisted_19, [
250
270
  (openBlock(true), createElementBlock(Fragment, null, renderList(contentGroup.options, (chip, chipIndex) => {
251
271
  return openBlock(), createElementBlock("button", {
252
272
  key: chipIndex,
253
- class: "blockspark-chip-button",
273
+ class: "custom-chip-button",
254
274
  type: "button",
255
275
  onClick: ($event) => handleChipClick(chip.text, chip.payload)
256
- }, toDisplayString(chip.text), 9, _hoisted_19);
276
+ }, toDisplayString(chip.text), 9, _hoisted_20);
257
277
  }), 128))
258
278
  ])) : createCommentVNode("", true)
259
279
  ], 64)) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(contentGroup, (content, contentIndex) => {
260
280
  return openBlock(), createElementBlock(Fragment, {
261
281
  key: `${groupIndex}-${contentIndex}`
262
282
  }, [
263
- content.type === "chips" && content.options ? (openBlock(), createElementBlock("div", _hoisted_20, [
283
+ content.type === "chips" && content.options ? (openBlock(), createElementBlock("div", _hoisted_21, [
264
284
  (openBlock(true), createElementBlock(Fragment, null, renderList(content.options, (chip, chipIndex) => {
265
285
  return openBlock(), createElementBlock("button", {
266
286
  key: chipIndex,
267
- class: "blockspark-chip-button",
287
+ class: "custom-chip-button",
268
288
  type: "button",
269
289
  onClick: ($event) => handleChipClick(chip.text, chip.payload)
270
- }, toDisplayString(chip.text), 9, _hoisted_21);
290
+ }, toDisplayString(chip.text), 9, _hoisted_22);
271
291
  }), 128))
272
292
  ])) : createCommentVNode("", true)
273
293
  ], 64);
@@ -275,23 +295,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
275
295
  ], 64);
276
296
  }), 128))
277
297
  ])) : createCommentVNode("", true),
278
- createElementVNode("div", _hoisted_22, toDisplayString(formatTime(message.timestamp)), 1)
298
+ createElementVNode("div", _hoisted_23, toDisplayString(formatTime(message.timestamp)), 1)
279
299
  ], 2);
280
300
  }), 128)),
281
- unref(state).isLoading ? (openBlock(), createElementBlock("div", _hoisted_23, [..._cache[3] || (_cache[3] = [
282
- createElementVNode("div", { class: "blockspark-typing-indicator" }, [
301
+ unref(state).isLoading ? (openBlock(), createElementBlock("div", _hoisted_24, [..._cache[4] || (_cache[4] = [
302
+ createElementVNode("div", { class: "custom-typing-indicator" }, [
283
303
  createElementVNode("span"),
284
304
  createElementVNode("span"),
285
305
  createElementVNode("span")
286
306
  ], -1)
287
307
  ])])) : createCommentVNode("", true),
288
- unref(state).chatMode === "human" && unref(agentTyping) ? (openBlock(), createElementBlock("div", _hoisted_24, [..._cache[4] || (_cache[4] = [
289
- createElementVNode("span", { class: "blockspark-typing-dots" }, [
308
+ unref(isConnectingToAgent) ? (openBlock(), createElementBlock("div", _hoisted_25, [..._cache[5] || (_cache[5] = [
309
+ createElementVNode("div", { class: "custom-typing-indicator" }, [
310
+ createElementVNode("span"),
311
+ createElementVNode("span"),
312
+ createElementVNode("span")
313
+ ], -1),
314
+ createElementVNode("div", { class: "custom-message-content" }, " Connecting to agent... ", -1)
315
+ ])])) : createCommentVNode("", true),
316
+ unref(state).chatMode === "human" && unref(agentTyping) ? (openBlock(), createElementBlock("div", _hoisted_26, [..._cache[6] || (_cache[6] = [
317
+ createElementVNode("span", { class: "custom-typing-dots" }, [
290
318
  createElementVNode("span"),
291
319
  createElementVNode("span"),
292
320
  createElementVNode("span")
293
321
  ], -1),
294
- createElementVNode("span", { class: "blockspark-typing-text" }, "Agent is typing...", -1)
322
+ createElementVNode("span", { class: "custom-typing-text" }, "Agent is typing...", -1)
295
323
  ])])) : createCommentVNode("", true),
296
324
  createElementVNode("div", {
297
325
  ref_key: "messagesEndRef",
@@ -299,22 +327,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
299
327
  }, null, 512)
300
328
  ], 512),
301
329
  createElementVNode("form", {
302
- class: "blockspark-chat-input-form",
330
+ class: "custom-chat-input-form",
303
331
  onSubmit: withModifiers(handleSubmit, ["prevent"])
304
332
  }, [
305
333
  createElementVNode("input", {
306
334
  type: "text",
307
- class: "blockspark-chat-input",
335
+ class: "custom-chat-input",
308
336
  value: unref(state).inputValue,
309
337
  onInput: handleInput,
310
338
  placeholder: config.value.inputPlaceholder,
311
- disabled: unref(state).isLoading
312
- }, null, 40, _hoisted_25),
339
+ disabled: unref(state).isLoading || isInitializing.value || isStartingNewChat.value
340
+ }, null, 40, _hoisted_27),
313
341
  createElementVNode("button", {
314
342
  type: "submit",
315
- class: "blockspark-chat-send-btn",
316
- disabled: !unref(state).inputValue.trim() || unref(state).isLoading
317
- }, [..._cache[5] || (_cache[5] = [
343
+ class: "custom-chat-send-btn",
344
+ disabled: !unref(state).inputValue.trim() || unref(state).isLoading || isInitializing.value || isStartingNewChat.value
345
+ }, [..._cache[7] || (_cache[7] = [
318
346
  createElementVNode("svg", {
319
347
  width: "20",
320
348
  height: "20",
@@ -333,7 +361,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
333
361
  }),
334
362
  createElementVNode("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
335
363
  ], -1)
336
- ])], 8, _hoisted_26)
364
+ ])], 8, _hoisted_28)
337
365
  ], 32)
338
366
  ])) : createCommentVNode("", true)
339
367
  ], 16);
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.vue.esm2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"blockspark-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"blockspark-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"blockspark-welcome-header\">\n <div class=\"blockspark-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"blockspark-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"blockspark-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"blockspark-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"blockspark-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"blockspark-chat-window\">\n <div class=\"blockspark-chat-header\">\n <div class=\"blockspark-chat-header-content\">\n <div class=\"blockspark-chat-title\">{{ config.title }}</div>\n <div class=\"blockspark-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"blockspark-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"blockspark-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"blockspark-agent-info\">\n <span class=\"blockspark-agent-label\">Agent:</span>\n <span class=\"blockspark-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"blockspark-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"blockspark-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"blockspark-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"state.messages.length === 0\" class=\"blockspark-chat-empty\">\n <div class=\"blockspark-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'blockspark-message', \n `blockspark-message-${message.sender}`,\n { 'blockspark-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"blockspark-message-content\"\n :class=\"{ 'blockspark-handoff-content': isHandoffMessage(message.text) }\"\n >\n <!-- Safe HTML rendering with sanitization -->\n <!-- Preserve line breaks for better formatting -->\n <span v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"></span>\n </div>\n\n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"blockspark-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"blockspark-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"blockspark-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"blockspark-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"blockspark-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"blockspark-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"blockspark-message blockspark-message-bot\">\n <div class=\"blockspark-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"blockspark-agent-typing-indicator\">\n <span class=\"blockspark-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"blockspark-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"blockspark-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"blockspark-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading\"\n />\n <button\n type=\"submit\"\n class=\"blockspark-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 BlockSpark AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to BlockSpark',\n welcomeMessage: \"My name is BlockSpark AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm BlockSpark AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["_openBlock","_createElementBlock","_mergeProps","$attrs","_unref","_createElementVNode","_toDisplayString","_Fragment","_renderList","_normalizeClass"],"mappings":"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"}
1
+ {"version":3,"file":"ChatWidget.vue.esm2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"custom-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"custom-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"custom-welcome-header\">\n <div class=\"custom-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"custom-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"custom-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"custom-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"custom-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"custom-chat-window\">\n <div class=\"custom-chat-header\">\n <div class=\"custom-chat-header-content\">\n <div class=\"custom-chat-title\">{{ config.title }}</div>\n <div class=\"custom-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"custom-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-agent-info\">\n <span class=\"custom-agent-label\">Agent:</span>\n <span class=\"custom-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"custom-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"custom-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"custom-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <p>Initializing chat...</p>\n </div>\n <div v-else-if=\"!isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'custom-message', \n `custom-message-${message.sender}`,\n { 'custom-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"custom-message-content\"\n :class=\"{ 'custom-handoff-content': isHandoffMessage(message.text) }\"\n v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"\n ></div>\n \n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"custom-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"custom-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Connecting to Agent Indicator -->\n <div v-if=\"isConnectingToAgent\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <div class=\"custom-message-content\">\n Connecting to agent...\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"custom-agent-typing-indicator\">\n <span class=\"custom-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"custom-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"custom-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"custom-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading || isInitializing || isStartingNewChat\"\n />\n <button\n type=\"submit\"\n class=\"custom-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading || isInitializing || isStartingNewChat\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 BlockSpark AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to BlockSpark',\n welcomeMessage: \"My name is BlockSpark AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm BlockSpark AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n isConnectingToAgent: isConnectingToAgentFromComposable,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Computed state for initialization and connection (matching React component)\nconst isInitializing = computed(() => {\n return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;\n});\n\nconst isStartingNewChat = computed(() => {\n // This would be tracked in manager if needed, for now return false\n return false;\n});\n\n// Use isConnectingToAgent from composable (already computed in manager)\nconst isConnectingToAgent = isConnectingToAgentFromComposable;\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["_openBlock","_createElementBlock","_mergeProps","$attrs","_unref","_createElementVNode","_toDisplayString","_Fragment","_renderList","_normalizeClass"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8OA,UAAM,QAAQ;AAed,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,qBAAqB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,IACE,cAAc,KAAK;AAGvB,UAAM,iBAAiB,IAA2B,IAAI;AACtD,UAAM,oBAAoB,IAA2B,IAAI;AAGzD,UAAM,SAAS,SAAS,MAAM,KAAK;AAGnC,UAAM,iBAAiB,SAAS,MAAM;AACpC,aAAO,MAAM,MAAM,aAAa,MAAM,MAAM,SAAS,WAAW,KAAK,CAAC,MAAM,MAAM;AAAA,IACpF,CAAC;AAED,UAAM,oBAAoB,SAAS,MAAM;AAEvC,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,sBAAsB;AAG5B;AAAA,MACE,MAAM,SAAS,MAAM;AAAA,MACrB,MAAM;AACJ,iBAAS,MAAM;AACb,yBAAe,OAAO,eAAe,EAAE,UAAU,UAAU;AAAA,QAC7D,CAAC;AAAA,MACH;AAAA,IAAA;AAIF,UAAM,iBAAiB,YAAY;AAEjC,UAAI,CAAC,MAAM,MAAM,QAAQ;AACvB,cAAM,MAAM,SAAS;AACrB,cAAM,MAAM,mBAAmB;AAAA,MACjC;AACA,YAAM,SAAA;AAAA,IACR;AAEA,UAAM,kBAAkB,MAAM;AAC5B,gBAAA;AAAA,IACF;AAEA,UAAM,0BAA0B,MAAM;AACpC,cAAQ,kBAAA;AAAA,IACV;AAEA,UAAM,cAAc,CAAC,UAAiB;AACpC,YAAM,SAAS,MAAM;AACrB,oBAAc,OAAO,KAAK;AAAA,IAC5B;AAEA,UAAM,eAAe,OAAO,UAAiB;AAC3C,YAAM,eAAA;AACN,UAAI,MAAM,MAAM,WAAW,KAAA,GAAQ;AACjC,cAAM,YAAY,MAAM,MAAM,UAAU;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,kBAAkB,OAAO,UAAkB,YAAqB;AACpE,YAAM,gBAAgB,YAAY,WAAW;AAC7C,YAAM,YAAY,aAAa;AAAA,IACjC;AAGA,UAAM,aAAa,CAAC,SAAuB;AACzC,aAAO,KAAK,mBAAmB,IAAI;AAAA,QACjC,MAAM;AAAA,QACN,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAGA,UAAM,mBAAmB,CAAC,SAA0B;AAClD,aAAO,KAAK,SAAS,IAAI,KAClB,KAAK,SAAS,iBAAiB,KAC/B,KAAK,SAAS,oBAAoB,KAClC,KAAK,SAAS,4BAA4B;AAAA,IACnD;AAGA,cAAU,MAAM;AACd,UAAI,OAAO,MAAM,oBAAoB,OAAO,WAAW,aAAa;AAClE,gBAAQ,uBAAA;AAAA,MACV;AAAA,IACF,CAAC;;AAtWC,aAAAA,UAAA,GAAAC,mBA4NM,OA5NNC,WA4NM,EA5ND,OAAM,qBAAA,GAA6BC,KAAAA,MAAM,GAAA;AAAA,QAGpCC,MAAA,KAAA,EAAM,oBAAgB,CAAKA,MAAA,KAAA,EAAM,uBADzCH,mBAiBM,OAAA;AAAA;UAfJ,OAAM;AAAA,UACL,SAAO;AAAA,QAAA;UAERI,mBASM,OATN,YASM;AAAA,YARJA,mBAAiE,OAAjE,YAAiEC,gBAA5B,OAAA,MAAO,YAAY,GAAA,CAAA;AAAA,YACxDD,mBAMS,UAAA;AAAA,cALP,OAAM;AAAA,cACL,uBAAY,yBAAuB,CAAA,MAAA,CAAA;AAAA,cACpC,cAAW;AAAA,YAAA,GACZ,KAED;AAAA,UAAA;UAEFA,mBAAqE,OAArE,YAAqEC,gBAA9B,OAAA,MAAO,cAAc,GAAA,CAAA;AAAA,UAC5DD,mBAA6D,OAA7D,YAA6DC,gBAA1B,OAAA,MAAO,UAAU,GAAA,CAAA;AAAA,QAAA;QAK7C,CAAAF,MAAA,KAAA,EAAM,uBADfH,mBAkBS,UAAA;AAAA;UAhBP,OAAM;AAAA,UACL,SAAO;AAAA,UACR,cAAW;AAAA,QAAA;UAEXI,mBAWM,OAAA;AAAA,YAVJ,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,QAAO;AAAA,YACP,gBAAa;AAAA,YACb,kBAAe;AAAA,YACf,mBAAgB;AAAA,UAAA;YAEhBA,mBAA+E,QAAA,EAAzE,GAAE,iEAA+D;AAAA,UAAA;;QAKhED,MAAA,KAAA,EAAM,UAAjBJ,aAAAC,mBAgLM,OAhLN,YAgLM;AAAA,UA/KJI,mBA2BM,OA3BN,YA2BM;AAAA,YA1BJA,mBAkBM,OAlBN,YAkBM;AAAA,cAjBJA,mBAAuD,OAAvD,YAAuDC,gBAArB,OAAA,MAAO,KAAK,GAAA,CAAA;AAAA,cAC9CD,mBAKM,OALN,YAKM;AAAA,gDAJD,OAAA,MAAO,QAAQ,IAAG,KACrB,CAAA;AAAA,gBAAYD,MAAA,KAAA,EAAM,aAAQ,WAA1BJ,aAAAC,mBAEO,QAFP,aAAsE,wBAC/DG,MAAA,WAAA,IAAW,iBAAA,kBAAA,GAAA,CAAA;;cAGTA,MAAA,KAAA,EAAM,aAAQ,wBAAzBH,mBAEM,OAFN,aAAiE,sBAEjE;cACWG,MAAA,KAAA,EAAM,aAAQ,WAAzBJ,aAAAC,mBAGM,OAHN,aAGM;AAAA,gBAFJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAI,mBAA8C,QAAA,EAAxC,OAAM,qBAAA,GAAqB,UAAM,EAAA;AAAA,gBACvCA,mBAA8D,QAA9D,aAA8DC,gBAA3BF,MAAA,YAAA,EAAa,IAAI,GAAA,CAAA;AAAA,cAAA;cAE3CA,MAAA,KAAA,EAAM,aAAQ,qBAAzBH,mBAEM,OAFN,aAA8D,YAE9D;;YAEFI,mBAMS,UAAA;AAAA,cALP,OAAM;AAAA,cACL,SAAO;AAAA,cACR,cAAW;AAAA,YAAA,GACZ,KAED;AAAA,UAAA;UAGFA,mBAkHM,OAAA;AAAA,YAlHD,OAAM;AAAA,qBAA2B;AAAA,YAAJ,KAAI;AAAA,UAAA;YAEzB,eAAA,SAAkBD,MAAA,KAAA,EAAM,SAAS,WAAM,KAAlDJ,UAAA,GAAAC,mBAOM,OAPN,aAOM,CAAA,GAAA,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA;AAAA,cANJI,mBAIM,OAAA,EAJD,OAAM,6BAAyB;AAAA,gBAClCA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,cAAA;cAEfA,mBAA2B,WAAxB,wBAAoB,EAAA;AAAA,YAAA,QAER,CAAA,eAAA,SAAkBD,MAAA,KAAA,EAAM,SAAS,WAAM,KAAxDJ,UAAA,GAAAC,mBAGM,OAHN,aAGM;AAAA,cAFJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAI,mBAA4C,OAAA,EAAvC,OAAM,yBAAA,GAAyB,MAAE,EAAA;AAAA,cACtCA,mBAAqC,KAAA,MAAAC,gBAA/B,OAAA,MAAO,iBAAiB,GAAA,CAAA;AAAA,YAAA;aAIhCN,UAAA,IAAA,GAAAC,mBAgEMM,UAAA,MAAAC,WA/DcJ,MAAA,KAAA,EAAM,WAAjB,YAAO;kCADhBH,mBAgEM,OAAA;AAAA,gBA9DH,KAAK,QAAQ;AAAA,gBACb,OAAKQ,eAAA;AAAA;kBAAiE,kBAAA,QAAQ,MAAM;AAAA,8CAA4C,iBAAiB,QAAQ,IAAI,EAAA;AAAA,gBAAA;;gBAM9JJ,mBAIO,OAAA;AAAA,kBAHL,uBAAM,0BAAwB,EAAA,0BACM,iBAAiB,QAAQ,IAAI,EAAA,CAAA,CAAA;AAAA,kBACjE,WAAQD,MAAA,eAAA,EAAgB,QAAQ,IAAI,EAAE,QAAO,OAAA,MAAA;AAAA,gBAAA;gBAKvC,QAAQ,eAAe,MAAM,QAAQ,QAAQ,WAAW,KAAK,QAAQ,YAAY,SAAM,KAD/FJ,UAAA,GAAAC,mBA2CM,OA3CN,aA2CM;AAAA,mBAvCJD,UAAA,IAAA,GAAAC,mBAsCWM,2BAtCoC,QAAQ,aAAW,CAAhD,cAAc,eAAU;4EAAgC,cAAU;AAAA,uBACjE,MAAM,QAAQ,YAAY,kBAA3CN,mBAeWM,UAAA,EAAA,KAAA,KAAA;AAAA,wBAbD,aAAa,SAAI,WAAgB,aAAa,WADtDP,aAAAC,mBAaM,OAbN,aAaM;AAAA,2BATJD,UAAA,IAAA,GAAAC,mBAQSM,2BAPqB,aAAa,SAAO,CAAxC,MAAM,cAAS;gDADzBN,mBAQS,UAAA;AAAA,8BANN,KAAK;AAAA,8BACN,OAAM;AAAA,8BACN,MAAK;AAAA,8BACJ,SAAK,CAAA,WAAE,gBAAgB,KAAK,MAAM,KAAK,OAAO;AAAA,4BAAA,GAE5CK,gBAAA,KAAK,IAAI,GAAA,GAAA,WAAA;AAAA;;iCAKhBN,UAAA,IAAA,GAAAC,mBAkBWM,UAAA,EAAA,KAAA,KAAAC,WAjByB,cAAY,CAAtC,SAAS,iBAAY;;0BACpB,KAAA,GAAA,UAAU,IAAI,YAAY;AAAA,wBAAA;0BAG3B,QAAQ,SAAI,WAAgB,QAAQ,WAD5CR,aAAAC,mBAaM,OAbN,aAaM;AAAA,6BATJD,UAAA,IAAA,GAAAC,mBAQSM,2BAPqB,QAAQ,SAAO,CAAnC,MAAM,cAAS;kDADzBN,mBAQS,UAAA;AAAA,gCANN,KAAK;AAAA,gCACN,OAAM;AAAA,gCACN,MAAK;AAAA,gCACJ,SAAK,CAAA,WAAE,gBAAgB,KAAK,MAAM,KAAK,OAAO;AAAA,8BAAA,GAE5CK,gBAAA,KAAK,IAAI,GAAA,GAAA,WAAA;AAAA;;;;;;;gBAQxBD,mBAEM,OAFN,aAEMC,gBADD,WAAW,QAAQ,SAAS,CAAA,GAAA,CAAA;AAAA,cAAA;;YAKxBF,MAAA,KAAA,EAAM,aAAjBJ,UAAA,GAAAC,mBAMM,OANN,aAMM,CAAA,GAAA,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA;AAAA,cALJI,mBAIM,OAAA,EAJD,OAAM,6BAAyB;AAAA,gBAClCA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,cAAA;;YAKND,MAAA,mBAAA,KAAXJ,UAAA,GAAAC,mBASM,OATN,aASM,CAAA,GAAA,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA;AAAA,cARJI,mBAIM,OAAA,EAJD,OAAM,6BAAyB;AAAA,gBAClCA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,cAAA;cAEfA,mBAEM,OAAA,EAFD,OAAM,yBAAA,GAAyB,4BAEpC,EAAA;AAAA,YAAA;YAISD,MAAA,KAAA,EAAM,aAAQ,WAAgBA,MAAA,WAAA,KAAzCJ,UAAA,GAAAC,mBAOM,OAPN,aAOM,CAAA,GAAA,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA;AAAA,cANJI,mBAIO,QAAA,EAJD,OAAM,wBAAoB;AAAA,gBAC9BA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,gBACbA,mBAAa,MAAA;AAAA,cAAA;cAEfA,mBAA0D,QAAA,EAApD,OAAM,qBAAA,GAAqB,sBAAkB,EAAA;AAAA,YAAA;YAGrDA,mBAAgC,OAAA;AAAA,uBAAvB;AAAA,cAAJ,KAAI;AAAA,YAAA;;UAIXA,mBA4BO,QAAA;AAAA,YA5BD,OAAM;AAAA,YAA0B,wBAAgB,cAAY,CAAA,SAAA,CAAA;AAAA,UAAA;YAChEA,mBAOE,SAAA;AAAA,cANA,MAAK;AAAA,cACL,OAAM;AAAA,cACL,OAAOD,MAAA,KAAA,EAAM;AAAA,cACb,SAAO;AAAA,cACP,aAAa,OAAA,MAAO;AAAA,cACpB,UAAUA,MAAA,KAAA,EAAM,aAAa,eAAA,SAAkB,kBAAA;AAAA,YAAA;YAElDC,mBAkBS,UAAA;AAAA,cAjBP,MAAK;AAAA,cACL,OAAM;AAAA,cACL,UAAQ,CAAGD,MAAA,KAAA,EAAM,WAAW,KAAA,KAAUA,MAAA,KAAA,EAAM,aAAa,eAAA,SAAkB,kBAAA;AAAA,YAAA;cAE5EC,mBAYM,OAAA;AAAA,gBAXJ,OAAM;AAAA,gBACN,QAAO;AAAA,gBACP,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,gBAAa;AAAA,gBACb,kBAAe;AAAA,gBACf,mBAAgB;AAAA,cAAA;gBAEhBA,mBAA4C,QAAA;AAAA,kBAAtC,IAAG;AAAA,kBAAK,IAAG;AAAA,kBAAI,IAAG;AAAA,kBAAK,IAAG;AAAA,gBAAA;gBAChCA,mBAAsD,WAAA,EAA7C,QAAO,6BAA2B;AAAA,cAAA;;;;;;;;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("../core/stateManager.cjs.js");exports.useChatWidget=function(a){const n=new t.WidgetStateManager(a),r=e.ref(n.getState()),s=e.ref(!1),o=e.ref(!1),u=e.ref({name:"Agent"}),c=n.subscribe(e=>{r.value={...e};const t=n.getAdditionalState();s.value=t.wsConnected,o.value=t.agentTyping,u.value=t.currentAgent}),g=e.computed(()=>r.value.isOpen),d=e.computed(()=>r.value.messages),i=e.computed(()=>r.value.isLoading),l=e.computed(()=>r.value.error),p=e.computed(()=>r.value.chatMode);return e.onUnmounted(()=>{c(),n.destroy()}),e.watch(()=>a,e=>{n.updateConfig(e)},{deep:!0}),{state:r,isOpen:g,messages:d,isLoading:i,error:l,chatMode:p,wsConnected:s,agentTyping:o,currentAgent:u,openChat:async()=>{await n.openChat()},closeChat:()=>{n.closeChat()},sendMessage:async e=>{await n.sendMessage(e)},toggleChat:async()=>{await n.toggleChat()},setInputValue:e=>{n.setInputValue(e)},clearError:()=>{n.clearError()},manager:n}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("../core/stateManager.cjs.js");exports.useChatWidget=function(a){const n=new t.WidgetStateManager(a),s=e.ref(n.getState()),o=e.ref(!1),r=e.ref(!1),u=e.ref({name:"Agent"}),g=e.ref(!1),c=n.subscribe(e=>{s.value={...e};const t=n.getAdditionalState();o.value=t.wsConnected,r.value=t.agentTyping,u.value=t.currentAgent,g.value=t.isConnectingToAgent}),i=e.computed(()=>s.value.isOpen),d=e.computed(()=>s.value.messages),l=e.computed(()=>s.value.isLoading),p=e.computed(()=>s.value.error),v=e.computed(()=>s.value.chatMode);return e.onUnmounted(()=>{c(),n.destroy()}),e.watch(()=>a,e=>{n.updateConfig(e)},{deep:!0}),{state:s,isOpen:i,messages:d,isLoading:l,error:p,chatMode:v,wsConnected:o,agentTyping:r,currentAgent:u,isConnectingToAgent:g,openChat:async()=>{await n.openChat()},closeChat:()=>{n.closeChat()},sendMessage:async e=>{await n.sendMessage(e)},toggleChat:async()=>{await n.toggleChat()},setInputValue:e=>{n.setInputValue(e)},clearError:()=>{n.clearError()},manager:n}};
2
2
  //# sourceMappingURL=useChatWidget.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useChatWidget.cjs.js","sources":["../../src/composables/useChatWidget.ts"],"sourcesContent":["/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n"],"names":["config","manager","WidgetStateManager","state","ref","getState","wsConnected","agentTyping","currentAgent","name","unsubscribe","subscribe","newState","value","additional","getAdditionalState","isOpen","computed","messages","isLoading","error","chatMode","onUnmounted","destroy","watch","newConfig","updateConfig","deep","openChat","async","closeChat","sendMessage","text","toggleChat","setInputValue","clearError"],"mappings":"sKAuCO,SAAuBA,GAE5B,MAAMC,EAAU,IAAIC,EAAAA,mBAAmBF,GAGjCG,EAAQC,EAAAA,IAAiBH,EAAQI,YACjCC,EAAcF,EAAAA,KAAI,GAClBG,EAAcH,EAAAA,KAAI,GAClBI,EAAeJ,EAAAA,IAAmC,CAAEK,KAAM,UAG1DC,EAAcT,EAAQU,UAAWC,IACrCT,EAAMU,MAAQ,IAAKD,GAGnB,MAAME,EAAab,EAAQc,qBAC3BT,EAAYO,MAAQC,EAAWR,YAC/BC,EAAYM,MAAQC,EAAWP,YAC/BC,EAAaK,MAAQC,EAAWN,eAI5BQ,EAASC,EAAAA,SAAS,IAAMd,EAAMU,MAAMG,QACpCE,EAAWD,EAAAA,SAAS,IAAMd,EAAMU,MAAMK,UACtCC,EAAYF,EAAAA,SAAS,IAAMd,EAAMU,MAAMM,WACvCC,EAAQH,EAAAA,SAAS,IAAMd,EAAMU,MAAMO,OACnCC,EAAWJ,EAAAA,SAAS,IAAMd,EAAMU,MAAMQ,UA0C5C,OAdAC,EAAAA,YAAY,KACVZ,IACAT,EAAQsB,YAIVC,EAAAA,MACE,IAAMxB,EACLyB,IACCxB,EAAQyB,aAAaD,IAEvB,CAAEE,MAAM,IAGH,CACLxB,QACAa,SACAE,WACAC,YACAC,QACAC,WACAf,cACAC,cACAC,eACAoB,SAjDeC,gBACT5B,EAAQ2B,YAiDdE,UA9CgB,KAChB7B,EAAQ6B,aA8CRC,YA3CkBF,MAAOG,UACnB/B,EAAQ8B,YAAYC,IA2C1BC,WAxCiBJ,gBACX5B,EAAQgC,cAwCdC,cArCqBrB,IACrBZ,EAAQiC,cAAcrB,IAqCtBsB,WAlCiB,KACjBlC,EAAQkC,cAkCRlC,UAEJ"}
1
+ {"version":3,"file":"useChatWidget.cjs.js","sources":["../../src/composables/useChatWidget.ts"],"sourcesContent":["/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n isConnectingToAgent: Readonly<Ref<boolean>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n const isConnectingToAgent = ref(false);\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n isConnectingToAgent.value = additional.isConnectingToAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n isConnectingToAgent: isConnectingToAgent as Readonly<Ref<boolean>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n"],"names":["config","manager","WidgetStateManager","state","ref","getState","wsConnected","agentTyping","currentAgent","name","isConnectingToAgent","unsubscribe","subscribe","newState","value","additional","getAdditionalState","isOpen","computed","messages","isLoading","error","chatMode","onUnmounted","destroy","watch","newConfig","updateConfig","deep","openChat","async","closeChat","sendMessage","text","toggleChat","setInputValue","clearError"],"mappings":"sKAwCO,SAAuBA,GAE5B,MAAMC,EAAU,IAAIC,EAAAA,mBAAmBF,GAGjCG,EAAQC,EAAAA,IAAiBH,EAAQI,YACjCC,EAAcF,EAAAA,KAAI,GAClBG,EAAcH,EAAAA,KAAI,GAClBI,EAAeJ,EAAAA,IAAmC,CAAEK,KAAM,UAC1DC,EAAsBN,EAAAA,KAAI,GAG1BO,EAAcV,EAAQW,UAAWC,IACrCV,EAAMW,MAAQ,IAAKD,GAGnB,MAAME,EAAad,EAAQe,qBAC3BV,EAAYQ,MAAQC,EAAWT,YAC/BC,EAAYO,MAAQC,EAAWR,YAC/BC,EAAaM,MAAQC,EAAWP,aAChCE,EAAoBI,MAAQC,EAAWL,sBAInCO,EAASC,EAAAA,SAAS,IAAMf,EAAMW,MAAMG,QACpCE,EAAWD,EAAAA,SAAS,IAAMf,EAAMW,MAAMK,UACtCC,EAAYF,EAAAA,SAAS,IAAMf,EAAMW,MAAMM,WACvCC,EAAQH,EAAAA,SAAS,IAAMf,EAAMW,MAAMO,OACnCC,EAAWJ,EAAAA,SAAS,IAAMf,EAAMW,MAAMQ,UA0C5C,OAdAC,EAAAA,YAAY,KACVZ,IACAV,EAAQuB,YAIVC,EAAAA,MACE,IAAMzB,EACL0B,IACCzB,EAAQ0B,aAAaD,IAEvB,CAAEE,MAAM,IAGH,CACLzB,QACAc,SACAE,WACAC,YACAC,QACAC,WACAhB,cACAC,cACAC,eACAE,sBACAmB,SAlDeC,gBACT7B,EAAQ4B,YAkDdE,UA/CgB,KAChB9B,EAAQ8B,aA+CRC,YA5CkBF,MAAOG,UACnBhC,EAAQ+B,YAAYC,IA4C1BC,WAzCiBJ,gBACX7B,EAAQiC,cAyCdC,cAtCqBrB,IACrBb,EAAQkC,cAAcrB,IAsCtBsB,WAnCiB,KACjBnC,EAAQmC,cAmCRnC,UAEJ"}
@@ -18,6 +18,7 @@ export interface UseChatWidgetReturn {
18
18
  name: string;
19
19
  id?: string;
20
20
  }>>;
21
+ isConnectingToAgent: Readonly<Ref<boolean>>;
21
22
  openChat: () => Promise<void>;
22
23
  closeChat: () => void;
23
24
  sendMessage: (text: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"useChatWidget.d.ts","sourceRoot":"","sources":["../../src/composables/useChatWidget.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA+C,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAElC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAClC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACpC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;IAGxC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAG3D,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,UAAU,EAAE,MAAM,IAAI,CAAC;IAGvB,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,mBAAmB,CAsFvE"}
1
+ {"version":3,"file":"useChatWidget.d.ts","sourceRoot":"","sources":["../../src/composables/useChatWidget.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA+C,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAElC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAClC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACpC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;IAGxC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC3D,mBAAmB,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAG5C,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,UAAU,EAAE,MAAM,IAAI,CAAC;IAGvB,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,mBAAmB,CAyFvE"}
@@ -6,12 +6,14 @@ function useChatWidget(config) {
6
6
  const wsConnected = ref(false);
7
7
  const agentTyping = ref(false);
8
8
  const currentAgent = ref({ name: "Agent" });
9
+ const isConnectingToAgent = ref(false);
9
10
  const unsubscribe = manager.subscribe((newState) => {
10
11
  state.value = { ...newState };
11
12
  const additional = manager.getAdditionalState();
12
13
  wsConnected.value = additional.wsConnected;
13
14
  agentTyping.value = additional.agentTyping;
14
15
  currentAgent.value = additional.currentAgent;
16
+ isConnectingToAgent.value = additional.isConnectingToAgent;
15
17
  });
16
18
  const isOpen = computed(() => state.value.isOpen);
17
19
  const messages = computed(() => state.value.messages);
@@ -57,6 +59,7 @@ function useChatWidget(config) {
57
59
  wsConnected,
58
60
  agentTyping,
59
61
  currentAgent,
62
+ isConnectingToAgent,
60
63
  openChat,
61
64
  closeChat,
62
65
  sendMessage,
@@ -1 +1 @@
1
- {"version":3,"file":"useChatWidget.esm.js","sources":["../../src/composables/useChatWidget.ts"],"sourcesContent":["/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n"],"names":[],"mappings":";;AAuCO,SAAS,cAAc,QAA2C;AAEvE,QAAM,UAAU,IAAI,mBAAmB,MAAM;AAG7C,QAAM,QAAQ,IAAiB,QAAQ,SAAA,CAAU;AACjD,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,eAAe,IAAmC,EAAE,MAAM,SAAS;AAGzE,QAAM,cAAc,QAAQ,UAAU,CAAC,aAAa;AAClD,UAAM,QAAQ,EAAE,GAAG,SAAA;AAGnB,UAAM,aAAa,QAAQ,mBAAA;AAC3B,gBAAY,QAAQ,WAAW;AAC/B,gBAAY,QAAQ,WAAW;AAC/B,iBAAa,QAAQ,WAAW;AAAA,EAClC,CAAC;AAGD,QAAM,SAAS,SAAS,MAAM,MAAM,MAAM,MAAM;AAChD,QAAM,WAAW,SAAS,MAAM,MAAM,MAAM,QAAQ;AACpD,QAAM,YAAY,SAAS,MAAM,MAAM,MAAM,SAAS;AACtD,QAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,KAAK;AAC9C,QAAM,WAAW,SAAS,MAAM,MAAM,MAAM,QAAQ;AAGpD,QAAM,WAAW,YAAY;AAC3B,UAAM,QAAQ,SAAA;AAAA,EAChB;AAEA,QAAM,YAAY,MAAM;AACtB,YAAQ,UAAA;AAAA,EACV;AAEA,QAAM,cAAc,OAAO,SAAiB;AAC1C,UAAM,QAAQ,YAAY,IAAI;AAAA,EAChC;AAEA,QAAM,aAAa,YAAY;AAC7B,UAAM,QAAQ,WAAA;AAAA,EAChB;AAEA,QAAM,gBAAgB,CAAC,UAAkB;AACvC,YAAQ,cAAc,KAAK;AAAA,EAC7B;AAEA,QAAM,aAAa,MAAM;AACvB,YAAQ,WAAA;AAAA,EACV;AAGA,cAAY,MAAM;AAChB,gBAAA;AACA,YAAQ,QAAA;AAAA,EACV,CAAC;AAGD;AAAA,IACE,MAAM;AAAA,IACN,CAAC,cAAc;AACb,cAAQ,aAAa,SAAS;AAAA,IAChC;AAAA,IACA,EAAE,MAAM,KAAA;AAAA,EAAK;AAGf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"useChatWidget.esm.js","sources":["../../src/composables/useChatWidget.ts"],"sourcesContent":["/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n isConnectingToAgent: Readonly<Ref<boolean>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n const isConnectingToAgent = ref(false);\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n isConnectingToAgent.value = additional.isConnectingToAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n isConnectingToAgent: isConnectingToAgent as Readonly<Ref<boolean>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n"],"names":[],"mappings":";;AAwCO,SAAS,cAAc,QAA2C;AAEvE,QAAM,UAAU,IAAI,mBAAmB,MAAM;AAG7C,QAAM,QAAQ,IAAiB,QAAQ,SAAA,CAAU;AACjD,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,eAAe,IAAmC,EAAE,MAAM,SAAS;AACzE,QAAM,sBAAsB,IAAI,KAAK;AAGrC,QAAM,cAAc,QAAQ,UAAU,CAAC,aAAa;AAClD,UAAM,QAAQ,EAAE,GAAG,SAAA;AAGnB,UAAM,aAAa,QAAQ,mBAAA;AAC3B,gBAAY,QAAQ,WAAW;AAC/B,gBAAY,QAAQ,WAAW;AAC/B,iBAAa,QAAQ,WAAW;AAChC,wBAAoB,QAAQ,WAAW;AAAA,EACzC,CAAC;AAGD,QAAM,SAAS,SAAS,MAAM,MAAM,MAAM,MAAM;AAChD,QAAM,WAAW,SAAS,MAAM,MAAM,MAAM,QAAQ;AACpD,QAAM,YAAY,SAAS,MAAM,MAAM,MAAM,SAAS;AACtD,QAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,KAAK;AAC9C,QAAM,WAAW,SAAS,MAAM,MAAM,MAAM,QAAQ;AAGpD,QAAM,WAAW,YAAY;AAC3B,UAAM,QAAQ,SAAA;AAAA,EAChB;AAEA,QAAM,YAAY,MAAM;AACtB,YAAQ,UAAA;AAAA,EACV;AAEA,QAAM,cAAc,OAAO,SAAiB;AAC1C,UAAM,QAAQ,YAAY,IAAI;AAAA,EAChC;AAEA,QAAM,aAAa,YAAY;AAC7B,UAAM,QAAQ,WAAA;AAAA,EAChB;AAEA,QAAM,gBAAgB,CAAC,UAAkB;AACvC,YAAQ,cAAc,KAAK;AAAA,EAC7B;AAEA,QAAM,aAAa,MAAM;AACvB,YAAQ,WAAA;AAAA,EACV;AAGA,cAAY,MAAM;AAChB,gBAAA;AACA,YAAQ,QAAA;AAAA,EACV,CAAC;AAGD;AAAA,IACE,MAAM;AAAA,IACN,CAAC,cAAc;AACb,cAAQ,aAAa,SAAS;AAAA,IAChC;AAAA,IACA,EAAE,MAAM,KAAA;AAAA,EAAK;AAGf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}
@@ -2,9 +2,11 @@
2
2
  * Nuxt 3 Entry Point
3
3
  * SSR-optimized entry point for Nuxt 3
4
4
  */
5
- export { default } from '../components/ChatWidget.vue';
6
- export { default as ChatWidget } from '../components/ChatWidget.vue';
5
+ import ChatWidgetComponent from '../components/ChatWidget.vue';
6
+ export default ChatWidgetComponent;
7
+ export { ChatWidgetComponent as ChatWidget };
7
8
  export { useChatWidget } from '../composables/useChatWidget';
8
9
  export type { UseChatWidgetReturn } from '../composables/useChatWidget';
9
- export type { WidgetConfig, WidgetState, ChatMessage, } from '../core/types';
10
+ export type { WidgetConfig, WidgetState, ChatMessage, RichContent, ChipOption, } from '../core/types';
11
+ export { WidgetStateManager } from '../core/stateManager';
10
12
  //# sourceMappingURL=nuxt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.d.ts","sourceRoot":"","sources":["../../src/entry/nuxt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGxE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"nuxt.d.ts","sourceRoot":"","sources":["../../src/entry/nuxt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,mBAAmB,MAAM,8BAA8B,CAAC;AAG/D,eAAe,mBAAmB,CAAC;AACnC,OAAO,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAG7C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGxE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,GACX,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/nuxt.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./components/ChatWidget.vue.cjs.js"),t=require("./composables/useChatWidget.cjs.js");exports.ChatWidget=e.default,exports.default=e.default,exports.useChatWidget=t.useChatWidget;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./components/ChatWidget.vue.cjs.js"),t=require("./composables/useChatWidget.cjs.js"),s=require("./core/stateManager.cjs.js");exports.ChatWidget=e.default,exports.default=e.default,exports.useChatWidget=t.useChatWidget,exports.WidgetStateManager=s.WidgetStateManager;
2
2
  //# sourceMappingURL=nuxt.cjs.js.map
package/dist/nuxt.esm.js CHANGED
@@ -1,8 +1,10 @@
1
- import { default as default2, default as default3 } from "./components/ChatWidget.vue.esm.js";
1
+ import ChatWidgetComponent from "./components/ChatWidget.vue.esm.js";
2
2
  import { useChatWidget } from "./composables/useChatWidget.esm.js";
3
+ import { WidgetStateManager } from "./core/stateManager.esm.js";
3
4
  export {
4
- default2 as ChatWidget,
5
- default3 as default,
5
+ ChatWidgetComponent as ChatWidget,
6
+ WidgetStateManager,
7
+ ChatWidgetComponent as default,
6
8
  useChatWidget
7
9
  };
8
10
  //# sourceMappingURL=nuxt.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"nuxt.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@om_patel_26/chat-widget",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Universal chat widget for Vue 3, Nuxt 3, React, and Next.js with SSR support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs.js",