(function() {
'use strict';
// Prevent multiple initialization
if (window.__KBEE_WIDGET_LOADED__) {
console.warn('[KBee Widget] Already loaded');
return;
}
window.__KBEE_WIDGET_LOADED__ = true;
// Find the script tag to read configuration
const scriptTag = document.currentScript ||
Array.from(document.querySelectorAll('script')).find(s => s.src && s.src.includes('serveWidgetScript'));
if (!scriptTag) {
console.error('[KBee Widget] Could not find widget script tag');
return;
}
// Read configuration from data attributes
const config = {
kbPath: scriptTag.getAttribute('data-kb-path'),
title: scriptTag.getAttribute('data-title') || 'Help Center',
position: scriptTag.getAttribute('data-position') || 'bottom-right',
icon: scriptTag.getAttribute('data-icon') || 'help-circle',
theme: scriptTag.getAttribute('data-theme') || 'daylight',
primaryColor: scriptTag.getAttribute('data-primary-color') || '#3B82F6'
};
// Validate required config
if (!config.kbPath) {
console.error('[KBee Widget] Error: data-kb-path attribute is required');
return;
}
console.log('[KBee Widget] Initializing with config:', config);
// State
let isPanelOpen = false;
// Build the iframe URL - use the full kbee.page domain
const embedUrl = 'https://kbee.page/functions/serveEmbedPage?path=' + encodeURIComponent(config.kbPath) +
'&theme=' + encodeURIComponent(config.theme);
console.log('[KBee Widget] Iframe URL:', embedUrl);
// Icon SVGs
const icons = {
'help-circle': '',
'message-circle': '',
'life-buoy': '',
'headphones': '',
'mail': ''
};
const iconSvg = icons[config.icon] || icons['help-circle'];
// Create styles
const styles = `
#kbee-widget-container * {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#kbee-widget-button {
position: fixed;
${config.position === 'bottom-left' ? 'left: 20px;' : 'right: 20px;'}
bottom: 20px;
width: 60px;
height: 60px;
border-radius: 50%;
background-color: ${config.primaryColor};
border: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
cursor: pointer;
z-index: 999998;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.2s ease, box-shadow 0.2s ease;
color: white;
font-size: 28px;
}
#kbee-widget-button:hover {
transform: scale(1.05);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
}
#kbee-widget-button:active {
transform: scale(0.95);
}
#kbee-widget-button svg {
width: 28px;
height: 28px;
}
#kbee-widget-panel {
position: fixed;
${config.position === 'bottom-left' ? 'left: 20px;' : 'right: 20px;'}
bottom: 90px;
width: 400px;
max-width: calc(100vw - 40px);
height: 70vh;
max-height: 700px;
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
z-index: 999999;
display: none;
flex-direction: column;
overflow: hidden;
transition: opacity 0.2s ease, transform 0.2s ease;
opacity: 0;
transform: translateY(10px);
}
#kbee-widget-panel.open {
display: flex;
opacity: 1;
transform: translateY(0);
}
#kbee-widget-header {
background-color: ${config.primaryColor};
color: white;
padding: 16px 20px;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
}
#kbee-widget-header h3 {
font-size: 18px;
font-weight: 600;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}
#kbee-widget-close {
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
padding: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: background-color 0.2s ease;
}
#kbee-widget-close:hover {
background-color: rgba(255, 255, 255, 0.1);
}
#kbee-widget-iframe {
flex: 1;
border: none;
width: 100%;
height: 100%;
}
#kbee-widget-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #666;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}
#kbee-widget-loading .spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid ${config.primaryColor};
border-radius: 50%;
width: 40px;
height: 40px;
animation: kbee-spin 1s linear infinite;
margin: 0 auto 12px;
}
@keyframes kbee-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (max-width: 480px) {
#kbee-widget-panel {
width: calc(100vw - 40px);
height: 80vh;
bottom: 10px;
${config.position === 'bottom-left' ? 'left: 20px;' : 'right: 20px;'}
}
#kbee-widget-button {
width: 56px;
height: 56px;
bottom: 16px;
${config.position === 'bottom-left' ? 'left: 16px;' : 'right: 16px;'}
}
}
`;
// Inject styles
const styleSheet = document.createElement('style');
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
// Create widget HTML
const container = document.createElement('div');
container.id = 'kbee-widget-container';
container.innerHTML = `
`;
// Wait for DOM to be ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(container);
initWidget();
});
} else {
document.body.appendChild(container);
initWidget();
}
function initWidget() {
const button = document.getElementById('kbee-widget-button');
const panel = document.getElementById('kbee-widget-panel');
const closeBtn = document.getElementById('kbee-widget-close');
const iframe = document.getElementById('kbee-widget-iframe');
const loading = document.getElementById('kbee-widget-loading');
if (!button || !panel || !closeBtn || !iframe) {
console.error('[KBee Widget] Widget elements not found');
return;
}
// Hide loading indicator when iframe loads
iframe.addEventListener('load', () => {
console.log('[KBee Widget] Iframe loaded successfully');
if (loading) {
loading.style.display = 'none';
}
});
// Handle iframe errors
iframe.addEventListener('error', () => {
console.error('[KBee Widget] Iframe failed to load');
if (loading) {
loading.innerHTML = 'Failed to load content
';
}
});
// Toggle panel
button.addEventListener('click', () => {
isPanelOpen = !isPanelOpen;
if (isPanelOpen) {
panel.classList.add('open');
console.log('[KBee Widget] Panel opened');
} else {
panel.classList.remove('open');
console.log('[KBee Widget] Panel closed');
}
});
// Close panel
closeBtn.addEventListener('click', () => {
isPanelOpen = false;
panel.classList.remove('open');
console.log('[KBee Widget] Panel closed via close button');
});
// Close on escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && isPanelOpen) {
isPanelOpen = false;
panel.classList.remove('open');
console.log('[KBee Widget] Panel closed via Escape key');
}
});
console.log('[KBee Widget] Initialized successfully');
}
})();