messaging-widget
Version:
Widget embebible multi-canal para WhatsApp, Instagram, Messenger y chat interno
2 lines • 16.8 kB
JavaScript
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.MessagingWidget=t():e.MessagingWidget=t()}("undefined"!=typeof self?self:this,(function(){return e={699:function(e){const t=new class{constructor(){this.config={},this.isOpen=!1,this.shadowRoot=null,this.analytics=[],this.socket=null,this.chatMessages=[],this.isInitialized=!1}init(e={}){this.isInitialized||(this.config=this.mergeConfig(e),this.createWidget(),this.bindEvents(),this.initInternalChat(),this.trackEvent("widget_initialized"),this.isInitialized=!0,this.config.hooks.onInit&&this.config.hooks.onInit())}mergeConfig(e){return this.deepMerge({channels:{whatsapp:{enabled:!0,number:"+56932027928",message:"¡Hola! Me gustaría obtener más información."},instagram:{enabled:!0,username:"@wazaut"},messenger:{enabled:!0,pageId:"608983195635240"},internalChat:{enabled:!0,socketUrl:null}},appearance:{position:"bottom-right",primaryColor:"#25D366",secondaryColor:"#128C7E",buttonSize:60,zIndex:9999},internalChat:{title:"Chat de Soporte",placeholder:"Escribe tu mensaje...",welcomeMessage:"¡Hola! ¿En qué podemos ayudarte?"},hooks:{onInit:null,onChatOpen:null,onMessageSend:null,onChatClose:null},analytics:{enabled:!0,trackClicks:!0,trackMessages:!0,endpoint:null}},e)}deepMerge(e,t){const n={...e};for(const s in t)t[s]&&"object"==typeof t[s]&&!Array.isArray(t[s])?n[s]=this.deepMerge(e[s]||{},t[s]):n[s]=t[s];return n}createWidget(){const e=document.createElement("div");e.id="messaging-widget-container",this.shadowRoot=e.attachShadow({mode:"closed"});const t=this.createStyles();this.shadowRoot.appendChild(t);const n=this.createWidgetStructure();this.shadowRoot.appendChild(n),document.body.appendChild(e)}createStyles(){const e=document.createElement("style"),{appearance:t}=this.config,n=this.getPositionStyles(t.position);return e.textContent=`\n * { box-sizing: border-box; }\n .widget-container { position: fixed; ${n} z-index: ${t.zIndex}; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }\n .main-button { width: ${t.buttonSize}px; height: ${t.buttonSize}px; background: ${t.primaryColor}; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.15); transition: all 0.3s ease; border: none; position: relative; overflow: hidden; }\n .main-button:hover { transform: scale(1.1); box-shadow: 0 6px 20px rgba(0,0,0,0.2); }\n .main-button svg { width: 24px; height: 24px; fill: white; }\n .channels-menu { position: absolute; bottom: ${t.buttonSize+10}px; right: 0; background: white; border-radius: 12px; box-shadow: 0 8px 25px rgba(0,0,0,0.15); opacity: 0; visibility: hidden; transform: translateY(10px); transition: all 0.3s ease; min-width: 200px; overflow: hidden; }\n .channels-menu.open { opacity: 1; visibility: visible; transform: translateY(0); }\n .channel-item { display: flex; align-items: center; padding: 12px 16px; cursor: pointer; transition: background 0.2s ease; border-bottom: 1px solid #f0f0f0; color: #333; }\n .channel-item:last-child { border-bottom: none; }\n .channel-item:hover { background: #f8f9fa; }\n .channel-icon { width: 24px; height: 24px; margin-right: 12px; flex-shrink: 0; }\n .channel-name { font-size: 14px; font-weight: 500; }\n .chat-window { position: absolute; bottom: 0; right: 0; width: 350px; height: 500px; background: white; border-radius: 12px 12px 0 0; box-shadow: 0 -5px 25px rgba(0,0,0,0.15); opacity: 0; visibility: hidden; transform: translateY(100%); transition: all 0.3s ease; display: flex; flex-direction: column; overflow: hidden; }\n .chat-window.open { opacity: 1; visibility: visible; transform: translateY(0); }\n .chat-header { background: ${t.primaryColor}; color: white; padding: 16px; display: flex; align-items: center; justify-content: space-between; }\n .chat-title { font-size: 16px; font-weight: 600; }\n .close-button { background: none; border: none; color: white; cursor: pointer; padding: 4px; border-radius: 4px; transition: background 0.2s ease; font-size: 18px; }\n .close-button:hover { background: rgba(255,255,255,0.1); }\n .chat-messages { flex: 1; padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; background: #f8f9fa; }\n .message { max-width: 80%; padding: 8px 12px; border-radius: 12px; font-size: 14px; line-height: 1.4; word-wrap: break-word; }\n .message.received { background: white; color: #333; align-self: flex-start; border-bottom-left-radius: 4px; }\n .message.sent { background: ${t.primaryColor}; color: white; align-self: flex-end; border-bottom-right-radius: 4px; }\n .chat-input-container { padding: 16px; border-top: 1px solid #e0e0e0; display: flex; gap: 8px; background: white; }\n .chat-input { flex: 1; border: 1px solid #e0e0e0; border-radius: 20px; padding: 8px 16px; font-size: 14px; outline: none; transition: border-color 0.2s ease; }\n .chat-input:focus { border-color: ${t.primaryColor}; }\n .send-button { width: 36px; height: 36px; background: ${t.primaryColor}; border: none; border-radius: 50%; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; }\n .send-button:hover { background: ${t.secondaryColor}; transform: scale(1.05); }\n .typing-indicator { padding: 8px 12px; background: white; border-radius: 12px; align-self: flex-start; font-style: italic; color: #666; animation: pulse 2s infinite; }\n @keyframes pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }\n @media (max-width: 480px) { \n .chat-window { width: 100vw; height: 100vh; border-radius: 0; }\n .channels-menu { left: 20px; right: 20px; }\n }\n `,e}getPositionStyles(e){const t={"bottom-right":"bottom: 20px; right: 20px;","bottom-left":"bottom: 20px; left: 20px;","top-right":"top: 20px; right: 20px;","top-left":"top: 20px; left: 20px;"};return t[e]||t["bottom-right"]}createWidgetStructure(){const e=document.createElement("div");e.className="widget-container";const t=document.createElement("button");t.className="main-button",t.innerHTML='<svg viewBox="0 0 24 24"><path d="M20,2H4A2,2 0 0,0 2,4V22L6,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2Z"/></svg>';const n=document.createElement("div");n.className="channels-menu",n.appendChild(this.createChannelsMenu());const s=document.createElement("div");return s.className="chat-window",s.appendChild(this.createChatWindow()),e.appendChild(t),e.appendChild(n),e.appendChild(s),e}createChannelsMenu(){const e=document.createDocumentFragment(),{channels:t}=this.config;return t.whatsapp.enabled&&e.appendChild(this.createChannelItem("whatsapp","WhatsApp",this.getWhatsAppIcon())),t.instagram.enabled&&e.appendChild(this.createChannelItem("instagram","Instagram",this.getInstagramIcon())),t.messenger.enabled&&e.appendChild(this.createChannelItem("messenger","Messenger",this.getMessengerIcon())),t.internalChat.enabled&&e.appendChild(this.createChannelItem("internal","Chat en vivo",this.getChatIcon())),e}createChannelItem(e,t,n){const s=document.createElement("div");return s.className="channel-item",s.dataset.channel=e,s.innerHTML=`<div class="channel-icon">${n}</div><div class="channel-name">${t}</div>`,s}createChatWindow(){const e=document.createDocumentFragment(),t=document.createElement("div");t.className="chat-header",t.innerHTML=`<div class="chat-title">${this.config.internalChat.title}</div><button class="close-button">✕</button>`;const n=document.createElement("div");if(n.className="chat-messages",this.config.internalChat.welcomeMessage){const e=document.createElement("div");e.className="message received",e.textContent=this.config.internalChat.welcomeMessage,n.appendChild(e)}const s=document.createElement("div");return s.className="chat-input-container",s.innerHTML=`\n <input type="text" class="chat-input" placeholder="${this.config.internalChat.placeholder}">\n <button class="send-button"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M2,21L23,12L2,3V10L17,12L2,14V21Z"/></svg></button>\n `,e.appendChild(t),e.appendChild(n),e.appendChild(s),e}bindEvents(){const e=this.shadowRoot.querySelector(".main-button"),t=this.shadowRoot.querySelector(".channels-menu"),n=this.shadowRoot.querySelector(".close-button"),s=this.shadowRoot.querySelector(".send-button"),i=this.shadowRoot.querySelector(".chat-input");e.addEventListener("click",(e=>{e.stopPropagation(),this.toggleMenu()})),t.addEventListener("click",(e=>{const t=e.target.closest(".channel-item");t&&this.openChannel(t.dataset.channel)})),n.addEventListener("click",(()=>this.closeChatWindow())),s.addEventListener("click",(()=>this.sendMessage())),i.addEventListener("keypress",(e=>{"Enter"===e.key&&this.sendMessage()})),document.addEventListener("click",(()=>this.closeMenu())),document.addEventListener("keydown",(e=>{"Escape"===e.key&&(this.closeMenu(),this.closeChatWindow())}))}toggleMenu(){const e=this.shadowRoot.querySelector(".channels-menu");this.isOpen=!this.isOpen,e.classList.toggle("open",this.isOpen),this.trackEvent(this.isOpen?"menu_opened":"menu_closed")}closeMenu(){this.shadowRoot.querySelector(".channels-menu").classList.remove("open"),this.isOpen=!1}openChannel(e){switch(this.closeMenu(),this.trackEvent("channel_clicked",{channel:e}),this.config.hooks.onChatOpen&&this.config.hooks.onChatOpen(e),e){case"whatsapp":this.openWhatsApp();break;case"instagram":this.openInstagram();break;case"messenger":this.openMessenger();break;case"internal":this.openChatWindow()}}openWhatsApp(){const{number:e,message:t}=this.config.channels.whatsapp,n=`https://wa.me/${e.replace("+","")}?text=${encodeURIComponent(t)}`;window.open(n,"_blank")}openInstagram(){const e=`https://instagram.com/${this.config.channels.instagram.username}`;window.open(e,"_blank")}openMessenger(){const e=`https://m.me/${this.config.channels.messenger.pageId}`;window.open(e,"_blank")}openChatWindow(){this.shadowRoot.querySelector(".chat-window").classList.add("open"),setTimeout((()=>this.shadowRoot.querySelector(".chat-input").focus()),300)}closeChatWindow(){this.shadowRoot.querySelector(".chat-window").classList.remove("open"),this.config.hooks.onChatClose&&this.config.hooks.onChatClose("internal")}sendMessage(){const e=this.shadowRoot.querySelector(".chat-input"),t=e.value.trim();t&&(this.addMessage(t,"sent"),e.value="",this.trackEvent("message_sent",{channel:"internal",message:t}),this.config.hooks.onMessageSend&&this.config.hooks.onMessageSend(t,"internal"),this.socket&&this.socket.readyState===WebSocket.OPEN?this.socket.send(JSON.stringify({type:"message",message:t,timestamp:Date.now()})):(this.showTypingIndicator(),setTimeout((()=>{this.hideTypingIndicator(),this.addMessage("Gracias por tu mensaje. Te responderemos pronto.","received")}),2e3)))}addMessage(e,t){const n=this.shadowRoot.querySelector(".chat-messages"),s=document.createElement("div");s.className=`message ${t}`,s.textContent=e,n.appendChild(s),n.scrollTop=n.scrollHeight,this.chatMessages.push({text:e,type:t,timestamp:Date.now()})}showTypingIndicator(){const e=this.shadowRoot.querySelector(".chat-messages"),t=document.createElement("div");t.className="typing-indicator",t.textContent="Escribiendo...",t.id="typing-indicator",e.appendChild(t),e.scrollTop=e.scrollHeight}hideTypingIndicator(){const e=this.shadowRoot.querySelector("#typing-indicator");e&&e.remove()}initInternalChat(){this.config.channels.internalChat.socketUrl&&this.connectWebSocket(this.config.channels.internalChat.socketUrl)}connectWebSocket(e){try{this.socket=new WebSocket(e),this.socket.onopen=()=>{this.trackEvent("websocket_connected")},this.socket.onmessage=e=>{try{const t=JSON.parse(e.data);this.addMessage(t.message,"received")}catch(t){this.addMessage(e.data,"received")}},this.socket.onclose=()=>{this.trackEvent("websocket_disconnected"),setTimeout((()=>this.connectWebSocket(e)),5e3)},this.socket.onerror=e=>{this.trackEvent("websocket_error",{error:e.message})}}catch(e){}}trackEvent(e,t={}){if(!this.config.analytics.enabled)return;const n={event:e,timestamp:Date.now(),url:window.location.href,userAgent:navigator.userAgent,sessionId:this.getSessionId(),...t};this.analytics.push(n),this.config.analytics.endpoint&&this.sendAnalytics(n)}sendAnalytics(e){fetch(this.config.analytics.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).catch((e=>{}))}getSessionId(){let e=sessionStorage.getItem("messaging-widget-session");return e||(e="mw_"+Date.now()+"_"+Math.random().toString(36).substr(2,9),sessionStorage.setItem("messaging-widget-session",e)),e}getWhatsAppIcon(){return'<svg fill="#25D366" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893A11.821 11.821 0 0020.465 3.63z"/></svg>'}getInstagramIcon(){return'<svg fill="#E4405F" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>'}getMessengerIcon(){return'<svg fill="#0084FF" viewBox="0 0 24 24"><path d="M12,2C6.486,2,2,6.262,2,11.5c0,2.665,1.113,5.073,2.914,6.825V22l3.539-1.935C9.507,20.352,10.727,20.5,12,20.5c5.514,0,10-4.262,10-9.5S17.514,2,12,2z M13.5,14.5l-2.5-2.667L6.5,14.5L11,9.5l2.5,2.667L17.5,9.5L13.5,14.5z"/></svg>'}getChatIcon(){return'<svg fill="#6c757d" viewBox="0 0 24 24"><path d="M20,2H4A2,2 0 0,0 2,4V22L6,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2Z"/></svg>'}destroy(){const e=document.getElementById("messaging-widget-container");e&&e.remove(),this.socket&&this.socket.close(),this.isInitialized=!1,this.analytics=[],this.chatMessages=[]}getAnalytics(){return[...this.analytics]}updateConfig(e){this.config=this.mergeConfig(e),this.destroy(),this.isInitialized=!1,this.init(this.config)}openChannelDirectly(e){this.openChannel(e)}addMessageProgrammatically(e,t="received"){this.shadowRoot&&this.addMessage(e,t)}getChatHistory(){return[...this.chatMessages]}clearChatHistory(){this.chatMessages=[];const e=this.shadowRoot?.querySelector(".chat-messages");if(e){const t=e.querySelector(".message.received");e.innerHTML="",t&&this.config.internalChat.welcomeMessage&&e.appendChild(t)}}isReady(){return this.isInitialized}};"undefined"!=typeof window&&(window.MessagingWidget=t),e.exports=t}},t={},function n(s){var i=t[s];if(void 0!==i)return i.exports;var o=t[s]={exports:{}};return e[s](o,o.exports,n),o.exports}(699).default;var e,t}));
//# sourceMappingURL=messaging-widget.min.js.map