@skywu/virtual-chat-sdk 2.1.0 → 2.2.0

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.
@@ -1 +1 @@
1
- class e extends Error{constructor(e,t,s){super(e),this.code=t,this.details=s,this.name="ChatSDKError"}}class t{constructor(){this.events=new Map}on(e,t){this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(t)}off(e,t){if(!this.events.has(e))return;if(!t)return void this.events.delete(e);const s=this.events.get(e),n=s.indexOf(t);n>-1&&s.splice(n,1),0===s.length&&this.events.delete(e)}emit(e,t){if(!this.events.has(e))return;this.events.get(e).forEach(s=>{try{s(t)}catch(t){console.error(`Error in event callback for "${e}":`,t)}})}getEventNames(){return Array.from(this.events.keys())}listenerCount(e){var t;return(null===(t=this.events.get(e))||void 0===t?void 0:t.length)||0}removeAllListeners(){this.events.clear()}}function s(e,t,s){const n=document.createElement(e);return t&&(n.className=t),n}function n(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function i(e,t=!0){e.scrollTop=e.scrollHeight,e.scrollTo&&e.scrollTo({top:e.scrollHeight,behavior:t?"smooth":"auto"})}class a extends t{constructor(e,t){super(),this.simulationData=null,this.displayedMessages=[],this.currentMessageIndex=0,this.isRunning=!1,this.isPaused=!1,this.intervalId=null,this.pollingId=null,this.burstPhase=!0,this.totalToShow=1/0,this.virtualLastTimestamp=null,this.realLastTimestamp=null,this.lastTimestamp=null,this.lastDelayMs=0,this.userId="",this.config=e,this.apiClient=t,this.pollingIntervalMs="number"==typeof e.pollingInterval&&e.pollingInterval>0?e.pollingInterval:6e3}async initialize(){try{const e=this.config.language||"en",t=this.getPersistedUserId(),s=t||this.config.userId||this.generateUserId();this.userId=s,t||this.persistUserId(s);const n=await this.apiClient.getSimulationData(this.config.projectId,s,e);if(!n.success||!n.data)throw new Error("Failed to load simulation data");this.simulationData=n.data;const i=this.simulationData.project.initialBurstCount+this.simulationData.project.continuousCount;this.totalToShow=Math.min(i,this.simulationData.messages.length);const a=this.loadProgress();a&&"number"==typeof a.index?(this.currentMessageIndex=a.index,a.lastTimestamp&&(this.virtualLastTimestamp=new Date(a.lastTimestamp),this.lastTimestamp=new Date(a.lastTimestamp))):(this.currentMessageIndex=0,this.virtualLastTimestamp=null,this.lastTimestamp=null),this.realLastTimestamp=null,await this.loadExistingMessages(),await this.reconstructVirtualHistoryForDisplay(),this.emit("initialized",this.simulationData),this.startPolling(),!1!==this.config.autoStart&&this.start()}catch(e){throw this.emit("error",e),e}}start(){this.simulationData&&!this.isRunning&&(this.isRunning=!0,this.isPaused=!1,this.burstPhase=!0,this.emit("simulationStart"),this.performInitialBurst(),this.currentMessageIndex<this.totalToShow?(this.burstPhase=!1,this.scheduleNextMessage()):(this.isRunning=!1,this.emit("simulationEnd")))}performInitialBurst(){if(!this.simulationData)return;const{project:e,messages:t}=this.simulationData,s=e.initialBurstCount,n=Math.min(s,this.totalToShow,t.length);if(this.currentMessageIndex>=n)return;if(this.displayedMessages.some(e=>e.id.startsWith("sim-"))&&this.currentMessageIndex>0)return;const i=new Date,a=new Array(n);let o=new Date(i);for(let e=n-1;e>=0;e--)if(a[e]=new Date(o),e>0){const e=10+Math.floor(11*Math.random());o=new Date(o.getTime()-60*e*1e3)}const r=[];let d=!1;for(let e=this.currentMessageIndex;e<n;e++){const s=t[e];if(s.hasScreenshot&&s.screenshotUrl){const t={id:`sim-${e}-text-${Date.now()}`,content:s.content,messageType:"text",timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t);const n=new Date(a[e].getTime()+2e3),i={id:`sim-${e}-image-${Date.now()}`,content:s.screenshotUrl,messageType:"image",timestamp:n,isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(i),r.push(i)}else{const t={id:`sim-${e}-${Date.now()}`,content:s.content,messageType:s.messageType,timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t)}this.currentMessageIndex=e+1,d=!0}d&&(this.lastTimestamp=a[n-1],this.virtualLastTimestamp=this.lastTimestamp,this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.emit("messages-batch",r)),this.saveProgress()}pause(){this.isRunning&&(this.isPaused=!0,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationPause"))}resume(){this.isRunning&&this.isPaused&&(this.isPaused=!1,this.scheduleNextMessage(),this.emit("simulationResume"))}stop(){this.isRunning=!1,this.isPaused=!1,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationStop")}destroy(){this.stop(),this.stopPolling(),this.removeAllListeners()}scheduleNextMessage(){if(!this.simulationData||!this.isRunning||this.isPaused)return;const{project:e,messages:t}=this.simulationData;if(this.currentMessageIndex>=this.totalToShow)return this.isRunning=!1,void this.emit("simulationEnd");let s;if(this.burstPhase){const n=Math.min(e.initialBurstCount,t.length);this.currentMessageIndex<n?s=500+1e3*Math.random():(this.burstPhase=!1,s=this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax))}else{const n=Math.min(e.initialBurstCount,t.length);s=this.currentMessageIndex-n<5?1e3*(e.initialMessageInterval||10):this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax)}this.lastDelayMs=s,this.intervalId=setTimeout(()=>{this.displayNextMessage(),this.scheduleNextMessage()},s)}displayNextMessage(){if(!this.simulationData||this.currentMessageIndex>=this.simulationData.messages.length)return;const e=this.simulationData.messages[this.currentMessageIndex],t=this.lastTimestamp||new Date,s=new Date(t.getTime()+(this.lastDelayMs||0));if(this.lastTimestamp=s,e.hasScreenshot&&e.screenshotUrl){const t={id:`sim-${this.currentMessageIndex}-text-${Date.now()}`,content:e.content,messageType:"text",timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t);const n=new Date(s.getTime()+2e3),i={id:`sim-${this.currentMessageIndex}-image-${Date.now()}`,content:e.screenshotUrl,messageType:"image",timestamp:n,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(i),this.lastTimestamp=n,setTimeout(()=>{this.emit("message",i)},2e3)}else{const t={id:`sim-${this.currentMessageIndex}-${Date.now()}`,content:e.content,messageType:e.messageType,timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t)}this.currentMessageIndex++,this.saveProgress()}async loadExistingMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=await this.apiClient.getSimulationMessages(this.config.projectId,e,void 0,100);if(t.success&&t.messages&&t.messages.length>0){const s=t.messages.sort((e,t)=>new Date(e.createdAt||e.timestamp).getTime()-new Date(t.createdAt||t.timestamp).getTime()),n=new Set(this.displayedMessages.map(e=>e.id));for(const t of s){if(n.has(t.id))continue;const s={id:t.id,content:t.content,messageType:t.messageType,timestamp:new Date(t.createdAt||t.timestamp),isOwnMessage:t.userId===e,virtualUser:t.virtualUser,user:t.userId===e?{id:e,username:this.config.username||"You"}:void 0};this.displayedMessages.push(s)}if(s.length>0){const e=s[s.length-1];this.realLastTimestamp=new Date(e.createdAt||e.timestamp)}this.displayedMessages.length>0&&this.emit("messages-batch",[...this.displayedMessages])}}catch(e){console.warn("Failed to load existing messages:",e)}}startPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null),this.pollingId=setInterval(async()=>{await this.pollForNewMessages()},this.pollingIntervalMs)}stopPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null)}setPollingInterval(e){!e||e<=0||(this.pollingIntervalMs=e,this.pollingId&&this.startPolling())}get isPolling(){return!!this.pollingId}async pollForNewMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=this.getLastMessageTimestamp(),s=await this.apiClient.getSimulationMessages(this.config.projectId,e,t);if(s.success&&s.messages&&s.messages.length>0){const t=new Set(this.displayedMessages.map(e=>e.id));let n=null;for(const i of s.messages){if(t.has(i.id))continue;const s=new Date(i.createdAt),a={id:i.id,content:i.content,messageType:i.messageType,timestamp:s,isOwnMessage:i.userId===e,virtualUser:i.virtualUser,user:i.userId===e?{id:e,username:this.config.username||"You"}:void 0};(!n||s>n)&&(n=s),this.displayedMessages.push(a),this.emit("message",a)}n&&(this.realLastTimestamp=n)}}catch(e){console.warn("Polling error:",e)}}async reconstructVirtualHistoryForDisplay(){if(!this.simulationData)return;const e=Math.min(this.currentMessageIndex,this.totalToShow,this.simulationData.messages.length);if(e<=0)return;const t=this.loadProgress(),s=(null==t?void 0:t.virtualMessages)||[];if(s.length>0){const e=[],t=new Set(this.displayedMessages.map(e=>e.id));for(const n of s)if(!t.has(n.id)){const t={id:n.id,content:n.content,messageType:n.messageType,timestamp:new Date(n.timestamp),isOwnMessage:!1,virtualUser:n.virtualUser};e.push(t)}if(e.length>0){this.displayedMessages.push(...e),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=e[e.length-1];this.virtualLastTimestamp=t.timestamp,this.lastTimestamp=t.timestamp,this.emit("messages-batch",e)}return}const n=new Date,i=new Array(e);let a=new Date(n);for(let t=e-1;t>=0;t--)if(i[t]=new Date(a),t>0){const e=10+Math.floor(11*Math.random());a=new Date(a.getTime()-60*e*1e3)}const o=[],{messages:r}=this.simulationData;for(let t=0;t<e;t++){const e=r[t],s=i[t];if(e.hasScreenshot&&e.screenshotUrl){const n={id:`sim-${t}-text`,content:e.content,messageType:"text",timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser},i={id:`sim-${t}-image`,content:e.screenshotUrl,messageType:"image",timestamp:new Date(s.getTime()+2e3),isOwnMessage:!1,virtualUser:e.virtualUser};o.push(n,i)}else{const n={id:`sim-${t}`,content:e.content,messageType:e.messageType,timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};o.push(n)}}const d=new Set(this.displayedMessages.map(e=>e.id)),l=o.filter(e=>!d.has(e.id));if(0===l.length)return;this.displayedMessages.push(...l),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const h=l[l.length-1];this.virtualLastTimestamp=h.timestamp,this.lastTimestamp=h.timestamp,this.emit("messages-batch",l)}getLastMessageTimestamp(){if(this.realLastTimestamp)return this.realLastTimestamp.toISOString()}getUserKey(){return`vcs:user:${this.config.projectId}`}getProgressKey(){const e=this.userId||this.config.userId||"anon";return`vcs:progress:${this.config.projectId}:${e}`}getPersistedUserId(){try{return"undefined"==typeof window?null:window.localStorage.getItem(this.getUserKey())}catch(e){return null}}persistUserId(e){try{if("undefined"==typeof window)return;window.localStorage.setItem(this.getUserKey(),e)}catch(e){}}loadProgress(){try{if("undefined"==typeof window)return null;const e=window.localStorage.getItem(this.getProgressKey());return e?JSON.parse(e):null}catch(e){return null}}saveProgress(){try{if("undefined"==typeof window)return;const e=this.displayedMessages.filter(e=>e.id.startsWith("sim-")).map(e=>({id:e.id,content:e.content,messageType:e.messageType,timestamp:e.timestamp.toISOString(),virtualUser:e.virtualUser})),t={index:this.currentMessageIndex,lastTimestamp:this.lastTimestamp?this.lastTimestamp.toISOString():void 0,virtualMessages:e};window.localStorage.setItem(this.getProgressKey(),JSON.stringify(t))}catch(e){}}clearProgress(){try{if("undefined"==typeof window)return;window.localStorage.removeItem(this.getProgressKey())}catch(e){}}clearCachedProgress(){this.clearProgress()}getRandomInterval(e,t){return 1e3*(e+Math.random()*(t-e))}generateUserId(){return`user-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}get messages(){return[...this.displayedMessages]}get isSimulationRunning(){return this.isRunning}get isSimulationPaused(){return this.isPaused}get data(){return this.simulationData}async sendMessage(e,t="text"){if(!this.simulationData)throw new Error("Simulation not initialized");const s=this.userId||this.config.userId||this.generateUserId(),n=this.config.username||"User";try{if("image"===t||"string"==typeof e&&e.startsWith("data:image/"))return;await Promise.all([this.apiClient.sendUserMessage(this.config.projectId,s,n,e,t),this.apiClient.triggerAIReply(this.config.projectId,s,n,e,t)])}catch(e){throw this.emit("error",e),e}}}class o{constructor(e){this.baseUrl=e.apiBaseUrl||window.location.origin,this.token=e.token}async request(t,s={}){const n=`${this.baseUrl}${t}`,i={"Content-Type":"application/json",...s.headers};this.token&&(i.Authorization=`Bearer ${this.token}`);try{const t=await fetch(n,{...s,headers:i,credentials:"include"});if(!t.ok)throw new e(`API request failed: ${t.status} ${t.statusText}`,"API_ERROR",{status:t.status,statusText:t.statusText});const a=await t.json();if(!a.success&&a.error)throw new e(a.error,"API_ERROR",a);return a}catch(t){if(t instanceof e)throw t;throw new e(`Network error: ${t.message}`,"NETWORK_ERROR",t)}}async getProject(e){return this.request(`/api/projects/${e}`)}async getTemplate(e,t){const s=t?`?lang=${encodeURIComponent(t)}`:"";return this.request(`/api/templates/${e}${s}`)}async getProjectTemplates(e){return this.request(`/api/projects/${e}/templates`)}async sendMessage(e,t,s,n="text"){return this.request("/api/chat/message",{method:"POST",body:JSON.stringify({projectId:e,userId:t,content:s,messageType:n})})}async joinProject(e,t,s){return this.request("/api/chat/join",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s})})}async leaveProject(e,t){return this.request("/api/chat/leave",{method:"POST",body:JSON.stringify({projectId:e,userId:t})})}async getSimulationData(e,t,s){const n=new URLSearchParams({userId:t});return s&&n.append("lang",s),this.request(`/api/chat/simulation/${e}?${n.toString()}`)}async getSimulationMessages(e,t,s,n){const i=new URLSearchParams({userId:t});return s&&i.append("since",s),n&&i.append("limit",n.toString()),this.request(`/api/chat/simulation/${e}/messages?${i.toString()}`)}async sendUserMessage(e,t,s,n,i="text"){return this.request("/api/chat/send",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}async triggerAIReply(e,t,s,n,i="text"){return this.request("/api/chat/ai-reply",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}setToken(e){this.token=e}setBaseUrl(e){this.baseUrl=e}}const r={en:{joinChat:"Join Chat",chatGroup:"{name} Group",online:"{count} online",inputPlaceholder:"Type a message...",send:"Send",messages:"messages",today:"Today",yesterday:"Yesterday",networkError:"Network error",sendFailed:"Failed to send"},zh:{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在线",inputPlaceholder:"输入消息...",send:"发送",messages:"条消息",today:"今天",yesterday:"昨天",networkError:"网络错误",sendFailed:"发送失败"},"zh-TW":{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在線",inputPlaceholder:"輸入訊息...",send:"發送",messages:"條訊息",today:"今天",yesterday:"昨天",networkError:"網路錯誤",sendFailed:"發送失敗"},es:{joinChat:"Unirse al Chat",chatGroup:"Grupo {name}",online:"{count} en línea",inputPlaceholder:"Escribe un mensaje...",send:"Enviar",messages:"mensajes",today:"Hoy",yesterday:"Ayer",networkError:"Error de red",sendFailed:"Error al enviar"},hi:{joinChat:"चैट में शामिल हों",chatGroup:"{name} समूह",online:"{count} ऑनलाइन",inputPlaceholder:"संदेश लिखें...",send:"भेजें",messages:"संदेश",today:"आज",yesterday:"कल",networkError:"नेटवर्क त्रुटि",sendFailed:"भेजने में विफल"},ar:{joinChat:"انضم للدردشة",chatGroup:"مجموعة {name}",online:"{count} متصل",inputPlaceholder:"اكتب رسالة...",send:"إرسال",messages:"رسائل",today:"اليوم",yesterday:"أمس",networkError:"خطأ في الشبكة",sendFailed:"فشل الإرسال"},pt:{joinChat:"Entrar no Chat",chatGroup:"Grupo {name}",online:"{count} online",inputPlaceholder:"Digite uma mensagem...",send:"Enviar",messages:"mensagens",today:"Hoje",yesterday:"Ontem",networkError:"Erro de rede",sendFailed:"Falha ao enviar"},bn:{joinChat:"চ্যাটে যোগ দিন",chatGroup:"{name} গ্রুপ",online:"{count} অনলাইন",inputPlaceholder:"একটি বার্তা লিখুন...",send:"পাঠান",messages:"বার্তা",today:"আজ",yesterday:"গতকাল",networkError:"নেটওয়ার্ক ত্রুটি",sendFailed:"পাঠাতে ব্যর্থ"},ru:{joinChat:"Присоединиться",chatGroup:"Группа {name}",online:"{count} онлайн",inputPlaceholder:"Введите сообщение...",send:"Отправить",messages:"сообщений",today:"Сегодня",yesterday:"Вчера",networkError:"Ошибка сети",sendFailed:"Не удалось отправить"},ja:{joinChat:"チャットに参加",chatGroup:"{name}グループ",online:"{count} オンライン",inputPlaceholder:"メッセージを入力...",send:"送信",messages:"メッセージ",today:"今日",yesterday:"昨日",networkError:"ネットワークエラー",sendFailed:"送信失敗"},de:{joinChat:"Chat beitreten",chatGroup:"{name} Gruppe",online:"{count} online",inputPlaceholder:"Nachricht eingeben...",send:"Senden",messages:"Nachrichten",today:"Heute",yesterday:"Gestern",networkError:"Netzwerkfehler",sendFailed:"Senden fehlgeschlagen"},fr:{joinChat:"Rejoindre le Chat",chatGroup:"Groupe {name}",online:"{count} en ligne",inputPlaceholder:"Tapez un message...",send:"Envoyer",messages:"messages",today:"Aujourd'hui",yesterday:"Hier",networkError:"Erreur réseau",sendFailed:"Échec de l'envoi"},ko:{joinChat:"채팅 참여",chatGroup:"{name} 그룹",online:"{count} 온라인",inputPlaceholder:"메시지 입력...",send:"전송",messages:"메시지",today:"오늘",yesterday:"어제",networkError:"네트워크 오류",sendFailed:"전송 실패"},it:{joinChat:"Unisciti alla Chat",chatGroup:"Gruppo {name}",online:"{count} online",inputPlaceholder:"Scrivi un messaggio...",send:"Invia",messages:"messaggi",today:"Oggi",yesterday:"Ieri",networkError:"Errore di rete",sendFailed:"Invio fallito"},tr:{joinChat:"Sohbete Katıl",chatGroup:"{name} Grubu",online:"{count} çevrimiçi",inputPlaceholder:"Bir mesaj yazın...",send:"Gönder",messages:"mesaj",today:"Bugün",yesterday:"Dün",networkError:"Ağ hatası",sendFailed:"Gönderilemedi"},vi:{joinChat:"Tham gia Chat",chatGroup:"Nhóm {name}",online:"{count} trực tuyến",inputPlaceholder:"Nhập tin nhắn...",send:"Gửi",messages:"tin nhắn",today:"Hôm nay",yesterday:"Hôm qua",networkError:"Lỗi mạng",sendFailed:"Gửi thất bại"},pl:{joinChat:"Dołącz do Czatu",chatGroup:"Grupa {name}",online:"{count} online",inputPlaceholder:"Wpisz wiadomość...",send:"Wyślij",messages:"wiadomości",today:"Dziś",yesterday:"Wczoraj",networkError:"Błąd sieci",sendFailed:"Nie udało się wysłać"},th:{joinChat:"เข้าร่วมแชท",chatGroup:"กลุ่ม {name}",online:"{count} ออนไลน์",inputPlaceholder:"พิมพ์ข้อความ...",send:"ส่ง",messages:"ข้อความ",today:"วันนี้",yesterday:"เมื่อวาน",networkError:"ข้อผิดพลาดเครือข่าย",sendFailed:"ส่งไม่สำเร็จ"},nl:{joinChat:"Deelnemen aan Chat",chatGroup:"{name} Groep",online:"{count} online",inputPlaceholder:"Typ een bericht...",send:"Verzenden",messages:"berichten",today:"Vandaag",yesterday:"Gisteren",networkError:"Netwerkfout",sendFailed:"Verzenden mislukt"},id:{joinChat:"Gabung Chat",chatGroup:"Grup {name}",online:"{count} online",inputPlaceholder:"Ketik pesan...",send:"Kirim",messages:"pesan",today:"Hari ini",yesterday:"Kemarin",networkError:"Kesalahan jaringan",sendFailed:"Gagal mengirim"},ms:{joinChat:"Sertai Chat",chatGroup:"Kumpulan {name}",online:"{count} dalam talian",inputPlaceholder:"Taip mesej...",send:"Hantar",messages:"mesej",today:"Hari ini",yesterday:"Semalam",networkError:"Ralat rangkaian",sendFailed:"Gagal menghantar"}};function d(e){if(r[e])return r[e];const t=e.split("-")[0];return r[t]?r[t]:r.en}function l(e,t){return e.replace(/\{(\w+)\}/g,(e,s)=>void 0!==t[s]?String(t[s]):e)}class h extends t{constructor(e){var t,s;super(),this.emojiPanelOpen=!1,this.onlineCount=0,this.currentTheme="whatsapp",this.isDarkMode=!1,this.customColors={},this.visibleStartIndex=0,this.hasInitializedData=!1,this.pollingStopTimer=null,this.config={...e,mode:e.mode||"floating"},this.t=d(e.language||"en"),this.currentTheme="telegram"===e.uiTemplate?"telegram":"whatsapp",this.isDarkMode="dark"===e.theme,this.customColors={primary:e.primaryColor,background:e.backgroundColor},this.onlineCount=500+Math.floor(301*Math.random()),this.initialRenderCount=null!==(t=this.config.initialRenderCount)&&void 0!==t?t:Number.MAX_SAFE_INTEGER,this.lazyLoadBatchSize=null!==(s=this.config.lazyLoadBatchSize)&&void 0!==s?s:20,this.state={isInitialized:!1,isOpen:!1,isJoined:!1,isConnected:!1,isSimulationRunning:!1,isSimulationPaused:!1,messages:[],virtualUsers:[],realUsers:[],typingUsers:[],simulationEnded:!1,displayedMessageCount:0,unreadCount:0,lastReadMessageId:null},this.apiClient=new o(e),this.simulator=new a(e,this.apiClient),this.setupSimulatorEvents(),this.init()}init(){try{this.setupContainer(),this.createWidget(),"floating"===this.config.mode&&(this.widgetElement.style.display="none",this.createFloatingButton()),this.setupEventListeners(),this.setupImageViewer(),this.state.isInitialized=!0,this.emit("ready")}catch(t){this.emit("error",new e("Failed to initialize chat widget","WIDGET_INIT_ERROR",t))}}setupSimulatorEvents(){this.simulator.on("initialized",e=>{var t;this.state.currentProject=e.project,this.state.currentTemplate=e.template,null!=this.config.initialRenderCount?this.initialRenderCount=this.config.initialRenderCount:this.initialRenderCount=Number.MAX_SAFE_INTEGER,this.setTitle((null===(t=e.project)||void 0===t?void 0:t.name)||"Chat",`0 ${this.t.messages}`),this.setLoading(!1),this.emit("simulationInitialized",e)}),this.simulator.on("message",e=>{var t;this.setLoading(!1),this.addMessage(e),this.state.displayedMessageCount++;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`)}),this.simulator.on("messages-batch",e=>{var t;this.setLoading(!1),this.addMessagesBulk(e),this.state.displayedMessageCount+=e.length;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`),setTimeout(()=>{this.scrollToBottom(!0)},100)}),this.simulator.on("simulationStart",()=>{var e,t;this.state.isSimulationRunning=!0,this.state.isSimulationPaused=!1,null===(t=(e=this.config).onSimulationStart)||void 0===t||t.call(e)}),this.simulator.on("simulationEnd",()=>{var e,t;this.state.isSimulationRunning=!1,this.state.simulationEnded=!0,null===(t=(e=this.config).onSimulationEnd)||void 0===t||t.call(e)}),this.simulator.on("simulationPause",()=>{this.state.isSimulationPaused=!0}),this.simulator.on("simulationResume",()=>{this.state.isSimulationPaused=!1}),this.simulator.on("error",e=>{this.emit("error",e)})}async initializeSimulation(){try{await this.simulator.initialize()}catch(t){this.emit("error",new e("Failed to initialize simulation","SIMULATION_INIT_ERROR",t))}}setupContainer(){var t;const s=function(e){if("string"==typeof e)return document.querySelector(e)||document.body;return e||document.body}(this.config.container);if(!s)throw new e("Container element not found","CONTAINER_NOT_FOUND");const n=null===(t=s.tagName)||void 0===t?void 0:t.toUpperCase();if("BODY"===n||"HTML"===n){const e=document.createElement("div");e.className="chat-sdk-host",e.style.position="static",e.style.width="0",e.style.height="0",document.body.appendChild(e),this.container=e}else this.container=s;this.shadowRoot=this.container.attachShadow({mode:"closed"});const i=this.getDefaultStyles();!function(e,t){const s=document.createElement("style");s.textContent=t,e.appendChild(s)}(this.shadowRoot,i)}createWidget(){var e;if(this.widgetElement&&this.messagesContainer)return;this.widgetElement=s("div","chat-sdk-container");const t="telegram"===this.config.uiTemplate?"telegram":"whatsapp";this.currentTheme=t,this.widgetElement.classList.add(`${t}-theme`),"telegram"===t&&"dark"===this.config.theme&&(this.widgetElement.classList.add("dark"),this.isDarkMode=!0),this.widgetElement.style.position="fixed",this.widgetElement.style.top="0",this.widgetElement.style.left="0",this.widgetElement.style.width="100vw",this.widgetElement.style.height="100vh",this.widgetElement.style.zIndex=String(null!==(e=this.config.zIndex)&&void 0!==e?e:2147483e3),this.widgetElement.innerHTML=`\n <div class="chat-sdk-header">\n <div class="chat-sdk-header-left">\n <div class="chat-sdk-title" id="chat-title"></div>\n <div class="chat-sdk-subtitle" id="chat-subtitle"></div>\n </div>\n <button class="chat-sdk-close-btn" type="button">\n <svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor">\n <path d="M8 7.293l2.146-2.147a.5.5 0 01.708.708L8.707 8l2.147 2.146a.5.5 0 01-.708.708L8 8.707l-2.146 2.147a.5.5 0 01-.708-.708L7.293 8 5.146 5.854a.5.5 0 01.708-.708L8 7.293z"/>\n </svg>\n </button>\n </div>\n\n <div class="chat-sdk-messages" id="messages-container">\n <div class="chat-sdk-loading">\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n </div>\n </div>\n\n <div class="chat-sdk-input-area">\n <button class="chat-sdk-icon-btn chat-sdk-emoji-btn" type="button" id="emoji-button" aria-label="Emoji">\n <span>😊</span>\n </button>\n <button class="chat-sdk-icon-btn chat-sdk-image-btn" type="button" id="image-button" aria-label="Image">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14h18zM5 5h14v8l-3-3-4 5-3-4-4 4V5z"/></svg>\n </button>\n <textarea\n class="chat-sdk-input"\n placeholder="${this.t.inputPlaceholder}"\n rows="1"\n id="message-input"\n ></textarea>\n <input type="file" accept="image/*" id="image-input" style="display:none" />\n <button class="chat-sdk-send-btn" type="button" id="send-button" disabled>\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <path d="M15.854.146a.5.5 0 01.11.54l-5.819 14.547a.75.75 0 01-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 01.124-1.33L15.314.037a.5.5 0 01.54.11z"/>\n </svg>\n </button>\n </div>\n <div class="chat-sdk-emoji-picker" id="emoji-picker" style="display:none">\n <div class="chat-sdk-emoji-grid">\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😀">😀</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😁">😁</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😂">😂</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤣">🤣</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😊">😊</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😍">😍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😎">😎</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤔">🤔</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="👍">👍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🙏">🙏</button>\n </div>\n </div>\n `,this.messagesContainer=this.widgetElement.querySelector("#messages-container"),this.inputElement=this.widgetElement.querySelector("#message-input"),this.sendButton=this.widgetElement.querySelector("#send-button"),this.emojiButton=this.widgetElement.querySelector("#emoji-button"),this.imageButton=this.widgetElement.querySelector("#image-button"),this.fileInput=this.widgetElement.querySelector("#image-input"),this.emojiPicker=this.widgetElement.querySelector("#emoji-picker"),this.shadowRoot.appendChild(this.widgetElement)}setupEventListeners(){var e,t,s,n;const i=this.widgetElement.querySelector(".chat-sdk-close-btn");null==i||i.addEventListener("click",()=>this.close()),this.messagesContainer.addEventListener("scroll",this.handleScrollLazyLoad.bind(this)),this.inputElement.addEventListener("input",this.handleInputChange.bind(this)),this.inputElement.addEventListener("keydown",this.handleKeyDown.bind(this)),this.sendButton.addEventListener("click",this.handleSendMessage.bind(this)),this.inputElement.addEventListener("input",this.autoResizeTextarea.bind(this)),null===(e=this.emojiButton)||void 0===e||e.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.toggleEmojiPicker(!this.emojiPanelOpen)}),null===(t=this.emojiPicker)||void 0===t||t.addEventListener("click",e=>{const t=e.target.closest(".chat-sdk-emoji-item");if(t&&t.hasAttribute("data-emoji")){const e=t.getAttribute("data-emoji")||"";this.insertEmojiAtCursor(e),this.toggleEmojiPicker(!1)}}),this.shadowRoot.addEventListener("click",e=>{const t=e.target,s=t.closest("#emoji-picker"),n=t.closest("#emoji-button");s||n||this.toggleEmojiPicker(!1)}),null===(s=this.imageButton)||void 0===s||s.addEventListener("click",e=>{var t;e.preventDefault(),e.stopPropagation(),null===(t=this.fileInput)||void 0===t||t.click()}),null===(n=this.fileInput)||void 0===n||n.addEventListener("change",this.handleImageSelected.bind(this)),document.addEventListener("keydown",e=>{"Escape"===e.key&&this.state.isOpen&&this.close()})}createFloatingButton(){var e,t,s,n,i,a,o,r,d,l,h;if(!this.shadowRoot)return;const c=this.config.floatingButton||{},g=c.position||"bottom-right",m=String(null!==(t=null!==(e=c.zIndex)&&void 0!==e?e:this.config.zIndex)&&void 0!==t?t:2147483e3),u={top:null===(s=c.offset)||void 0===s?void 0:s.top,right:null===(n=c.offset)||void 0===n?void 0:n.right,bottom:null!==(a=null===(i=c.offset)||void 0===i?void 0:i.bottom)&&void 0!==a?a:20,left:null===(o=c.offset)||void 0===o?void 0:o.left},p=document.createElement("button");p.className="chat-sdk-floating-btn",p.setAttribute("aria-label","Open chat");const y=this.t.joinChat;p.innerHTML=`\n <div style="\n position: relative;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 6px;\n ">\n \x3c!-- Group chat icon (users) --\x3e\n <svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" style="margin-bottom: 2px;">\n <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/>\n </svg>\n\n \x3c!-- Text overlay at bottom --\x3e\n <div style="\n font-size: 10px;\n font-weight: 600;\n color: rgba(255, 255, 255, 0.95);\n text-align: center;\n line-height: 1.2;\n letter-spacing: 0.3px;\n text-shadow: 0 1px 2px rgba(0,0,0,0.2);\n ">${y}</div>\n\n \x3c!-- Unread badge --\x3e\n <span class="chat-sdk-unread-badge" style="\n position: absolute;\n top: -6px;\n right: -6px;\n background: #ff4444;\n color: white;\n border-radius: 10px;\n min-width: 18px;\n height: 18px;\n display: none;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n padding: 0 5px;\n "></span>\n </div>\n `,p.style.position="fixed",p.style.zIndex=m,p.style.width="60px",p.style.height="60px",p.style.borderRadius="50%",p.style.border="none",p.style.cursor="pointer",p.style.display="flex",p.style.alignItems="center",p.style.justifyContent="center",p.style.color="#fff",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)",p.style.background="linear-gradient(145deg, #25D366 0%, #128C7E 100%)",p.style.transition="transform .15s ease, box-shadow .15s ease",p.style.overflow="visible",g.includes("bottom")?(p.style.bottom=(null!==(r=u.bottom)&&void 0!==r?r:20)+"px",p.style.top=""):(p.style.top=(null!==(d=u.top)&&void 0!==d?d:20)+"px",p.style.bottom=""),g.includes("right")?(p.style.right=(null!==(l=u.right)&&void 0!==l?l:20)+"px",p.style.left=""):(p.style.left=(null!==(h=u.left)&&void 0!==h?h:20)+"px",p.style.right=""),p.addEventListener("mouseenter",()=>{p.style.transform="scale(1.06)",p.style.boxShadow="0 14px 28px rgba(0,0,0,0.30), inset 0 2px 4px rgba(255,255,255,0.2)"}),p.addEventListener("mouseleave",()=>{p.style.transform="scale(1)",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)"}),p.addEventListener("mousedown",()=>{p.style.transform="scale(0.95)"}),p.addEventListener("mouseup",()=>{p.style.transform="scale(1.05)",setTimeout(()=>p.style.transform="scale(1)",100)}),p.addEventListener("click",e=>{e.preventDefault(),this.open()}),this.shadowRoot.appendChild(p),this.floatingButtonEl=p}updateUnreadBadge(){if(!this.floatingButtonEl)return;const e=this.floatingButtonEl.querySelector(".chat-sdk-unread-badge");if(!e)return;const t=this.state.unreadCount;t>0?(e.textContent=t>99?"99+":t.toString(),e.style.display="flex"):e.style.display="none"}markAllAsRead(){if(this.state.messages.length>0){const e=this.state.messages[this.state.messages.length-1];this.state.lastReadMessageId=e.id}this.state.unreadCount=0,this.updateUnreadBadge()}incrementUnreadCount(){this.state.isOpen||(this.state.unreadCount++,this.updateUnreadBadge())}toggleEmojiPicker(e){const t=this.emojiPicker;if(!t)return;const s="boolean"==typeof e?e:"none"===t.style.display;t.style.display=s?"block":"none",this.emojiPanelOpen=s}insertEmojiAtCursor(e){const t=this.inputElement,s=t.selectionStart||0,n=t.selectionEnd||0,i=t.value.substring(0,s),a=t.value.substring(n);t.value=i+e+a;const o=s+e.length;t.setSelectionRange(o,o),t.focus(),this.handleInputChange(),this.autoResizeTextarea()}isEmojiOnly(e){const t=e.trim();if(!t)return!1;if(t.length>6)return!1;let s=!1;for(let e=0;e<t.length;){const n=t.codePointAt(e)||0;if(e+=n>65535?2:1,!(n>=126976))return!1;s=!0}return s}async handleImageSelected(){const t=this.fileInput;if(!t||!t.files||0===t.files.length)return;const s=t.files[0];try{const e=await this.resizeImageFile(s,1280,.85),n={id:`local-img-failed-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:e,messageType:"image",timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"},failed:!0};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),t.value=""}catch(t){console.error("Image processing failed",t),this.emit("error",new e("Image processing failed","IMAGE_PROCESS_ERROR",t))}}resizeImageFile(e,t=1280,s=.85){return new Promise((n,i)=>{const a=URL.createObjectURL(e),o=new Image;o.onload=()=>{let{width:e,height:r}=o;const d=Math.min(1,t/Math.max(e,r)),l=document.createElement("canvas");d<1&&(e=Math.round(e*d),r=Math.round(r*d)),l.width=e,l.height=r;const h=l.getContext("2d");if(!h)return URL.revokeObjectURL(a),void i(new Error("Canvas not supported"));h.drawImage(o,0,0,e,r);const c=l.toDataURL("image/jpeg",s);URL.revokeObjectURL(a),n(c)},o.onerror=e=>{URL.revokeObjectURL(a),i(e)},o.src=a})}handleInputChange(){const e=this.inputElement.value.trim().length>0,t=!1!==this.config.enableUserInput&&!1!==this.config.allowInput;this.sendButton.disabled=!e||!t,e&&t&&this.emit("typing")}handleKeyDown(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),this.handleSendMessage())}async handleSendMessage(){const t=this.inputElement.value.trim();if(!t)return;if(!1===this.config.enableUserInput||!1===this.config.allowInput)return;const s=this.isEmojiOnly(t)?"emoji":"text",n={id:`local-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:t,messageType:s,timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"}};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),this.inputElement.value="",this.sendButton.disabled=!0,this.autoResizeTextarea(),this.simulator.sendMessage(t,s).catch(t=>{console.error("Failed to send message:",t),this.emit("error",new e("Failed to send message","SEND_MESSAGE_ERROR",t))})}autoResizeTextarea(){this.inputElement.style.height="auto",this.inputElement.style.height=Math.min(this.inputElement.scrollHeight,100)+"px"}open(){var e;if(this.state.isOpen)return;if(this.hasInitializedData)try{this.simulator.startPolling()}catch(e){}else this.hasInitializedData=!0,this.setLoading(!0),this.initializeSimulation().catch(e=>{console.error("Failed to initialize simulation on open:",e),this.setLoading(!1)});this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null),this.floatingButtonEl&&(this.floatingButtonEl.style.display="none"),this.widgetElement.style.opacity="0",this.widgetElement.style.display="flex",requestAnimationFrame(()=>{this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="1"}),this.state.isOpen=!0,this.markAllAsRead(),this.emit("open");const t=(null===(e=this.state.currentProject)||void 0===e?void 0:e.name)||"Chat";this.setTitle(t,`${this.state.displayedMessageCount} ${this.t.messages}`),this.scrollToBottom(!0),requestAnimationFrame(()=>this.scrollToBottom(!0)),setTimeout(()=>this.scrollToBottom(!0),0)}close(){this.state.isOpen&&(this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="0",setTimeout(()=>{this.widgetElement.style.display="none",this.floatingButtonEl&&(this.floatingButtonEl.style.display="flex")},200),this.state.isOpen=!1,this.pollingStopTimer&&clearTimeout(this.pollingStopTimer),this.pollingStopTimer=setTimeout(()=>{try{this.simulator.stopPolling()}catch(e){}this.pollingStopTimer=null},1e4),this.emit("close"))}setTitle(e,t){var s,n;const i=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector("#chat-title"),a=null===(n=this.widgetElement)||void 0===n?void 0:n.querySelector("#chat-subtitle"),o=l(this.t.chatGroup,{name:e||"Chat"});this.currentTheme,i&&(i.textContent=o),a&&(a.textContent=l(this.t.online,{count:this.onlineCount}),a.style.display="block")}buildMessageElement(e,t){const n=s("div","chat-sdk-message");e.isOwnMessage&&n.classList.add("own");const i=!!t&&this.shouldGroupWithPrev(t,e);i&&n.classList.add("grouped");let a=null;e.isOwnMessage||(a=this.createAvatar(e),i&&a&&(a.style.visibility="hidden"));const o=!e.isOwnMessage&&!i,r="whatsapp"===this.currentTheme,d="telegram"===this.currentTheme&&e.isOwnMessage,l=this.createMessageContent(e,o,r,d);return a&&n.appendChild(a),n.appendChild(l),n}shouldGroupWithPrev(e,t){var s,n,i,a,o,r,d;if(!1===this.config.groupMessages)return!1;const l=null!==(s=this.config.groupTimeThresholdSec)&&void 0!==s?s:120,h=e.isOwnMessage===t.isOwnMessage,c=(null===(n=e.virtualUser)||void 0===n?void 0:n.id)&&(null===(i=e.virtualUser)||void 0===i?void 0:i.id)===(null===(a=t.virtualUser)||void 0===a?void 0:a.id),g=(null===(o=e.user)||void 0===o?void 0:o.id)&&(null===(r=e.user)||void 0===r?void 0:r.id)===(null===(d=t.user)||void 0===d?void 0:d.id),m=h&&(c||g||e.isOwnMessage&&t.isOwnMessage),u=Math.abs(t.timestamp.getTime()-e.timestamp.getTime())/1e3;return!!m&&u<=l}handleScrollLazyLoad(){if(this.messagesContainer.scrollTop<=20&&this.visibleStartIndex>0){const e=this.messagesContainer.scrollHeight,t=this.lazyLoadBatchSize,s=Math.max(0,this.visibleStartIndex-t),n=this.state.messages.slice(s,this.visibleStartIndex),i=document.createDocumentFragment();for(const e of n){const t=this.buildMessageElement(e);i.appendChild(t)}this.messagesContainer.insertBefore(i,this.messagesContainer.firstChild),this.visibleStartIndex=s;const a=this.messagesContainer.scrollHeight;this.messagesContainer.scrollTop+=a-e}}setLoading(e){if(e){if(!this.messagesContainer.querySelector(".chat-sdk-loading")){const e=document.createElement("div");e.className="chat-sdk-loading",e.innerHTML='\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n ',this.messagesContainer.appendChild(e)}}else{const e=this.messagesContainer.querySelector(".chat-sdk-loading");null==e||e.remove()}}showJoinOverlay(){const e=s("div","chat-sdk-overlay");e.innerHTML='\n <div class="chat-sdk-join-card">\n <h3 class="chat-sdk-join-title">Join the conversation</h3>\n <p class="chat-sdk-join-description">\n Click below to join this group chat and start interacting with other members.\n </p>\n <button class="chat-sdk-join-btn" type="button">Join Chat</button>\n </div>\n ';const t=e.querySelector(".chat-sdk-join-btn");null==t||t.addEventListener("click",()=>{this.hideJoinOverlay(),this.emit("join-requested")}),this.widgetElement.appendChild(e)}hideJoinOverlay(){const e=this.widgetElement.querySelector(".chat-sdk-overlay");e&&e.remove()}addMessage(e){if(e.isOwnMessage)for(let t=this.state.messages.length-1;t>=0;t--){const s=this.state.messages[t];if(s.isOwnMessage&&s.content===e.content){if(Math.abs(e.timestamp.getTime()-s.timestamp.getTime())<=1e4)return;break}}this.state.messages.find(t=>t.id===e.id)?console.warn("Duplicate message detected and ignored:",e.id):(this.state.messages.push(e),this.renderMessage(e),e.isOwnMessage||this.incrementUnreadCount(),this.scrollToBottom(!0))}addMessagesBulk(e){if(!e||0===e.length)return;if(0===this.messagesContainer.querySelectorAll(".chat-sdk-message").length){this.state.messages=[...e].sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=this.state.messages.length,s=this.initialRenderCount;this.visibleStartIndex=Math.max(0,t-s);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),setTimeout(()=>{this.scrollToBottom(!0)},0)}else{const t=new Set(this.state.messages.map(e=>e.id)),s=e.filter(e=>!t.has(e.id));if(s.length>0){this.state.messages.push(...s),this.state.messages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=this.initialRenderCount;this.visibleStartIndex=Math.max(0,e-t);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),this.scrollToBottom()}}}reRenderAllMessages(){this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=Math.max(0,e-this.initialRenderCount);this.state.messages.slice(t).forEach(e=>{this.renderMessage(e)}),this.scrollToBottom()}renderMessage(e){const t=this.state.messages.length-1,s=t>0?this.state.messages[t-1]:void 0,n=this.buildMessageElement(e,s);this.messagesContainer.appendChild(n)}createAvatar(e){var t,n,i,a;const o=s("div","chat-sdk-message-avatar");if(null===(t=e.virtualUser)||void 0===t?void 0:t.avatar)o.style.backgroundImage=`url(${e.virtualUser.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else if(null===(n=e.user)||void 0===n?void 0:n.avatar)o.style.backgroundImage=`url(${e.user.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else{const t=(null===(i=e.virtualUser)||void 0===i?void 0:i.username)||(null===(a=e.user)||void 0===a?void 0:a.username)||"U";o.textContent=t.charAt(0).toUpperCase()}return o}createMessageContent(e,t=!0,i=!1,a=!1){var o,r,d;const l=s("div","chat-sdk-message-content"),h=(null===(o=e.virtualUser)||void 0===o?void 0:o.displayName)||(null===(r=e.virtualUser)||void 0===r?void 0:r.username)||(null===(d=e.user)||void 0===d?void 0:d.username)||"Unknown";let c="";if("image"===e.messageType){c=`\n <div class="chat-sdk-message-image${e.failed?" failed":""}">\n <img src="${n(e.content)}" alt="Image"\n style="max-width: 100%; height: auto; cursor: pointer;"\n data-image-url="${n(e.content)}"\n class="chat-sdk-image-preview" />\n </div>\n `}else c="emoji"===e.messageType?`<div class="chat-sdk-message-emoji" style="font-size: 2em; line-height: 1;">${n(e.content)}</div>`:`<p class="chat-sdk-message-text">${n(e.content)}</p>`;const g=`${function(e,t){const s=new Date,n=Math.floor((s.getTime()-e.getTime())/1e3),i=(t||("undefined"!=typeof navigator?navigator.language:"en")).toLowerCase().startsWith("zh");if(n<60)return i?"刚刚":"just now";if(n<3600){const e=Math.floor(n/60);return i?`${e} 分钟前`:`${e}m ago`}if(n<86400){const e=Math.floor(n/3600);return i?`${e} 小时前`:`${e}h ago`}const a=new Date(s.getFullYear(),s.getMonth(),s.getDate());if(e>=new Date(a.getTime()-864e5)&&e<a){const t=e.toLocaleTimeString(i?"zh-CN":void 0,{hour:"2-digit",minute:"2-digit",hour12:!1});return i?`昨天 ${t}`:`yesterday ${t}`}return s.getTime()-e.getTime()<6048e5?e.toLocaleString(i?"zh-CN":void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}):e.toLocaleString(i?"zh-CN":void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1})}(e.timestamp,this.config.language)}`,m=a?'<span class="chat-sdk-read-status">✓✓</span>':"",u=e.failed&&e.isOwnMessage?'<div class="chat-sdk-message-failed-indicator">\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <circle cx="8" cy="8" r="8" fill="#ff4444"/>\n <path d="M8 4v4M8 10h.01" stroke="white" stroke-width="1.5" stroke-linecap="round"/>\n </svg>\n </div>':"";l.innerHTML=i?`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${n(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n <div class="chat-sdk-message-time-inside">${g}${m?" "+m:""}</div>\n </div>\n ${u}\n `:`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${n(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n </div>\n <div class="chat-sdk-message-time">${g}${m?" "+m:""}</div>\n ${u}\n `;const p=l.querySelector(".chat-sdk-image-preview");return p&&p.addEventListener("click",e=>{e.preventDefault();const t=e.target.getAttribute("data-image-url");t&&this.showImagePreview(t)}),l}scrollToBottom(e=!1){const t=this.messagesContainer;if(e)return void i(t);t.scrollTop+t.clientHeight>=t.scrollHeight-40&&i(t)}setupImageViewer(){this.messagesContainer.addEventListener("click",e=>{const t=e.target;if(t.classList.contains("chat-sdk-image-preview")){const e=t.getAttribute("data-image-url");e&&this.openImageViewer(e)}})}openImageViewer(e){const t=s("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-backdrop">\n <div class="chat-sdk-image-container">\n <button class="chat-sdk-image-close" aria-label="Close">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n <img class="chat-sdk-image-full" src="${n(e)}" alt="Full size image" />\n </div>\n </div>\n `,this.shadowRoot.appendChild(t);const i=t.querySelector(".chat-sdk-image-close"),a=t.querySelector(".chat-sdk-image-backdrop"),o=()=>{t.remove()};null==i||i.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r),requestAnimationFrame(()=>{t.classList.add("chat-sdk-image-modal-open")})}showImagePreview(e){const t=s("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-modal-overlay">\n <div class="chat-sdk-image-modal-content">\n <button class="chat-sdk-image-modal-close">&times;</button>\n <img src="${n(e)}" alt="Image Preview" class="chat-sdk-image-modal-img" />\n </div>\n </div>\n `,this.widgetElement.appendChild(t);const i=t.querySelector(".chat-sdk-image-modal-close"),a=t.querySelector(".chat-sdk-image-modal-overlay"),o=()=>{t.remove()};null==i||i.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r)}setJoined(e){this.state.isJoined=e,this.handleInputChange()}setUITemplate(e){this.currentTheme=e,this.config.uiTemplate=e,this.widgetElement.classList.remove("whatsapp-theme","telegram-theme","dark"),this.widgetElement.classList.add(`${e}-theme`),"telegram"===e&&this.isDarkMode&&this.widgetElement.classList.add("dark"),this.updateThemeStyles(),this.reRenderAllMessages()}setTheme(e){this.isDarkMode="dark"===e,this.config.theme=e,"telegram"===this.currentTheme&&(this.isDarkMode?this.widgetElement.classList.add("dark"):this.widgetElement.classList.remove("dark"),this.updateThemeStyles())}setCustomColors(e){this.customColors={...this.customColors,...e},this.config.primaryColor=e.primary,this.config.backgroundColor=e.background,this.updateThemeStyles()}updateThemeStyles(){const e=this.currentTheme,t=this.isDarkMode&&"telegram"===e,s=this.shadowRoot||document.documentElement;"whatsapp"===e?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#25D366"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#ECE5DD"),this.setCSSProperty(s,"--chat-message-own-bg","#DCF8C6"),this.setCSSProperty(s,"--chat-message-other-bg","#FFFFFF"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #075e54 0%, #128c7e 100%)")):"telegram"===e&&(t?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#4FC3F7"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#212121"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#2F2F2F"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #1976d2 0%, #1565c0 100%)"),this.setCSSProperty(s,"--chat-text-color","#FFFFFF")):(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#2481CC"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#FFFFFF"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#F1F1F1"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%)"),this.setCSSProperty(s,"--chat-text-color","#000000")))}setCSSProperty(e,t,s){if(e instanceof ShadowRoot){const n=e.querySelector("style");if(n){const e=n.textContent||"",i=new RegExp(`${t}\\s*:\\s*[^;]+;`,"g"),a=`${t}: ${s};`;if(i.test(e))n.textContent=e.replace(i,a);else{const t=/:host\s*\{([^}]*)\}/;t.test(e)?n.textContent=e.replace(t,(e,t)=>`:host { ${t} ${a} }`):n.textContent=`:host { ${a} }\n${e}`}}}else e.style.setProperty(t,s)}getState(){return{...this.state}}getDefaultStyles(){return"\n :host {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #333333;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: var(--chat-text-color);\n background: var(--chat-background-color);\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n position: relative;\n max-width: 100%;\n max-height: 100%;\n }\n\n .chat-sdk-container * {\n box-sizing: border-box;\n }\n\n /* WhatsApp Theme */\n .chat-sdk-container.whatsapp-theme .chat-sdk-header {\n background: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-header-left { display: none; }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-messages {\n background-color: #ece5dd;\n background-image: url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23e5ddd5' fill-opacity='0.08'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\");\n }\n\n .chat-sdk-container.whatsapp-theme {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #303030;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* WhatsApp input + details */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-content {\n max-width: 70%;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input-area {\n background: #f0f2f5;\n border-top: none;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input {\n background: #fff;\n border: none;\n border-radius: 22px;\n padding: 10px 14px;\n box-shadow: inset 0 1px 0 rgba(0,0,0,0.02);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-send-btn {\n background: #25D366;\n box-shadow: 0 2px 4px rgba(0,0,0,0.12);\n }\n\n\n /* Telegram Theme */\n .chat-sdk-container.telegram-theme {\n --chat-primary-color: #2481CC;\n --chat-background-color: #FFFFFF;\n --chat-message-own-bg: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);\n --chat-message-other-bg: #F1F1F1;\n --chat-header-bg: linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%);\n --chat-text-color: #000000;\n --chat-border-radius-message: 12px;\n --chat-border-radius-input: 12px;\n\n /* Telegram input + details */\n .chat-sdk-container.telegram-theme .chat-sdk-message-content {\n max-width: 75%;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input-area {\n background: #ffffff;\n border-top: 1px solid #e6e6e6;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input {\n background: #fff;\n border: 1px solid #cfd6dd;\n border-radius: 12px;\n padding: 9px 14px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-send-btn {\n background: #2481CC;\n border-radius: 10px;\n width: 38px;\n height: 36px;\n box-shadow: none;\n }\n /* Telegram dark */\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input-area {\n background: #1f1f1f;\n border-top: 1px solid #2a2a2a;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input {\n background: #2b2b2b;\n color: #e0e0e0;\n border-color: #444;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-send-btn {\n background: #1976d2;\n }\n\n\n .chat-sdk-container.telegram-theme .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-messages {\n background-color: var(--chat-background-color);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* Telegram Dark Theme */\n .chat-sdk-container.telegram-theme.dark {\n --chat-background-color: #212121;\n --chat-message-other-bg: #2F2F2F;\n --chat-header-bg: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);\n --chat-text-color: #FFFFFF;\n }\n\n /* Default header (fallback) */\n .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n }\n\n .chat-sdk-header-left { display: flex; flex-direction: column; gap: 2px; }\n .chat-sdk-title { font-size: 15px; font-weight: 600; }\n .chat-sdk-subtitle { font-size: 12px; opacity: 0.9; }\n\n .chat-sdk-close-btn {\n background: none;\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n opacity: 0.8;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n }\n\n .chat-sdk-close-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .chat-sdk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n background: var(--chat-background-color);\n min-height: 0; /* allow flex to use full height */\n }\n\n .chat-sdk-message {\n margin-bottom: 12px;\n display: flex;\n align-items: flex-end;\n gap: 8px;\n }\n\n .chat-sdk-message.own {\n flex-direction: row-reverse;\n }\n\n .chat-sdk-message-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: #ddd;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n color: #666;\n flex-shrink: 0;\n }\n\n .chat-sdk-message-content {\n max-width: 70%;\n position: relative;\n }\n\n .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n padding: 8px 12px;\n border-radius: var(--chat-border-radius-message);\n position: relative;\n word-wrap: break-word;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n }\n\n .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n }\n\n .chat-sdk-message-username {\n font-size: 11px;\n color: #666;\n margin-bottom: 2px;\n font-weight: 600;\n }\n\n .chat-sdk-message-text {\n margin: 0;\n line-height: 1.4;\n }\n\n .chat-sdk-message-time {\n font-size: 10px;\n color: #999;\n margin-top: 4px;\n text-align: right;\n }\n\n /* Message grouping */\n .chat-sdk-message.grouped {\n margin-top: 4px;\n }\n .chat-sdk-message.grouped .chat-sdk-message-username { display: none; }\n .chat-sdk-message.grouped .chat-sdk-message-avatar { visibility: hidden; }\n\n /* WhatsApp: time inside bubble */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n position: relative;\n padding-right: 44px;\n padding-bottom: 16px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-time-inside {\n position: absolute;\n right: 8px;\n bottom: 4px;\n font-size: 11px;\n color: rgba(0,0,0,0.55);\n }\n\n /* Telegram: read status */\n .chat-sdk-container.telegram-theme .chat-sdk-message-time {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-read-status {\n font-size: 12px;\n color: var(--chat-primary-color);\n line-height: 1;\n }\n\n /* Theme-specific image radii */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-image img { border-radius: 12px; }\n .chat-sdk-container.telegram-theme .chat-sdk-message-image img { border-radius: 6px; }\n\n\n .chat-sdk-input-area {\n padding: 12px 16px;\n background: white;\n border-top: 1px solid #e0e0e0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n\n .chat-sdk-icon-btn {\n background: transparent;\n border: none;\n width: 32px;\n height: 32px;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #666;\n }\n .chat-sdk-icon-btn:hover { background: rgba(0,0,0,0.06); }\n\n .chat-sdk-emoji-picker {\n position: absolute;\n left: 12px;\n bottom: 64px;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n box-shadow: 0 6px 16px rgba(0,0,0,0.12);\n padding: 6px;\n z-index: 5;\n }\n .chat-sdk-emoji-grid {\n display: grid;\n grid-template-columns: repeat(5, 28px);\n gap: 6px;\n }\n\n /* Failed message styles - Telegram style */\n .chat-sdk-message-failed-indicator {\n display: inline-flex;\n align-items: center;\n margin-left: 6px;\n color: #ff4444;\n cursor: pointer;\n }\n .chat-sdk-message-failed-indicator svg {\n width: 16px;\n height: 16px;\n }\n .chat-sdk-message.own .chat-sdk-message-content {\n display: flex;\n align-items: flex-end;\n gap: 6px;\n }\n .chat-sdk-message.own .chat-sdk-message-bubble {\n flex: 1;\n }\n .chat-sdk-emoji-item {\n background: none;\n border: none;\n font-size: 20px;\n line-height: 1;\n cursor: pointer;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n }\n .chat-sdk-emoji-item:hover { background: #f3f4f6; }\n\n\n .chat-sdk-input {\n flex: 1;\n border: 1px solid #ddd;\n border-radius: var(--chat-border-radius-input);\n padding: 8px 16px;\n font-size: 14px;\n outline: none;\n resize: none;\n min-height: 36px;\n max-height: 100px;\n }\n\n .chat-sdk-input:focus {\n border-color: var(--chat-primary-color);\n }\n\n .chat-sdk-send-btn {\n background: var(--chat-primary-color);\n color: white;\n border: none;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n }\n\n .chat-sdk-send-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-send-btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n }\n\n .chat-sdk-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n }\n\n .chat-sdk-join-card {\n background: white;\n border-radius: 12px;\n padding: 24px;\n max-width: 300px;\n margin: 16px;\n text-align: center;\n }\n\n .chat-sdk-join-title {\n font-size: 18px;\n font-weight: 600;\n margin: 0 0 8px 0;\n color: #333;\n }\n\n .chat-sdk-join-description {\n font-size: 14px;\n color: #666;\n margin: 0 0 20px 0;\n line-height: 1.4;\n }\n\n .chat-sdk-join-btn {\n background: #075e54;\n color: white;\n border: none;\n border-radius: 8px;\n padding: 12px 24px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s;\n width: 100%;\n }\n\n .chat-sdk-join-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: #666;\n }\n\n .chat-sdk-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid #e0e0e0;\n border-top: 2px solid #075e54;\n border-radius: 50%;\n animation: chat-sdk-spin 1s linear infinite;\n margin-right: 8px;\n }\n\n @keyframes chat-sdk-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n\n .chat-sdk-container.dark {\n background: #1f1f1f;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-header {\n background: #2d2d2d;\n }\n\n .chat-sdk-container.dark .chat-sdk-messages {\n background: #0d1117;\n }\n\n .chat-sdk-container.dark .chat-sdk-message-bubble {\n background: #2d2d2d;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-message.own .chat-sdk-message-bubble {\n background: #0969da;\n color: white;\n }\n\n /* Image Modal Viewer */\n .chat-sdk-image-modal {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n z-index: 9999;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s ease, visibility 0.2s ease;\n }\n\n .chat-sdk-image-modal-open {\n opacity: 1;\n visibility: visible;\n }\n\n .chat-sdk-image-backdrop {\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0, 0, 0, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n\n .chat-sdk-image-container {\n position: relative;\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-sdk-image-close {\n position: absolute;\n top: -50px;\n right: 0;\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 50%;\n width: 40px;\n height: 40px;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n z-index: 1;\n }\n\n .chat-sdk-image-close:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n\n .chat-sdk-image-full {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 8px;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);\n }\n\n /* Responsive Design */\n @media (max-width: 640px) {\n .chat-sdk-container {\n border-radius: 0;\n height: 100vh;\n max-height: 100vh;\n }\n\n .chat-sdk-message-content {\n max-width: 85%;\n }\n\n .chat-sdk-message-bubble {\n font-size: 14px;\n padding: 8px 12px;\n }\n\n .chat-sdk-input {\n font-size: 16px; /* Prevent zoom on iOS */\n padding: 10px 14px;\n }\n\n .chat-sdk-header {\n padding: 8px 12px;\n min-height: 50px;\n }\n\n .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n font-size: 11px;\n }\n }\n\n @media (min-width: 1024px) {\n .chat-sdk-message-content {\n max-width: 60%;\n }\n\n .chat-sdk-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n transition: all 0.2s ease;\n }\n }\n\n "}startSimulation(){this.simulator.start()}stopSimulation(){this.simulator.stop()}pauseSimulation(){this.simulator.pause()}resumeSimulation(){this.simulator.resume()}async sendMessage(e,t="text"){await this.simulator.sendMessage(e,t)}get isSimulationRunning(){return this.state.isSimulationRunning}get isSimulationPaused(){return this.state.isSimulationPaused}get simulationEnded(){return this.state.simulationEnded}get messageCount(){return this.state.displayedMessageCount}get messages(){return[...this.state.messages]}async reinitializeLanguage(e){this.config.language=e,this.setLoading(!0),this.messagesContainer.innerHTML="",this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.updateUnreadBadge();try{this.simulator.clearCachedProgress()}catch(e){}try{this.simulator.destroy()}catch(e){}this.simulator=new a(this.config,this.apiClient),this.setupSimulatorEvents(),await this.initializeSimulation()}destroy(){this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null);try{this.simulator.destroy()}catch(e){}if(this.shadowRoot)try{for(;this.shadowRoot.firstChild;)this.shadowRoot.removeChild(this.shadowRoot.firstChild)}catch(e){}this.state.isOpen=!1,this.removeAllListeners()}clearMessages(){this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.messagesContainer.innerHTML="",this.updateUnreadBadge()}rerender(){this.reRenderAllMessages()}getMessageCount(){return this.state.displayedMessageCount}isOpen(){return this.state.isOpen}updateLanguageElements(e){var t,s,n;this.t=d(e);const i=null===(t=this.widgetElement)||void 0===t?void 0:t.querySelector("#message-input");i&&(i.placeholder=this.t.inputPlaceholder);const a=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector(".send-button");a&&a.textContent&&(a.textContent=this.t.send);const o=this.getMessageCount(),r=(null===(n=this.state.currentProject)||void 0===n?void 0:n.name)||"Chat";this.setTitle(r,`${o} ${this.t.messages}`)}}const c=h;function g(e){return new h(e)}var m={init:g,ChatSDK:c,ChatSDKError:e};"undefined"!=typeof window&&(window.ChatSDK={init:g,ChatSDK:c,ChatSDKError:e});export{c as ChatSDK,e as ChatSDKError,m as default,g as init};
1
+ class e extends Error{constructor(e,t,s){super(e),this.code=t,this.details=s,this.name="ChatSDKError"}}class t{constructor(){this.events=new Map}on(e,t){this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(t)}off(e,t){if(!this.events.has(e))return;if(!t)return void this.events.delete(e);const s=this.events.get(e),n=s.indexOf(t);n>-1&&s.splice(n,1),0===s.length&&this.events.delete(e)}emit(e,t){if(!this.events.has(e))return;this.events.get(e).forEach(s=>{try{s(t)}catch(t){console.error(`Error in event callback for "${e}":`,t)}})}getEventNames(){return Array.from(this.events.keys())}listenerCount(e){var t;return(null===(t=this.events.get(e))||void 0===t?void 0:t.length)||0}removeAllListeners(){this.events.clear()}}function s(e,t,s){const n=document.createElement(e);return t&&(n.className=t),n}function n(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function i(e,t=!0){e.scrollTop=e.scrollHeight,e.scrollTo&&e.scrollTo({top:e.scrollHeight,behavior:t?"smooth":"auto"})}const a={USD:1,EUR:.92,GBP:.79,JPY:149.5,CNY:7.24,INR:83.12,BRL:4.97,RUB:92.5,KRW:1320,MXN:17.15,CAD:1.38,AUD:1.53,CHF:.88,SEK:10.85,NZD:1.67,SGD:1.34,HKD:7.82,NOK:10.95,TRY:28.5,ZAR:18.65,PLN:4.05,THB:35.2,IDR:15650,MYR:4.68,PHP:56.2,DKK:6.88,CZK:22.85,HUF:355,ILS:3.72,CLP:920,ARS:350,COP:4050,PEN:3.75,EGP:30.9,SAR:3.75,AED:3.67,VND:24500,PKR:278,BDT:110,NGN:775,UAH:36.5,RON:4.58,TWD:31.5,QAR:3.64,KWD:.31,OMR:.38,BHD:.38},o={USD:"$",EUR:"€",GBP:"£",JPY:"¥",CNY:"¥",INR:"₹",BRL:"R$",RUB:"₽",KRW:"₩",MXN:"$",CAD:"C$",AUD:"A$",CHF:"CHF",SEK:"kr",NZD:"NZ$",SGD:"S$",HKD:"HK$",NOK:"kr",TRY:"₺",ZAR:"R",PLN:"zł",THB:"฿",IDR:"Rp",MYR:"RM",PHP:"₱",DKK:"kr",CZK:"Kč",HUF:"Ft",ILS:"₪",CLP:"$",ARS:"$",COP:"$",PEN:"S/",EGP:"E£",SAR:"﷼",AED:"د.إ",VND:"₫",PKR:"₨",BDT:"৳",NGN:"₦",UAH:"₴",RON:"lei",TWD:"NT$",QAR:"﷼",KWD:"د.ك",OMR:"﷼",BHD:"د.ب"},r={USD:",",EUR:".",GBP:",",JPY:",",CNY:",",INR:",",BRL:".",RUB:" ",KRW:",",MXN:",",CAD:",",AUD:",",CHF:"'",SEK:" ",PLN:" ",THB:",",IDR:".",MYR:",",PHP:",",DKK:".",CZK:" ",HUF:" "},d={USD:".",EUR:",",GBP:".",JPY:".",CNY:".",INR:".",BRL:",",RUB:",",KRW:".",MXN:".",CAD:".",AUD:".",CHF:".",SEK:",",PLN:",",THB:".",IDR:",",MYR:".",PHP:".",DKK:",",CZK:",",HUF:","},l={US:"USD",CA:"CAD",MX:"MXN",BR:"BRL",AR:"ARS",CL:"CLP",CO:"COP",PE:"PEN",GB:"GBP",DE:"EUR",FR:"EUR",IT:"EUR",ES:"EUR",NL:"EUR",BE:"EUR",AT:"EUR",PT:"EUR",IE:"EUR",GR:"EUR",FI:"EUR",CH:"CHF",NO:"NOK",SE:"SEK",DK:"DKK",PL:"PLN",CZ:"CZK",HU:"HUF",RO:"RON",RU:"RUB",UA:"UAH",TR:"TRY",IL:"ILS",SA:"SAR",AE:"AED",EG:"EGP",CN:"CNY",JP:"JPY",KR:"KRW",IN:"INR",ID:"IDR",TH:"THB",VN:"VND",MY:"MYR",SG:"SGD",PH:"PHP",PK:"PKR",BD:"BDT",HK:"HKD",TW:"TWD",AU:"AUD",NZ:"NZD",ZA:"ZAR",NG:"NGN",KE:"KES",QA:"QAR",KW:"KWD",OM:"OMR",BH:"BHD"},h=new Set(["JPY","KRW","IDR","VND","CLP","PYG","UGX"]);function c(e,t){if(!e||!t)return e;const s=function(e){return l[e.toUpperCase()]||"USD"}(t);return e.replace(/\{\{AMOUNT:(\d+(?:\.\d+)?)\}\}/g,(e,t)=>{const n=parseFloat(t);return isNaN(n)?e:function(e,t){var s,n,i,l;const c=null!==(s=a[t])&&void 0!==s?s:1,g=null!==(n=o[t])&&void 0!==n?n:t+" ",m=null!==(i=r[t])&&void 0!==i?i:",",u=null!==(l=d[t])&&void 0!==l?l:".",p=h.has(t),y=e*c,v=p?Math.round(y):Math.round(100*y)/100,b=Math.floor(v).toString().replace(/\B(?=(\d{3})+(?!\d))/g,m);return p?`${g}${b}`:`${g}${b}${u}${(v%1).toFixed(2).slice(2)}`}(n,s)})}class g extends t{constructor(e,t){super(),this.simulationData=null,this.displayedMessages=[],this.currentMessageIndex=0,this.isRunning=!1,this.isPaused=!1,this.intervalId=null,this.pollingId=null,this.burstPhase=!0,this.totalToShow=1/0,this.virtualLastTimestamp=null,this.realLastTimestamp=null,this.lastTimestamp=null,this.lastDelayMs=0,this.userId="",this.config=e,this.apiClient=t,this.pollingIntervalMs="number"==typeof e.pollingInterval&&e.pollingInterval>0?e.pollingInterval:6e3}async initialize(){try{const e=this.config.language||"en",t=(this.config.country||"").toUpperCase()||void 0,s=this.getPersistedUserId(),n=s||this.config.userId||this.generateUserId();this.userId=n,s||this.persistUserId(n);const i=await this.apiClient.getSimulationData(this.config.projectId,n,e,t);if(!i.success||!i.data)throw new Error("Failed to load simulation data");this.simulationData=i.data;const a=this.simulationData.project.initialBurstCount+this.simulationData.project.continuousCount;this.totalToShow=Math.min(a,this.simulationData.messages.length);const o=this.loadProgress();o&&"number"==typeof o.index?(this.currentMessageIndex=o.index,o.lastTimestamp&&(this.virtualLastTimestamp=new Date(o.lastTimestamp),this.lastTimestamp=new Date(o.lastTimestamp))):(this.currentMessageIndex=0,this.virtualLastTimestamp=null,this.lastTimestamp=null),this.realLastTimestamp=null,await this.loadExistingMessages(),await this.reconstructVirtualHistoryForDisplay(),this.emit("initialized",this.simulationData),this.startPolling(),!1!==this.config.autoStart&&this.start()}catch(e){throw this.emit("error",e),e}}start(){this.simulationData&&!this.isRunning&&(this.isRunning=!0,this.isPaused=!1,this.burstPhase=!0,this.emit("simulationStart"),this.performInitialBurst(),this.currentMessageIndex<this.totalToShow?(this.burstPhase=!1,this.scheduleNextMessage()):(this.isRunning=!1,this.emit("simulationEnd")))}performInitialBurst(){if(!this.simulationData)return;const{project:e,messages:t}=this.simulationData,s=e.initialBurstCount,n=Math.min(s,this.totalToShow,t.length);if(this.currentMessageIndex>=n)return;if(this.displayedMessages.some(e=>e.id.startsWith("sim-"))&&this.currentMessageIndex>0)return;const i=new Date,a=new Array(n);let o=new Date(i);for(let e=n-1;e>=0;e--)if(a[e]=new Date(o),e>0){const e=10+Math.floor(11*Math.random());o=new Date(o.getTime()-60*e*1e3)}const r=[],d=(this.config.country||"US").toUpperCase();let l=!1;for(let e=this.currentMessageIndex;e<n;e++){const s=t[e],n=c(s.content,d);if(s.hasScreenshot&&s.screenshotUrl){const t={id:`sim-${e}-text-${Date.now()}`,content:n,messageType:"text",timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t);const i=new Date(a[e].getTime()+2e3),o={id:`sim-${e}-image-${Date.now()}`,content:s.screenshotUrl,messageType:"image",timestamp:i,isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(o),r.push(o)}else{const t={id:`sim-${e}-${Date.now()}`,content:n,messageType:s.messageType,timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t)}this.currentMessageIndex=e+1,l=!0}l&&(this.lastTimestamp=a[n-1],this.virtualLastTimestamp=this.lastTimestamp,this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.emit("messages-batch",r)),this.saveProgress()}pause(){this.isRunning&&(this.isPaused=!0,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationPause"))}resume(){this.isRunning&&this.isPaused&&(this.isPaused=!1,this.scheduleNextMessage(),this.emit("simulationResume"))}stop(){this.isRunning=!1,this.isPaused=!1,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationStop")}destroy(){this.stop(),this.stopPolling(),this.removeAllListeners()}scheduleNextMessage(){if(!this.simulationData||!this.isRunning||this.isPaused)return;const{project:e,messages:t}=this.simulationData;if(this.currentMessageIndex>=this.totalToShow)return this.isRunning=!1,void this.emit("simulationEnd");let s;if(this.burstPhase){const n=Math.min(e.initialBurstCount,t.length);this.currentMessageIndex<n?s=500+1e3*Math.random():(this.burstPhase=!1,s=this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax))}else{const n=Math.min(e.initialBurstCount,t.length);s=this.currentMessageIndex-n<5?1e3*(e.initialMessageInterval||10):this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax)}this.lastDelayMs=s,this.intervalId=setTimeout(()=>{this.displayNextMessage(),this.scheduleNextMessage()},s)}displayNextMessage(){if(!this.simulationData||this.currentMessageIndex>=this.simulationData.messages.length)return;const e=this.simulationData.messages[this.currentMessageIndex],t=(this.config.country||"US").toUpperCase(),s=c(e.content,t),n=this.lastTimestamp||new Date,i=new Date(n.getTime()+(this.lastDelayMs||0));if(this.lastTimestamp=i,e.hasScreenshot&&e.screenshotUrl){const t={id:`sim-${this.currentMessageIndex}-text-${Date.now()}`,content:s,messageType:"text",timestamp:i,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t);const n=new Date(i.getTime()+2e3),a={id:`sim-${this.currentMessageIndex}-image-${Date.now()}`,content:e.screenshotUrl,messageType:"image",timestamp:n,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(a),this.lastTimestamp=n,setTimeout(()=>{this.emit("message",a)},2e3)}else{const t={id:`sim-${this.currentMessageIndex}-${Date.now()}`,content:s,messageType:e.messageType,timestamp:i,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t)}this.currentMessageIndex++,this.saveProgress()}async loadExistingMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=await this.apiClient.getSimulationMessages(this.config.projectId,e,void 0,100);if(t.success&&t.messages&&t.messages.length>0){const s=t.messages.sort((e,t)=>new Date(e.createdAt||e.timestamp).getTime()-new Date(t.createdAt||t.timestamp).getTime()),n=new Set(this.displayedMessages.map(e=>e.id));for(const t of s){if(n.has(t.id))continue;const s={id:t.id,content:t.content,messageType:t.messageType,timestamp:new Date(t.createdAt||t.timestamp),isOwnMessage:t.userId===e,virtualUser:t.virtualUser,user:t.userId===e?{id:e,username:this.config.username||"You"}:void 0};this.displayedMessages.push(s)}if(s.length>0){const e=s[s.length-1];this.realLastTimestamp=new Date(e.createdAt||e.timestamp)}this.displayedMessages.length>0&&this.emit("messages-batch",[...this.displayedMessages])}}catch(e){console.warn("Failed to load existing messages:",e)}}startPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null),this.pollingId=setInterval(async()=>{await this.pollForNewMessages()},this.pollingIntervalMs)}stopPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null)}setPollingInterval(e){!e||e<=0||(this.pollingIntervalMs=e,this.pollingId&&this.startPolling())}get isPolling(){return!!this.pollingId}async pollForNewMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=this.getLastMessageTimestamp(),s=await this.apiClient.getSimulationMessages(this.config.projectId,e,t);if(s.success&&s.messages&&s.messages.length>0){const t=new Set(this.displayedMessages.map(e=>e.id));let n=null;for(const i of s.messages){if(t.has(i.id))continue;const s=new Date(i.createdAt),a={id:i.id,content:i.content,messageType:i.messageType,timestamp:s,isOwnMessage:i.userId===e,virtualUser:i.virtualUser,user:i.userId===e?{id:e,username:this.config.username||"You"}:void 0};(!n||s>n)&&(n=s),this.displayedMessages.push(a),this.emit("message",a)}n&&(this.realLastTimestamp=n)}}catch(e){console.warn("Polling error:",e)}}async reconstructVirtualHistoryForDisplay(){if(!this.simulationData)return;const e=Math.min(this.currentMessageIndex,this.totalToShow,this.simulationData.messages.length);if(e<=0)return;const t=this.loadProgress(),s=(null==t?void 0:t.virtualMessages)||[];if(s.length>0){const e=[],t=new Set(this.displayedMessages.map(e=>e.id));for(const n of s)if(!t.has(n.id)){const t={id:n.id,content:n.content,messageType:n.messageType,timestamp:new Date(n.timestamp),isOwnMessage:!1,virtualUser:n.virtualUser};e.push(t)}if(e.length>0){this.displayedMessages.push(...e),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=e[e.length-1];this.virtualLastTimestamp=t.timestamp,this.lastTimestamp=t.timestamp,this.emit("messages-batch",e)}return}const n=new Date,i=new Array(e);let a=new Date(n);for(let t=e-1;t>=0;t--)if(i[t]=new Date(a),t>0){const e=10+Math.floor(11*Math.random());a=new Date(a.getTime()-60*e*1e3)}const o=[],{messages:r}=this.simulationData,d=(this.config.country||"US").toUpperCase();for(let t=0;t<e;t++){const e=r[t],s=i[t],n=c(e.content,d);if(e.hasScreenshot&&e.screenshotUrl){const i={id:`sim-${t}-text`,content:n,messageType:"text",timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser},a={id:`sim-${t}-image`,content:e.screenshotUrl,messageType:"image",timestamp:new Date(s.getTime()+2e3),isOwnMessage:!1,virtualUser:e.virtualUser};o.push(i,a)}else{const i={id:`sim-${t}`,content:n,messageType:e.messageType,timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};o.push(i)}}const l=new Set(this.displayedMessages.map(e=>e.id)),h=o.filter(e=>!l.has(e.id));if(0===h.length)return;this.displayedMessages.push(...h),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const g=h[h.length-1];this.virtualLastTimestamp=g.timestamp,this.lastTimestamp=g.timestamp,this.emit("messages-batch",h)}getLastMessageTimestamp(){if(this.realLastTimestamp)return this.realLastTimestamp.toISOString()}getUserKey(){return`vcs:user:${this.config.projectId}`}getProgressKey(){const e=this.userId||this.config.userId||"anon";return`vcs:progress:${this.config.projectId}:${e}`}getPersistedUserId(){try{return"undefined"==typeof window?null:window.localStorage.getItem(this.getUserKey())}catch(e){return null}}persistUserId(e){try{if("undefined"==typeof window)return;window.localStorage.setItem(this.getUserKey(),e)}catch(e){}}loadProgress(){try{if("undefined"==typeof window)return null;const e=window.localStorage.getItem(this.getProgressKey());return e?JSON.parse(e):null}catch(e){return null}}saveProgress(){try{if("undefined"==typeof window)return;const e=this.displayedMessages.filter(e=>e.id.startsWith("sim-")).map(e=>({id:e.id,content:e.content,messageType:e.messageType,timestamp:e.timestamp.toISOString(),virtualUser:e.virtualUser})),t={index:this.currentMessageIndex,lastTimestamp:this.lastTimestamp?this.lastTimestamp.toISOString():void 0,virtualMessages:e};window.localStorage.setItem(this.getProgressKey(),JSON.stringify(t))}catch(e){}}clearProgress(){try{if("undefined"==typeof window)return;window.localStorage.removeItem(this.getProgressKey())}catch(e){}}clearCachedProgress(){this.clearProgress()}getRandomInterval(e,t){return 1e3*(e+Math.random()*(t-e))}generateUserId(){return`user-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}get messages(){return[...this.displayedMessages]}get isSimulationRunning(){return this.isRunning}get isSimulationPaused(){return this.isPaused}get data(){return this.simulationData}async sendMessage(e,t="text"){if(!this.simulationData)throw new Error("Simulation not initialized");const s=this.userId||this.config.userId||this.generateUserId(),n=this.config.username||"User";try{if("image"===t||"string"==typeof e&&e.startsWith("data:image/"))return;await Promise.all([this.apiClient.sendUserMessage(this.config.projectId,s,n,e,t),this.apiClient.triggerAIReply(this.config.projectId,s,n,e,t)])}catch(e){throw this.emit("error",e),e}}}class m{constructor(e){this.baseUrl=e.apiBaseUrl||window.location.origin,this.token=e.token}async request(t,s={}){const n=`${this.baseUrl}${t}`,i={"Content-Type":"application/json",...s.headers};this.token&&(i.Authorization=`Bearer ${this.token}`);try{const t=await fetch(n,{...s,headers:i,credentials:"include"});if(!t.ok)throw new e(`API request failed: ${t.status} ${t.statusText}`,"API_ERROR",{status:t.status,statusText:t.statusText});const a=await t.json();if(!a.success&&a.error)throw new e(a.error,"API_ERROR",a);return a}catch(t){if(t instanceof e)throw t;throw new e(`Network error: ${t.message}`,"NETWORK_ERROR",t)}}async getProject(e){return this.request(`/api/projects/${e}`)}async getTemplate(e,t,s){const n=new URLSearchParams;t&&n.set("lang",t),s&&n.set("country",s);const i=n.toString()?`?${n.toString()}`:"";return this.request(`/api/templates/${e}${i}`)}async getProjectTemplates(e){return this.request(`/api/projects/${e}/templates`)}async sendMessage(e,t,s,n="text"){return this.request("/api/chat/message",{method:"POST",body:JSON.stringify({projectId:e,userId:t,content:s,messageType:n})})}async joinProject(e,t,s){return this.request("/api/chat/join",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s})})}async leaveProject(e,t){return this.request("/api/chat/leave",{method:"POST",body:JSON.stringify({projectId:e,userId:t})})}async getSimulationData(e,t,s,n){const i=new URLSearchParams({userId:t});return s&&i.append("lang",s),n&&i.append("country",n),this.request(`/api/chat/simulation/${e}?${i.toString()}`)}async getSimulationMessages(e,t,s,n){const i=new URLSearchParams({userId:t});return s&&i.append("since",s),n&&i.append("limit",n.toString()),this.request(`/api/chat/simulation/${e}/messages?${i.toString()}`)}async sendUserMessage(e,t,s,n,i="text"){return this.request("/api/chat/send",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}async triggerAIReply(e,t,s,n,i="text"){return this.request("/api/chat/ai-reply",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}setToken(e){this.token=e}setBaseUrl(e){this.baseUrl=e}}const u={en:{joinChat:"Join Chat",chatGroup:"{name} Group",online:"{count} online",inputPlaceholder:"Type a message...",send:"Send",messages:"messages",today:"Today",yesterday:"Yesterday",networkError:"Network error",sendFailed:"Failed to send"},zh:{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在线",inputPlaceholder:"输入消息...",send:"发送",messages:"条消息",today:"今天",yesterday:"昨天",networkError:"网络错误",sendFailed:"发送失败"},"zh-TW":{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在線",inputPlaceholder:"輸入訊息...",send:"發送",messages:"條訊息",today:"今天",yesterday:"昨天",networkError:"網路錯誤",sendFailed:"發送失敗"},es:{joinChat:"Unirse al Chat",chatGroup:"Grupo {name}",online:"{count} en línea",inputPlaceholder:"Escribe un mensaje...",send:"Enviar",messages:"mensajes",today:"Hoy",yesterday:"Ayer",networkError:"Error de red",sendFailed:"Error al enviar"},hi:{joinChat:"चैट में शामिल हों",chatGroup:"{name} समूह",online:"{count} ऑनलाइन",inputPlaceholder:"संदेश लिखें...",send:"भेजें",messages:"संदेश",today:"आज",yesterday:"कल",networkError:"नेटवर्क त्रुटि",sendFailed:"भेजने में विफल"},ar:{joinChat:"انضم للدردشة",chatGroup:"مجموعة {name}",online:"{count} متصل",inputPlaceholder:"اكتب رسالة...",send:"إرسال",messages:"رسائل",today:"اليوم",yesterday:"أمس",networkError:"خطأ في الشبكة",sendFailed:"فشل الإرسال"},pt:{joinChat:"Entrar no Chat",chatGroup:"Grupo {name}",online:"{count} online",inputPlaceholder:"Digite uma mensagem...",send:"Enviar",messages:"mensagens",today:"Hoje",yesterday:"Ontem",networkError:"Erro de rede",sendFailed:"Falha ao enviar"},bn:{joinChat:"চ্যাটে যোগ দিন",chatGroup:"{name} গ্রুপ",online:"{count} অনলাইন",inputPlaceholder:"একটি বার্তা লিখুন...",send:"পাঠান",messages:"বার্তা",today:"আজ",yesterday:"গতকাল",networkError:"নেটওয়ার্ক ত্রুটি",sendFailed:"পাঠাতে ব্যর্থ"},ru:{joinChat:"Присоединиться",chatGroup:"Группа {name}",online:"{count} онлайн",inputPlaceholder:"Введите сообщение...",send:"Отправить",messages:"сообщений",today:"Сегодня",yesterday:"Вчера",networkError:"Ошибка сети",sendFailed:"Не удалось отправить"},ja:{joinChat:"チャットに参加",chatGroup:"{name}グループ",online:"{count} オンライン",inputPlaceholder:"メッセージを入力...",send:"送信",messages:"メッセージ",today:"今日",yesterday:"昨日",networkError:"ネットワークエラー",sendFailed:"送信失敗"},de:{joinChat:"Chat beitreten",chatGroup:"{name} Gruppe",online:"{count} online",inputPlaceholder:"Nachricht eingeben...",send:"Senden",messages:"Nachrichten",today:"Heute",yesterday:"Gestern",networkError:"Netzwerkfehler",sendFailed:"Senden fehlgeschlagen"},fr:{joinChat:"Rejoindre le Chat",chatGroup:"Groupe {name}",online:"{count} en ligne",inputPlaceholder:"Tapez un message...",send:"Envoyer",messages:"messages",today:"Aujourd'hui",yesterday:"Hier",networkError:"Erreur réseau",sendFailed:"Échec de l'envoi"},ko:{joinChat:"채팅 참여",chatGroup:"{name} 그룹",online:"{count} 온라인",inputPlaceholder:"메시지 입력...",send:"전송",messages:"메시지",today:"오늘",yesterday:"어제",networkError:"네트워크 오류",sendFailed:"전송 실패"},it:{joinChat:"Unisciti alla Chat",chatGroup:"Gruppo {name}",online:"{count} online",inputPlaceholder:"Scrivi un messaggio...",send:"Invia",messages:"messaggi",today:"Oggi",yesterday:"Ieri",networkError:"Errore di rete",sendFailed:"Invio fallito"},tr:{joinChat:"Sohbete Katıl",chatGroup:"{name} Grubu",online:"{count} çevrimiçi",inputPlaceholder:"Bir mesaj yazın...",send:"Gönder",messages:"mesaj",today:"Bugün",yesterday:"Dün",networkError:"Ağ hatası",sendFailed:"Gönderilemedi"},vi:{joinChat:"Tham gia Chat",chatGroup:"Nhóm {name}",online:"{count} trực tuyến",inputPlaceholder:"Nhập tin nhắn...",send:"Gửi",messages:"tin nhắn",today:"Hôm nay",yesterday:"Hôm qua",networkError:"Lỗi mạng",sendFailed:"Gửi thất bại"},pl:{joinChat:"Dołącz do Czatu",chatGroup:"Grupa {name}",online:"{count} online",inputPlaceholder:"Wpisz wiadomość...",send:"Wyślij",messages:"wiadomości",today:"Dziś",yesterday:"Wczoraj",networkError:"Błąd sieci",sendFailed:"Nie udało się wysłać"},th:{joinChat:"เข้าร่วมแชท",chatGroup:"กลุ่ม {name}",online:"{count} ออนไลน์",inputPlaceholder:"พิมพ์ข้อความ...",send:"ส่ง",messages:"ข้อความ",today:"วันนี้",yesterday:"เมื่อวาน",networkError:"ข้อผิดพลาดเครือข่าย",sendFailed:"ส่งไม่สำเร็จ"},nl:{joinChat:"Deelnemen aan Chat",chatGroup:"{name} Groep",online:"{count} online",inputPlaceholder:"Typ een bericht...",send:"Verzenden",messages:"berichten",today:"Vandaag",yesterday:"Gisteren",networkError:"Netwerkfout",sendFailed:"Verzenden mislukt"},id:{joinChat:"Gabung Chat",chatGroup:"Grup {name}",online:"{count} online",inputPlaceholder:"Ketik pesan...",send:"Kirim",messages:"pesan",today:"Hari ini",yesterday:"Kemarin",networkError:"Kesalahan jaringan",sendFailed:"Gagal mengirim"},ms:{joinChat:"Sertai Chat",chatGroup:"Kumpulan {name}",online:"{count} dalam talian",inputPlaceholder:"Taip mesej...",send:"Hantar",messages:"mesej",today:"Hari ini",yesterday:"Semalam",networkError:"Ralat rangkaian",sendFailed:"Gagal menghantar"}};function p(e){if(u[e])return u[e];const t=e.split("-")[0];return u[t]?u[t]:u.en}function y(e,t){return e.replace(/\{(\w+)\}/g,(e,s)=>void 0!==t[s]?String(t[s]):e)}class v extends t{constructor(e){var t,s;super(),this.emojiPanelOpen=!1,this.onlineCount=0,this.currentTheme="whatsapp",this.isDarkMode=!1,this.customColors={},this.visibleStartIndex=0,this.hasInitializedData=!1,this.pollingStopTimer=null,this.config={...e,mode:e.mode||"floating"},this.t=p(e.language||"en"),this.currentTheme="telegram"===e.uiTemplate?"telegram":"whatsapp",this.isDarkMode="dark"===e.theme,this.customColors={primary:e.primaryColor,background:e.backgroundColor},this.onlineCount=500+Math.floor(301*Math.random()),this.initialRenderCount=null!==(t=this.config.initialRenderCount)&&void 0!==t?t:Number.MAX_SAFE_INTEGER,this.lazyLoadBatchSize=null!==(s=this.config.lazyLoadBatchSize)&&void 0!==s?s:20,this.state={isInitialized:!1,isOpen:!1,isJoined:!1,isConnected:!1,isSimulationRunning:!1,isSimulationPaused:!1,messages:[],virtualUsers:[],realUsers:[],typingUsers:[],simulationEnded:!1,displayedMessageCount:0,unreadCount:0,lastReadMessageId:null},this.apiClient=new m(e),this.simulator=new g(e,this.apiClient),this.setupSimulatorEvents(),this.init()}init(){try{this.setupContainer(),this.createWidget(),"floating"===this.config.mode&&(this.widgetElement.style.display="none",this.createFloatingButton()),this.setupEventListeners(),this.setupImageViewer(),this.state.isInitialized=!0,this.emit("ready")}catch(t){this.emit("error",new e("Failed to initialize chat widget","WIDGET_INIT_ERROR",t))}}setupSimulatorEvents(){this.simulator.on("initialized",e=>{var t;this.state.currentProject=e.project,this.state.currentTemplate=e.template,null!=this.config.initialRenderCount?this.initialRenderCount=this.config.initialRenderCount:this.initialRenderCount=Number.MAX_SAFE_INTEGER,this.setTitle((null===(t=e.project)||void 0===t?void 0:t.name)||"Chat",`0 ${this.t.messages}`),this.setLoading(!1),this.emit("simulationInitialized",e)}),this.simulator.on("message",e=>{var t;this.setLoading(!1),this.addMessage(e),this.state.displayedMessageCount++;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`)}),this.simulator.on("messages-batch",e=>{var t;this.setLoading(!1),this.addMessagesBulk(e),this.state.displayedMessageCount+=e.length;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`),setTimeout(()=>{this.scrollToBottom(!0)},100)}),this.simulator.on("simulationStart",()=>{var e,t;this.state.isSimulationRunning=!0,this.state.isSimulationPaused=!1,null===(t=(e=this.config).onSimulationStart)||void 0===t||t.call(e)}),this.simulator.on("simulationEnd",()=>{var e,t;this.state.isSimulationRunning=!1,this.state.simulationEnded=!0,null===(t=(e=this.config).onSimulationEnd)||void 0===t||t.call(e)}),this.simulator.on("simulationPause",()=>{this.state.isSimulationPaused=!0}),this.simulator.on("simulationResume",()=>{this.state.isSimulationPaused=!1}),this.simulator.on("error",e=>{this.emit("error",e)})}async initializeSimulation(){try{await this.simulator.initialize()}catch(t){this.emit("error",new e("Failed to initialize simulation","SIMULATION_INIT_ERROR",t))}}setupContainer(){var t;const s=function(e){if("string"==typeof e)return document.querySelector(e)||document.body;return e||document.body}(this.config.container);if(!s)throw new e("Container element not found","CONTAINER_NOT_FOUND");const n=null===(t=s.tagName)||void 0===t?void 0:t.toUpperCase();if("BODY"===n||"HTML"===n){const e=document.createElement("div");e.className="chat-sdk-host",e.style.position="static",e.style.width="0",e.style.height="0",document.body.appendChild(e),this.container=e}else this.container=s;this.shadowRoot=this.container.attachShadow({mode:"closed"});const i=this.getDefaultStyles();!function(e,t){const s=document.createElement("style");s.textContent=t,e.appendChild(s)}(this.shadowRoot,i)}createWidget(){var e;if(this.widgetElement&&this.messagesContainer)return;this.widgetElement=s("div","chat-sdk-container");const t="telegram"===this.config.uiTemplate?"telegram":"whatsapp";this.currentTheme=t,this.widgetElement.classList.add(`${t}-theme`),"telegram"===t&&"dark"===this.config.theme&&(this.widgetElement.classList.add("dark"),this.isDarkMode=!0),this.widgetElement.style.position="fixed",this.widgetElement.style.top="0",this.widgetElement.style.left="0",this.widgetElement.style.width="100vw",this.widgetElement.style.height="100vh",this.widgetElement.style.zIndex=String(null!==(e=this.config.zIndex)&&void 0!==e?e:2147483e3),this.widgetElement.innerHTML=`\n <div class="chat-sdk-header">\n <div class="chat-sdk-header-left">\n <div class="chat-sdk-title" id="chat-title"></div>\n <div class="chat-sdk-subtitle" id="chat-subtitle"></div>\n </div>\n <button class="chat-sdk-close-btn" type="button">\n <svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor">\n <path d="M8 7.293l2.146-2.147a.5.5 0 01.708.708L8.707 8l2.147 2.146a.5.5 0 01-.708.708L8 8.707l-2.146 2.147a.5.5 0 01-.708-.708L7.293 8 5.146 5.854a.5.5 0 01.708-.708L8 7.293z"/>\n </svg>\n </button>\n </div>\n\n <div class="chat-sdk-messages" id="messages-container">\n <div class="chat-sdk-loading">\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n </div>\n </div>\n\n <div class="chat-sdk-input-area">\n <button class="chat-sdk-icon-btn chat-sdk-emoji-btn" type="button" id="emoji-button" aria-label="Emoji">\n <span>😊</span>\n </button>\n <button class="chat-sdk-icon-btn chat-sdk-image-btn" type="button" id="image-button" aria-label="Image">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14h18zM5 5h14v8l-3-3-4 5-3-4-4 4V5z"/></svg>\n </button>\n <textarea\n class="chat-sdk-input"\n placeholder="${this.t.inputPlaceholder}"\n rows="1"\n id="message-input"\n ></textarea>\n <input type="file" accept="image/*" id="image-input" style="display:none" />\n <button class="chat-sdk-send-btn" type="button" id="send-button" disabled>\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <path d="M15.854.146a.5.5 0 01.11.54l-5.819 14.547a.75.75 0 01-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 01.124-1.33L15.314.037a.5.5 0 01.54.11z"/>\n </svg>\n </button>\n </div>\n <div class="chat-sdk-emoji-picker" id="emoji-picker" style="display:none">\n <div class="chat-sdk-emoji-grid">\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😀">😀</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😁">😁</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😂">😂</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤣">🤣</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😊">😊</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😍">😍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😎">😎</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤔">🤔</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="👍">👍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🙏">🙏</button>\n </div>\n </div>\n `,this.messagesContainer=this.widgetElement.querySelector("#messages-container"),this.inputElement=this.widgetElement.querySelector("#message-input"),this.sendButton=this.widgetElement.querySelector("#send-button"),this.emojiButton=this.widgetElement.querySelector("#emoji-button"),this.imageButton=this.widgetElement.querySelector("#image-button"),this.fileInput=this.widgetElement.querySelector("#image-input"),this.emojiPicker=this.widgetElement.querySelector("#emoji-picker"),this.shadowRoot.appendChild(this.widgetElement)}setupEventListeners(){var e,t,s,n;const i=this.widgetElement.querySelector(".chat-sdk-close-btn");null==i||i.addEventListener("click",()=>this.close()),this.messagesContainer.addEventListener("scroll",this.handleScrollLazyLoad.bind(this)),this.inputElement.addEventListener("input",this.handleInputChange.bind(this)),this.inputElement.addEventListener("keydown",this.handleKeyDown.bind(this)),this.sendButton.addEventListener("click",this.handleSendMessage.bind(this)),this.inputElement.addEventListener("input",this.autoResizeTextarea.bind(this)),null===(e=this.emojiButton)||void 0===e||e.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.toggleEmojiPicker(!this.emojiPanelOpen)}),null===(t=this.emojiPicker)||void 0===t||t.addEventListener("click",e=>{const t=e.target.closest(".chat-sdk-emoji-item");if(t&&t.hasAttribute("data-emoji")){const e=t.getAttribute("data-emoji")||"";this.insertEmojiAtCursor(e),this.toggleEmojiPicker(!1)}}),this.shadowRoot.addEventListener("click",e=>{const t=e.target,s=t.closest("#emoji-picker"),n=t.closest("#emoji-button");s||n||this.toggleEmojiPicker(!1)}),null===(s=this.imageButton)||void 0===s||s.addEventListener("click",e=>{var t;e.preventDefault(),e.stopPropagation(),null===(t=this.fileInput)||void 0===t||t.click()}),null===(n=this.fileInput)||void 0===n||n.addEventListener("change",this.handleImageSelected.bind(this)),document.addEventListener("keydown",e=>{"Escape"===e.key&&this.state.isOpen&&this.close()})}createFloatingButton(){var e,t,s,n,i,a,o,r,d,l,h;if(!this.shadowRoot)return;const c=this.config.floatingButton||{},g=c.position||"bottom-right",m=String(null!==(t=null!==(e=c.zIndex)&&void 0!==e?e:this.config.zIndex)&&void 0!==t?t:2147483e3),u={top:null===(s=c.offset)||void 0===s?void 0:s.top,right:null===(n=c.offset)||void 0===n?void 0:n.right,bottom:null!==(a=null===(i=c.offset)||void 0===i?void 0:i.bottom)&&void 0!==a?a:20,left:null===(o=c.offset)||void 0===o?void 0:o.left},p=document.createElement("button");p.className="chat-sdk-floating-btn",p.setAttribute("aria-label","Open chat");const y=this.t.joinChat;p.innerHTML=`\n <div style="\n position: relative;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 6px;\n ">\n \x3c!-- Group chat icon (users) --\x3e\n <svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" style="margin-bottom: 2px;">\n <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/>\n </svg>\n\n \x3c!-- Text overlay at bottom --\x3e\n <div style="\n font-size: 10px;\n font-weight: 600;\n color: rgba(255, 255, 255, 0.95);\n text-align: center;\n line-height: 1.2;\n letter-spacing: 0.3px;\n text-shadow: 0 1px 2px rgba(0,0,0,0.2);\n ">${y}</div>\n\n \x3c!-- Unread badge --\x3e\n <span class="chat-sdk-unread-badge" style="\n position: absolute;\n top: -6px;\n right: -6px;\n background: #ff4444;\n color: white;\n border-radius: 10px;\n min-width: 18px;\n height: 18px;\n display: none;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n padding: 0 5px;\n "></span>\n </div>\n `,p.style.position="fixed",p.style.zIndex=m,p.style.width="60px",p.style.height="60px",p.style.borderRadius="50%",p.style.border="none",p.style.cursor="pointer",p.style.display="flex",p.style.alignItems="center",p.style.justifyContent="center",p.style.color="#fff",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)",p.style.background="linear-gradient(145deg, #25D366 0%, #128C7E 100%)",p.style.transition="transform .15s ease, box-shadow .15s ease",p.style.overflow="visible",g.includes("bottom")?(p.style.bottom=(null!==(r=u.bottom)&&void 0!==r?r:20)+"px",p.style.top=""):(p.style.top=(null!==(d=u.top)&&void 0!==d?d:20)+"px",p.style.bottom=""),g.includes("right")?(p.style.right=(null!==(l=u.right)&&void 0!==l?l:20)+"px",p.style.left=""):(p.style.left=(null!==(h=u.left)&&void 0!==h?h:20)+"px",p.style.right=""),p.addEventListener("mouseenter",()=>{p.style.transform="scale(1.06)",p.style.boxShadow="0 14px 28px rgba(0,0,0,0.30), inset 0 2px 4px rgba(255,255,255,0.2)"}),p.addEventListener("mouseleave",()=>{p.style.transform="scale(1)",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)"}),p.addEventListener("mousedown",()=>{p.style.transform="scale(0.95)"}),p.addEventListener("mouseup",()=>{p.style.transform="scale(1.05)",setTimeout(()=>p.style.transform="scale(1)",100)}),p.addEventListener("click",e=>{e.preventDefault(),this.open()}),this.shadowRoot.appendChild(p),this.floatingButtonEl=p}updateUnreadBadge(){if(!this.floatingButtonEl)return;const e=this.floatingButtonEl.querySelector(".chat-sdk-unread-badge");if(!e)return;const t=this.state.unreadCount;t>0?(e.textContent=t>99?"99+":t.toString(),e.style.display="flex"):e.style.display="none"}markAllAsRead(){if(this.state.messages.length>0){const e=this.state.messages[this.state.messages.length-1];this.state.lastReadMessageId=e.id}this.state.unreadCount=0,this.updateUnreadBadge()}incrementUnreadCount(){this.state.isOpen||(this.state.unreadCount++,this.updateUnreadBadge())}toggleEmojiPicker(e){const t=this.emojiPicker;if(!t)return;const s="boolean"==typeof e?e:"none"===t.style.display;t.style.display=s?"block":"none",this.emojiPanelOpen=s}insertEmojiAtCursor(e){const t=this.inputElement,s=t.selectionStart||0,n=t.selectionEnd||0,i=t.value.substring(0,s),a=t.value.substring(n);t.value=i+e+a;const o=s+e.length;t.setSelectionRange(o,o),t.focus(),this.handleInputChange(),this.autoResizeTextarea()}isEmojiOnly(e){const t=e.trim();if(!t)return!1;if(t.length>6)return!1;let s=!1;for(let e=0;e<t.length;){const n=t.codePointAt(e)||0;if(e+=n>65535?2:1,!(n>=126976))return!1;s=!0}return s}async handleImageSelected(){const t=this.fileInput;if(!t||!t.files||0===t.files.length)return;const s=t.files[0];try{const e=await this.resizeImageFile(s,1280,.85),n={id:`local-img-failed-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:e,messageType:"image",timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"},failed:!0};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),t.value=""}catch(t){console.error("Image processing failed",t),this.emit("error",new e("Image processing failed","IMAGE_PROCESS_ERROR",t))}}resizeImageFile(e,t=1280,s=.85){return new Promise((n,i)=>{const a=URL.createObjectURL(e),o=new Image;o.onload=()=>{let{width:e,height:r}=o;const d=Math.min(1,t/Math.max(e,r)),l=document.createElement("canvas");d<1&&(e=Math.round(e*d),r=Math.round(r*d)),l.width=e,l.height=r;const h=l.getContext("2d");if(!h)return URL.revokeObjectURL(a),void i(new Error("Canvas not supported"));h.drawImage(o,0,0,e,r);const c=l.toDataURL("image/jpeg",s);URL.revokeObjectURL(a),n(c)},o.onerror=e=>{URL.revokeObjectURL(a),i(e)},o.src=a})}handleInputChange(){const e=this.inputElement.value.trim().length>0,t=!1!==this.config.enableUserInput&&!1!==this.config.allowInput;this.sendButton.disabled=!e||!t,e&&t&&this.emit("typing")}handleKeyDown(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),this.handleSendMessage())}async handleSendMessage(){const t=this.inputElement.value.trim();if(!t)return;if(!1===this.config.enableUserInput||!1===this.config.allowInput)return;const s=this.isEmojiOnly(t)?"emoji":"text",n={id:`local-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:t,messageType:s,timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"}};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),this.inputElement.value="",this.sendButton.disabled=!0,this.autoResizeTextarea(),this.simulator.sendMessage(t,s).catch(t=>{console.error("Failed to send message:",t),this.emit("error",new e("Failed to send message","SEND_MESSAGE_ERROR",t))})}autoResizeTextarea(){this.inputElement.style.height="auto",this.inputElement.style.height=Math.min(this.inputElement.scrollHeight,100)+"px"}open(){var e;if(this.state.isOpen)return;if(this.hasInitializedData)try{this.simulator.startPolling()}catch(e){}else this.hasInitializedData=!0,this.setLoading(!0),this.initializeSimulation().catch(e=>{console.error("Failed to initialize simulation on open:",e),this.setLoading(!1)});this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null),this.floatingButtonEl&&(this.floatingButtonEl.style.display="none"),this.widgetElement.style.opacity="0",this.widgetElement.style.display="flex",requestAnimationFrame(()=>{this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="1"}),this.state.isOpen=!0,this.markAllAsRead(),this.emit("open");const t=(null===(e=this.state.currentProject)||void 0===e?void 0:e.name)||"Chat";this.setTitle(t,`${this.state.displayedMessageCount} ${this.t.messages}`),this.scrollToBottom(!0),requestAnimationFrame(()=>this.scrollToBottom(!0)),setTimeout(()=>this.scrollToBottom(!0),0)}close(){this.state.isOpen&&(this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="0",setTimeout(()=>{this.widgetElement.style.display="none",this.floatingButtonEl&&(this.floatingButtonEl.style.display="flex")},200),this.state.isOpen=!1,this.pollingStopTimer&&clearTimeout(this.pollingStopTimer),this.pollingStopTimer=setTimeout(()=>{try{this.simulator.stopPolling()}catch(e){}this.pollingStopTimer=null},1e4),this.emit("close"))}setTitle(e,t){var s,n;const i=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector("#chat-title"),a=null===(n=this.widgetElement)||void 0===n?void 0:n.querySelector("#chat-subtitle"),o=y(this.t.chatGroup,{name:e||"Chat"});this.currentTheme,i&&(i.textContent=o),a&&(a.textContent=y(this.t.online,{count:this.onlineCount}),a.style.display="block")}buildMessageElement(e,t){const n=s("div","chat-sdk-message");e.isOwnMessage&&n.classList.add("own");const i=!!t&&this.shouldGroupWithPrev(t,e);i&&n.classList.add("grouped");let a=null;e.isOwnMessage||(a=this.createAvatar(e),i&&a&&(a.style.visibility="hidden"));const o=!e.isOwnMessage&&!i,r="whatsapp"===this.currentTheme,d="telegram"===this.currentTheme&&e.isOwnMessage,l=this.createMessageContent(e,o,r,d);return a&&n.appendChild(a),n.appendChild(l),n}shouldGroupWithPrev(e,t){var s,n,i,a,o,r,d;if(!1===this.config.groupMessages)return!1;const l=null!==(s=this.config.groupTimeThresholdSec)&&void 0!==s?s:120,h=e.isOwnMessage===t.isOwnMessage,c=(null===(n=e.virtualUser)||void 0===n?void 0:n.id)&&(null===(i=e.virtualUser)||void 0===i?void 0:i.id)===(null===(a=t.virtualUser)||void 0===a?void 0:a.id),g=(null===(o=e.user)||void 0===o?void 0:o.id)&&(null===(r=e.user)||void 0===r?void 0:r.id)===(null===(d=t.user)||void 0===d?void 0:d.id),m=h&&(c||g||e.isOwnMessage&&t.isOwnMessage),u=Math.abs(t.timestamp.getTime()-e.timestamp.getTime())/1e3;return!!m&&u<=l}handleScrollLazyLoad(){if(this.messagesContainer.scrollTop<=20&&this.visibleStartIndex>0){const e=this.messagesContainer.scrollHeight,t=this.lazyLoadBatchSize,s=Math.max(0,this.visibleStartIndex-t),n=this.state.messages.slice(s,this.visibleStartIndex),i=document.createDocumentFragment();for(const e of n){const t=this.buildMessageElement(e);i.appendChild(t)}this.messagesContainer.insertBefore(i,this.messagesContainer.firstChild),this.visibleStartIndex=s;const a=this.messagesContainer.scrollHeight;this.messagesContainer.scrollTop+=a-e}}setLoading(e){if(e){if(!this.messagesContainer.querySelector(".chat-sdk-loading")){const e=document.createElement("div");e.className="chat-sdk-loading",e.innerHTML='\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n ',this.messagesContainer.appendChild(e)}}else{const e=this.messagesContainer.querySelector(".chat-sdk-loading");null==e||e.remove()}}showJoinOverlay(){const e=s("div","chat-sdk-overlay");e.innerHTML='\n <div class="chat-sdk-join-card">\n <h3 class="chat-sdk-join-title">Join the conversation</h3>\n <p class="chat-sdk-join-description">\n Click below to join this group chat and start interacting with other members.\n </p>\n <button class="chat-sdk-join-btn" type="button">Join Chat</button>\n </div>\n ';const t=e.querySelector(".chat-sdk-join-btn");null==t||t.addEventListener("click",()=>{this.hideJoinOverlay(),this.emit("join-requested")}),this.widgetElement.appendChild(e)}hideJoinOverlay(){const e=this.widgetElement.querySelector(".chat-sdk-overlay");e&&e.remove()}addMessage(e){if(e.isOwnMessage)for(let t=this.state.messages.length-1;t>=0;t--){const s=this.state.messages[t];if(s.isOwnMessage&&s.content===e.content){if(Math.abs(e.timestamp.getTime()-s.timestamp.getTime())<=1e4)return;break}}this.state.messages.find(t=>t.id===e.id)?console.warn("Duplicate message detected and ignored:",e.id):(this.state.messages.push(e),this.renderMessage(e),e.isOwnMessage||this.incrementUnreadCount(),this.scrollToBottom(!0))}addMessagesBulk(e){if(!e||0===e.length)return;if(0===this.messagesContainer.querySelectorAll(".chat-sdk-message").length){this.state.messages=[...e].sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=this.state.messages.length,s=this.initialRenderCount;this.visibleStartIndex=Math.max(0,t-s);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),setTimeout(()=>{this.scrollToBottom(!0)},0)}else{const t=new Set(this.state.messages.map(e=>e.id)),s=e.filter(e=>!t.has(e.id));if(s.length>0){this.state.messages.push(...s),this.state.messages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=this.initialRenderCount;this.visibleStartIndex=Math.max(0,e-t);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),this.scrollToBottom()}}}reRenderAllMessages(){this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=Math.max(0,e-this.initialRenderCount);this.state.messages.slice(t).forEach(e=>{this.renderMessage(e)}),this.scrollToBottom()}renderMessage(e){const t=this.state.messages.length-1,s=t>0?this.state.messages[t-1]:void 0,n=this.buildMessageElement(e,s);this.messagesContainer.appendChild(n)}createAvatar(e){var t,n,i,a;const o=s("div","chat-sdk-message-avatar");if(null===(t=e.virtualUser)||void 0===t?void 0:t.avatar)o.style.backgroundImage=`url(${e.virtualUser.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else if(null===(n=e.user)||void 0===n?void 0:n.avatar)o.style.backgroundImage=`url(${e.user.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else{const t=(null===(i=e.virtualUser)||void 0===i?void 0:i.username)||(null===(a=e.user)||void 0===a?void 0:a.username)||"U";o.textContent=t.charAt(0).toUpperCase()}return o}createMessageContent(e,t=!0,i=!1,a=!1){var o,r,d;const l=s("div","chat-sdk-message-content"),h=(null===(o=e.virtualUser)||void 0===o?void 0:o.displayName)||(null===(r=e.virtualUser)||void 0===r?void 0:r.username)||(null===(d=e.user)||void 0===d?void 0:d.username)||"Unknown";let c="";if("image"===e.messageType){c=`\n <div class="chat-sdk-message-image${e.failed?" failed":""}">\n <img src="${n(e.content)}" alt="Image"\n style="max-width: 100%; height: auto; cursor: pointer;"\n data-image-url="${n(e.content)}"\n class="chat-sdk-image-preview" />\n </div>\n `}else c="emoji"===e.messageType?`<div class="chat-sdk-message-emoji" style="font-size: 2em; line-height: 1;">${n(e.content)}</div>`:`<p class="chat-sdk-message-text">${n(e.content)}</p>`;const g=`${function(e,t){const s=new Date,n=Math.floor((s.getTime()-e.getTime())/1e3),i=(t||("undefined"!=typeof navigator?navigator.language:"en")).toLowerCase().startsWith("zh");if(n<60)return i?"刚刚":"just now";if(n<3600){const e=Math.floor(n/60);return i?`${e} 分钟前`:`${e}m ago`}if(n<86400){const e=Math.floor(n/3600);return i?`${e} 小时前`:`${e}h ago`}const a=new Date(s.getFullYear(),s.getMonth(),s.getDate());if(e>=new Date(a.getTime()-864e5)&&e<a){const t=e.toLocaleTimeString(i?"zh-CN":void 0,{hour:"2-digit",minute:"2-digit",hour12:!1});return i?`昨天 ${t}`:`yesterday ${t}`}return s.getTime()-e.getTime()<6048e5?e.toLocaleString(i?"zh-CN":void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}):e.toLocaleString(i?"zh-CN":void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1})}(e.timestamp,this.config.language)}`,m=a?'<span class="chat-sdk-read-status">✓✓</span>':"",u=e.failed&&e.isOwnMessage?'<div class="chat-sdk-message-failed-indicator">\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <circle cx="8" cy="8" r="8" fill="#ff4444"/>\n <path d="M8 4v4M8 10h.01" stroke="white" stroke-width="1.5" stroke-linecap="round"/>\n </svg>\n </div>':"";l.innerHTML=i?`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${n(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n <div class="chat-sdk-message-time-inside">${g}${m?" "+m:""}</div>\n </div>\n ${u}\n `:`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${n(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n </div>\n <div class="chat-sdk-message-time">${g}${m?" "+m:""}</div>\n ${u}\n `;const p=l.querySelector(".chat-sdk-image-preview");return p&&p.addEventListener("click",e=>{e.preventDefault();const t=e.target.getAttribute("data-image-url");t&&this.showImagePreview(t)}),l}scrollToBottom(e=!1){const t=this.messagesContainer;if(e)return void i(t);t.scrollTop+t.clientHeight>=t.scrollHeight-40&&i(t)}setupImageViewer(){this.messagesContainer.addEventListener("click",e=>{const t=e.target;if(t.classList.contains("chat-sdk-image-preview")){const e=t.getAttribute("data-image-url");e&&this.openImageViewer(e)}})}openImageViewer(e){const t=s("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-backdrop">\n <div class="chat-sdk-image-container">\n <button class="chat-sdk-image-close" aria-label="Close">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n <img class="chat-sdk-image-full" src="${n(e)}" alt="Full size image" />\n </div>\n </div>\n `,this.shadowRoot.appendChild(t);const i=t.querySelector(".chat-sdk-image-close"),a=t.querySelector(".chat-sdk-image-backdrop"),o=()=>{t.remove()};null==i||i.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r),requestAnimationFrame(()=>{t.classList.add("chat-sdk-image-modal-open")})}showImagePreview(e){const t=s("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-modal-overlay">\n <div class="chat-sdk-image-modal-content">\n <button class="chat-sdk-image-modal-close">&times;</button>\n <img src="${n(e)}" alt="Image Preview" class="chat-sdk-image-modal-img" />\n </div>\n </div>\n `,this.widgetElement.appendChild(t);const i=t.querySelector(".chat-sdk-image-modal-close"),a=t.querySelector(".chat-sdk-image-modal-overlay"),o=()=>{t.remove()};null==i||i.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r)}setJoined(e){this.state.isJoined=e,this.handleInputChange()}setUITemplate(e){this.currentTheme=e,this.config.uiTemplate=e,this.widgetElement.classList.remove("whatsapp-theme","telegram-theme","dark"),this.widgetElement.classList.add(`${e}-theme`),"telegram"===e&&this.isDarkMode&&this.widgetElement.classList.add("dark"),this.updateThemeStyles(),this.reRenderAllMessages()}setTheme(e){this.isDarkMode="dark"===e,this.config.theme=e,"telegram"===this.currentTheme&&(this.isDarkMode?this.widgetElement.classList.add("dark"):this.widgetElement.classList.remove("dark"),this.updateThemeStyles())}setCustomColors(e){this.customColors={...this.customColors,...e},this.config.primaryColor=e.primary,this.config.backgroundColor=e.background,this.updateThemeStyles()}updateThemeStyles(){const e=this.currentTheme,t=this.isDarkMode&&"telegram"===e,s=this.shadowRoot||document.documentElement;"whatsapp"===e?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#25D366"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#ECE5DD"),this.setCSSProperty(s,"--chat-message-own-bg","#DCF8C6"),this.setCSSProperty(s,"--chat-message-other-bg","#FFFFFF"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #075e54 0%, #128c7e 100%)")):"telegram"===e&&(t?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#4FC3F7"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#212121"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#2F2F2F"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #1976d2 0%, #1565c0 100%)"),this.setCSSProperty(s,"--chat-text-color","#FFFFFF")):(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#2481CC"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#FFFFFF"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#F1F1F1"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%)"),this.setCSSProperty(s,"--chat-text-color","#000000")))}setCSSProperty(e,t,s){if(e instanceof ShadowRoot){const n=e.querySelector("style");if(n){const e=n.textContent||"",i=new RegExp(`${t}\\s*:\\s*[^;]+;`,"g"),a=`${t}: ${s};`;if(i.test(e))n.textContent=e.replace(i,a);else{const t=/:host\s*\{([^}]*)\}/;t.test(e)?n.textContent=e.replace(t,(e,t)=>`:host { ${t} ${a} }`):n.textContent=`:host { ${a} }\n${e}`}}}else e.style.setProperty(t,s)}getState(){return{...this.state}}getDefaultStyles(){return"\n :host {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #333333;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: var(--chat-text-color);\n background: var(--chat-background-color);\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n position: relative;\n max-width: 100%;\n max-height: 100%;\n }\n\n .chat-sdk-container * {\n box-sizing: border-box;\n }\n\n /* WhatsApp Theme */\n .chat-sdk-container.whatsapp-theme .chat-sdk-header {\n background: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-header-left { display: none; }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-messages {\n background-color: #ece5dd;\n background-image: url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23e5ddd5' fill-opacity='0.08'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\");\n }\n\n .chat-sdk-container.whatsapp-theme {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #303030;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* WhatsApp input + details */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-content {\n max-width: 70%;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input-area {\n background: #f0f2f5;\n border-top: none;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input {\n background: #fff;\n border: none;\n border-radius: 22px;\n padding: 10px 14px;\n box-shadow: inset 0 1px 0 rgba(0,0,0,0.02);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-send-btn {\n background: #25D366;\n box-shadow: 0 2px 4px rgba(0,0,0,0.12);\n }\n\n\n /* Telegram Theme */\n .chat-sdk-container.telegram-theme {\n --chat-primary-color: #2481CC;\n --chat-background-color: #FFFFFF;\n --chat-message-own-bg: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);\n --chat-message-other-bg: #F1F1F1;\n --chat-header-bg: linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%);\n --chat-text-color: #000000;\n --chat-border-radius-message: 12px;\n --chat-border-radius-input: 12px;\n\n /* Telegram input + details */\n .chat-sdk-container.telegram-theme .chat-sdk-message-content {\n max-width: 75%;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input-area {\n background: #ffffff;\n border-top: 1px solid #e6e6e6;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input {\n background: #fff;\n border: 1px solid #cfd6dd;\n border-radius: 12px;\n padding: 9px 14px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-send-btn {\n background: #2481CC;\n border-radius: 10px;\n width: 38px;\n height: 36px;\n box-shadow: none;\n }\n /* Telegram dark */\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input-area {\n background: #1f1f1f;\n border-top: 1px solid #2a2a2a;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input {\n background: #2b2b2b;\n color: #e0e0e0;\n border-color: #444;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-send-btn {\n background: #1976d2;\n }\n\n\n .chat-sdk-container.telegram-theme .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-messages {\n background-color: var(--chat-background-color);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* Telegram Dark Theme */\n .chat-sdk-container.telegram-theme.dark {\n --chat-background-color: #212121;\n --chat-message-other-bg: #2F2F2F;\n --chat-header-bg: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);\n --chat-text-color: #FFFFFF;\n }\n\n /* Default header (fallback) */\n .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n }\n\n .chat-sdk-header-left { display: flex; flex-direction: column; gap: 2px; }\n .chat-sdk-title { font-size: 15px; font-weight: 600; }\n .chat-sdk-subtitle { font-size: 12px; opacity: 0.9; }\n\n .chat-sdk-close-btn {\n background: none;\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n opacity: 0.8;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n }\n\n .chat-sdk-close-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .chat-sdk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n background: var(--chat-background-color);\n min-height: 0; /* allow flex to use full height */\n }\n\n .chat-sdk-message {\n margin-bottom: 12px;\n display: flex;\n align-items: flex-end;\n gap: 8px;\n }\n\n .chat-sdk-message.own {\n flex-direction: row-reverse;\n }\n\n .chat-sdk-message-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: #ddd;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n color: #666;\n flex-shrink: 0;\n }\n\n .chat-sdk-message-content {\n max-width: 70%;\n position: relative;\n }\n\n .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n padding: 8px 12px;\n border-radius: var(--chat-border-radius-message);\n position: relative;\n word-wrap: break-word;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n }\n\n .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n }\n\n .chat-sdk-message-username {\n font-size: 11px;\n color: #666;\n margin-bottom: 2px;\n font-weight: 600;\n }\n\n .chat-sdk-message-text {\n margin: 0;\n line-height: 1.4;\n }\n\n .chat-sdk-message-time {\n font-size: 10px;\n color: #999;\n margin-top: 4px;\n text-align: right;\n }\n\n /* Message grouping */\n .chat-sdk-message.grouped {\n margin-top: 4px;\n }\n .chat-sdk-message.grouped .chat-sdk-message-username { display: none; }\n .chat-sdk-message.grouped .chat-sdk-message-avatar { visibility: hidden; }\n\n /* WhatsApp: time inside bubble */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n position: relative;\n padding-right: 44px;\n padding-bottom: 16px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-time-inside {\n position: absolute;\n right: 8px;\n bottom: 4px;\n font-size: 11px;\n color: rgba(0,0,0,0.55);\n }\n\n /* Telegram: read status */\n .chat-sdk-container.telegram-theme .chat-sdk-message-time {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-read-status {\n font-size: 12px;\n color: var(--chat-primary-color);\n line-height: 1;\n }\n\n /* Theme-specific image radii */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-image img { border-radius: 12px; }\n .chat-sdk-container.telegram-theme .chat-sdk-message-image img { border-radius: 6px; }\n\n\n .chat-sdk-input-area {\n padding: 12px 16px;\n background: white;\n border-top: 1px solid #e0e0e0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n\n .chat-sdk-icon-btn {\n background: transparent;\n border: none;\n width: 32px;\n height: 32px;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #666;\n }\n .chat-sdk-icon-btn:hover { background: rgba(0,0,0,0.06); }\n\n .chat-sdk-emoji-picker {\n position: absolute;\n left: 12px;\n bottom: 64px;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n box-shadow: 0 6px 16px rgba(0,0,0,0.12);\n padding: 6px;\n z-index: 5;\n }\n .chat-sdk-emoji-grid {\n display: grid;\n grid-template-columns: repeat(5, 28px);\n gap: 6px;\n }\n\n /* Failed message styles - Telegram style */\n .chat-sdk-message-failed-indicator {\n display: inline-flex;\n align-items: center;\n margin-left: 6px;\n color: #ff4444;\n cursor: pointer;\n }\n .chat-sdk-message-failed-indicator svg {\n width: 16px;\n height: 16px;\n }\n .chat-sdk-message.own .chat-sdk-message-content {\n display: flex;\n align-items: flex-end;\n gap: 6px;\n }\n .chat-sdk-message.own .chat-sdk-message-bubble {\n flex: 1;\n }\n .chat-sdk-emoji-item {\n background: none;\n border: none;\n font-size: 20px;\n line-height: 1;\n cursor: pointer;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n }\n .chat-sdk-emoji-item:hover { background: #f3f4f6; }\n\n\n .chat-sdk-input {\n flex: 1;\n border: 1px solid #ddd;\n border-radius: var(--chat-border-radius-input);\n padding: 8px 16px;\n font-size: 14px;\n outline: none;\n resize: none;\n min-height: 36px;\n max-height: 100px;\n }\n\n .chat-sdk-input:focus {\n border-color: var(--chat-primary-color);\n }\n\n .chat-sdk-send-btn {\n background: var(--chat-primary-color);\n color: white;\n border: none;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n }\n\n .chat-sdk-send-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-send-btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n }\n\n .chat-sdk-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n }\n\n .chat-sdk-join-card {\n background: white;\n border-radius: 12px;\n padding: 24px;\n max-width: 300px;\n margin: 16px;\n text-align: center;\n }\n\n .chat-sdk-join-title {\n font-size: 18px;\n font-weight: 600;\n margin: 0 0 8px 0;\n color: #333;\n }\n\n .chat-sdk-join-description {\n font-size: 14px;\n color: #666;\n margin: 0 0 20px 0;\n line-height: 1.4;\n }\n\n .chat-sdk-join-btn {\n background: #075e54;\n color: white;\n border: none;\n border-radius: 8px;\n padding: 12px 24px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s;\n width: 100%;\n }\n\n .chat-sdk-join-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: #666;\n }\n\n .chat-sdk-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid #e0e0e0;\n border-top: 2px solid #075e54;\n border-radius: 50%;\n animation: chat-sdk-spin 1s linear infinite;\n margin-right: 8px;\n }\n\n @keyframes chat-sdk-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n\n .chat-sdk-container.dark {\n background: #1f1f1f;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-header {\n background: #2d2d2d;\n }\n\n .chat-sdk-container.dark .chat-sdk-messages {\n background: #0d1117;\n }\n\n .chat-sdk-container.dark .chat-sdk-message-bubble {\n background: #2d2d2d;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-message.own .chat-sdk-message-bubble {\n background: #0969da;\n color: white;\n }\n\n /* Image Modal Viewer */\n .chat-sdk-image-modal {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n z-index: 9999;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s ease, visibility 0.2s ease;\n }\n\n .chat-sdk-image-modal-open {\n opacity: 1;\n visibility: visible;\n }\n\n .chat-sdk-image-backdrop {\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0, 0, 0, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n\n .chat-sdk-image-container {\n position: relative;\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-sdk-image-close {\n position: absolute;\n top: -50px;\n right: 0;\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 50%;\n width: 40px;\n height: 40px;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n z-index: 1;\n }\n\n .chat-sdk-image-close:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n\n .chat-sdk-image-full {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 8px;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);\n }\n\n /* Responsive Design */\n @media (max-width: 640px) {\n .chat-sdk-container {\n border-radius: 0;\n height: 100vh;\n max-height: 100vh;\n }\n\n .chat-sdk-message-content {\n max-width: 85%;\n }\n\n .chat-sdk-message-bubble {\n font-size: 14px;\n padding: 8px 12px;\n }\n\n .chat-sdk-input {\n font-size: 16px; /* Prevent zoom on iOS */\n padding: 10px 14px;\n }\n\n .chat-sdk-header {\n padding: 8px 12px;\n min-height: 50px;\n }\n\n .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n font-size: 11px;\n }\n }\n\n @media (min-width: 1024px) {\n .chat-sdk-message-content {\n max-width: 60%;\n }\n\n .chat-sdk-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n transition: all 0.2s ease;\n }\n }\n\n "}startSimulation(){this.simulator.start()}stopSimulation(){this.simulator.stop()}pauseSimulation(){this.simulator.pause()}resumeSimulation(){this.simulator.resume()}async sendMessage(e,t="text"){await this.simulator.sendMessage(e,t)}get isSimulationRunning(){return this.state.isSimulationRunning}get isSimulationPaused(){return this.state.isSimulationPaused}get simulationEnded(){return this.state.simulationEnded}get messageCount(){return this.state.displayedMessageCount}get messages(){return[...this.state.messages]}async reinitializeLanguage(e){this.config.language=e,this.setLoading(!0),this.messagesContainer.innerHTML="",this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.updateUnreadBadge();try{this.simulator.clearCachedProgress()}catch(e){}try{this.simulator.destroy()}catch(e){}this.simulator=new g(this.config,this.apiClient),this.setupSimulatorEvents(),await this.initializeSimulation()}destroy(){this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null);try{this.simulator.destroy()}catch(e){}if(this.shadowRoot)try{for(;this.shadowRoot.firstChild;)this.shadowRoot.removeChild(this.shadowRoot.firstChild)}catch(e){}this.state.isOpen=!1,this.removeAllListeners()}clearMessages(){this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.messagesContainer.innerHTML="",this.updateUnreadBadge()}rerender(){this.reRenderAllMessages()}getMessageCount(){return this.state.displayedMessageCount}isOpen(){return this.state.isOpen}updateLanguageElements(e){var t,s,n;this.t=p(e);const i=null===(t=this.widgetElement)||void 0===t?void 0:t.querySelector("#message-input");i&&(i.placeholder=this.t.inputPlaceholder);const a=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector(".send-button");a&&a.textContent&&(a.textContent=this.t.send);const o=this.getMessageCount(),r=(null===(n=this.state.currentProject)||void 0===n?void 0:n.name)||"Chat";this.setTitle(r,`${o} ${this.t.messages}`)}}const b=v;function f(e){return new v(e)}var k={init:f,ChatSDK:b,ChatSDKError:e};"undefined"!=typeof window&&(window.ChatSDK={init:f,ChatSDK:b,ChatSDKError:e});export{b as ChatSDK,e as ChatSDKError,k as default,f as init};
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ChatSDK={})}(this,function(e){"use strict";class t extends Error{constructor(e,t,s){super(e),this.code=t,this.details=s,this.name="ChatSDKError"}}class s{constructor(){this.events=new Map}on(e,t){this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(t)}off(e,t){if(!this.events.has(e))return;if(!t)return void this.events.delete(e);const s=this.events.get(e),n=s.indexOf(t);n>-1&&s.splice(n,1),0===s.length&&this.events.delete(e)}emit(e,t){if(!this.events.has(e))return;this.events.get(e).forEach(s=>{try{s(t)}catch(t){console.error(`Error in event callback for "${e}":`,t)}})}getEventNames(){return Array.from(this.events.keys())}listenerCount(e){var t;return(null===(t=this.events.get(e))||void 0===t?void 0:t.length)||0}removeAllListeners(){this.events.clear()}}function n(e,t,s){const n=document.createElement(e);return t&&(n.className=t),n}function i(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function a(e,t=!0){e.scrollTop=e.scrollHeight,e.scrollTo&&e.scrollTo({top:e.scrollHeight,behavior:t?"smooth":"auto"})}class o extends s{constructor(e,t){super(),this.simulationData=null,this.displayedMessages=[],this.currentMessageIndex=0,this.isRunning=!1,this.isPaused=!1,this.intervalId=null,this.pollingId=null,this.burstPhase=!0,this.totalToShow=1/0,this.virtualLastTimestamp=null,this.realLastTimestamp=null,this.lastTimestamp=null,this.lastDelayMs=0,this.userId="",this.config=e,this.apiClient=t,this.pollingIntervalMs="number"==typeof e.pollingInterval&&e.pollingInterval>0?e.pollingInterval:6e3}async initialize(){try{const e=this.config.language||"en",t=this.getPersistedUserId(),s=t||this.config.userId||this.generateUserId();this.userId=s,t||this.persistUserId(s);const n=await this.apiClient.getSimulationData(this.config.projectId,s,e);if(!n.success||!n.data)throw new Error("Failed to load simulation data");this.simulationData=n.data;const i=this.simulationData.project.initialBurstCount+this.simulationData.project.continuousCount;this.totalToShow=Math.min(i,this.simulationData.messages.length);const a=this.loadProgress();a&&"number"==typeof a.index?(this.currentMessageIndex=a.index,a.lastTimestamp&&(this.virtualLastTimestamp=new Date(a.lastTimestamp),this.lastTimestamp=new Date(a.lastTimestamp))):(this.currentMessageIndex=0,this.virtualLastTimestamp=null,this.lastTimestamp=null),this.realLastTimestamp=null,await this.loadExistingMessages(),await this.reconstructVirtualHistoryForDisplay(),this.emit("initialized",this.simulationData),this.startPolling(),!1!==this.config.autoStart&&this.start()}catch(e){throw this.emit("error",e),e}}start(){this.simulationData&&!this.isRunning&&(this.isRunning=!0,this.isPaused=!1,this.burstPhase=!0,this.emit("simulationStart"),this.performInitialBurst(),this.currentMessageIndex<this.totalToShow?(this.burstPhase=!1,this.scheduleNextMessage()):(this.isRunning=!1,this.emit("simulationEnd")))}performInitialBurst(){if(!this.simulationData)return;const{project:e,messages:t}=this.simulationData,s=e.initialBurstCount,n=Math.min(s,this.totalToShow,t.length);if(this.currentMessageIndex>=n)return;if(this.displayedMessages.some(e=>e.id.startsWith("sim-"))&&this.currentMessageIndex>0)return;const i=new Date,a=new Array(n);let o=new Date(i);for(let e=n-1;e>=0;e--)if(a[e]=new Date(o),e>0){const e=10+Math.floor(11*Math.random());o=new Date(o.getTime()-60*e*1e3)}const r=[];let d=!1;for(let e=this.currentMessageIndex;e<n;e++){const s=t[e];if(s.hasScreenshot&&s.screenshotUrl){const t={id:`sim-${e}-text-${Date.now()}`,content:s.content,messageType:"text",timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t);const n=new Date(a[e].getTime()+2e3),i={id:`sim-${e}-image-${Date.now()}`,content:s.screenshotUrl,messageType:"image",timestamp:n,isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(i),r.push(i)}else{const t={id:`sim-${e}-${Date.now()}`,content:s.content,messageType:s.messageType,timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t)}this.currentMessageIndex=e+1,d=!0}d&&(this.lastTimestamp=a[n-1],this.virtualLastTimestamp=this.lastTimestamp,this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.emit("messages-batch",r)),this.saveProgress()}pause(){this.isRunning&&(this.isPaused=!0,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationPause"))}resume(){this.isRunning&&this.isPaused&&(this.isPaused=!1,this.scheduleNextMessage(),this.emit("simulationResume"))}stop(){this.isRunning=!1,this.isPaused=!1,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationStop")}destroy(){this.stop(),this.stopPolling(),this.removeAllListeners()}scheduleNextMessage(){if(!this.simulationData||!this.isRunning||this.isPaused)return;const{project:e,messages:t}=this.simulationData;if(this.currentMessageIndex>=this.totalToShow)return this.isRunning=!1,void this.emit("simulationEnd");let s;if(this.burstPhase){const n=Math.min(e.initialBurstCount,t.length);this.currentMessageIndex<n?s=500+1e3*Math.random():(this.burstPhase=!1,s=this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax))}else{const n=Math.min(e.initialBurstCount,t.length);s=this.currentMessageIndex-n<5?1e3*(e.initialMessageInterval||10):this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax)}this.lastDelayMs=s,this.intervalId=setTimeout(()=>{this.displayNextMessage(),this.scheduleNextMessage()},s)}displayNextMessage(){if(!this.simulationData||this.currentMessageIndex>=this.simulationData.messages.length)return;const e=this.simulationData.messages[this.currentMessageIndex],t=this.lastTimestamp||new Date,s=new Date(t.getTime()+(this.lastDelayMs||0));if(this.lastTimestamp=s,e.hasScreenshot&&e.screenshotUrl){const t={id:`sim-${this.currentMessageIndex}-text-${Date.now()}`,content:e.content,messageType:"text",timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t);const n=new Date(s.getTime()+2e3),i={id:`sim-${this.currentMessageIndex}-image-${Date.now()}`,content:e.screenshotUrl,messageType:"image",timestamp:n,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(i),this.lastTimestamp=n,setTimeout(()=>{this.emit("message",i)},2e3)}else{const t={id:`sim-${this.currentMessageIndex}-${Date.now()}`,content:e.content,messageType:e.messageType,timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t)}this.currentMessageIndex++,this.saveProgress()}async loadExistingMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=await this.apiClient.getSimulationMessages(this.config.projectId,e,void 0,100);if(t.success&&t.messages&&t.messages.length>0){const s=t.messages.sort((e,t)=>new Date(e.createdAt||e.timestamp).getTime()-new Date(t.createdAt||t.timestamp).getTime()),n=new Set(this.displayedMessages.map(e=>e.id));for(const t of s){if(n.has(t.id))continue;const s={id:t.id,content:t.content,messageType:t.messageType,timestamp:new Date(t.createdAt||t.timestamp),isOwnMessage:t.userId===e,virtualUser:t.virtualUser,user:t.userId===e?{id:e,username:this.config.username||"You"}:void 0};this.displayedMessages.push(s)}if(s.length>0){const e=s[s.length-1];this.realLastTimestamp=new Date(e.createdAt||e.timestamp)}this.displayedMessages.length>0&&this.emit("messages-batch",[...this.displayedMessages])}}catch(e){console.warn("Failed to load existing messages:",e)}}startPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null),this.pollingId=setInterval(async()=>{await this.pollForNewMessages()},this.pollingIntervalMs)}stopPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null)}setPollingInterval(e){!e||e<=0||(this.pollingIntervalMs=e,this.pollingId&&this.startPolling())}get isPolling(){return!!this.pollingId}async pollForNewMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=this.getLastMessageTimestamp(),s=await this.apiClient.getSimulationMessages(this.config.projectId,e,t);if(s.success&&s.messages&&s.messages.length>0){const t=new Set(this.displayedMessages.map(e=>e.id));let n=null;for(const i of s.messages){if(t.has(i.id))continue;const s=new Date(i.createdAt),a={id:i.id,content:i.content,messageType:i.messageType,timestamp:s,isOwnMessage:i.userId===e,virtualUser:i.virtualUser,user:i.userId===e?{id:e,username:this.config.username||"You"}:void 0};(!n||s>n)&&(n=s),this.displayedMessages.push(a),this.emit("message",a)}n&&(this.realLastTimestamp=n)}}catch(e){console.warn("Polling error:",e)}}async reconstructVirtualHistoryForDisplay(){if(!this.simulationData)return;const e=Math.min(this.currentMessageIndex,this.totalToShow,this.simulationData.messages.length);if(e<=0)return;const t=this.loadProgress(),s=(null==t?void 0:t.virtualMessages)||[];if(s.length>0){const e=[],t=new Set(this.displayedMessages.map(e=>e.id));for(const n of s)if(!t.has(n.id)){const t={id:n.id,content:n.content,messageType:n.messageType,timestamp:new Date(n.timestamp),isOwnMessage:!1,virtualUser:n.virtualUser};e.push(t)}if(e.length>0){this.displayedMessages.push(...e),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=e[e.length-1];this.virtualLastTimestamp=t.timestamp,this.lastTimestamp=t.timestamp,this.emit("messages-batch",e)}return}const n=new Date,i=new Array(e);let a=new Date(n);for(let t=e-1;t>=0;t--)if(i[t]=new Date(a),t>0){const e=10+Math.floor(11*Math.random());a=new Date(a.getTime()-60*e*1e3)}const o=[],{messages:r}=this.simulationData;for(let t=0;t<e;t++){const e=r[t],s=i[t];if(e.hasScreenshot&&e.screenshotUrl){const n={id:`sim-${t}-text`,content:e.content,messageType:"text",timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser},i={id:`sim-${t}-image`,content:e.screenshotUrl,messageType:"image",timestamp:new Date(s.getTime()+2e3),isOwnMessage:!1,virtualUser:e.virtualUser};o.push(n,i)}else{const n={id:`sim-${t}`,content:e.content,messageType:e.messageType,timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};o.push(n)}}const d=new Set(this.displayedMessages.map(e=>e.id)),l=o.filter(e=>!d.has(e.id));if(0===l.length)return;this.displayedMessages.push(...l),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const h=l[l.length-1];this.virtualLastTimestamp=h.timestamp,this.lastTimestamp=h.timestamp,this.emit("messages-batch",l)}getLastMessageTimestamp(){if(this.realLastTimestamp)return this.realLastTimestamp.toISOString()}getUserKey(){return`vcs:user:${this.config.projectId}`}getProgressKey(){const e=this.userId||this.config.userId||"anon";return`vcs:progress:${this.config.projectId}:${e}`}getPersistedUserId(){try{return"undefined"==typeof window?null:window.localStorage.getItem(this.getUserKey())}catch(e){return null}}persistUserId(e){try{if("undefined"==typeof window)return;window.localStorage.setItem(this.getUserKey(),e)}catch(e){}}loadProgress(){try{if("undefined"==typeof window)return null;const e=window.localStorage.getItem(this.getProgressKey());return e?JSON.parse(e):null}catch(e){return null}}saveProgress(){try{if("undefined"==typeof window)return;const e=this.displayedMessages.filter(e=>e.id.startsWith("sim-")).map(e=>({id:e.id,content:e.content,messageType:e.messageType,timestamp:e.timestamp.toISOString(),virtualUser:e.virtualUser})),t={index:this.currentMessageIndex,lastTimestamp:this.lastTimestamp?this.lastTimestamp.toISOString():void 0,virtualMessages:e};window.localStorage.setItem(this.getProgressKey(),JSON.stringify(t))}catch(e){}}clearProgress(){try{if("undefined"==typeof window)return;window.localStorage.removeItem(this.getProgressKey())}catch(e){}}clearCachedProgress(){this.clearProgress()}getRandomInterval(e,t){return 1e3*(e+Math.random()*(t-e))}generateUserId(){return`user-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}get messages(){return[...this.displayedMessages]}get isSimulationRunning(){return this.isRunning}get isSimulationPaused(){return this.isPaused}get data(){return this.simulationData}async sendMessage(e,t="text"){if(!this.simulationData)throw new Error("Simulation not initialized");const s=this.userId||this.config.userId||this.generateUserId(),n=this.config.username||"User";try{if("image"===t||"string"==typeof e&&e.startsWith("data:image/"))return;await Promise.all([this.apiClient.sendUserMessage(this.config.projectId,s,n,e,t),this.apiClient.triggerAIReply(this.config.projectId,s,n,e,t)])}catch(e){throw this.emit("error",e),e}}}class r{constructor(e){this.baseUrl=e.apiBaseUrl||window.location.origin,this.token=e.token}async request(e,s={}){const n=`${this.baseUrl}${e}`,i={"Content-Type":"application/json",...s.headers};this.token&&(i.Authorization=`Bearer ${this.token}`);try{const e=await fetch(n,{...s,headers:i,credentials:"include"});if(!e.ok)throw new t(`API request failed: ${e.status} ${e.statusText}`,"API_ERROR",{status:e.status,statusText:e.statusText});const a=await e.json();if(!a.success&&a.error)throw new t(a.error,"API_ERROR",a);return a}catch(e){if(e instanceof t)throw e;throw new t(`Network error: ${e.message}`,"NETWORK_ERROR",e)}}async getProject(e){return this.request(`/api/projects/${e}`)}async getTemplate(e,t){const s=t?`?lang=${encodeURIComponent(t)}`:"";return this.request(`/api/templates/${e}${s}`)}async getProjectTemplates(e){return this.request(`/api/projects/${e}/templates`)}async sendMessage(e,t,s,n="text"){return this.request("/api/chat/message",{method:"POST",body:JSON.stringify({projectId:e,userId:t,content:s,messageType:n})})}async joinProject(e,t,s){return this.request("/api/chat/join",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s})})}async leaveProject(e,t){return this.request("/api/chat/leave",{method:"POST",body:JSON.stringify({projectId:e,userId:t})})}async getSimulationData(e,t,s){const n=new URLSearchParams({userId:t});return s&&n.append("lang",s),this.request(`/api/chat/simulation/${e}?${n.toString()}`)}async getSimulationMessages(e,t,s,n){const i=new URLSearchParams({userId:t});return s&&i.append("since",s),n&&i.append("limit",n.toString()),this.request(`/api/chat/simulation/${e}/messages?${i.toString()}`)}async sendUserMessage(e,t,s,n,i="text"){return this.request("/api/chat/send",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}async triggerAIReply(e,t,s,n,i="text"){return this.request("/api/chat/ai-reply",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}setToken(e){this.token=e}setBaseUrl(e){this.baseUrl=e}}const d={en:{joinChat:"Join Chat",chatGroup:"{name} Group",online:"{count} online",inputPlaceholder:"Type a message...",send:"Send",messages:"messages",today:"Today",yesterday:"Yesterday",networkError:"Network error",sendFailed:"Failed to send"},zh:{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在线",inputPlaceholder:"输入消息...",send:"发送",messages:"条消息",today:"今天",yesterday:"昨天",networkError:"网络错误",sendFailed:"发送失败"},"zh-TW":{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在線",inputPlaceholder:"輸入訊息...",send:"發送",messages:"條訊息",today:"今天",yesterday:"昨天",networkError:"網路錯誤",sendFailed:"發送失敗"},es:{joinChat:"Unirse al Chat",chatGroup:"Grupo {name}",online:"{count} en línea",inputPlaceholder:"Escribe un mensaje...",send:"Enviar",messages:"mensajes",today:"Hoy",yesterday:"Ayer",networkError:"Error de red",sendFailed:"Error al enviar"},hi:{joinChat:"चैट में शामिल हों",chatGroup:"{name} समूह",online:"{count} ऑनलाइन",inputPlaceholder:"संदेश लिखें...",send:"भेजें",messages:"संदेश",today:"आज",yesterday:"कल",networkError:"नेटवर्क त्रुटि",sendFailed:"भेजने में विफल"},ar:{joinChat:"انضم للدردشة",chatGroup:"مجموعة {name}",online:"{count} متصل",inputPlaceholder:"اكتب رسالة...",send:"إرسال",messages:"رسائل",today:"اليوم",yesterday:"أمس",networkError:"خطأ في الشبكة",sendFailed:"فشل الإرسال"},pt:{joinChat:"Entrar no Chat",chatGroup:"Grupo {name}",online:"{count} online",inputPlaceholder:"Digite uma mensagem...",send:"Enviar",messages:"mensagens",today:"Hoje",yesterday:"Ontem",networkError:"Erro de rede",sendFailed:"Falha ao enviar"},bn:{joinChat:"চ্যাটে যোগ দিন",chatGroup:"{name} গ্রুপ",online:"{count} অনলাইন",inputPlaceholder:"একটি বার্তা লিখুন...",send:"পাঠান",messages:"বার্তা",today:"আজ",yesterday:"গতকাল",networkError:"নেটওয়ার্ক ত্রুটি",sendFailed:"পাঠাতে ব্যর্থ"},ru:{joinChat:"Присоединиться",chatGroup:"Группа {name}",online:"{count} онлайн",inputPlaceholder:"Введите сообщение...",send:"Отправить",messages:"сообщений",today:"Сегодня",yesterday:"Вчера",networkError:"Ошибка сети",sendFailed:"Не удалось отправить"},ja:{joinChat:"チャットに参加",chatGroup:"{name}グループ",online:"{count} オンライン",inputPlaceholder:"メッセージを入力...",send:"送信",messages:"メッセージ",today:"今日",yesterday:"昨日",networkError:"ネットワークエラー",sendFailed:"送信失敗"},de:{joinChat:"Chat beitreten",chatGroup:"{name} Gruppe",online:"{count} online",inputPlaceholder:"Nachricht eingeben...",send:"Senden",messages:"Nachrichten",today:"Heute",yesterday:"Gestern",networkError:"Netzwerkfehler",sendFailed:"Senden fehlgeschlagen"},fr:{joinChat:"Rejoindre le Chat",chatGroup:"Groupe {name}",online:"{count} en ligne",inputPlaceholder:"Tapez un message...",send:"Envoyer",messages:"messages",today:"Aujourd'hui",yesterday:"Hier",networkError:"Erreur réseau",sendFailed:"Échec de l'envoi"},ko:{joinChat:"채팅 참여",chatGroup:"{name} 그룹",online:"{count} 온라인",inputPlaceholder:"메시지 입력...",send:"전송",messages:"메시지",today:"오늘",yesterday:"어제",networkError:"네트워크 오류",sendFailed:"전송 실패"},it:{joinChat:"Unisciti alla Chat",chatGroup:"Gruppo {name}",online:"{count} online",inputPlaceholder:"Scrivi un messaggio...",send:"Invia",messages:"messaggi",today:"Oggi",yesterday:"Ieri",networkError:"Errore di rete",sendFailed:"Invio fallito"},tr:{joinChat:"Sohbete Katıl",chatGroup:"{name} Grubu",online:"{count} çevrimiçi",inputPlaceholder:"Bir mesaj yazın...",send:"Gönder",messages:"mesaj",today:"Bugün",yesterday:"Dün",networkError:"Ağ hatası",sendFailed:"Gönderilemedi"},vi:{joinChat:"Tham gia Chat",chatGroup:"Nhóm {name}",online:"{count} trực tuyến",inputPlaceholder:"Nhập tin nhắn...",send:"Gửi",messages:"tin nhắn",today:"Hôm nay",yesterday:"Hôm qua",networkError:"Lỗi mạng",sendFailed:"Gửi thất bại"},pl:{joinChat:"Dołącz do Czatu",chatGroup:"Grupa {name}",online:"{count} online",inputPlaceholder:"Wpisz wiadomość...",send:"Wyślij",messages:"wiadomości",today:"Dziś",yesterday:"Wczoraj",networkError:"Błąd sieci",sendFailed:"Nie udało się wysłać"},th:{joinChat:"เข้าร่วมแชท",chatGroup:"กลุ่ม {name}",online:"{count} ออนไลน์",inputPlaceholder:"พิมพ์ข้อความ...",send:"ส่ง",messages:"ข้อความ",today:"วันนี้",yesterday:"เมื่อวาน",networkError:"ข้อผิดพลาดเครือข่าย",sendFailed:"ส่งไม่สำเร็จ"},nl:{joinChat:"Deelnemen aan Chat",chatGroup:"{name} Groep",online:"{count} online",inputPlaceholder:"Typ een bericht...",send:"Verzenden",messages:"berichten",today:"Vandaag",yesterday:"Gisteren",networkError:"Netwerkfout",sendFailed:"Verzenden mislukt"},id:{joinChat:"Gabung Chat",chatGroup:"Grup {name}",online:"{count} online",inputPlaceholder:"Ketik pesan...",send:"Kirim",messages:"pesan",today:"Hari ini",yesterday:"Kemarin",networkError:"Kesalahan jaringan",sendFailed:"Gagal mengirim"},ms:{joinChat:"Sertai Chat",chatGroup:"Kumpulan {name}",online:"{count} dalam talian",inputPlaceholder:"Taip mesej...",send:"Hantar",messages:"mesej",today:"Hari ini",yesterday:"Semalam",networkError:"Ralat rangkaian",sendFailed:"Gagal menghantar"}};function l(e){if(d[e])return d[e];const t=e.split("-")[0];return d[t]?d[t]:d.en}function h(e,t){return e.replace(/\{(\w+)\}/g,(e,s)=>void 0!==t[s]?String(t[s]):e)}class c extends s{constructor(e){var t,s;super(),this.emojiPanelOpen=!1,this.onlineCount=0,this.currentTheme="whatsapp",this.isDarkMode=!1,this.customColors={},this.visibleStartIndex=0,this.hasInitializedData=!1,this.pollingStopTimer=null,this.config={...e,mode:e.mode||"floating"},this.t=l(e.language||"en"),this.currentTheme="telegram"===e.uiTemplate?"telegram":"whatsapp",this.isDarkMode="dark"===e.theme,this.customColors={primary:e.primaryColor,background:e.backgroundColor},this.onlineCount=500+Math.floor(301*Math.random()),this.initialRenderCount=null!==(t=this.config.initialRenderCount)&&void 0!==t?t:Number.MAX_SAFE_INTEGER,this.lazyLoadBatchSize=null!==(s=this.config.lazyLoadBatchSize)&&void 0!==s?s:20,this.state={isInitialized:!1,isOpen:!1,isJoined:!1,isConnected:!1,isSimulationRunning:!1,isSimulationPaused:!1,messages:[],virtualUsers:[],realUsers:[],typingUsers:[],simulationEnded:!1,displayedMessageCount:0,unreadCount:0,lastReadMessageId:null},this.apiClient=new r(e),this.simulator=new o(e,this.apiClient),this.setupSimulatorEvents(),this.init()}init(){try{this.setupContainer(),this.createWidget(),"floating"===this.config.mode&&(this.widgetElement.style.display="none",this.createFloatingButton()),this.setupEventListeners(),this.setupImageViewer(),this.state.isInitialized=!0,this.emit("ready")}catch(e){this.emit("error",new t("Failed to initialize chat widget","WIDGET_INIT_ERROR",e))}}setupSimulatorEvents(){this.simulator.on("initialized",e=>{var t;this.state.currentProject=e.project,this.state.currentTemplate=e.template,null!=this.config.initialRenderCount?this.initialRenderCount=this.config.initialRenderCount:this.initialRenderCount=Number.MAX_SAFE_INTEGER,this.setTitle((null===(t=e.project)||void 0===t?void 0:t.name)||"Chat",`0 ${this.t.messages}`),this.setLoading(!1),this.emit("simulationInitialized",e)}),this.simulator.on("message",e=>{var t;this.setLoading(!1),this.addMessage(e),this.state.displayedMessageCount++;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`)}),this.simulator.on("messages-batch",e=>{var t;this.setLoading(!1),this.addMessagesBulk(e),this.state.displayedMessageCount+=e.length;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`),setTimeout(()=>{this.scrollToBottom(!0)},100)}),this.simulator.on("simulationStart",()=>{var e,t;this.state.isSimulationRunning=!0,this.state.isSimulationPaused=!1,null===(t=(e=this.config).onSimulationStart)||void 0===t||t.call(e)}),this.simulator.on("simulationEnd",()=>{var e,t;this.state.isSimulationRunning=!1,this.state.simulationEnded=!0,null===(t=(e=this.config).onSimulationEnd)||void 0===t||t.call(e)}),this.simulator.on("simulationPause",()=>{this.state.isSimulationPaused=!0}),this.simulator.on("simulationResume",()=>{this.state.isSimulationPaused=!1}),this.simulator.on("error",e=>{this.emit("error",e)})}async initializeSimulation(){try{await this.simulator.initialize()}catch(e){this.emit("error",new t("Failed to initialize simulation","SIMULATION_INIT_ERROR",e))}}setupContainer(){var e;const s=function(e){if("string"==typeof e)return document.querySelector(e)||document.body;return e||document.body}(this.config.container);if(!s)throw new t("Container element not found","CONTAINER_NOT_FOUND");const n=null===(e=s.tagName)||void 0===e?void 0:e.toUpperCase();if("BODY"===n||"HTML"===n){const e=document.createElement("div");e.className="chat-sdk-host",e.style.position="static",e.style.width="0",e.style.height="0",document.body.appendChild(e),this.container=e}else this.container=s;this.shadowRoot=this.container.attachShadow({mode:"closed"});const i=this.getDefaultStyles();!function(e,t){const s=document.createElement("style");s.textContent=t,e.appendChild(s)}(this.shadowRoot,i)}createWidget(){var e;if(this.widgetElement&&this.messagesContainer)return;this.widgetElement=n("div","chat-sdk-container");const t="telegram"===this.config.uiTemplate?"telegram":"whatsapp";this.currentTheme=t,this.widgetElement.classList.add(`${t}-theme`),"telegram"===t&&"dark"===this.config.theme&&(this.widgetElement.classList.add("dark"),this.isDarkMode=!0),this.widgetElement.style.position="fixed",this.widgetElement.style.top="0",this.widgetElement.style.left="0",this.widgetElement.style.width="100vw",this.widgetElement.style.height="100vh",this.widgetElement.style.zIndex=String(null!==(e=this.config.zIndex)&&void 0!==e?e:2147483e3),this.widgetElement.innerHTML=`\n <div class="chat-sdk-header">\n <div class="chat-sdk-header-left">\n <div class="chat-sdk-title" id="chat-title"></div>\n <div class="chat-sdk-subtitle" id="chat-subtitle"></div>\n </div>\n <button class="chat-sdk-close-btn" type="button">\n <svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor">\n <path d="M8 7.293l2.146-2.147a.5.5 0 01.708.708L8.707 8l2.147 2.146a.5.5 0 01-.708.708L8 8.707l-2.146 2.147a.5.5 0 01-.708-.708L7.293 8 5.146 5.854a.5.5 0 01.708-.708L8 7.293z"/>\n </svg>\n </button>\n </div>\n\n <div class="chat-sdk-messages" id="messages-container">\n <div class="chat-sdk-loading">\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n </div>\n </div>\n\n <div class="chat-sdk-input-area">\n <button class="chat-sdk-icon-btn chat-sdk-emoji-btn" type="button" id="emoji-button" aria-label="Emoji">\n <span>😊</span>\n </button>\n <button class="chat-sdk-icon-btn chat-sdk-image-btn" type="button" id="image-button" aria-label="Image">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14h18zM5 5h14v8l-3-3-4 5-3-4-4 4V5z"/></svg>\n </button>\n <textarea\n class="chat-sdk-input"\n placeholder="${this.t.inputPlaceholder}"\n rows="1"\n id="message-input"\n ></textarea>\n <input type="file" accept="image/*" id="image-input" style="display:none" />\n <button class="chat-sdk-send-btn" type="button" id="send-button" disabled>\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <path d="M15.854.146a.5.5 0 01.11.54l-5.819 14.547a.75.75 0 01-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 01.124-1.33L15.314.037a.5.5 0 01.54.11z"/>\n </svg>\n </button>\n </div>\n <div class="chat-sdk-emoji-picker" id="emoji-picker" style="display:none">\n <div class="chat-sdk-emoji-grid">\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😀">😀</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😁">😁</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😂">😂</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤣">🤣</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😊">😊</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😍">😍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😎">😎</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤔">🤔</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="👍">👍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🙏">🙏</button>\n </div>\n </div>\n `,this.messagesContainer=this.widgetElement.querySelector("#messages-container"),this.inputElement=this.widgetElement.querySelector("#message-input"),this.sendButton=this.widgetElement.querySelector("#send-button"),this.emojiButton=this.widgetElement.querySelector("#emoji-button"),this.imageButton=this.widgetElement.querySelector("#image-button"),this.fileInput=this.widgetElement.querySelector("#image-input"),this.emojiPicker=this.widgetElement.querySelector("#emoji-picker"),this.shadowRoot.appendChild(this.widgetElement)}setupEventListeners(){var e,t,s,n;const i=this.widgetElement.querySelector(".chat-sdk-close-btn");null==i||i.addEventListener("click",()=>this.close()),this.messagesContainer.addEventListener("scroll",this.handleScrollLazyLoad.bind(this)),this.inputElement.addEventListener("input",this.handleInputChange.bind(this)),this.inputElement.addEventListener("keydown",this.handleKeyDown.bind(this)),this.sendButton.addEventListener("click",this.handleSendMessage.bind(this)),this.inputElement.addEventListener("input",this.autoResizeTextarea.bind(this)),null===(e=this.emojiButton)||void 0===e||e.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.toggleEmojiPicker(!this.emojiPanelOpen)}),null===(t=this.emojiPicker)||void 0===t||t.addEventListener("click",e=>{const t=e.target.closest(".chat-sdk-emoji-item");if(t&&t.hasAttribute("data-emoji")){const e=t.getAttribute("data-emoji")||"";this.insertEmojiAtCursor(e),this.toggleEmojiPicker(!1)}}),this.shadowRoot.addEventListener("click",e=>{const t=e.target,s=t.closest("#emoji-picker"),n=t.closest("#emoji-button");s||n||this.toggleEmojiPicker(!1)}),null===(s=this.imageButton)||void 0===s||s.addEventListener("click",e=>{var t;e.preventDefault(),e.stopPropagation(),null===(t=this.fileInput)||void 0===t||t.click()}),null===(n=this.fileInput)||void 0===n||n.addEventListener("change",this.handleImageSelected.bind(this)),document.addEventListener("keydown",e=>{"Escape"===e.key&&this.state.isOpen&&this.close()})}createFloatingButton(){var e,t,s,n,i,a,o,r,d,l,h;if(!this.shadowRoot)return;const c=this.config.floatingButton||{},g=c.position||"bottom-right",m=String(null!==(t=null!==(e=c.zIndex)&&void 0!==e?e:this.config.zIndex)&&void 0!==t?t:2147483e3),u={top:null===(s=c.offset)||void 0===s?void 0:s.top,right:null===(n=c.offset)||void 0===n?void 0:n.right,bottom:null!==(a=null===(i=c.offset)||void 0===i?void 0:i.bottom)&&void 0!==a?a:20,left:null===(o=c.offset)||void 0===o?void 0:o.left},p=document.createElement("button");p.className="chat-sdk-floating-btn",p.setAttribute("aria-label","Open chat");const y=this.t.joinChat;p.innerHTML=`\n <div style="\n position: relative;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 6px;\n ">\n \x3c!-- Group chat icon (users) --\x3e\n <svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" style="margin-bottom: 2px;">\n <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/>\n </svg>\n\n \x3c!-- Text overlay at bottom --\x3e\n <div style="\n font-size: 10px;\n font-weight: 600;\n color: rgba(255, 255, 255, 0.95);\n text-align: center;\n line-height: 1.2;\n letter-spacing: 0.3px;\n text-shadow: 0 1px 2px rgba(0,0,0,0.2);\n ">${y}</div>\n\n \x3c!-- Unread badge --\x3e\n <span class="chat-sdk-unread-badge" style="\n position: absolute;\n top: -6px;\n right: -6px;\n background: #ff4444;\n color: white;\n border-radius: 10px;\n min-width: 18px;\n height: 18px;\n display: none;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n padding: 0 5px;\n "></span>\n </div>\n `,p.style.position="fixed",p.style.zIndex=m,p.style.width="60px",p.style.height="60px",p.style.borderRadius="50%",p.style.border="none",p.style.cursor="pointer",p.style.display="flex",p.style.alignItems="center",p.style.justifyContent="center",p.style.color="#fff",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)",p.style.background="linear-gradient(145deg, #25D366 0%, #128C7E 100%)",p.style.transition="transform .15s ease, box-shadow .15s ease",p.style.overflow="visible",g.includes("bottom")?(p.style.bottom=(null!==(r=u.bottom)&&void 0!==r?r:20)+"px",p.style.top=""):(p.style.top=(null!==(d=u.top)&&void 0!==d?d:20)+"px",p.style.bottom=""),g.includes("right")?(p.style.right=(null!==(l=u.right)&&void 0!==l?l:20)+"px",p.style.left=""):(p.style.left=(null!==(h=u.left)&&void 0!==h?h:20)+"px",p.style.right=""),p.addEventListener("mouseenter",()=>{p.style.transform="scale(1.06)",p.style.boxShadow="0 14px 28px rgba(0,0,0,0.30), inset 0 2px 4px rgba(255,255,255,0.2)"}),p.addEventListener("mouseleave",()=>{p.style.transform="scale(1)",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)"}),p.addEventListener("mousedown",()=>{p.style.transform="scale(0.95)"}),p.addEventListener("mouseup",()=>{p.style.transform="scale(1.05)",setTimeout(()=>p.style.transform="scale(1)",100)}),p.addEventListener("click",e=>{e.preventDefault(),this.open()}),this.shadowRoot.appendChild(p),this.floatingButtonEl=p}updateUnreadBadge(){if(!this.floatingButtonEl)return;const e=this.floatingButtonEl.querySelector(".chat-sdk-unread-badge");if(!e)return;const t=this.state.unreadCount;t>0?(e.textContent=t>99?"99+":t.toString(),e.style.display="flex"):e.style.display="none"}markAllAsRead(){if(this.state.messages.length>0){const e=this.state.messages[this.state.messages.length-1];this.state.lastReadMessageId=e.id}this.state.unreadCount=0,this.updateUnreadBadge()}incrementUnreadCount(){this.state.isOpen||(this.state.unreadCount++,this.updateUnreadBadge())}toggleEmojiPicker(e){const t=this.emojiPicker;if(!t)return;const s="boolean"==typeof e?e:"none"===t.style.display;t.style.display=s?"block":"none",this.emojiPanelOpen=s}insertEmojiAtCursor(e){const t=this.inputElement,s=t.selectionStart||0,n=t.selectionEnd||0,i=t.value.substring(0,s),a=t.value.substring(n);t.value=i+e+a;const o=s+e.length;t.setSelectionRange(o,o),t.focus(),this.handleInputChange(),this.autoResizeTextarea()}isEmojiOnly(e){const t=e.trim();if(!t)return!1;if(t.length>6)return!1;let s=!1;for(let e=0;e<t.length;){const n=t.codePointAt(e)||0;if(e+=n>65535?2:1,!(n>=126976))return!1;s=!0}return s}async handleImageSelected(){const e=this.fileInput;if(!e||!e.files||0===e.files.length)return;const s=e.files[0];try{const t=await this.resizeImageFile(s,1280,.85),n={id:`local-img-failed-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:t,messageType:"image",timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"},failed:!0};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),e.value=""}catch(e){console.error("Image processing failed",e),this.emit("error",new t("Image processing failed","IMAGE_PROCESS_ERROR",e))}}resizeImageFile(e,t=1280,s=.85){return new Promise((n,i)=>{const a=URL.createObjectURL(e),o=new Image;o.onload=()=>{let{width:e,height:r}=o;const d=Math.min(1,t/Math.max(e,r)),l=document.createElement("canvas");d<1&&(e=Math.round(e*d),r=Math.round(r*d)),l.width=e,l.height=r;const h=l.getContext("2d");if(!h)return URL.revokeObjectURL(a),void i(new Error("Canvas not supported"));h.drawImage(o,0,0,e,r);const c=l.toDataURL("image/jpeg",s);URL.revokeObjectURL(a),n(c)},o.onerror=e=>{URL.revokeObjectURL(a),i(e)},o.src=a})}handleInputChange(){const e=this.inputElement.value.trim().length>0,t=!1!==this.config.enableUserInput&&!1!==this.config.allowInput;this.sendButton.disabled=!e||!t,e&&t&&this.emit("typing")}handleKeyDown(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),this.handleSendMessage())}async handleSendMessage(){const e=this.inputElement.value.trim();if(!e)return;if(!1===this.config.enableUserInput||!1===this.config.allowInput)return;const s=this.isEmojiOnly(e)?"emoji":"text",n={id:`local-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:e,messageType:s,timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"}};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),this.inputElement.value="",this.sendButton.disabled=!0,this.autoResizeTextarea(),this.simulator.sendMessage(e,s).catch(e=>{console.error("Failed to send message:",e),this.emit("error",new t("Failed to send message","SEND_MESSAGE_ERROR",e))})}autoResizeTextarea(){this.inputElement.style.height="auto",this.inputElement.style.height=Math.min(this.inputElement.scrollHeight,100)+"px"}open(){var e;if(this.state.isOpen)return;if(this.hasInitializedData)try{this.simulator.startPolling()}catch(e){}else this.hasInitializedData=!0,this.setLoading(!0),this.initializeSimulation().catch(e=>{console.error("Failed to initialize simulation on open:",e),this.setLoading(!1)});this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null),this.floatingButtonEl&&(this.floatingButtonEl.style.display="none"),this.widgetElement.style.opacity="0",this.widgetElement.style.display="flex",requestAnimationFrame(()=>{this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="1"}),this.state.isOpen=!0,this.markAllAsRead(),this.emit("open");const t=(null===(e=this.state.currentProject)||void 0===e?void 0:e.name)||"Chat";this.setTitle(t,`${this.state.displayedMessageCount} ${this.t.messages}`),this.scrollToBottom(!0),requestAnimationFrame(()=>this.scrollToBottom(!0)),setTimeout(()=>this.scrollToBottom(!0),0)}close(){this.state.isOpen&&(this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="0",setTimeout(()=>{this.widgetElement.style.display="none",this.floatingButtonEl&&(this.floatingButtonEl.style.display="flex")},200),this.state.isOpen=!1,this.pollingStopTimer&&clearTimeout(this.pollingStopTimer),this.pollingStopTimer=setTimeout(()=>{try{this.simulator.stopPolling()}catch(e){}this.pollingStopTimer=null},1e4),this.emit("close"))}setTitle(e,t){var s,n;const i=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector("#chat-title"),a=null===(n=this.widgetElement)||void 0===n?void 0:n.querySelector("#chat-subtitle"),o=h(this.t.chatGroup,{name:e||"Chat"});this.currentTheme,i&&(i.textContent=o),a&&(a.textContent=h(this.t.online,{count:this.onlineCount}),a.style.display="block")}buildMessageElement(e,t){const s=n("div","chat-sdk-message");e.isOwnMessage&&s.classList.add("own");const i=!!t&&this.shouldGroupWithPrev(t,e);i&&s.classList.add("grouped");let a=null;e.isOwnMessage||(a=this.createAvatar(e),i&&a&&(a.style.visibility="hidden"));const o=!e.isOwnMessage&&!i,r="whatsapp"===this.currentTheme,d="telegram"===this.currentTheme&&e.isOwnMessage,l=this.createMessageContent(e,o,r,d);return a&&s.appendChild(a),s.appendChild(l),s}shouldGroupWithPrev(e,t){var s,n,i,a,o,r,d;if(!1===this.config.groupMessages)return!1;const l=null!==(s=this.config.groupTimeThresholdSec)&&void 0!==s?s:120,h=e.isOwnMessage===t.isOwnMessage,c=(null===(n=e.virtualUser)||void 0===n?void 0:n.id)&&(null===(i=e.virtualUser)||void 0===i?void 0:i.id)===(null===(a=t.virtualUser)||void 0===a?void 0:a.id),g=(null===(o=e.user)||void 0===o?void 0:o.id)&&(null===(r=e.user)||void 0===r?void 0:r.id)===(null===(d=t.user)||void 0===d?void 0:d.id),m=h&&(c||g||e.isOwnMessage&&t.isOwnMessage),u=Math.abs(t.timestamp.getTime()-e.timestamp.getTime())/1e3;return!!m&&u<=l}handleScrollLazyLoad(){if(this.messagesContainer.scrollTop<=20&&this.visibleStartIndex>0){const e=this.messagesContainer.scrollHeight,t=this.lazyLoadBatchSize,s=Math.max(0,this.visibleStartIndex-t),n=this.state.messages.slice(s,this.visibleStartIndex),i=document.createDocumentFragment();for(const e of n){const t=this.buildMessageElement(e);i.appendChild(t)}this.messagesContainer.insertBefore(i,this.messagesContainer.firstChild),this.visibleStartIndex=s;const a=this.messagesContainer.scrollHeight;this.messagesContainer.scrollTop+=a-e}}setLoading(e){if(e){if(!this.messagesContainer.querySelector(".chat-sdk-loading")){const e=document.createElement("div");e.className="chat-sdk-loading",e.innerHTML='\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n ',this.messagesContainer.appendChild(e)}}else{const e=this.messagesContainer.querySelector(".chat-sdk-loading");null==e||e.remove()}}showJoinOverlay(){const e=n("div","chat-sdk-overlay");e.innerHTML='\n <div class="chat-sdk-join-card">\n <h3 class="chat-sdk-join-title">Join the conversation</h3>\n <p class="chat-sdk-join-description">\n Click below to join this group chat and start interacting with other members.\n </p>\n <button class="chat-sdk-join-btn" type="button">Join Chat</button>\n </div>\n ';const t=e.querySelector(".chat-sdk-join-btn");null==t||t.addEventListener("click",()=>{this.hideJoinOverlay(),this.emit("join-requested")}),this.widgetElement.appendChild(e)}hideJoinOverlay(){const e=this.widgetElement.querySelector(".chat-sdk-overlay");e&&e.remove()}addMessage(e){if(e.isOwnMessage)for(let t=this.state.messages.length-1;t>=0;t--){const s=this.state.messages[t];if(s.isOwnMessage&&s.content===e.content){if(Math.abs(e.timestamp.getTime()-s.timestamp.getTime())<=1e4)return;break}}this.state.messages.find(t=>t.id===e.id)?console.warn("Duplicate message detected and ignored:",e.id):(this.state.messages.push(e),this.renderMessage(e),e.isOwnMessage||this.incrementUnreadCount(),this.scrollToBottom(!0))}addMessagesBulk(e){if(!e||0===e.length)return;if(0===this.messagesContainer.querySelectorAll(".chat-sdk-message").length){this.state.messages=[...e].sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=this.state.messages.length,s=this.initialRenderCount;this.visibleStartIndex=Math.max(0,t-s);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),setTimeout(()=>{this.scrollToBottom(!0)},0)}else{const t=new Set(this.state.messages.map(e=>e.id)),s=e.filter(e=>!t.has(e.id));if(s.length>0){this.state.messages.push(...s),this.state.messages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=this.initialRenderCount;this.visibleStartIndex=Math.max(0,e-t);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),this.scrollToBottom()}}}reRenderAllMessages(){this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=Math.max(0,e-this.initialRenderCount);this.state.messages.slice(t).forEach(e=>{this.renderMessage(e)}),this.scrollToBottom()}renderMessage(e){const t=this.state.messages.length-1,s=t>0?this.state.messages[t-1]:void 0,n=this.buildMessageElement(e,s);this.messagesContainer.appendChild(n)}createAvatar(e){var t,s,i,a;const o=n("div","chat-sdk-message-avatar");if(null===(t=e.virtualUser)||void 0===t?void 0:t.avatar)o.style.backgroundImage=`url(${e.virtualUser.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else if(null===(s=e.user)||void 0===s?void 0:s.avatar)o.style.backgroundImage=`url(${e.user.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else{const t=(null===(i=e.virtualUser)||void 0===i?void 0:i.username)||(null===(a=e.user)||void 0===a?void 0:a.username)||"U";o.textContent=t.charAt(0).toUpperCase()}return o}createMessageContent(e,t=!0,s=!1,a=!1){var o,r,d;const l=n("div","chat-sdk-message-content"),h=(null===(o=e.virtualUser)||void 0===o?void 0:o.displayName)||(null===(r=e.virtualUser)||void 0===r?void 0:r.username)||(null===(d=e.user)||void 0===d?void 0:d.username)||"Unknown";let c="";if("image"===e.messageType){c=`\n <div class="chat-sdk-message-image${e.failed?" failed":""}">\n <img src="${i(e.content)}" alt="Image"\n style="max-width: 100%; height: auto; cursor: pointer;"\n data-image-url="${i(e.content)}"\n class="chat-sdk-image-preview" />\n </div>\n `}else c="emoji"===e.messageType?`<div class="chat-sdk-message-emoji" style="font-size: 2em; line-height: 1;">${i(e.content)}</div>`:`<p class="chat-sdk-message-text">${i(e.content)}</p>`;const g=`${function(e,t){const s=new Date,n=Math.floor((s.getTime()-e.getTime())/1e3),i=(t||("undefined"!=typeof navigator?navigator.language:"en")).toLowerCase().startsWith("zh");if(n<60)return i?"刚刚":"just now";if(n<3600){const e=Math.floor(n/60);return i?`${e} 分钟前`:`${e}m ago`}if(n<86400){const e=Math.floor(n/3600);return i?`${e} 小时前`:`${e}h ago`}const a=new Date(s.getFullYear(),s.getMonth(),s.getDate());if(e>=new Date(a.getTime()-864e5)&&e<a){const t=e.toLocaleTimeString(i?"zh-CN":void 0,{hour:"2-digit",minute:"2-digit",hour12:!1});return i?`昨天 ${t}`:`yesterday ${t}`}return s.getTime()-e.getTime()<6048e5?e.toLocaleString(i?"zh-CN":void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}):e.toLocaleString(i?"zh-CN":void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1})}(e.timestamp,this.config.language)}`,m=a?'<span class="chat-sdk-read-status">✓✓</span>':"",u=e.failed&&e.isOwnMessage?'<div class="chat-sdk-message-failed-indicator">\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <circle cx="8" cy="8" r="8" fill="#ff4444"/>\n <path d="M8 4v4M8 10h.01" stroke="white" stroke-width="1.5" stroke-linecap="round"/>\n </svg>\n </div>':"";l.innerHTML=s?`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${i(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n <div class="chat-sdk-message-time-inside">${g}${m?" "+m:""}</div>\n </div>\n ${u}\n `:`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${i(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n </div>\n <div class="chat-sdk-message-time">${g}${m?" "+m:""}</div>\n ${u}\n `;const p=l.querySelector(".chat-sdk-image-preview");return p&&p.addEventListener("click",e=>{e.preventDefault();const t=e.target.getAttribute("data-image-url");t&&this.showImagePreview(t)}),l}scrollToBottom(e=!1){const t=this.messagesContainer;if(e)return void a(t);t.scrollTop+t.clientHeight>=t.scrollHeight-40&&a(t)}setupImageViewer(){this.messagesContainer.addEventListener("click",e=>{const t=e.target;if(t.classList.contains("chat-sdk-image-preview")){const e=t.getAttribute("data-image-url");e&&this.openImageViewer(e)}})}openImageViewer(e){const t=n("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-backdrop">\n <div class="chat-sdk-image-container">\n <button class="chat-sdk-image-close" aria-label="Close">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n <img class="chat-sdk-image-full" src="${i(e)}" alt="Full size image" />\n </div>\n </div>\n `,this.shadowRoot.appendChild(t);const s=t.querySelector(".chat-sdk-image-close"),a=t.querySelector(".chat-sdk-image-backdrop"),o=()=>{t.remove()};null==s||s.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r),requestAnimationFrame(()=>{t.classList.add("chat-sdk-image-modal-open")})}showImagePreview(e){const t=n("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-modal-overlay">\n <div class="chat-sdk-image-modal-content">\n <button class="chat-sdk-image-modal-close">&times;</button>\n <img src="${i(e)}" alt="Image Preview" class="chat-sdk-image-modal-img" />\n </div>\n </div>\n `,this.widgetElement.appendChild(t);const s=t.querySelector(".chat-sdk-image-modal-close"),a=t.querySelector(".chat-sdk-image-modal-overlay"),o=()=>{t.remove()};null==s||s.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r)}setJoined(e){this.state.isJoined=e,this.handleInputChange()}setUITemplate(e){this.currentTheme=e,this.config.uiTemplate=e,this.widgetElement.classList.remove("whatsapp-theme","telegram-theme","dark"),this.widgetElement.classList.add(`${e}-theme`),"telegram"===e&&this.isDarkMode&&this.widgetElement.classList.add("dark"),this.updateThemeStyles(),this.reRenderAllMessages()}setTheme(e){this.isDarkMode="dark"===e,this.config.theme=e,"telegram"===this.currentTheme&&(this.isDarkMode?this.widgetElement.classList.add("dark"):this.widgetElement.classList.remove("dark"),this.updateThemeStyles())}setCustomColors(e){this.customColors={...this.customColors,...e},this.config.primaryColor=e.primary,this.config.backgroundColor=e.background,this.updateThemeStyles()}updateThemeStyles(){const e=this.currentTheme,t=this.isDarkMode&&"telegram"===e,s=this.shadowRoot||document.documentElement;"whatsapp"===e?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#25D366"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#ECE5DD"),this.setCSSProperty(s,"--chat-message-own-bg","#DCF8C6"),this.setCSSProperty(s,"--chat-message-other-bg","#FFFFFF"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #075e54 0%, #128c7e 100%)")):"telegram"===e&&(t?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#4FC3F7"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#212121"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#2F2F2F"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #1976d2 0%, #1565c0 100%)"),this.setCSSProperty(s,"--chat-text-color","#FFFFFF")):(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#2481CC"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#FFFFFF"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#F1F1F1"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%)"),this.setCSSProperty(s,"--chat-text-color","#000000")))}setCSSProperty(e,t,s){if(e instanceof ShadowRoot){const n=e.querySelector("style");if(n){const e=n.textContent||"",i=new RegExp(`${t}\\s*:\\s*[^;]+;`,"g"),a=`${t}: ${s};`;if(i.test(e))n.textContent=e.replace(i,a);else{const t=/:host\s*\{([^}]*)\}/;t.test(e)?n.textContent=e.replace(t,(e,t)=>`:host { ${t} ${a} }`):n.textContent=`:host { ${a} }\n${e}`}}}else e.style.setProperty(t,s)}getState(){return{...this.state}}getDefaultStyles(){return"\n :host {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #333333;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: var(--chat-text-color);\n background: var(--chat-background-color);\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n position: relative;\n max-width: 100%;\n max-height: 100%;\n }\n\n .chat-sdk-container * {\n box-sizing: border-box;\n }\n\n /* WhatsApp Theme */\n .chat-sdk-container.whatsapp-theme .chat-sdk-header {\n background: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-header-left { display: none; }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-messages {\n background-color: #ece5dd;\n background-image: url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23e5ddd5' fill-opacity='0.08'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\");\n }\n\n .chat-sdk-container.whatsapp-theme {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #303030;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* WhatsApp input + details */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-content {\n max-width: 70%;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input-area {\n background: #f0f2f5;\n border-top: none;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input {\n background: #fff;\n border: none;\n border-radius: 22px;\n padding: 10px 14px;\n box-shadow: inset 0 1px 0 rgba(0,0,0,0.02);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-send-btn {\n background: #25D366;\n box-shadow: 0 2px 4px rgba(0,0,0,0.12);\n }\n\n\n /* Telegram Theme */\n .chat-sdk-container.telegram-theme {\n --chat-primary-color: #2481CC;\n --chat-background-color: #FFFFFF;\n --chat-message-own-bg: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);\n --chat-message-other-bg: #F1F1F1;\n --chat-header-bg: linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%);\n --chat-text-color: #000000;\n --chat-border-radius-message: 12px;\n --chat-border-radius-input: 12px;\n\n /* Telegram input + details */\n .chat-sdk-container.telegram-theme .chat-sdk-message-content {\n max-width: 75%;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input-area {\n background: #ffffff;\n border-top: 1px solid #e6e6e6;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input {\n background: #fff;\n border: 1px solid #cfd6dd;\n border-radius: 12px;\n padding: 9px 14px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-send-btn {\n background: #2481CC;\n border-radius: 10px;\n width: 38px;\n height: 36px;\n box-shadow: none;\n }\n /* Telegram dark */\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input-area {\n background: #1f1f1f;\n border-top: 1px solid #2a2a2a;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input {\n background: #2b2b2b;\n color: #e0e0e0;\n border-color: #444;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-send-btn {\n background: #1976d2;\n }\n\n\n .chat-sdk-container.telegram-theme .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-messages {\n background-color: var(--chat-background-color);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* Telegram Dark Theme */\n .chat-sdk-container.telegram-theme.dark {\n --chat-background-color: #212121;\n --chat-message-other-bg: #2F2F2F;\n --chat-header-bg: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);\n --chat-text-color: #FFFFFF;\n }\n\n /* Default header (fallback) */\n .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n }\n\n .chat-sdk-header-left { display: flex; flex-direction: column; gap: 2px; }\n .chat-sdk-title { font-size: 15px; font-weight: 600; }\n .chat-sdk-subtitle { font-size: 12px; opacity: 0.9; }\n\n .chat-sdk-close-btn {\n background: none;\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n opacity: 0.8;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n }\n\n .chat-sdk-close-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .chat-sdk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n background: var(--chat-background-color);\n min-height: 0; /* allow flex to use full height */\n }\n\n .chat-sdk-message {\n margin-bottom: 12px;\n display: flex;\n align-items: flex-end;\n gap: 8px;\n }\n\n .chat-sdk-message.own {\n flex-direction: row-reverse;\n }\n\n .chat-sdk-message-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: #ddd;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n color: #666;\n flex-shrink: 0;\n }\n\n .chat-sdk-message-content {\n max-width: 70%;\n position: relative;\n }\n\n .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n padding: 8px 12px;\n border-radius: var(--chat-border-radius-message);\n position: relative;\n word-wrap: break-word;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n }\n\n .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n }\n\n .chat-sdk-message-username {\n font-size: 11px;\n color: #666;\n margin-bottom: 2px;\n font-weight: 600;\n }\n\n .chat-sdk-message-text {\n margin: 0;\n line-height: 1.4;\n }\n\n .chat-sdk-message-time {\n font-size: 10px;\n color: #999;\n margin-top: 4px;\n text-align: right;\n }\n\n /* Message grouping */\n .chat-sdk-message.grouped {\n margin-top: 4px;\n }\n .chat-sdk-message.grouped .chat-sdk-message-username { display: none; }\n .chat-sdk-message.grouped .chat-sdk-message-avatar { visibility: hidden; }\n\n /* WhatsApp: time inside bubble */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n position: relative;\n padding-right: 44px;\n padding-bottom: 16px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-time-inside {\n position: absolute;\n right: 8px;\n bottom: 4px;\n font-size: 11px;\n color: rgba(0,0,0,0.55);\n }\n\n /* Telegram: read status */\n .chat-sdk-container.telegram-theme .chat-sdk-message-time {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-read-status {\n font-size: 12px;\n color: var(--chat-primary-color);\n line-height: 1;\n }\n\n /* Theme-specific image radii */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-image img { border-radius: 12px; }\n .chat-sdk-container.telegram-theme .chat-sdk-message-image img { border-radius: 6px; }\n\n\n .chat-sdk-input-area {\n padding: 12px 16px;\n background: white;\n border-top: 1px solid #e0e0e0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n\n .chat-sdk-icon-btn {\n background: transparent;\n border: none;\n width: 32px;\n height: 32px;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #666;\n }\n .chat-sdk-icon-btn:hover { background: rgba(0,0,0,0.06); }\n\n .chat-sdk-emoji-picker {\n position: absolute;\n left: 12px;\n bottom: 64px;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n box-shadow: 0 6px 16px rgba(0,0,0,0.12);\n padding: 6px;\n z-index: 5;\n }\n .chat-sdk-emoji-grid {\n display: grid;\n grid-template-columns: repeat(5, 28px);\n gap: 6px;\n }\n\n /* Failed message styles - Telegram style */\n .chat-sdk-message-failed-indicator {\n display: inline-flex;\n align-items: center;\n margin-left: 6px;\n color: #ff4444;\n cursor: pointer;\n }\n .chat-sdk-message-failed-indicator svg {\n width: 16px;\n height: 16px;\n }\n .chat-sdk-message.own .chat-sdk-message-content {\n display: flex;\n align-items: flex-end;\n gap: 6px;\n }\n .chat-sdk-message.own .chat-sdk-message-bubble {\n flex: 1;\n }\n .chat-sdk-emoji-item {\n background: none;\n border: none;\n font-size: 20px;\n line-height: 1;\n cursor: pointer;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n }\n .chat-sdk-emoji-item:hover { background: #f3f4f6; }\n\n\n .chat-sdk-input {\n flex: 1;\n border: 1px solid #ddd;\n border-radius: var(--chat-border-radius-input);\n padding: 8px 16px;\n font-size: 14px;\n outline: none;\n resize: none;\n min-height: 36px;\n max-height: 100px;\n }\n\n .chat-sdk-input:focus {\n border-color: var(--chat-primary-color);\n }\n\n .chat-sdk-send-btn {\n background: var(--chat-primary-color);\n color: white;\n border: none;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n }\n\n .chat-sdk-send-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-send-btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n }\n\n .chat-sdk-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n }\n\n .chat-sdk-join-card {\n background: white;\n border-radius: 12px;\n padding: 24px;\n max-width: 300px;\n margin: 16px;\n text-align: center;\n }\n\n .chat-sdk-join-title {\n font-size: 18px;\n font-weight: 600;\n margin: 0 0 8px 0;\n color: #333;\n }\n\n .chat-sdk-join-description {\n font-size: 14px;\n color: #666;\n margin: 0 0 20px 0;\n line-height: 1.4;\n }\n\n .chat-sdk-join-btn {\n background: #075e54;\n color: white;\n border: none;\n border-radius: 8px;\n padding: 12px 24px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s;\n width: 100%;\n }\n\n .chat-sdk-join-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: #666;\n }\n\n .chat-sdk-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid #e0e0e0;\n border-top: 2px solid #075e54;\n border-radius: 50%;\n animation: chat-sdk-spin 1s linear infinite;\n margin-right: 8px;\n }\n\n @keyframes chat-sdk-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n\n .chat-sdk-container.dark {\n background: #1f1f1f;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-header {\n background: #2d2d2d;\n }\n\n .chat-sdk-container.dark .chat-sdk-messages {\n background: #0d1117;\n }\n\n .chat-sdk-container.dark .chat-sdk-message-bubble {\n background: #2d2d2d;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-message.own .chat-sdk-message-bubble {\n background: #0969da;\n color: white;\n }\n\n /* Image Modal Viewer */\n .chat-sdk-image-modal {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n z-index: 9999;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s ease, visibility 0.2s ease;\n }\n\n .chat-sdk-image-modal-open {\n opacity: 1;\n visibility: visible;\n }\n\n .chat-sdk-image-backdrop {\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0, 0, 0, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n\n .chat-sdk-image-container {\n position: relative;\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-sdk-image-close {\n position: absolute;\n top: -50px;\n right: 0;\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 50%;\n width: 40px;\n height: 40px;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n z-index: 1;\n }\n\n .chat-sdk-image-close:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n\n .chat-sdk-image-full {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 8px;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);\n }\n\n /* Responsive Design */\n @media (max-width: 640px) {\n .chat-sdk-container {\n border-radius: 0;\n height: 100vh;\n max-height: 100vh;\n }\n\n .chat-sdk-message-content {\n max-width: 85%;\n }\n\n .chat-sdk-message-bubble {\n font-size: 14px;\n padding: 8px 12px;\n }\n\n .chat-sdk-input {\n font-size: 16px; /* Prevent zoom on iOS */\n padding: 10px 14px;\n }\n\n .chat-sdk-header {\n padding: 8px 12px;\n min-height: 50px;\n }\n\n .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n font-size: 11px;\n }\n }\n\n @media (min-width: 1024px) {\n .chat-sdk-message-content {\n max-width: 60%;\n }\n\n .chat-sdk-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n transition: all 0.2s ease;\n }\n }\n\n "}startSimulation(){this.simulator.start()}stopSimulation(){this.simulator.stop()}pauseSimulation(){this.simulator.pause()}resumeSimulation(){this.simulator.resume()}async sendMessage(e,t="text"){await this.simulator.sendMessage(e,t)}get isSimulationRunning(){return this.state.isSimulationRunning}get isSimulationPaused(){return this.state.isSimulationPaused}get simulationEnded(){return this.state.simulationEnded}get messageCount(){return this.state.displayedMessageCount}get messages(){return[...this.state.messages]}async reinitializeLanguage(e){this.config.language=e,this.setLoading(!0),this.messagesContainer.innerHTML="",this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.updateUnreadBadge();try{this.simulator.clearCachedProgress()}catch(e){}try{this.simulator.destroy()}catch(e){}this.simulator=new o(this.config,this.apiClient),this.setupSimulatorEvents(),await this.initializeSimulation()}destroy(){this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null);try{this.simulator.destroy()}catch(e){}if(this.shadowRoot)try{for(;this.shadowRoot.firstChild;)this.shadowRoot.removeChild(this.shadowRoot.firstChild)}catch(e){}this.state.isOpen=!1,this.removeAllListeners()}clearMessages(){this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.messagesContainer.innerHTML="",this.updateUnreadBadge()}rerender(){this.reRenderAllMessages()}getMessageCount(){return this.state.displayedMessageCount}isOpen(){return this.state.isOpen}updateLanguageElements(e){var t,s,n;this.t=l(e);const i=null===(t=this.widgetElement)||void 0===t?void 0:t.querySelector("#message-input");i&&(i.placeholder=this.t.inputPlaceholder);const a=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector(".send-button");a&&a.textContent&&(a.textContent=this.t.send);const o=this.getMessageCount(),r=(null===(n=this.state.currentProject)||void 0===n?void 0:n.name)||"Chat";this.setTitle(r,`${o} ${this.t.messages}`)}}const g=c;function m(e){return new c(e)}var u={init:m,ChatSDK:g,ChatSDKError:t};"undefined"!=typeof window&&(window.ChatSDK={init:m,ChatSDK:g,ChatSDKError:t}),e.ChatSDK=g,e.ChatSDKError=t,e.default=u,e.init=m,Object.defineProperty(e,"__esModule",{value:!0})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ChatSDK={})}(this,function(e){"use strict";class t extends Error{constructor(e,t,s){super(e),this.code=t,this.details=s,this.name="ChatSDKError"}}class s{constructor(){this.events=new Map}on(e,t){this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(t)}off(e,t){if(!this.events.has(e))return;if(!t)return void this.events.delete(e);const s=this.events.get(e),n=s.indexOf(t);n>-1&&s.splice(n,1),0===s.length&&this.events.delete(e)}emit(e,t){if(!this.events.has(e))return;this.events.get(e).forEach(s=>{try{s(t)}catch(t){console.error(`Error in event callback for "${e}":`,t)}})}getEventNames(){return Array.from(this.events.keys())}listenerCount(e){var t;return(null===(t=this.events.get(e))||void 0===t?void 0:t.length)||0}removeAllListeners(){this.events.clear()}}function n(e,t,s){const n=document.createElement(e);return t&&(n.className=t),n}function i(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function a(e,t=!0){e.scrollTop=e.scrollHeight,e.scrollTo&&e.scrollTo({top:e.scrollHeight,behavior:t?"smooth":"auto"})}const o={USD:1,EUR:.92,GBP:.79,JPY:149.5,CNY:7.24,INR:83.12,BRL:4.97,RUB:92.5,KRW:1320,MXN:17.15,CAD:1.38,AUD:1.53,CHF:.88,SEK:10.85,NZD:1.67,SGD:1.34,HKD:7.82,NOK:10.95,TRY:28.5,ZAR:18.65,PLN:4.05,THB:35.2,IDR:15650,MYR:4.68,PHP:56.2,DKK:6.88,CZK:22.85,HUF:355,ILS:3.72,CLP:920,ARS:350,COP:4050,PEN:3.75,EGP:30.9,SAR:3.75,AED:3.67,VND:24500,PKR:278,BDT:110,NGN:775,UAH:36.5,RON:4.58,TWD:31.5,QAR:3.64,KWD:.31,OMR:.38,BHD:.38},r={USD:"$",EUR:"€",GBP:"£",JPY:"¥",CNY:"¥",INR:"₹",BRL:"R$",RUB:"₽",KRW:"₩",MXN:"$",CAD:"C$",AUD:"A$",CHF:"CHF",SEK:"kr",NZD:"NZ$",SGD:"S$",HKD:"HK$",NOK:"kr",TRY:"₺",ZAR:"R",PLN:"zł",THB:"฿",IDR:"Rp",MYR:"RM",PHP:"₱",DKK:"kr",CZK:"Kč",HUF:"Ft",ILS:"₪",CLP:"$",ARS:"$",COP:"$",PEN:"S/",EGP:"E£",SAR:"﷼",AED:"د.إ",VND:"₫",PKR:"₨",BDT:"৳",NGN:"₦",UAH:"₴",RON:"lei",TWD:"NT$",QAR:"﷼",KWD:"د.ك",OMR:"﷼",BHD:"د.ب"},d={USD:",",EUR:".",GBP:",",JPY:",",CNY:",",INR:",",BRL:".",RUB:" ",KRW:",",MXN:",",CAD:",",AUD:",",CHF:"'",SEK:" ",PLN:" ",THB:",",IDR:".",MYR:",",PHP:",",DKK:".",CZK:" ",HUF:" "},l={USD:".",EUR:",",GBP:".",JPY:".",CNY:".",INR:".",BRL:",",RUB:",",KRW:".",MXN:".",CAD:".",AUD:".",CHF:".",SEK:",",PLN:",",THB:".",IDR:",",MYR:".",PHP:".",DKK:",",CZK:",",HUF:","},h={US:"USD",CA:"CAD",MX:"MXN",BR:"BRL",AR:"ARS",CL:"CLP",CO:"COP",PE:"PEN",GB:"GBP",DE:"EUR",FR:"EUR",IT:"EUR",ES:"EUR",NL:"EUR",BE:"EUR",AT:"EUR",PT:"EUR",IE:"EUR",GR:"EUR",FI:"EUR",CH:"CHF",NO:"NOK",SE:"SEK",DK:"DKK",PL:"PLN",CZ:"CZK",HU:"HUF",RO:"RON",RU:"RUB",UA:"UAH",TR:"TRY",IL:"ILS",SA:"SAR",AE:"AED",EG:"EGP",CN:"CNY",JP:"JPY",KR:"KRW",IN:"INR",ID:"IDR",TH:"THB",VN:"VND",MY:"MYR",SG:"SGD",PH:"PHP",PK:"PKR",BD:"BDT",HK:"HKD",TW:"TWD",AU:"AUD",NZ:"NZD",ZA:"ZAR",NG:"NGN",KE:"KES",QA:"QAR",KW:"KWD",OM:"OMR",BH:"BHD"},c=new Set(["JPY","KRW","IDR","VND","CLP","PYG","UGX"]);function g(e,t){if(!e||!t)return e;const s=function(e){return h[e.toUpperCase()]||"USD"}(t);return e.replace(/\{\{AMOUNT:(\d+(?:\.\d+)?)\}\}/g,(e,t)=>{const n=parseFloat(t);return isNaN(n)?e:function(e,t){var s,n,i,a;const h=null!==(s=o[t])&&void 0!==s?s:1,g=null!==(n=r[t])&&void 0!==n?n:t+" ",m=null!==(i=d[t])&&void 0!==i?i:",",u=null!==(a=l[t])&&void 0!==a?a:".",p=c.has(t),y=e*h,v=p?Math.round(y):Math.round(100*y)/100,b=Math.floor(v).toString().replace(/\B(?=(\d{3})+(?!\d))/g,m);return p?`${g}${b}`:`${g}${b}${u}${(v%1).toFixed(2).slice(2)}`}(n,s)})}class m extends s{constructor(e,t){super(),this.simulationData=null,this.displayedMessages=[],this.currentMessageIndex=0,this.isRunning=!1,this.isPaused=!1,this.intervalId=null,this.pollingId=null,this.burstPhase=!0,this.totalToShow=1/0,this.virtualLastTimestamp=null,this.realLastTimestamp=null,this.lastTimestamp=null,this.lastDelayMs=0,this.userId="",this.config=e,this.apiClient=t,this.pollingIntervalMs="number"==typeof e.pollingInterval&&e.pollingInterval>0?e.pollingInterval:6e3}async initialize(){try{const e=this.config.language||"en",t=(this.config.country||"").toUpperCase()||void 0,s=this.getPersistedUserId(),n=s||this.config.userId||this.generateUserId();this.userId=n,s||this.persistUserId(n);const i=await this.apiClient.getSimulationData(this.config.projectId,n,e,t);if(!i.success||!i.data)throw new Error("Failed to load simulation data");this.simulationData=i.data;const a=this.simulationData.project.initialBurstCount+this.simulationData.project.continuousCount;this.totalToShow=Math.min(a,this.simulationData.messages.length);const o=this.loadProgress();o&&"number"==typeof o.index?(this.currentMessageIndex=o.index,o.lastTimestamp&&(this.virtualLastTimestamp=new Date(o.lastTimestamp),this.lastTimestamp=new Date(o.lastTimestamp))):(this.currentMessageIndex=0,this.virtualLastTimestamp=null,this.lastTimestamp=null),this.realLastTimestamp=null,await this.loadExistingMessages(),await this.reconstructVirtualHistoryForDisplay(),this.emit("initialized",this.simulationData),this.startPolling(),!1!==this.config.autoStart&&this.start()}catch(e){throw this.emit("error",e),e}}start(){this.simulationData&&!this.isRunning&&(this.isRunning=!0,this.isPaused=!1,this.burstPhase=!0,this.emit("simulationStart"),this.performInitialBurst(),this.currentMessageIndex<this.totalToShow?(this.burstPhase=!1,this.scheduleNextMessage()):(this.isRunning=!1,this.emit("simulationEnd")))}performInitialBurst(){if(!this.simulationData)return;const{project:e,messages:t}=this.simulationData,s=e.initialBurstCount,n=Math.min(s,this.totalToShow,t.length);if(this.currentMessageIndex>=n)return;if(this.displayedMessages.some(e=>e.id.startsWith("sim-"))&&this.currentMessageIndex>0)return;const i=new Date,a=new Array(n);let o=new Date(i);for(let e=n-1;e>=0;e--)if(a[e]=new Date(o),e>0){const e=10+Math.floor(11*Math.random());o=new Date(o.getTime()-60*e*1e3)}const r=[],d=(this.config.country||"US").toUpperCase();let l=!1;for(let e=this.currentMessageIndex;e<n;e++){const s=t[e],n=g(s.content,d);if(s.hasScreenshot&&s.screenshotUrl){const t={id:`sim-${e}-text-${Date.now()}`,content:n,messageType:"text",timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t);const i=new Date(a[e].getTime()+2e3),o={id:`sim-${e}-image-${Date.now()}`,content:s.screenshotUrl,messageType:"image",timestamp:i,isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(o),r.push(o)}else{const t={id:`sim-${e}-${Date.now()}`,content:n,messageType:s.messageType,timestamp:a[e],isOwnMessage:!1,virtualUser:s.virtualUser};this.displayedMessages.push(t),r.push(t)}this.currentMessageIndex=e+1,l=!0}l&&(this.lastTimestamp=a[n-1],this.virtualLastTimestamp=this.lastTimestamp,this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.emit("messages-batch",r)),this.saveProgress()}pause(){this.isRunning&&(this.isPaused=!0,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationPause"))}resume(){this.isRunning&&this.isPaused&&(this.isPaused=!1,this.scheduleNextMessage(),this.emit("simulationResume"))}stop(){this.isRunning=!1,this.isPaused=!1,this.intervalId&&(clearTimeout(this.intervalId),this.intervalId=null),this.emit("simulationStop")}destroy(){this.stop(),this.stopPolling(),this.removeAllListeners()}scheduleNextMessage(){if(!this.simulationData||!this.isRunning||this.isPaused)return;const{project:e,messages:t}=this.simulationData;if(this.currentMessageIndex>=this.totalToShow)return this.isRunning=!1,void this.emit("simulationEnd");let s;if(this.burstPhase){const n=Math.min(e.initialBurstCount,t.length);this.currentMessageIndex<n?s=500+1e3*Math.random():(this.burstPhase=!1,s=this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax))}else{const n=Math.min(e.initialBurstCount,t.length);s=this.currentMessageIndex-n<5?1e3*(e.initialMessageInterval||10):this.getRandomInterval(e.messageIntervalMin,e.messageIntervalMax)}this.lastDelayMs=s,this.intervalId=setTimeout(()=>{this.displayNextMessage(),this.scheduleNextMessage()},s)}displayNextMessage(){if(!this.simulationData||this.currentMessageIndex>=this.simulationData.messages.length)return;const e=this.simulationData.messages[this.currentMessageIndex],t=(this.config.country||"US").toUpperCase(),s=g(e.content,t),n=this.lastTimestamp||new Date,i=new Date(n.getTime()+(this.lastDelayMs||0));if(this.lastTimestamp=i,e.hasScreenshot&&e.screenshotUrl){const t={id:`sim-${this.currentMessageIndex}-text-${Date.now()}`,content:s,messageType:"text",timestamp:i,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t);const n=new Date(i.getTime()+2e3),a={id:`sim-${this.currentMessageIndex}-image-${Date.now()}`,content:e.screenshotUrl,messageType:"image",timestamp:n,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(a),this.lastTimestamp=n,setTimeout(()=>{this.emit("message",a)},2e3)}else{const t={id:`sim-${this.currentMessageIndex}-${Date.now()}`,content:s,messageType:e.messageType,timestamp:i,isOwnMessage:!1,virtualUser:e.virtualUser};this.displayedMessages.push(t),this.emit("message",t)}this.currentMessageIndex++,this.saveProgress()}async loadExistingMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=await this.apiClient.getSimulationMessages(this.config.projectId,e,void 0,100);if(t.success&&t.messages&&t.messages.length>0){const s=t.messages.sort((e,t)=>new Date(e.createdAt||e.timestamp).getTime()-new Date(t.createdAt||t.timestamp).getTime()),n=new Set(this.displayedMessages.map(e=>e.id));for(const t of s){if(n.has(t.id))continue;const s={id:t.id,content:t.content,messageType:t.messageType,timestamp:new Date(t.createdAt||t.timestamp),isOwnMessage:t.userId===e,virtualUser:t.virtualUser,user:t.userId===e?{id:e,username:this.config.username||"You"}:void 0};this.displayedMessages.push(s)}if(s.length>0){const e=s[s.length-1];this.realLastTimestamp=new Date(e.createdAt||e.timestamp)}this.displayedMessages.length>0&&this.emit("messages-batch",[...this.displayedMessages])}}catch(e){console.warn("Failed to load existing messages:",e)}}startPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null),this.pollingId=setInterval(async()=>{await this.pollForNewMessages()},this.pollingIntervalMs)}stopPolling(){this.pollingId&&(clearInterval(this.pollingId),this.pollingId=null)}setPollingInterval(e){!e||e<=0||(this.pollingIntervalMs=e,this.pollingId&&this.startPolling())}get isPolling(){return!!this.pollingId}async pollForNewMessages(){if(this.simulationData)try{const e=this.userId||this.config.userId||this.generateUserId(),t=this.getLastMessageTimestamp(),s=await this.apiClient.getSimulationMessages(this.config.projectId,e,t);if(s.success&&s.messages&&s.messages.length>0){const t=new Set(this.displayedMessages.map(e=>e.id));let n=null;for(const i of s.messages){if(t.has(i.id))continue;const s=new Date(i.createdAt),a={id:i.id,content:i.content,messageType:i.messageType,timestamp:s,isOwnMessage:i.userId===e,virtualUser:i.virtualUser,user:i.userId===e?{id:e,username:this.config.username||"You"}:void 0};(!n||s>n)&&(n=s),this.displayedMessages.push(a),this.emit("message",a)}n&&(this.realLastTimestamp=n)}}catch(e){console.warn("Polling error:",e)}}async reconstructVirtualHistoryForDisplay(){if(!this.simulationData)return;const e=Math.min(this.currentMessageIndex,this.totalToShow,this.simulationData.messages.length);if(e<=0)return;const t=this.loadProgress(),s=(null==t?void 0:t.virtualMessages)||[];if(s.length>0){const e=[],t=new Set(this.displayedMessages.map(e=>e.id));for(const n of s)if(!t.has(n.id)){const t={id:n.id,content:n.content,messageType:n.messageType,timestamp:new Date(n.timestamp),isOwnMessage:!1,virtualUser:n.virtualUser};e.push(t)}if(e.length>0){this.displayedMessages.push(...e),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=e[e.length-1];this.virtualLastTimestamp=t.timestamp,this.lastTimestamp=t.timestamp,this.emit("messages-batch",e)}return}const n=new Date,i=new Array(e);let a=new Date(n);for(let t=e-1;t>=0;t--)if(i[t]=new Date(a),t>0){const e=10+Math.floor(11*Math.random());a=new Date(a.getTime()-60*e*1e3)}const o=[],{messages:r}=this.simulationData,d=(this.config.country||"US").toUpperCase();for(let t=0;t<e;t++){const e=r[t],s=i[t],n=g(e.content,d);if(e.hasScreenshot&&e.screenshotUrl){const i={id:`sim-${t}-text`,content:n,messageType:"text",timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser},a={id:`sim-${t}-image`,content:e.screenshotUrl,messageType:"image",timestamp:new Date(s.getTime()+2e3),isOwnMessage:!1,virtualUser:e.virtualUser};o.push(i,a)}else{const i={id:`sim-${t}`,content:n,messageType:e.messageType,timestamp:s,isOwnMessage:!1,virtualUser:e.virtualUser};o.push(i)}}const l=new Set(this.displayedMessages.map(e=>e.id)),h=o.filter(e=>!l.has(e.id));if(0===h.length)return;this.displayedMessages.push(...h),this.displayedMessages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const c=h[h.length-1];this.virtualLastTimestamp=c.timestamp,this.lastTimestamp=c.timestamp,this.emit("messages-batch",h)}getLastMessageTimestamp(){if(this.realLastTimestamp)return this.realLastTimestamp.toISOString()}getUserKey(){return`vcs:user:${this.config.projectId}`}getProgressKey(){const e=this.userId||this.config.userId||"anon";return`vcs:progress:${this.config.projectId}:${e}`}getPersistedUserId(){try{return"undefined"==typeof window?null:window.localStorage.getItem(this.getUserKey())}catch(e){return null}}persistUserId(e){try{if("undefined"==typeof window)return;window.localStorage.setItem(this.getUserKey(),e)}catch(e){}}loadProgress(){try{if("undefined"==typeof window)return null;const e=window.localStorage.getItem(this.getProgressKey());return e?JSON.parse(e):null}catch(e){return null}}saveProgress(){try{if("undefined"==typeof window)return;const e=this.displayedMessages.filter(e=>e.id.startsWith("sim-")).map(e=>({id:e.id,content:e.content,messageType:e.messageType,timestamp:e.timestamp.toISOString(),virtualUser:e.virtualUser})),t={index:this.currentMessageIndex,lastTimestamp:this.lastTimestamp?this.lastTimestamp.toISOString():void 0,virtualMessages:e};window.localStorage.setItem(this.getProgressKey(),JSON.stringify(t))}catch(e){}}clearProgress(){try{if("undefined"==typeof window)return;window.localStorage.removeItem(this.getProgressKey())}catch(e){}}clearCachedProgress(){this.clearProgress()}getRandomInterval(e,t){return 1e3*(e+Math.random()*(t-e))}generateUserId(){return`user-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}get messages(){return[...this.displayedMessages]}get isSimulationRunning(){return this.isRunning}get isSimulationPaused(){return this.isPaused}get data(){return this.simulationData}async sendMessage(e,t="text"){if(!this.simulationData)throw new Error("Simulation not initialized");const s=this.userId||this.config.userId||this.generateUserId(),n=this.config.username||"User";try{if("image"===t||"string"==typeof e&&e.startsWith("data:image/"))return;await Promise.all([this.apiClient.sendUserMessage(this.config.projectId,s,n,e,t),this.apiClient.triggerAIReply(this.config.projectId,s,n,e,t)])}catch(e){throw this.emit("error",e),e}}}class u{constructor(e){this.baseUrl=e.apiBaseUrl||window.location.origin,this.token=e.token}async request(e,s={}){const n=`${this.baseUrl}${e}`,i={"Content-Type":"application/json",...s.headers};this.token&&(i.Authorization=`Bearer ${this.token}`);try{const e=await fetch(n,{...s,headers:i,credentials:"include"});if(!e.ok)throw new t(`API request failed: ${e.status} ${e.statusText}`,"API_ERROR",{status:e.status,statusText:e.statusText});const a=await e.json();if(!a.success&&a.error)throw new t(a.error,"API_ERROR",a);return a}catch(e){if(e instanceof t)throw e;throw new t(`Network error: ${e.message}`,"NETWORK_ERROR",e)}}async getProject(e){return this.request(`/api/projects/${e}`)}async getTemplate(e,t,s){const n=new URLSearchParams;t&&n.set("lang",t),s&&n.set("country",s);const i=n.toString()?`?${n.toString()}`:"";return this.request(`/api/templates/${e}${i}`)}async getProjectTemplates(e){return this.request(`/api/projects/${e}/templates`)}async sendMessage(e,t,s,n="text"){return this.request("/api/chat/message",{method:"POST",body:JSON.stringify({projectId:e,userId:t,content:s,messageType:n})})}async joinProject(e,t,s){return this.request("/api/chat/join",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s})})}async leaveProject(e,t){return this.request("/api/chat/leave",{method:"POST",body:JSON.stringify({projectId:e,userId:t})})}async getSimulationData(e,t,s,n){const i=new URLSearchParams({userId:t});return s&&i.append("lang",s),n&&i.append("country",n),this.request(`/api/chat/simulation/${e}?${i.toString()}`)}async getSimulationMessages(e,t,s,n){const i=new URLSearchParams({userId:t});return s&&i.append("since",s),n&&i.append("limit",n.toString()),this.request(`/api/chat/simulation/${e}/messages?${i.toString()}`)}async sendUserMessage(e,t,s,n,i="text"){return this.request("/api/chat/send",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}async triggerAIReply(e,t,s,n,i="text"){return this.request("/api/chat/ai-reply",{method:"POST",body:JSON.stringify({projectId:e,userId:t,username:s,content:n,messageType:i})})}setToken(e){this.token=e}setBaseUrl(e){this.baseUrl=e}}const p={en:{joinChat:"Join Chat",chatGroup:"{name} Group",online:"{count} online",inputPlaceholder:"Type a message...",send:"Send",messages:"messages",today:"Today",yesterday:"Yesterday",networkError:"Network error",sendFailed:"Failed to send"},zh:{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在线",inputPlaceholder:"输入消息...",send:"发送",messages:"条消息",today:"今天",yesterday:"昨天",networkError:"网络错误",sendFailed:"发送失败"},"zh-TW":{joinChat:"加入群聊",chatGroup:"{name}交流群",online:"{count} 人在線",inputPlaceholder:"輸入訊息...",send:"發送",messages:"條訊息",today:"今天",yesterday:"昨天",networkError:"網路錯誤",sendFailed:"發送失敗"},es:{joinChat:"Unirse al Chat",chatGroup:"Grupo {name}",online:"{count} en línea",inputPlaceholder:"Escribe un mensaje...",send:"Enviar",messages:"mensajes",today:"Hoy",yesterday:"Ayer",networkError:"Error de red",sendFailed:"Error al enviar"},hi:{joinChat:"चैट में शामिल हों",chatGroup:"{name} समूह",online:"{count} ऑनलाइन",inputPlaceholder:"संदेश लिखें...",send:"भेजें",messages:"संदेश",today:"आज",yesterday:"कल",networkError:"नेटवर्क त्रुटि",sendFailed:"भेजने में विफल"},ar:{joinChat:"انضم للدردشة",chatGroup:"مجموعة {name}",online:"{count} متصل",inputPlaceholder:"اكتب رسالة...",send:"إرسال",messages:"رسائل",today:"اليوم",yesterday:"أمس",networkError:"خطأ في الشبكة",sendFailed:"فشل الإرسال"},pt:{joinChat:"Entrar no Chat",chatGroup:"Grupo {name}",online:"{count} online",inputPlaceholder:"Digite uma mensagem...",send:"Enviar",messages:"mensagens",today:"Hoje",yesterday:"Ontem",networkError:"Erro de rede",sendFailed:"Falha ao enviar"},bn:{joinChat:"চ্যাটে যোগ দিন",chatGroup:"{name} গ্রুপ",online:"{count} অনলাইন",inputPlaceholder:"একটি বার্তা লিখুন...",send:"পাঠান",messages:"বার্তা",today:"আজ",yesterday:"গতকাল",networkError:"নেটওয়ার্ক ত্রুটি",sendFailed:"পাঠাতে ব্যর্থ"},ru:{joinChat:"Присоединиться",chatGroup:"Группа {name}",online:"{count} онлайн",inputPlaceholder:"Введите сообщение...",send:"Отправить",messages:"сообщений",today:"Сегодня",yesterday:"Вчера",networkError:"Ошибка сети",sendFailed:"Не удалось отправить"},ja:{joinChat:"チャットに参加",chatGroup:"{name}グループ",online:"{count} オンライン",inputPlaceholder:"メッセージを入力...",send:"送信",messages:"メッセージ",today:"今日",yesterday:"昨日",networkError:"ネットワークエラー",sendFailed:"送信失敗"},de:{joinChat:"Chat beitreten",chatGroup:"{name} Gruppe",online:"{count} online",inputPlaceholder:"Nachricht eingeben...",send:"Senden",messages:"Nachrichten",today:"Heute",yesterday:"Gestern",networkError:"Netzwerkfehler",sendFailed:"Senden fehlgeschlagen"},fr:{joinChat:"Rejoindre le Chat",chatGroup:"Groupe {name}",online:"{count} en ligne",inputPlaceholder:"Tapez un message...",send:"Envoyer",messages:"messages",today:"Aujourd'hui",yesterday:"Hier",networkError:"Erreur réseau",sendFailed:"Échec de l'envoi"},ko:{joinChat:"채팅 참여",chatGroup:"{name} 그룹",online:"{count} 온라인",inputPlaceholder:"메시지 입력...",send:"전송",messages:"메시지",today:"오늘",yesterday:"어제",networkError:"네트워크 오류",sendFailed:"전송 실패"},it:{joinChat:"Unisciti alla Chat",chatGroup:"Gruppo {name}",online:"{count} online",inputPlaceholder:"Scrivi un messaggio...",send:"Invia",messages:"messaggi",today:"Oggi",yesterday:"Ieri",networkError:"Errore di rete",sendFailed:"Invio fallito"},tr:{joinChat:"Sohbete Katıl",chatGroup:"{name} Grubu",online:"{count} çevrimiçi",inputPlaceholder:"Bir mesaj yazın...",send:"Gönder",messages:"mesaj",today:"Bugün",yesterday:"Dün",networkError:"Ağ hatası",sendFailed:"Gönderilemedi"},vi:{joinChat:"Tham gia Chat",chatGroup:"Nhóm {name}",online:"{count} trực tuyến",inputPlaceholder:"Nhập tin nhắn...",send:"Gửi",messages:"tin nhắn",today:"Hôm nay",yesterday:"Hôm qua",networkError:"Lỗi mạng",sendFailed:"Gửi thất bại"},pl:{joinChat:"Dołącz do Czatu",chatGroup:"Grupa {name}",online:"{count} online",inputPlaceholder:"Wpisz wiadomość...",send:"Wyślij",messages:"wiadomości",today:"Dziś",yesterday:"Wczoraj",networkError:"Błąd sieci",sendFailed:"Nie udało się wysłać"},th:{joinChat:"เข้าร่วมแชท",chatGroup:"กลุ่ม {name}",online:"{count} ออนไลน์",inputPlaceholder:"พิมพ์ข้อความ...",send:"ส่ง",messages:"ข้อความ",today:"วันนี้",yesterday:"เมื่อวาน",networkError:"ข้อผิดพลาดเครือข่าย",sendFailed:"ส่งไม่สำเร็จ"},nl:{joinChat:"Deelnemen aan Chat",chatGroup:"{name} Groep",online:"{count} online",inputPlaceholder:"Typ een bericht...",send:"Verzenden",messages:"berichten",today:"Vandaag",yesterday:"Gisteren",networkError:"Netwerkfout",sendFailed:"Verzenden mislukt"},id:{joinChat:"Gabung Chat",chatGroup:"Grup {name}",online:"{count} online",inputPlaceholder:"Ketik pesan...",send:"Kirim",messages:"pesan",today:"Hari ini",yesterday:"Kemarin",networkError:"Kesalahan jaringan",sendFailed:"Gagal mengirim"},ms:{joinChat:"Sertai Chat",chatGroup:"Kumpulan {name}",online:"{count} dalam talian",inputPlaceholder:"Taip mesej...",send:"Hantar",messages:"mesej",today:"Hari ini",yesterday:"Semalam",networkError:"Ralat rangkaian",sendFailed:"Gagal menghantar"}};function y(e){if(p[e])return p[e];const t=e.split("-")[0];return p[t]?p[t]:p.en}function v(e,t){return e.replace(/\{(\w+)\}/g,(e,s)=>void 0!==t[s]?String(t[s]):e)}class b extends s{constructor(e){var t,s;super(),this.emojiPanelOpen=!1,this.onlineCount=0,this.currentTheme="whatsapp",this.isDarkMode=!1,this.customColors={},this.visibleStartIndex=0,this.hasInitializedData=!1,this.pollingStopTimer=null,this.config={...e,mode:e.mode||"floating"},this.t=y(e.language||"en"),this.currentTheme="telegram"===e.uiTemplate?"telegram":"whatsapp",this.isDarkMode="dark"===e.theme,this.customColors={primary:e.primaryColor,background:e.backgroundColor},this.onlineCount=500+Math.floor(301*Math.random()),this.initialRenderCount=null!==(t=this.config.initialRenderCount)&&void 0!==t?t:Number.MAX_SAFE_INTEGER,this.lazyLoadBatchSize=null!==(s=this.config.lazyLoadBatchSize)&&void 0!==s?s:20,this.state={isInitialized:!1,isOpen:!1,isJoined:!1,isConnected:!1,isSimulationRunning:!1,isSimulationPaused:!1,messages:[],virtualUsers:[],realUsers:[],typingUsers:[],simulationEnded:!1,displayedMessageCount:0,unreadCount:0,lastReadMessageId:null},this.apiClient=new u(e),this.simulator=new m(e,this.apiClient),this.setupSimulatorEvents(),this.init()}init(){try{this.setupContainer(),this.createWidget(),"floating"===this.config.mode&&(this.widgetElement.style.display="none",this.createFloatingButton()),this.setupEventListeners(),this.setupImageViewer(),this.state.isInitialized=!0,this.emit("ready")}catch(e){this.emit("error",new t("Failed to initialize chat widget","WIDGET_INIT_ERROR",e))}}setupSimulatorEvents(){this.simulator.on("initialized",e=>{var t;this.state.currentProject=e.project,this.state.currentTemplate=e.template,null!=this.config.initialRenderCount?this.initialRenderCount=this.config.initialRenderCount:this.initialRenderCount=Number.MAX_SAFE_INTEGER,this.setTitle((null===(t=e.project)||void 0===t?void 0:t.name)||"Chat",`0 ${this.t.messages}`),this.setLoading(!1),this.emit("simulationInitialized",e)}),this.simulator.on("message",e=>{var t;this.setLoading(!1),this.addMessage(e),this.state.displayedMessageCount++;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`)}),this.simulator.on("messages-batch",e=>{var t;this.setLoading(!1),this.addMessagesBulk(e),this.state.displayedMessageCount+=e.length;const s=(null===(t=this.state.currentProject)||void 0===t?void 0:t.name)||"Chat";this.setTitle(s,`${this.state.displayedMessageCount} ${this.t.messages}`),setTimeout(()=>{this.scrollToBottom(!0)},100)}),this.simulator.on("simulationStart",()=>{var e,t;this.state.isSimulationRunning=!0,this.state.isSimulationPaused=!1,null===(t=(e=this.config).onSimulationStart)||void 0===t||t.call(e)}),this.simulator.on("simulationEnd",()=>{var e,t;this.state.isSimulationRunning=!1,this.state.simulationEnded=!0,null===(t=(e=this.config).onSimulationEnd)||void 0===t||t.call(e)}),this.simulator.on("simulationPause",()=>{this.state.isSimulationPaused=!0}),this.simulator.on("simulationResume",()=>{this.state.isSimulationPaused=!1}),this.simulator.on("error",e=>{this.emit("error",e)})}async initializeSimulation(){try{await this.simulator.initialize()}catch(e){this.emit("error",new t("Failed to initialize simulation","SIMULATION_INIT_ERROR",e))}}setupContainer(){var e;const s=function(e){if("string"==typeof e)return document.querySelector(e)||document.body;return e||document.body}(this.config.container);if(!s)throw new t("Container element not found","CONTAINER_NOT_FOUND");const n=null===(e=s.tagName)||void 0===e?void 0:e.toUpperCase();if("BODY"===n||"HTML"===n){const e=document.createElement("div");e.className="chat-sdk-host",e.style.position="static",e.style.width="0",e.style.height="0",document.body.appendChild(e),this.container=e}else this.container=s;this.shadowRoot=this.container.attachShadow({mode:"closed"});const i=this.getDefaultStyles();!function(e,t){const s=document.createElement("style");s.textContent=t,e.appendChild(s)}(this.shadowRoot,i)}createWidget(){var e;if(this.widgetElement&&this.messagesContainer)return;this.widgetElement=n("div","chat-sdk-container");const t="telegram"===this.config.uiTemplate?"telegram":"whatsapp";this.currentTheme=t,this.widgetElement.classList.add(`${t}-theme`),"telegram"===t&&"dark"===this.config.theme&&(this.widgetElement.classList.add("dark"),this.isDarkMode=!0),this.widgetElement.style.position="fixed",this.widgetElement.style.top="0",this.widgetElement.style.left="0",this.widgetElement.style.width="100vw",this.widgetElement.style.height="100vh",this.widgetElement.style.zIndex=String(null!==(e=this.config.zIndex)&&void 0!==e?e:2147483e3),this.widgetElement.innerHTML=`\n <div class="chat-sdk-header">\n <div class="chat-sdk-header-left">\n <div class="chat-sdk-title" id="chat-title"></div>\n <div class="chat-sdk-subtitle" id="chat-subtitle"></div>\n </div>\n <button class="chat-sdk-close-btn" type="button">\n <svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor">\n <path d="M8 7.293l2.146-2.147a.5.5 0 01.708.708L8.707 8l2.147 2.146a.5.5 0 01-.708.708L8 8.707l-2.146 2.147a.5.5 0 01-.708-.708L7.293 8 5.146 5.854a.5.5 0 01.708-.708L8 7.293z"/>\n </svg>\n </button>\n </div>\n\n <div class="chat-sdk-messages" id="messages-container">\n <div class="chat-sdk-loading">\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n </div>\n </div>\n\n <div class="chat-sdk-input-area">\n <button class="chat-sdk-icon-btn chat-sdk-emoji-btn" type="button" id="emoji-button" aria-label="Emoji">\n <span>😊</span>\n </button>\n <button class="chat-sdk-icon-btn chat-sdk-image-btn" type="button" id="image-button" aria-label="Image">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14h18zM5 5h14v8l-3-3-4 5-3-4-4 4V5z"/></svg>\n </button>\n <textarea\n class="chat-sdk-input"\n placeholder="${this.t.inputPlaceholder}"\n rows="1"\n id="message-input"\n ></textarea>\n <input type="file" accept="image/*" id="image-input" style="display:none" />\n <button class="chat-sdk-send-btn" type="button" id="send-button" disabled>\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <path d="M15.854.146a.5.5 0 01.11.54l-5.819 14.547a.75.75 0 01-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 01.124-1.33L15.314.037a.5.5 0 01.54.11z"/>\n </svg>\n </button>\n </div>\n <div class="chat-sdk-emoji-picker" id="emoji-picker" style="display:none">\n <div class="chat-sdk-emoji-grid">\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😀">😀</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😁">😁</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😂">😂</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤣">🤣</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😊">😊</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😍">😍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="😎">😎</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🤔">🤔</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="👍">👍</button>\n <button type="button" class="chat-sdk-emoji-item" data-emoji="🙏">🙏</button>\n </div>\n </div>\n `,this.messagesContainer=this.widgetElement.querySelector("#messages-container"),this.inputElement=this.widgetElement.querySelector("#message-input"),this.sendButton=this.widgetElement.querySelector("#send-button"),this.emojiButton=this.widgetElement.querySelector("#emoji-button"),this.imageButton=this.widgetElement.querySelector("#image-button"),this.fileInput=this.widgetElement.querySelector("#image-input"),this.emojiPicker=this.widgetElement.querySelector("#emoji-picker"),this.shadowRoot.appendChild(this.widgetElement)}setupEventListeners(){var e,t,s,n;const i=this.widgetElement.querySelector(".chat-sdk-close-btn");null==i||i.addEventListener("click",()=>this.close()),this.messagesContainer.addEventListener("scroll",this.handleScrollLazyLoad.bind(this)),this.inputElement.addEventListener("input",this.handleInputChange.bind(this)),this.inputElement.addEventListener("keydown",this.handleKeyDown.bind(this)),this.sendButton.addEventListener("click",this.handleSendMessage.bind(this)),this.inputElement.addEventListener("input",this.autoResizeTextarea.bind(this)),null===(e=this.emojiButton)||void 0===e||e.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.toggleEmojiPicker(!this.emojiPanelOpen)}),null===(t=this.emojiPicker)||void 0===t||t.addEventListener("click",e=>{const t=e.target.closest(".chat-sdk-emoji-item");if(t&&t.hasAttribute("data-emoji")){const e=t.getAttribute("data-emoji")||"";this.insertEmojiAtCursor(e),this.toggleEmojiPicker(!1)}}),this.shadowRoot.addEventListener("click",e=>{const t=e.target,s=t.closest("#emoji-picker"),n=t.closest("#emoji-button");s||n||this.toggleEmojiPicker(!1)}),null===(s=this.imageButton)||void 0===s||s.addEventListener("click",e=>{var t;e.preventDefault(),e.stopPropagation(),null===(t=this.fileInput)||void 0===t||t.click()}),null===(n=this.fileInput)||void 0===n||n.addEventListener("change",this.handleImageSelected.bind(this)),document.addEventListener("keydown",e=>{"Escape"===e.key&&this.state.isOpen&&this.close()})}createFloatingButton(){var e,t,s,n,i,a,o,r,d,l,h;if(!this.shadowRoot)return;const c=this.config.floatingButton||{},g=c.position||"bottom-right",m=String(null!==(t=null!==(e=c.zIndex)&&void 0!==e?e:this.config.zIndex)&&void 0!==t?t:2147483e3),u={top:null===(s=c.offset)||void 0===s?void 0:s.top,right:null===(n=c.offset)||void 0===n?void 0:n.right,bottom:null!==(a=null===(i=c.offset)||void 0===i?void 0:i.bottom)&&void 0!==a?a:20,left:null===(o=c.offset)||void 0===o?void 0:o.left},p=document.createElement("button");p.className="chat-sdk-floating-btn",p.setAttribute("aria-label","Open chat");const y=this.t.joinChat;p.innerHTML=`\n <div style="\n position: relative;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 6px;\n ">\n \x3c!-- Group chat icon (users) --\x3e\n <svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" style="margin-bottom: 2px;">\n <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/>\n </svg>\n\n \x3c!-- Text overlay at bottom --\x3e\n <div style="\n font-size: 10px;\n font-weight: 600;\n color: rgba(255, 255, 255, 0.95);\n text-align: center;\n line-height: 1.2;\n letter-spacing: 0.3px;\n text-shadow: 0 1px 2px rgba(0,0,0,0.2);\n ">${y}</div>\n\n \x3c!-- Unread badge --\x3e\n <span class="chat-sdk-unread-badge" style="\n position: absolute;\n top: -6px;\n right: -6px;\n background: #ff4444;\n color: white;\n border-radius: 10px;\n min-width: 18px;\n height: 18px;\n display: none;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n padding: 0 5px;\n "></span>\n </div>\n `,p.style.position="fixed",p.style.zIndex=m,p.style.width="60px",p.style.height="60px",p.style.borderRadius="50%",p.style.border="none",p.style.cursor="pointer",p.style.display="flex",p.style.alignItems="center",p.style.justifyContent="center",p.style.color="#fff",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)",p.style.background="linear-gradient(145deg, #25D366 0%, #128C7E 100%)",p.style.transition="transform .15s ease, box-shadow .15s ease",p.style.overflow="visible",g.includes("bottom")?(p.style.bottom=(null!==(r=u.bottom)&&void 0!==r?r:20)+"px",p.style.top=""):(p.style.top=(null!==(d=u.top)&&void 0!==d?d:20)+"px",p.style.bottom=""),g.includes("right")?(p.style.right=(null!==(l=u.right)&&void 0!==l?l:20)+"px",p.style.left=""):(p.style.left=(null!==(h=u.left)&&void 0!==h?h:20)+"px",p.style.right=""),p.addEventListener("mouseenter",()=>{p.style.transform="scale(1.06)",p.style.boxShadow="0 14px 28px rgba(0,0,0,0.30), inset 0 2px 4px rgba(255,255,255,0.2)"}),p.addEventListener("mouseleave",()=>{p.style.transform="scale(1)",p.style.boxShadow="0 10px 24px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.15)"}),p.addEventListener("mousedown",()=>{p.style.transform="scale(0.95)"}),p.addEventListener("mouseup",()=>{p.style.transform="scale(1.05)",setTimeout(()=>p.style.transform="scale(1)",100)}),p.addEventListener("click",e=>{e.preventDefault(),this.open()}),this.shadowRoot.appendChild(p),this.floatingButtonEl=p}updateUnreadBadge(){if(!this.floatingButtonEl)return;const e=this.floatingButtonEl.querySelector(".chat-sdk-unread-badge");if(!e)return;const t=this.state.unreadCount;t>0?(e.textContent=t>99?"99+":t.toString(),e.style.display="flex"):e.style.display="none"}markAllAsRead(){if(this.state.messages.length>0){const e=this.state.messages[this.state.messages.length-1];this.state.lastReadMessageId=e.id}this.state.unreadCount=0,this.updateUnreadBadge()}incrementUnreadCount(){this.state.isOpen||(this.state.unreadCount++,this.updateUnreadBadge())}toggleEmojiPicker(e){const t=this.emojiPicker;if(!t)return;const s="boolean"==typeof e?e:"none"===t.style.display;t.style.display=s?"block":"none",this.emojiPanelOpen=s}insertEmojiAtCursor(e){const t=this.inputElement,s=t.selectionStart||0,n=t.selectionEnd||0,i=t.value.substring(0,s),a=t.value.substring(n);t.value=i+e+a;const o=s+e.length;t.setSelectionRange(o,o),t.focus(),this.handleInputChange(),this.autoResizeTextarea()}isEmojiOnly(e){const t=e.trim();if(!t)return!1;if(t.length>6)return!1;let s=!1;for(let e=0;e<t.length;){const n=t.codePointAt(e)||0;if(e+=n>65535?2:1,!(n>=126976))return!1;s=!0}return s}async handleImageSelected(){const e=this.fileInput;if(!e||!e.files||0===e.files.length)return;const s=e.files[0];try{const t=await this.resizeImageFile(s,1280,.85),n={id:`local-img-failed-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:t,messageType:"image",timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"},failed:!0};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),e.value=""}catch(e){console.error("Image processing failed",e),this.emit("error",new t("Image processing failed","IMAGE_PROCESS_ERROR",e))}}resizeImageFile(e,t=1280,s=.85){return new Promise((n,i)=>{const a=URL.createObjectURL(e),o=new Image;o.onload=()=>{let{width:e,height:r}=o;const d=Math.min(1,t/Math.max(e,r)),l=document.createElement("canvas");d<1&&(e=Math.round(e*d),r=Math.round(r*d)),l.width=e,l.height=r;const h=l.getContext("2d");if(!h)return URL.revokeObjectURL(a),void i(new Error("Canvas not supported"));h.drawImage(o,0,0,e,r);const c=l.toDataURL("image/jpeg",s);URL.revokeObjectURL(a),n(c)},o.onerror=e=>{URL.revokeObjectURL(a),i(e)},o.src=a})}handleInputChange(){const e=this.inputElement.value.trim().length>0,t=!1!==this.config.enableUserInput&&!1!==this.config.allowInput;this.sendButton.disabled=!e||!t,e&&t&&this.emit("typing")}handleKeyDown(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),this.handleSendMessage())}async handleSendMessage(){const e=this.inputElement.value.trim();if(!e)return;if(!1===this.config.enableUserInput||!1===this.config.allowInput)return;const s=this.isEmojiOnly(e)?"emoji":"text",n={id:`local-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,content:e,messageType:s,timestamp:new Date,isOwnMessage:!0,user:{id:this.config.userId||"me",username:this.config.username||"You"}};this.state.messages.push(n),this.renderMessage(n),this.scrollToBottom(!0),this.inputElement.value="",this.sendButton.disabled=!0,this.autoResizeTextarea(),this.simulator.sendMessage(e,s).catch(e=>{console.error("Failed to send message:",e),this.emit("error",new t("Failed to send message","SEND_MESSAGE_ERROR",e))})}autoResizeTextarea(){this.inputElement.style.height="auto",this.inputElement.style.height=Math.min(this.inputElement.scrollHeight,100)+"px"}open(){var e;if(this.state.isOpen)return;if(this.hasInitializedData)try{this.simulator.startPolling()}catch(e){}else this.hasInitializedData=!0,this.setLoading(!0),this.initializeSimulation().catch(e=>{console.error("Failed to initialize simulation on open:",e),this.setLoading(!1)});this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null),this.floatingButtonEl&&(this.floatingButtonEl.style.display="none"),this.widgetElement.style.opacity="0",this.widgetElement.style.display="flex",requestAnimationFrame(()=>{this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="1"}),this.state.isOpen=!0,this.markAllAsRead(),this.emit("open");const t=(null===(e=this.state.currentProject)||void 0===e?void 0:e.name)||"Chat";this.setTitle(t,`${this.state.displayedMessageCount} ${this.t.messages}`),this.scrollToBottom(!0),requestAnimationFrame(()=>this.scrollToBottom(!0)),setTimeout(()=>this.scrollToBottom(!0),0)}close(){this.state.isOpen&&(this.widgetElement.style.transition="opacity .2s ease",this.widgetElement.style.opacity="0",setTimeout(()=>{this.widgetElement.style.display="none",this.floatingButtonEl&&(this.floatingButtonEl.style.display="flex")},200),this.state.isOpen=!1,this.pollingStopTimer&&clearTimeout(this.pollingStopTimer),this.pollingStopTimer=setTimeout(()=>{try{this.simulator.stopPolling()}catch(e){}this.pollingStopTimer=null},1e4),this.emit("close"))}setTitle(e,t){var s,n;const i=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector("#chat-title"),a=null===(n=this.widgetElement)||void 0===n?void 0:n.querySelector("#chat-subtitle"),o=v(this.t.chatGroup,{name:e||"Chat"});this.currentTheme,i&&(i.textContent=o),a&&(a.textContent=v(this.t.online,{count:this.onlineCount}),a.style.display="block")}buildMessageElement(e,t){const s=n("div","chat-sdk-message");e.isOwnMessage&&s.classList.add("own");const i=!!t&&this.shouldGroupWithPrev(t,e);i&&s.classList.add("grouped");let a=null;e.isOwnMessage||(a=this.createAvatar(e),i&&a&&(a.style.visibility="hidden"));const o=!e.isOwnMessage&&!i,r="whatsapp"===this.currentTheme,d="telegram"===this.currentTheme&&e.isOwnMessage,l=this.createMessageContent(e,o,r,d);return a&&s.appendChild(a),s.appendChild(l),s}shouldGroupWithPrev(e,t){var s,n,i,a,o,r,d;if(!1===this.config.groupMessages)return!1;const l=null!==(s=this.config.groupTimeThresholdSec)&&void 0!==s?s:120,h=e.isOwnMessage===t.isOwnMessage,c=(null===(n=e.virtualUser)||void 0===n?void 0:n.id)&&(null===(i=e.virtualUser)||void 0===i?void 0:i.id)===(null===(a=t.virtualUser)||void 0===a?void 0:a.id),g=(null===(o=e.user)||void 0===o?void 0:o.id)&&(null===(r=e.user)||void 0===r?void 0:r.id)===(null===(d=t.user)||void 0===d?void 0:d.id),m=h&&(c||g||e.isOwnMessage&&t.isOwnMessage),u=Math.abs(t.timestamp.getTime()-e.timestamp.getTime())/1e3;return!!m&&u<=l}handleScrollLazyLoad(){if(this.messagesContainer.scrollTop<=20&&this.visibleStartIndex>0){const e=this.messagesContainer.scrollHeight,t=this.lazyLoadBatchSize,s=Math.max(0,this.visibleStartIndex-t),n=this.state.messages.slice(s,this.visibleStartIndex),i=document.createDocumentFragment();for(const e of n){const t=this.buildMessageElement(e);i.appendChild(t)}this.messagesContainer.insertBefore(i,this.messagesContainer.firstChild),this.visibleStartIndex=s;const a=this.messagesContainer.scrollHeight;this.messagesContainer.scrollTop+=a-e}}setLoading(e){if(e){if(!this.messagesContainer.querySelector(".chat-sdk-loading")){const e=document.createElement("div");e.className="chat-sdk-loading",e.innerHTML='\n <div class="chat-sdk-spinner"></div>\n Loading chat...\n ',this.messagesContainer.appendChild(e)}}else{const e=this.messagesContainer.querySelector(".chat-sdk-loading");null==e||e.remove()}}showJoinOverlay(){const e=n("div","chat-sdk-overlay");e.innerHTML='\n <div class="chat-sdk-join-card">\n <h3 class="chat-sdk-join-title">Join the conversation</h3>\n <p class="chat-sdk-join-description">\n Click below to join this group chat and start interacting with other members.\n </p>\n <button class="chat-sdk-join-btn" type="button">Join Chat</button>\n </div>\n ';const t=e.querySelector(".chat-sdk-join-btn");null==t||t.addEventListener("click",()=>{this.hideJoinOverlay(),this.emit("join-requested")}),this.widgetElement.appendChild(e)}hideJoinOverlay(){const e=this.widgetElement.querySelector(".chat-sdk-overlay");e&&e.remove()}addMessage(e){if(e.isOwnMessage)for(let t=this.state.messages.length-1;t>=0;t--){const s=this.state.messages[t];if(s.isOwnMessage&&s.content===e.content){if(Math.abs(e.timestamp.getTime()-s.timestamp.getTime())<=1e4)return;break}}this.state.messages.find(t=>t.id===e.id)?console.warn("Duplicate message detected and ignored:",e.id):(this.state.messages.push(e),this.renderMessage(e),e.isOwnMessage||this.incrementUnreadCount(),this.scrollToBottom(!0))}addMessagesBulk(e){if(!e||0===e.length)return;if(0===this.messagesContainer.querySelectorAll(".chat-sdk-message").length){this.state.messages=[...e].sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());const t=this.state.messages.length,s=this.initialRenderCount;this.visibleStartIndex=Math.max(0,t-s);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),setTimeout(()=>{this.scrollToBottom(!0)},0)}else{const t=new Set(this.state.messages.map(e=>e.id)),s=e.filter(e=>!t.has(e.id));if(s.length>0){this.state.messages.push(...s),this.state.messages.sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime()),this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=this.initialRenderCount;this.visibleStartIndex=Math.max(0,e-t);const n=this.state.messages.slice(this.visibleStartIndex),i=document.createDocumentFragment();let a;for(const e of n){const t=this.buildMessageElement(e,a);i.appendChild(t),a=e}this.messagesContainer.appendChild(i),this.scrollToBottom()}}}reRenderAllMessages(){this.messagesContainer.innerHTML="";const e=this.state.messages.length,t=Math.max(0,e-this.initialRenderCount);this.state.messages.slice(t).forEach(e=>{this.renderMessage(e)}),this.scrollToBottom()}renderMessage(e){const t=this.state.messages.length-1,s=t>0?this.state.messages[t-1]:void 0,n=this.buildMessageElement(e,s);this.messagesContainer.appendChild(n)}createAvatar(e){var t,s,i,a;const o=n("div","chat-sdk-message-avatar");if(null===(t=e.virtualUser)||void 0===t?void 0:t.avatar)o.style.backgroundImage=`url(${e.virtualUser.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else if(null===(s=e.user)||void 0===s?void 0:s.avatar)o.style.backgroundImage=`url(${e.user.avatar})`,o.style.backgroundSize="cover",o.style.backgroundPosition="center";else{const t=(null===(i=e.virtualUser)||void 0===i?void 0:i.username)||(null===(a=e.user)||void 0===a?void 0:a.username)||"U";o.textContent=t.charAt(0).toUpperCase()}return o}createMessageContent(e,t=!0,s=!1,a=!1){var o,r,d;const l=n("div","chat-sdk-message-content"),h=(null===(o=e.virtualUser)||void 0===o?void 0:o.displayName)||(null===(r=e.virtualUser)||void 0===r?void 0:r.username)||(null===(d=e.user)||void 0===d?void 0:d.username)||"Unknown";let c="";if("image"===e.messageType){c=`\n <div class="chat-sdk-message-image${e.failed?" failed":""}">\n <img src="${i(e.content)}" alt="Image"\n style="max-width: 100%; height: auto; cursor: pointer;"\n data-image-url="${i(e.content)}"\n class="chat-sdk-image-preview" />\n </div>\n `}else c="emoji"===e.messageType?`<div class="chat-sdk-message-emoji" style="font-size: 2em; line-height: 1;">${i(e.content)}</div>`:`<p class="chat-sdk-message-text">${i(e.content)}</p>`;const g=`${function(e,t){const s=new Date,n=Math.floor((s.getTime()-e.getTime())/1e3),i=(t||("undefined"!=typeof navigator?navigator.language:"en")).toLowerCase().startsWith("zh");if(n<60)return i?"刚刚":"just now";if(n<3600){const e=Math.floor(n/60);return i?`${e} 分钟前`:`${e}m ago`}if(n<86400){const e=Math.floor(n/3600);return i?`${e} 小时前`:`${e}h ago`}const a=new Date(s.getFullYear(),s.getMonth(),s.getDate());if(e>=new Date(a.getTime()-864e5)&&e<a){const t=e.toLocaleTimeString(i?"zh-CN":void 0,{hour:"2-digit",minute:"2-digit",hour12:!1});return i?`昨天 ${t}`:`yesterday ${t}`}return s.getTime()-e.getTime()<6048e5?e.toLocaleString(i?"zh-CN":void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}):e.toLocaleString(i?"zh-CN":void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1})}(e.timestamp,this.config.language)}`,m=a?'<span class="chat-sdk-read-status">✓✓</span>':"",u=e.failed&&e.isOwnMessage?'<div class="chat-sdk-message-failed-indicator">\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <circle cx="8" cy="8" r="8" fill="#ff4444"/>\n <path d="M8 4v4M8 10h.01" stroke="white" stroke-width="1.5" stroke-linecap="round"/>\n </svg>\n </div>':"";l.innerHTML=s?`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${i(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n <div class="chat-sdk-message-time-inside">${g}${m?" "+m:""}</div>\n </div>\n ${u}\n `:`\n ${t&&!e.isOwnMessage?`<div class="chat-sdk-message-username">${i(h)}</div>`:""}\n <div class="chat-sdk-message-bubble">\n ${c}\n </div>\n <div class="chat-sdk-message-time">${g}${m?" "+m:""}</div>\n ${u}\n `;const p=l.querySelector(".chat-sdk-image-preview");return p&&p.addEventListener("click",e=>{e.preventDefault();const t=e.target.getAttribute("data-image-url");t&&this.showImagePreview(t)}),l}scrollToBottom(e=!1){const t=this.messagesContainer;if(e)return void a(t);t.scrollTop+t.clientHeight>=t.scrollHeight-40&&a(t)}setupImageViewer(){this.messagesContainer.addEventListener("click",e=>{const t=e.target;if(t.classList.contains("chat-sdk-image-preview")){const e=t.getAttribute("data-image-url");e&&this.openImageViewer(e)}})}openImageViewer(e){const t=n("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-backdrop">\n <div class="chat-sdk-image-container">\n <button class="chat-sdk-image-close" aria-label="Close">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n <img class="chat-sdk-image-full" src="${i(e)}" alt="Full size image" />\n </div>\n </div>\n `,this.shadowRoot.appendChild(t);const s=t.querySelector(".chat-sdk-image-close"),a=t.querySelector(".chat-sdk-image-backdrop"),o=()=>{t.remove()};null==s||s.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r),requestAnimationFrame(()=>{t.classList.add("chat-sdk-image-modal-open")})}showImagePreview(e){const t=n("div","chat-sdk-image-modal");t.innerHTML=`\n <div class="chat-sdk-image-modal-overlay">\n <div class="chat-sdk-image-modal-content">\n <button class="chat-sdk-image-modal-close">&times;</button>\n <img src="${i(e)}" alt="Image Preview" class="chat-sdk-image-modal-img" />\n </div>\n </div>\n `,this.widgetElement.appendChild(t);const s=t.querySelector(".chat-sdk-image-modal-close"),a=t.querySelector(".chat-sdk-image-modal-overlay"),o=()=>{t.remove()};null==s||s.addEventListener("click",o),null==a||a.addEventListener("click",e=>{e.target===a&&o()});const r=e=>{"Escape"===e.key&&(o(),document.removeEventListener("keydown",r))};document.addEventListener("keydown",r)}setJoined(e){this.state.isJoined=e,this.handleInputChange()}setUITemplate(e){this.currentTheme=e,this.config.uiTemplate=e,this.widgetElement.classList.remove("whatsapp-theme","telegram-theme","dark"),this.widgetElement.classList.add(`${e}-theme`),"telegram"===e&&this.isDarkMode&&this.widgetElement.classList.add("dark"),this.updateThemeStyles(),this.reRenderAllMessages()}setTheme(e){this.isDarkMode="dark"===e,this.config.theme=e,"telegram"===this.currentTheme&&(this.isDarkMode?this.widgetElement.classList.add("dark"):this.widgetElement.classList.remove("dark"),this.updateThemeStyles())}setCustomColors(e){this.customColors={...this.customColors,...e},this.config.primaryColor=e.primary,this.config.backgroundColor=e.background,this.updateThemeStyles()}updateThemeStyles(){const e=this.currentTheme,t=this.isDarkMode&&"telegram"===e,s=this.shadowRoot||document.documentElement;"whatsapp"===e?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#25D366"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#ECE5DD"),this.setCSSProperty(s,"--chat-message-own-bg","#DCF8C6"),this.setCSSProperty(s,"--chat-message-other-bg","#FFFFFF"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #075e54 0%, #128c7e 100%)")):"telegram"===e&&(t?(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#4FC3F7"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#212121"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#2F2F2F"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #1976d2 0%, #1565c0 100%)"),this.setCSSProperty(s,"--chat-text-color","#FFFFFF")):(this.setCSSProperty(s,"--chat-primary-color",this.customColors.primary||"#2481CC"),this.setCSSProperty(s,"--chat-background-color",this.customColors.background||"#FFFFFF"),this.setCSSProperty(s,"--chat-message-own-bg","linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%)"),this.setCSSProperty(s,"--chat-message-other-bg","#F1F1F1"),this.setCSSProperty(s,"--chat-header-bg","linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%)"),this.setCSSProperty(s,"--chat-text-color","#000000")))}setCSSProperty(e,t,s){if(e instanceof ShadowRoot){const n=e.querySelector("style");if(n){const e=n.textContent||"",i=new RegExp(`${t}\\s*:\\s*[^;]+;`,"g"),a=`${t}: ${s};`;if(i.test(e))n.textContent=e.replace(i,a);else{const t=/:host\s*\{([^}]*)\}/;t.test(e)?n.textContent=e.replace(t,(e,t)=>`:host { ${t} ${a} }`):n.textContent=`:host { ${a} }\n${e}`}}}else e.style.setProperty(t,s)}getState(){return{...this.state}}getDefaultStyles(){return"\n :host {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #333333;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: var(--chat-text-color);\n background: var(--chat-background-color);\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n position: relative;\n max-width: 100%;\n max-height: 100%;\n }\n\n .chat-sdk-container * {\n box-sizing: border-box;\n }\n\n /* WhatsApp Theme */\n .chat-sdk-container.whatsapp-theme .chat-sdk-header {\n background: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-header-left { display: none; }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-messages {\n background-color: #ece5dd;\n background-image: url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23e5ddd5' fill-opacity='0.08'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\");\n }\n\n .chat-sdk-container.whatsapp-theme {\n --chat-primary-color: #25D366;\n --chat-background-color: #ECE5DD;\n --chat-message-own-bg: #DCF8C6;\n --chat-message-other-bg: #FFFFFF;\n --chat-header-bg: linear-gradient(135deg, #075e54 0%, #128c7e 100%);\n --chat-text-color: #303030;\n --chat-border-radius-message: 18px;\n --chat-border-radius-input: 25px;\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.whatsapp-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* WhatsApp input + details */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-content {\n max-width: 70%;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input-area {\n background: #f0f2f5;\n border-top: none;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-input {\n background: #fff;\n border: none;\n border-radius: 22px;\n padding: 10px 14px;\n box-shadow: inset 0 1px 0 rgba(0,0,0,0.02);\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-send-btn {\n background: #25D366;\n box-shadow: 0 2px 4px rgba(0,0,0,0.12);\n }\n\n\n /* Telegram Theme */\n .chat-sdk-container.telegram-theme {\n --chat-primary-color: #2481CC;\n --chat-background-color: #FFFFFF;\n --chat-message-own-bg: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);\n --chat-message-other-bg: #F1F1F1;\n --chat-header-bg: linear-gradient(135deg, #2481cc 0%, #1c7cd6 100%);\n --chat-text-color: #000000;\n --chat-border-radius-message: 12px;\n --chat-border-radius-input: 12px;\n\n /* Telegram input + details */\n .chat-sdk-container.telegram-theme .chat-sdk-message-content {\n max-width: 75%;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message-bubble {\n box-shadow: 0 1px 1px rgba(0,0,0,0.06);\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input-area {\n background: #ffffff;\n border-top: 1px solid #e6e6e6;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-input {\n background: #fff;\n border: 1px solid #cfd6dd;\n border-radius: 12px;\n padding: 9px 14px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-send-btn {\n background: #2481CC;\n border-radius: 10px;\n width: 38px;\n height: 36px;\n box-shadow: none;\n }\n /* Telegram dark */\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input-area {\n background: #1f1f1f;\n border-top: 1px solid #2a2a2a;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-input {\n background: #2b2b2b;\n color: #e0e0e0;\n border-color: #444;\n }\n .chat-sdk-container.telegram-theme.dark .chat-sdk-send-btn {\n background: #1976d2;\n }\n\n\n .chat-sdk-container.telegram-theme .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-messages {\n background-color: var(--chat-background-color);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) 4px var(--chat-border-radius-message);\n }\n\n .chat-sdk-container.telegram-theme .chat-sdk-message:not(.own) .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n border-radius: var(--chat-border-radius-message) var(--chat-border-radius-message) var(--chat-border-radius-message) 4px;\n }\n\n /* Telegram Dark Theme */\n .chat-sdk-container.telegram-theme.dark {\n --chat-background-color: #212121;\n --chat-message-other-bg: #2F2F2F;\n --chat-header-bg: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);\n --chat-text-color: #FFFFFF;\n }\n\n /* Default header (fallback) */\n .chat-sdk-header {\n background: var(--chat-header-bg);\n color: white;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 60px;\n }\n\n .chat-sdk-header-left { display: flex; flex-direction: column; gap: 2px; }\n .chat-sdk-title { font-size: 15px; font-weight: 600; }\n .chat-sdk-subtitle { font-size: 12px; opacity: 0.9; }\n\n .chat-sdk-close-btn {\n background: none;\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n opacity: 0.8;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n }\n\n .chat-sdk-close-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .chat-sdk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n background: var(--chat-background-color);\n min-height: 0; /* allow flex to use full height */\n }\n\n .chat-sdk-message {\n margin-bottom: 12px;\n display: flex;\n align-items: flex-end;\n gap: 8px;\n }\n\n .chat-sdk-message.own {\n flex-direction: row-reverse;\n }\n\n .chat-sdk-message-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: #ddd;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n color: #666;\n flex-shrink: 0;\n }\n\n .chat-sdk-message-content {\n max-width: 70%;\n position: relative;\n }\n\n .chat-sdk-message-bubble {\n background: var(--chat-message-other-bg);\n color: var(--chat-text-color);\n padding: 8px 12px;\n border-radius: var(--chat-border-radius-message);\n position: relative;\n word-wrap: break-word;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n }\n\n .chat-sdk-message.own .chat-sdk-message-bubble {\n background: var(--chat-message-own-bg);\n color: white;\n }\n\n .chat-sdk-message-username {\n font-size: 11px;\n color: #666;\n margin-bottom: 2px;\n font-weight: 600;\n }\n\n .chat-sdk-message-text {\n margin: 0;\n line-height: 1.4;\n }\n\n .chat-sdk-message-time {\n font-size: 10px;\n color: #999;\n margin-top: 4px;\n text-align: right;\n }\n\n /* Message grouping */\n .chat-sdk-message.grouped {\n margin-top: 4px;\n }\n .chat-sdk-message.grouped .chat-sdk-message-username { display: none; }\n .chat-sdk-message.grouped .chat-sdk-message-avatar { visibility: hidden; }\n\n /* WhatsApp: time inside bubble */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-bubble {\n position: relative;\n padding-right: 44px;\n padding-bottom: 16px;\n }\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-time-inside {\n position: absolute;\n right: 8px;\n bottom: 4px;\n font-size: 11px;\n color: rgba(0,0,0,0.55);\n }\n\n /* Telegram: read status */\n .chat-sdk-container.telegram-theme .chat-sdk-message-time {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n }\n .chat-sdk-container.telegram-theme .chat-sdk-message.own .chat-sdk-read-status {\n font-size: 12px;\n color: var(--chat-primary-color);\n line-height: 1;\n }\n\n /* Theme-specific image radii */\n .chat-sdk-container.whatsapp-theme .chat-sdk-message-image img { border-radius: 12px; }\n .chat-sdk-container.telegram-theme .chat-sdk-message-image img { border-radius: 6px; }\n\n\n .chat-sdk-input-area {\n padding: 12px 16px;\n background: white;\n border-top: 1px solid #e0e0e0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n\n .chat-sdk-icon-btn {\n background: transparent;\n border: none;\n width: 32px;\n height: 32px;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #666;\n }\n .chat-sdk-icon-btn:hover { background: rgba(0,0,0,0.06); }\n\n .chat-sdk-emoji-picker {\n position: absolute;\n left: 12px;\n bottom: 64px;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n box-shadow: 0 6px 16px rgba(0,0,0,0.12);\n padding: 6px;\n z-index: 5;\n }\n .chat-sdk-emoji-grid {\n display: grid;\n grid-template-columns: repeat(5, 28px);\n gap: 6px;\n }\n\n /* Failed message styles - Telegram style */\n .chat-sdk-message-failed-indicator {\n display: inline-flex;\n align-items: center;\n margin-left: 6px;\n color: #ff4444;\n cursor: pointer;\n }\n .chat-sdk-message-failed-indicator svg {\n width: 16px;\n height: 16px;\n }\n .chat-sdk-message.own .chat-sdk-message-content {\n display: flex;\n align-items: flex-end;\n gap: 6px;\n }\n .chat-sdk-message.own .chat-sdk-message-bubble {\n flex: 1;\n }\n .chat-sdk-emoji-item {\n background: none;\n border: none;\n font-size: 20px;\n line-height: 1;\n cursor: pointer;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n }\n .chat-sdk-emoji-item:hover { background: #f3f4f6; }\n\n\n .chat-sdk-input {\n flex: 1;\n border: 1px solid #ddd;\n border-radius: var(--chat-border-radius-input);\n padding: 8px 16px;\n font-size: 14px;\n outline: none;\n resize: none;\n min-height: 36px;\n max-height: 100px;\n }\n\n .chat-sdk-input:focus {\n border-color: var(--chat-primary-color);\n }\n\n .chat-sdk-send-btn {\n background: var(--chat-primary-color);\n color: white;\n border: none;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n }\n\n .chat-sdk-send-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-send-btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n }\n\n .chat-sdk-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n }\n\n .chat-sdk-join-card {\n background: white;\n border-radius: 12px;\n padding: 24px;\n max-width: 300px;\n margin: 16px;\n text-align: center;\n }\n\n .chat-sdk-join-title {\n font-size: 18px;\n font-weight: 600;\n margin: 0 0 8px 0;\n color: #333;\n }\n\n .chat-sdk-join-description {\n font-size: 14px;\n color: #666;\n margin: 0 0 20px 0;\n line-height: 1.4;\n }\n\n .chat-sdk-join-btn {\n background: #075e54;\n color: white;\n border: none;\n border-radius: 8px;\n padding: 12px 24px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s;\n width: 100%;\n }\n\n .chat-sdk-join-btn:hover {\n background: #064e45;\n }\n\n .chat-sdk-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: #666;\n }\n\n .chat-sdk-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid #e0e0e0;\n border-top: 2px solid #075e54;\n border-radius: 50%;\n animation: chat-sdk-spin 1s linear infinite;\n margin-right: 8px;\n }\n\n @keyframes chat-sdk-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n\n .chat-sdk-container.dark {\n background: #1f1f1f;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-header {\n background: #2d2d2d;\n }\n\n .chat-sdk-container.dark .chat-sdk-messages {\n background: #0d1117;\n }\n\n .chat-sdk-container.dark .chat-sdk-message-bubble {\n background: #2d2d2d;\n color: #e0e0e0;\n }\n\n .chat-sdk-container.dark .chat-sdk-message.own .chat-sdk-message-bubble {\n background: #0969da;\n color: white;\n }\n\n /* Image Modal Viewer */\n .chat-sdk-image-modal {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n z-index: 9999;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s ease, visibility 0.2s ease;\n }\n\n .chat-sdk-image-modal-open {\n opacity: 1;\n visibility: visible;\n }\n\n .chat-sdk-image-backdrop {\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0, 0, 0, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n\n .chat-sdk-image-container {\n position: relative;\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-sdk-image-close {\n position: absolute;\n top: -50px;\n right: 0;\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 50%;\n width: 40px;\n height: 40px;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n z-index: 1;\n }\n\n .chat-sdk-image-close:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n\n .chat-sdk-image-full {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 8px;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);\n }\n\n /* Responsive Design */\n @media (max-width: 640px) {\n .chat-sdk-container {\n border-radius: 0;\n height: 100vh;\n max-height: 100vh;\n }\n\n .chat-sdk-message-content {\n max-width: 85%;\n }\n\n .chat-sdk-message-bubble {\n font-size: 14px;\n padding: 8px 12px;\n }\n\n .chat-sdk-input {\n font-size: 16px; /* Prevent zoom on iOS */\n padding: 10px 14px;\n }\n\n .chat-sdk-header {\n padding: 8px 12px;\n min-height: 50px;\n }\n\n .chat-sdk-message-avatar {\n width: 28px;\n height: 28px;\n font-size: 11px;\n }\n }\n\n @media (min-width: 1024px) {\n .chat-sdk-message-content {\n max-width: 60%;\n }\n\n .chat-sdk-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n transition: all 0.2s ease;\n }\n }\n\n "}startSimulation(){this.simulator.start()}stopSimulation(){this.simulator.stop()}pauseSimulation(){this.simulator.pause()}resumeSimulation(){this.simulator.resume()}async sendMessage(e,t="text"){await this.simulator.sendMessage(e,t)}get isSimulationRunning(){return this.state.isSimulationRunning}get isSimulationPaused(){return this.state.isSimulationPaused}get simulationEnded(){return this.state.simulationEnded}get messageCount(){return this.state.displayedMessageCount}get messages(){return[...this.state.messages]}async reinitializeLanguage(e){this.config.language=e,this.setLoading(!0),this.messagesContainer.innerHTML="",this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.updateUnreadBadge();try{this.simulator.clearCachedProgress()}catch(e){}try{this.simulator.destroy()}catch(e){}this.simulator=new m(this.config,this.apiClient),this.setupSimulatorEvents(),await this.initializeSimulation()}destroy(){this.pollingStopTimer&&(clearTimeout(this.pollingStopTimer),this.pollingStopTimer=null);try{this.simulator.destroy()}catch(e){}if(this.shadowRoot)try{for(;this.shadowRoot.firstChild;)this.shadowRoot.removeChild(this.shadowRoot.firstChild)}catch(e){}this.state.isOpen=!1,this.removeAllListeners()}clearMessages(){this.state.messages=[],this.state.displayedMessageCount=0,this.state.unreadCount=0,this.messagesContainer.innerHTML="",this.updateUnreadBadge()}rerender(){this.reRenderAllMessages()}getMessageCount(){return this.state.displayedMessageCount}isOpen(){return this.state.isOpen}updateLanguageElements(e){var t,s,n;this.t=y(e);const i=null===(t=this.widgetElement)||void 0===t?void 0:t.querySelector("#message-input");i&&(i.placeholder=this.t.inputPlaceholder);const a=null===(s=this.widgetElement)||void 0===s?void 0:s.querySelector(".send-button");a&&a.textContent&&(a.textContent=this.t.send);const o=this.getMessageCount(),r=(null===(n=this.state.currentProject)||void 0===n?void 0:n.name)||"Chat";this.setTitle(r,`${o} ${this.t.messages}`)}}const f=b;function k(e){return new b(e)}var w={init:k,ChatSDK:f,ChatSDKError:t};"undefined"!=typeof window&&(window.ChatSDK={init:k,ChatSDK:f,ChatSDKError:t}),e.ChatSDK=f,e.ChatSDKError=t,e.default=w,e.init=k,Object.defineProperty(e,"__esModule",{value:!0})});
@@ -5,12 +5,12 @@ export declare class APIClient {
5
5
  constructor(config: ChatSDKConfig);
6
6
  private request;
7
7
  getProject(projectId: string): Promise<ProjectResponse>;
8
- getTemplate(templateId: string, language?: string): Promise<TemplateResponse>;
8
+ getTemplate(templateId: string, language?: string, country?: string): Promise<TemplateResponse>;
9
9
  getProjectTemplates(projectId: string): Promise<APIResponse>;
10
10
  sendMessage(projectId: string, userId: string, content: string, messageType?: string): Promise<APIResponse>;
11
11
  joinProject(projectId: string, userId: string, username: string): Promise<APIResponse>;
12
12
  leaveProject(projectId: string, userId: string): Promise<APIResponse>;
13
- getSimulationData(projectId: string, userId: string, language?: string): Promise<APIResponse>;
13
+ getSimulationData(projectId: string, userId: string, language?: string, country?: string): Promise<APIResponse>;
14
14
  getSimulationMessages(projectId: string, userId: string, since?: string, limit?: number): Promise<APIResponse>;
15
15
  sendUserMessage(projectId: string, userId: string, username: string, content: string, messageType?: string): Promise<APIResponse>;
16
16
  triggerAIReply(projectId: string, userId: string, username: string, content: string, messageType?: string): Promise<APIResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,WAAW,EAEZ,MAAM,UAAU,CAAA;AAEjB,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,KAAK,CAAC,CAAQ;gBAEV,MAAM,EAAE,aAAa;YAKnB,OAAO;IAsDf,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIvD,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAK7E,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI5D,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAe,GAC3B,OAAO,CAAC,WAAW,CAAC;IAYjB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAWtF,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAWrE,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ7F,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,CAAC;IAOjB,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAe,GAC3B,OAAO,CAAC,WAAW,CAAC;IAajB,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAe,GAC3B,OAAO,CAAC,WAAW,CAAC;IAcvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAGlC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,WAAW,EAEZ,MAAM,UAAU,CAAA;AAEjB,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,KAAK,CAAC,CAAQ;gBAEV,MAAM,EAAE,aAAa;YAKnB,OAAO;IAsDf,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIvD,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQ/F,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI5D,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAe,GAC3B,OAAO,CAAC,WAAW,CAAC;IAYjB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAWtF,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAWrE,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAO/G,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,CAAC;IAOjB,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAe,GAC3B,OAAO,CAAC,WAAW,CAAC;IAajB,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAe,GAC3B,OAAO,CAAC,WAAW,CAAC;IAcvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAGlC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-simulator.d.ts","sourceRoot":"","sources":["../../../src/simulation/chat-simulator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-simulator.d.ts","sourceRoot":"","sources":["../../../src/simulation/chat-simulator.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@ export interface ChatSDKConfig {
18
18
  userId?: string;
19
19
  username?: string;
20
20
  language?: string;
21
+ country?: string;
21
22
  theme?: 'light' | 'dark' | 'auto';
22
23
  uiTemplate?: 'whatsapp' | 'telegram';
23
24
  primaryColor?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Currency Placeholder Resolver for the ChatSDK.
3
+ *
4
+ * Resolves {{AMOUNT:N}} placeholders in message content to the viewer's
5
+ * local currency based on their country code, using currency.json data.
6
+ *
7
+ * Format: {{AMOUNT:N}} where N is a raw integer representing USD amount.
8
+ * Example: {{AMOUNT:150}} with country 'JP' → '¥22,425'
9
+ */
10
+ /**
11
+ * Optionally load full currency data from the server (enhances accuracy).
12
+ * Call once on SDK init if you want to override the embedded data.
13
+ */
14
+ export declare function loadCurrencyData(apiBaseUrl: string): Promise<void>;
15
+ /**
16
+ * Resolves all {{AMOUNT:N}} placeholders in a message to the local currency.
17
+ * @param text - Raw message content (may contain {{AMOUNT:N}} patterns)
18
+ * @param country - ISO 3166-1 alpha-2 country code, e.g. 'JP'
19
+ */
20
+ export declare function resolveCurrencyPlaceholders(text: string, country: string): string;
21
+ //# sourceMappingURL=currencyResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currencyResolver.d.ts","sourceRoot":"","sources":["../../../src/utils/currencyResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA8DH;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAcxE;AAmCD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQjF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skywu/virtual-chat-sdk",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Virtual Chat SDK - Floating chat widget with 20+ languages support for seamless website integration",
5
5
  "type": "module",
6
6
  "main": "dist/chat-sdk.umd.js",