(function () { function createIframe(targetSelector, src) { const container = document.querySelector(targetSelector); if (!container) return null; // Set container styles for fixed positioning container.style.position = 'fixed'; container.style.right = '0px'; container.style.bottom = '0px'; container.style.zIndex = '9999'; container.style.overflow = 'hidden'; // Start with button size (will be updated on 'loaded' message) container.style.width = '150px'; container.style.height = '150px'; const iframe = document.createElement('iframe'); iframe.style.opacity = '0'; iframe.style.transition = 'opacity 0.3s ease-in-out'; iframe.style.width = '100%'; iframe.style.height = '100%'; iframe.style.border = 'none'; iframe.style.overflow = 'hidden'; iframe.style.background = 'transparent'; iframe.style.backgroundColor = 'transparent'; iframe.setAttribute('allowTransparency', 'true'); // Track current states let currentIsOpen = false; let currentShowTeaser = false; let metadata = {}; let onMessageSentCallback = null; // Resize helper - handles three states: closed, teaser, and open const setSize = (isOpen, showTeaser = false) => { currentIsOpen = isOpen; currentShowTeaser = showTeaser; if (isOpen) { // Full screen for open chat container.style.width = '100%'; container.style.height = '100%'; } else if (showTeaser) { // Expanded size for teaser bubble (button + teaser card) container.style.width = '340px'; container.style.height = '280px'; } else { // Compact size for button only container.style.width = '150px'; container.style.height = '150px'; } }; // Listen for messages from the iframe window.addEventListener('message', (event) => { if (event.data.type === 'resize') { setSize(event.data.isOpen, event.data.showTeaser); } if (event.data.type === 'loaded') { iframe.style.opacity = '1'; setSize(event.data.isOpen, event.data.showTeaser); if (iframe.contentWindow) { // Send parent URL iframe.contentWindow.postMessage({ type: 'parentUrl', url: window.location.href }, '*'); // Send any stored metadata if (Object.keys(metadata).length > 0) { iframe.contentWindow.postMessage({ type: 'metadata', data: metadata }, '*'); } } } if (event.data.type === 'messageSent') { // Call the callback if it's defined if (onMessageSentCallback && typeof onMessageSentCallback === 'function') { onMessageSentCallback(event.data.message); } } }); // Function to send URL to iframe const sendUrlToIframe = () => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'parentUrl', url: window.location.href }, '*'); } }; // Listen for URL changes in the parent window window.addEventListener('popstate', sendUrlToIframe); window.addEventListener('hashchange', sendUrlToIframe); container.appendChild(iframe); iframe.src = src; // Return controller object for programmatic control return { // Set open state setOpen: (isOpen) => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'setOpen', isOpen: !!isOpen }, '*'); } }, // Open the chat open: () => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'setOpen', isOpen: true }, '*'); } }, // Close the chat close: () => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'setOpen', isOpen: false }, '*'); } }, // Toggle the chat toggle: () => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'setOpen', isOpen: !currentIsOpen }, '*'); } }, // Show the teaser bubble showTeaser: () => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'setTeaser', show: true }, '*'); } }, // Hide the teaser bubble hideTeaser: () => { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'setTeaser', show: false }, '*'); } }, // Get current open state isOpen: () => currentIsOpen, // Get current teaser state isTeaserVisible: () => currentShowTeaser, // Set metadata to be sent to the iframe setMetadata: (data) => { if (data && typeof data === 'object') { metadata = { ...metadata, ...data }; // Send metadata immediately if iframe is loaded if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({ type: 'metadata', data: metadata }, '*'); } } }, // Get current metadata getMetadata: () => ({ ...metadata }), // Set callback for when a message is sent onMessageSent: (callback) => { if (typeof callback === 'function') { onMessageSentCallback = callback; } }, // Get the iframe element iframe: iframe }; } // Expose the function globally window.createEventsIframe = function (targetSelector, iframeId, options = {}) { const baseUrl = options.baseUrl || 'https://platform.timbal.ai'; const language = options.language || navigator.language || navigator.userLanguage; const userAgent = options.userAgent || navigator.userAgent; const url = `${baseUrl}/iframe/chat?id=${iframeId}&lang=${encodeURIComponent(language)}&ua=${encodeURIComponent(userAgent)}`; const controller = createIframe(targetSelector, url); // Set initial metadata if provided if (options.metadata && typeof options.metadata === 'object') { controller.setMetadata(options.metadata); } // Set message sent callback if provided if (options.onMessageSent && typeof options.onMessageSent === 'function') { controller.onMessageSent(options.onMessageSent); } return controller; }; })();