UNPKG

overcentric

Version:

A lightweight, privacy-focused toolkit for modern SaaS web applications

184 lines (183 loc) 7.6 kB
var _a, _b; // Compute normalized hostname once when the module loads const normalizedHostname = typeof window !== 'undefined' ? window.location.hostname.replace(/^www\./, '') : ''; let dockIframe = null; let dockOrigin = 'https://app.overcentric.com'; try { if (typeof window !== 'undefined' && typeof document !== 'undefined' && (document === null || document === void 0 ? void 0 : document.readyState) !== undefined) { dockOrigin = ((_b = (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.origin) === null || _b === void 0 ? void 0 : _b.includes('localhost')) ? 'http://localhost:4000' : 'https://app.overcentric.com'; } } catch (error) { } const closedIcon = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.076-4.076a1.526 1.526 0 0 1 1.037-.443 48.282 48.282 0 0 0 5.68-.494c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" /> </svg> `; /** * Initialize the dock with a floating button and iframe. * @param options - The options for the dock. */ export function initDock(options) { // Create container for the dock const dockContainer = document.createElement('div'); dockContainer.className = 'oc-dock-container'; dockContainer.style.position = 'fixed'; dockContainer.style.zIndex = '9999'; // Position the dock based on config if (options.position === 'bottom-right') { dockContainer.style.bottom = '20px'; dockContainer.style.right = '20px'; } else if (options.position === 'bottom-left') { dockContainer.style.bottom = '20px'; dockContainer.style.left = '20px'; } // Create the floating button const button = document.createElement('button'); button.innerHTML = closedIcon; button.style.backgroundColor = 'rgba(255, 255, 255, 0.25)'; button.style.backdropFilter = 'blur(5px)'; button.style.color = '#5c5c5c'; button.style.border = 'none'; button.style.borderRadius = '17px'; button.style.width = '50px'; button.style.height = '50px'; button.style.cursor = 'pointer'; button.style.transition = 'background-color 0.3s ease'; button.style.outline = 'none'; button.style.boxShadow = '0 4px 30px rgba(0, 0, 0, 0.1)'; button.style.padding = '10px'; button.style.display = 'flex'; button.style.alignItems = 'center'; button.style.justifyContent = 'center'; button.style.transition = 'opacity 0.3s ease'; // Add a unique class to the button for styling const buttonClass = 'oc-dock-launcher'; button.classList.add(buttonClass); // Create notification dot (hidden by default) const notificationDot = document.createElement('div'); notificationDot.className = 'oc-dock-notification-dot'; notificationDot.style.position = 'absolute'; notificationDot.style.top = '-2px'; notificationDot.style.right = '-4px'; notificationDot.style.width = '16px'; notificationDot.style.height = '16px'; notificationDot.style.backgroundColor = '#ff7451'; notificationDot.style.borderRadius = '50%'; notificationDot.style.border = '2px solid white'; notificationDot.style.display = 'none'; // Create the iframe for the dock dockIframe = document.createElement('iframe'); dockIframe.style.position = 'fixed'; dockIframe.style.bottom = '80px'; dockIframe.style.right = '20px'; dockIframe.style.zIndex = '1000'; dockIframe.style.display = 'none'; // Make the dock responsive based on screen size const isMobile = window.innerWidth <= 768; if (isMobile) { dockIframe.style.width = '100%'; dockIframe.style.height = `calc(100% - 80px)`; dockIframe.style.left = '0'; dockIframe.style.right = '0'; dockIframe.style.bottom = '80px'; } else { dockIframe.style.width = '360px'; dockIframe.style.height = '540px'; } dockIframe.style.borderRadius = '12px'; dockIframe.style.backgroundColor = 'rgba(255, 255, 255, 0.5)'; dockIframe.style.backdropFilter = 'blur(50px)'; dockIframe.style.boxShadow = 'rgb(0 0 0 / 5%) 0px 2px 15px 5px'; dockIframe.src = `${dockOrigin}/dock`; dockContainer.appendChild(button); dockContainer.appendChild(dockIframe); dockContainer.appendChild(notificationDot); document.body.appendChild(dockContainer); // Create and append style element with hover effect const style = document.createElement('style'); style.textContent = ` .${buttonClass}:hover { opacity: 0.8; } `; document.head.appendChild(style); // Toggle iframe visibility on button click dockContainer.addEventListener('click', () => { dockIframe.style.display = dockIframe.style.display === 'none' ? 'block' : 'none'; }); window.addEventListener('message', (event) => { // Verify origin for security if (event.origin !== dockOrigin) return; if (event.data && event.data.type === 'DOCK_READY') { // Iframe is ready, now send the data sendDataToIframe(dockIframe, { context: options.context, position: options.position, isChatEnabled: options.isChatEnabled, isKBEnabled: options.isKBEnabled }); } else if (event.data.type === 'DOCK_NOTIFICATION') { // Handle notification status update if (event.data.hasUnread) { console.log('Has unread notifications'); notificationDot.style.display = 'block'; } else { console.log('No unread notifications'); notificationDot.style.display = 'none'; } } }); } // Function to send data to iframe function sendDataToIframe(iframe, options) { var _a; if (!iframe.contentWindow) return; const dataToSend = { type: 'DOCK_PARENT_INFO', project_id: window.overcentricProjectId, device_id: window.overcentricDeviceId, identity: window.overcentricUserIdentity, session_id: window.overcentricSessionId, url: window.location.href, hostname: normalizedHostname, context: options.context, position: options.position, isChatEnabled: options.isChatEnabled, isKBEnabled: options.isKBEnabled }; // Send message to iframe with specific target origin for security (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage(dataToSend, dockOrigin); } /** * Update the dock iframe with the identity ID. * @param identity - The identity to be added to the iframe URL. */ export function updateDockIdentity(identity) { if (dockIframe) { const currentSrc = new URL(dockIframe.src); currentSrc.searchParams.set('identityId', identity.uniqueIdentifier); dockIframe.src = currentSrc.toString(); } } export function setDockUrl(urlSuffix) { if (dockIframe) { dockIframe.src = `${dockOrigin}/dock/${urlSuffix}`; } } export function openDock() { if (dockIframe) { dockIframe.style.display = 'block'; } } export function closeDock() { if (dockIframe) { dockIframe.style.display = 'none'; } }