overcentric
Version:
A lightweight, privacy-focused toolkit for modern SaaS web applications
184 lines (183 loc) • 7.6 kB
JavaScript
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';
}
}