UNPKG

@gameon/web

Version:
899 lines (890 loc) 37.9 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { onChatCardContext, } from '@gameon/on-ui-components/chat/card/context'; import { onChatCarouselContext, } from '@gameon/on-ui-components/chat/carousel/context'; import { onChatInputContext, } from '@gameon/on-ui-components/chat/input/context'; import { onChatMessageContext, } from '@gameon/on-ui-components/chat/message/context'; import '@gameon/on-ui-components/chat/widget'; import '@gameon/on-ui-components/chat/window'; import '@gameon/on-ui-components/chat/notification'; import { ContextProvider } from '@lit-labs/context'; import { css, html, LitElement, nothing } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import { v4 as uuidv4 } from 'uuid'; import { notificationsContext } from '../notifications/notifications.context'; import { Breakpoint, getCurrentBreakpoint } from './breakpoints'; import { prodConfig as firebaseProdConfig, stgConfig as firebaseStgConfig, } from './firebase/firebase-config'; import { FirebaseInstance } from './firebase/firebase-instance'; import '@lottiefiles/lottie-player'; import '../notifications/notifications'; import '@gameon/on-ui-components/base/button'; const USER_STORAGE_KEY = 'ON_CHAT_BOT_CLIENT_USER_ID'; const CONVERSATION_STORAGE_KEY = 'ON_CHAT_BOT_CLIENT_CONVERSATION_ID'; const STG_WEB_CHANNEL_API_URL = 'https://web-channel.services.stg.tuul.com'; const PROD_WEB_CHANNEL_API_URL = 'https://web-channel.services.tuul.com'; const DEFAULT_HISTORY_LIMIT = 100; const OPENED_DESKTOP_STORAGE_KEY = 'ON_CHAT_BOT_CLIENT_HAS_OPENED_DESKTOP'; const OPENED_MOBILE_STORAGE_KEY = 'ON_CHAT_BOT_CLIENT_HAS_OPENED_MOBILE'; const SURFACE_BACKDROP_Z_INDEX = 999; const SURFACE_INPUT_Z_INDEX = 2000; const SURFACE_WINDOW_CLOSE_BUTTON_Z_INDEX = 1001; const SURFACE_WINDOW_Z_INDEX = 1000; export var Environment; (function (Environment) { Environment["PRODUCTION"] = "PRODUCTION"; Environment["STAGING"] = "STAGING"; Environment["LOCAL"] = "LOCAL"; })(Environment || (Environment = {})); export var DisplayMode; (function (DisplayMode) { DisplayMode["FULL_SCREEN"] = "FULL_SCREEN"; DisplayMode["SURFACE"] = "SURFACE"; DisplayMode["WIDGET"] = "WIDGET"; DisplayMode["WIDGET_WITHOUT_BUTTON"] = "WIDGET_WITHOUT_BUTTON"; })(DisplayMode || (DisplayMode = {})); export var OnSearchParams; (function (OnSearchParams) { OnSearchParams["INITIAL_PROMPT"] = "on_initial_prompt"; OnSearchParams["SHOULD_AUTO_OPEN"] = "on_should_auto_open"; OnSearchParams["SHOULD_AUTO_OPEN_MOBILE"] = "on_should_auto_open_mobile"; })(OnSearchParams || (OnSearchParams = {})); export var WidgetVisibility; (function (WidgetVisibility) { WidgetVisibility["HIDDEN"] = "hidden"; WidgetVisibility["VISIBLE"] = "visible"; })(WidgetVisibility || (WidgetVisibility = {})); let OnChatBotClient = class OnChatBotClient extends LitElement { constructor() { super(...arguments); this.clientId = ''; this.debug = false; this.messageHistoryLimit = DEFAULT_HISTORY_LIMIT; this.displayMode = DisplayMode.FULL_SCREEN; this.env = Environment.PRODUCTION; this.isSurfaceChatOpen = false; this.persistMessagesAcrossSessions = false; this.shouldAutoOpen = false; this.shouldAutoOpenMobile = false; this.customStyles = new Map(); this.messages = []; this.speakers = []; this.surfaceChatInputValue = ''; this.userId = ''; this.usersTyping = new Set(); this.webChannelParticipants = []; this.lastSeenMessageProvider = new ContextProvider(this, notificationsContext, { lastSeenMessageTimestamp: undefined, unreadMessages: [] }); this.onChatCardContextProvider = new ContextProvider(this, onChatCardContext, { linkTarget: '_blank' }); this.onChatCarouselContextProvider = new ContextProvider(this, onChatCarouselContext, { renderButtons: true }); this.onChatInputContextProvider = new ContextProvider(this, onChatInputContext, { enableVoice: false, placeholder: 'Aa', sendIcon: 'send', voiceIcon: 'microphone-01', }); this.onChatMessageContextProvider = new ContextProvider(this, onChatMessageContext, { stackQuickReplies: true }); } get webChannelApiBaseUrl() { switch (this.env) { case Environment.LOCAL: return ''; case Environment.STAGING: return STG_WEB_CHANNEL_API_URL; } return PROD_WEB_CHANNEL_API_URL; } get firebaseConfig() { switch (this.env) { case Environment.LOCAL: case Environment.STAGING: return firebaseStgConfig; } return firebaseProdConfig; } open() { if (this.onChatWidgetEl) { this.onChatWidgetEl.isOpen = true; this.connectToFirestore(); this.resetLastSeenMessage(); } } close() { if (this.onChatWidgetEl) { this.onChatWidgetEl.isOpen = false; } } toggle() { if (this.onChatWidgetEl && this.onChatWidgetEl.isOpen) { this.close(); } else { this.open(); } } getConversationId(clientId, userId) { const store = this.persistMessagesAcrossSessions ? window.localStorage : window.sessionStorage; let conversationId = store.getItem(`${CONVERSATION_STORAGE_KEY}_${clientId}_${userId}`); // if there is no conversation id in storage, generate a new one and store it if (!conversationId) { conversationId = uuidv4(); this.setConversationId(conversationId, clientId, userId); } return conversationId; } setConversationId(conversationId, clientId, userId) { const store = this.persistMessagesAcrossSessions ? window.localStorage : window.sessionStorage; store.setItem(`${CONVERSATION_STORAGE_KEY}_${clientId}_${userId}`, conversationId); } getWebChannelBotId() { var _a, _b; return ((_b = (_a = this.webChannelParticipants.find((p) => p.type === 'BOT')) === null || _a === void 0 ? void 0 : _a.userId) !== null && _b !== void 0 ? _b : ''); } willUpdate(changedProperties) { // Compute speakers if (changedProperties.has('botAvatarUrl') || changedProperties.has('webChannelParticipants')) { this.speakers = []; // for each participant, add a speaker this.webChannelParticipants.forEach((participant) => { switch (participant.type) { case 'BOT': this.speakers.push({ avatarUrl: this.botAvatarUrl, id: participant.userId, }); break; case 'USER': this.speakers.push({ id: participant.userId }); break; } }); } // Load bot details if (changedProperties.has('clientId') && this.clientId) { this.loadBotConfig(this.clientId).then((config) => { this.configureClient(config); if (this.displayMode === DisplayMode.FULL_SCREEN || this.displayMode === DisplayMode.SURFACE || this.shouldAutoOpen || this.shouldAutoOpenMobile) { this.connectToFirestore(); } }); } } getBotMessages() { return this.messages.filter((message) => message.speakerId === this.getWebChannelBotId()); } resetLastSeenMessage() { const lastBotMessage = this.getBotMessages().at(-1); this.lastSeenMessageProvider.setValue({ lastSeenMessageTimestamp: lastBotMessage === null || lastBotMessage === void 0 ? void 0 : lastBotMessage.timestamp, unreadMessages: [], }); } firstUpdated() { const storedUserId = this.fetchStoredUserId(); this.userId = storedUserId || uuidv4(); this.storeUserId(this.userId); this.addEventListener('on-chat-widget-open', this.connectToFirestore.bind(this), { once: true }); const params = new URLSearchParams(window.location.search); if (!this.initialPrompt) { const initialPromptParam = params.get(OnSearchParams.INITIAL_PROMPT); this.initialPrompt = initialPromptParam !== null && initialPromptParam !== void 0 ? initialPromptParam : undefined; } window.addEventListener('on-chat-widget-open', () => { this.resetLastSeenMessage(); }); } handleLottieLoad(event) { // Update the lottie-player aspect-ratio style property dynamically; Needed to tell Safari how to handle resizing the player based on height. const player = event.currentTarget; const svgElement = player.shadowRoot.querySelector('svg'); if (svgElement) { const aspectRatio = svgElement.viewBox.baseVal.width / svgElement.viewBox.baseVal.height; player.style.aspectRatio = `${aspectRatio}`; } } async configureClient(config) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z; this.botAvatarUrl = config.avatar; this.botId = this.clientId; this.botName = config.title; this.startingContent = config.startingContent; this.widgetVisibility = config.widgetVisibility; this.customStyles = this.computeCustomStyles(config); if ((_b = (_a = config.renderSettings) === null || _a === void 0 ? void 0 : _a.compatibility) === null || _b === void 0 ? void 0 : _b['link-target-mode']) { this.onChatCardContextProvider.setValue({ linkTarget: config.renderSettings.compatibility['link-target-mode'], }); } if (((_d = (_c = config.renderSettings) === null || _c === void 0 ? void 0 : _c.compatibility) === null || _d === void 0 ? void 0 : _d['render-carousel-buttons']) !== undefined) { this.onChatCarouselContextProvider.setValue({ renderButtons: config.renderSettings.compatibility['render-carousel-buttons'], }); } if (((_e = config.renderSettings) === null || _e === void 0 ? void 0 : _e.compatibility['chat-input-enable-voice']) || ((_g = (_f = config.renderSettings) === null || _f === void 0 ? void 0 : _f.compatibility) === null || _g === void 0 ? void 0 : _g['chat-input-placeholder']) || ((_h = config.renderSettings) === null || _h === void 0 ? void 0 : _h.compatibility['chat-input-send-icon']) || ((_j = config.renderSettings) === null || _j === void 0 ? void 0 : _j.compatibility['chat-input-voice-icon'])) { this.onChatInputContextProvider.setValue({ enableVoice: (_k = config.renderSettings.compatibility['chat-input-enable-voice']) !== null && _k !== void 0 ? _k : false, placeholder: (_l = config.renderSettings.compatibility['chat-input-placeholder']) !== null && _l !== void 0 ? _l : 'Aa', sendIcon: (_m = config.renderSettings.compatibility['chat-input-send-icon']) !== null && _m !== void 0 ? _m : 'send', voiceIcon: (_o = config.renderSettings.compatibility['chat-input-voice-icon']) !== null && _o !== void 0 ? _o : 'microphone-01', }); } if (((_q = (_p = config.renderSettings) === null || _p === void 0 ? void 0 : _p.compatibility) === null || _q === void 0 ? void 0 : _q['stack-quick-replies']) !== undefined) { this.onChatMessageContextProvider.setValue({ stackQuickReplies: (_r = config.renderSettings) === null || _r === void 0 ? void 0 : _r.compatibility['stack-quick-replies'], }); } if ((_t = (_s = config.renderSettings) === null || _s === void 0 ? void 0 : _s.compatibility) === null || _t === void 0 ? void 0 : _t['custom-close-button-image']) { this.chatCloseImageUrl = config.renderSettings.compatibility['custom-close-button-image']; } if ((_v = (_u = config.renderSettings) === null || _u === void 0 ? void 0 : _u.compatibility) === null || _v === void 0 ? void 0 : _v['custom-open-button-image']) { this.chatOpenImageUrl = config.renderSettings.compatibility['custom-open-button-image']; } if ((_x = (_w = config.renderSettings) === null || _w === void 0 ? void 0 : _w.compatibility) === null || _x === void 0 ? void 0 : _x['custom-stylesheets']) { const customStylesheetUrls = (_z = (_y = config.renderSettings) === null || _y === void 0 ? void 0 : _y.compatibility) === null || _z === void 0 ? void 0 : _z['custom-stylesheets']; customStylesheetUrls.forEach((stylesheetUrl) => { const link = document.createElement('link'); link.type = 'text/css'; link.rel = 'stylesheet'; link.href = stylesheetUrl; document.head.appendChild(link); }); } // Auto open the widget this.updateComplete.then(() => { const params = new URLSearchParams(window.location.search); const shouldAutoOpenParam = params.has(OnSearchParams.SHOULD_AUTO_OPEN); const shouldAutoOpenMobileParam = params.has(OnSearchParams.SHOULD_AUTO_OPEN_MOBILE); if (this.onChatWidgetEl) { if (getCurrentBreakpoint() > Breakpoint.SMALL) { this.onChatWidgetEl.isOpen = (shouldAutoOpenParam || this.shouldAutoOpen) && !this.hasAutoOpenedThisSession(OPENED_DESKTOP_STORAGE_KEY); } else { this.onChatWidgetEl.isOpen = (shouldAutoOpenMobileParam || this.shouldAutoOpenMobile) && !this.hasAutoOpenedThisSession(OPENED_MOBILE_STORAGE_KEY); } if (this.onChatWidgetEl.isOpen === true) { this.connectToFirestore(); } } }); } updateMessages(documents) { if (this.debug) { console.log(' updateMessages() start'); } // Gather all message events, with a valid content. const messages = documents.filter((doc) => doc.eventData && doc.eventData.eventType === 'message' && doc.channelData && doc.channelData.content.length > 0); // Gather all typing events. const typingEvents = documents.filter((doc) => doc.eventData && (doc.eventData.eventType === 'typing_start' || doc.eventData.eventType === 'typing_end')); // Compute the users that are currently typing. this.usersTyping = typingEvents.reduce((usersTyping, currentEvent) => { if (currentEvent.eventData.eventType === 'typing_start') { usersTyping.add(currentEvent.channelData.user.id); } if (currentEvent.eventData.eventType === 'typing_end') { usersTyping.delete(currentEvent.channelData.user.id); } return usersTyping; }, new Set()); if (this.debug) { console.log(' Messages filtered: ', messages); console.log(' Typing events: ', typingEvents); console.log(' Users typing: ', this.usersTyping); } // Find optimistic message. const optimisticMessages = this.messages.filter((message) => message.isOptimistic); if (this.debug) { console.log(' Optimistic messages: ', optimisticMessages); } this.messages = messages.map((message) => ({ contents: message.channelData.content, speakerId: message.channelData.user.id, timestamp: message.timestamp, })); if (this.debug) { console.log(' this.messages set: ', this.messages); } // If optimistic messages were found, add them back unless there's a // message in the conversation with a later timestamp. if (optimisticMessages.length > 0) { const lastMessage = this.messages[this.messages.length - 1]; optimisticMessages.forEach((optimisticMessage) => { if (!lastMessage || lastMessage.timestamp < optimisticMessage.timestamp) { if (this.debug) { console.log(' adding back optimistic message: ', optimisticMessage); } this.messages.push(optimisticMessage); } }); } // Set the initial message timestamp to be the earliest message. if (this.initialMessage) { const firstMessage = messages[0]; if (firstMessage) { this.initialMessage.timestamp = firstMessage.timestamp - 1; } } // Insert the initial message again, and add user typing messages. this.messages = [ ...(this.initialMessage ? [this.initialMessage] : []), ...this.messages, ]; if (this.debug) { console.log(' final this.messages state:', this.messages); console.log(' updateMessages() end'); } } computeCustomStyles(config) { var _a, _b, _c, _d, _e; const customStyles = new Map(); if (!config.renderSettings) { return customStyles; } // For backwards compaitibility, search for specific customizations by name const colorPrimary = (_a = config.colors) === null || _a === void 0 ? void 0 : _a.primary; const colorTitleFont = (_b = config.colors) === null || _b === void 0 ? void 0 : _b.titleFont; const attachmentFit = (_c = config.renderSettings.attachments) === null || _c === void 0 ? void 0 : _c['--attachment-fit']; const primaryButtonText = (_d = config.renderSettings.colors) === null || _d === void 0 ? void 0 : _d['--primary-button-text']; const primaryMessageBg = (_e = config.renderSettings.colors) === null || _e === void 0 ? void 0 : _e['--primary-message-bg']; if (colorPrimary) { customStyles.set('--on-chat-widget-primary-color', colorPrimary); customStyles.set('--on-linear-progress-active-indicator-color', colorPrimary); } if (colorTitleFont) { customStyles.set('--on-chat-widget-text-on-primary-color', colorTitleFont); } if (attachmentFit) { customStyles.set('--on-chat-card-image-fit', attachmentFit); } if (primaryButtonText) { customStyles.set('--on-chat-input-button-color', primaryButtonText); } if (primaryMessageBg) { customStyles.set('--on-chat-conversation-primary-background-color', primaryMessageBg); } // Add arbitrary customizations in the config if (config.renderSettings.customStyles) { Object.entries(config.renderSettings.customStyles).forEach((keyValuePair) => customStyles.set(keyValuePair[0], keyValuePair[1])); } return customStyles; } fetchStoredUserId() { return window.localStorage.getItem(USER_STORAGE_KEY); } storeUserId(userId) { window.localStorage.setItem(USER_STORAGE_KEY, userId); } async loadBotConfig(clientId) { const response = await fetch(`${this.webChannelApiBaseUrl}/v1/config/${clientId}`); if (response.ok) { return await response.json(); } else { throw new Error(`A bot config failed to load for client ID: ${clientId}`); } } pushNotifications() { var _a; if (this.debug) { console.log('pushNotifications() start'); } if ((_a = this.onChatWidgetEl) === null || _a === void 0 ? void 0 : _a.isOpen) { this.resetLastSeenMessage(); } else if (this.lastSeenMessageProvider.value.lastSeenMessageTimestamp) { const botMessages = this.getBotMessages(); const lastBotMessage = botMessages.at(-1); if (lastBotMessage && lastBotMessage.timestamp > this.lastSeenMessageProvider.value.lastSeenMessageTimestamp) { const unreadMessages = botMessages.filter((message) => { var _a; return message.timestamp > ((_a = this.lastSeenMessageProvider.value.lastSeenMessageTimestamp) !== null && _a !== void 0 ? _a : 0) && !message.contents.find((content) => content.text === '<on-chat-typing-indicator></on-chat-typing-indicator>'); }); this.lastSeenMessageProvider.setValue({ lastSeenMessageTimestamp: this.lastSeenMessageProvider.value.lastSeenMessageTimestamp, unreadMessages: [...unreadMessages], }); } } if (this.debug) { console.log(' lastSeenMessageProvider.value: ', this.lastSeenMessageProvider.value); console.log('pushNotifications() end'); } } async initializeConversation(userId, clientId, conversationId, baseURL) { const response = await fetch(`${baseURL}/v1/initialize`, { body: JSON.stringify({ userId: userId, clientId: clientId, conversationId: conversationId, }), headers: { 'Content-Type': 'application/json', }, method: 'POST', }); const result = await response.json(); this.setConversationId(result.conversation.id, clientId, userId); return result; } async initializeFirestoreConversation(userId, clientId, conversationId, baseURL, startingContent) { if (this.debug) { console.log('initializeFirestoreConversation() start'); } const resp = await this.initializeConversation(userId, clientId, conversationId, baseURL); this.webChannelUserId = resp.conversation.userId; this.webChannelParticipants = resp.conversation.participants; this.initialMessage = { contents: startingContent, speakerId: this.getWebChannelBotId(), timestamp: Date.now(), }; const messageInitData = { app: resp.conversation.app, channel: resp.conversation.channel, conversationId: resp.conversation.id, }; let fb; fb = new FirebaseInstance(this.firebaseConfig); if (this.debug) { console.log(' FirebaseInstance initialized: ', fb); } fb.listenToConvo(messageInitData, this.messageHistoryLimit, (snapshot) => { if (this.debug) { console.log('FirebaseInstance.listenToConvo() onSuccess() start'); console.log(' Got a new snapshot: ', snapshot); } const messagesData = snapshot.docs.map((doc) => doc.data()).reverse(); if (this.debug) { console.log(' Snapshot docs processed: ', messagesData); } this.updateMessages(messagesData); this.pushNotifications(); if (this.debug) { console.log('FirebaseInstance.listenToConvo() onSuccess() end'); } }, (error) => { console.error('Firestore error', error); }); if (this.initialPrompt) { this.sendMessage(this.initialPrompt); } if (this.debug) { console.log('initializeFirestoreConversation() end'); } } async sendMessage(text) { var _a; if (!this.clientId || !text.length) { return; } const payload = JSON.stringify({ message: { text }, clientId: this.clientId, userId: this.userId, conversationId: this.getConversationId(this.clientId, this.userId), }); const sentMessageResponse = await fetch(`${this.webChannelApiBaseUrl}/v1/message`, { body: payload, headers: { 'Content-Type': 'application/json', }, method: 'POST', }); const sentMessageMeta = await sentMessageResponse.json(); const message = { contents: [{ text }], speakerId: (_a = this.webChannelUserId) !== null && _a !== void 0 ? _a : '', timestamp: sentMessageMeta.timestamp, isOptimistic: true, }; this.messages = [...this.messages, message]; // Fix the initial message timestamp if the sent message is behind the // initial message. if (this.initialMessage && this.initialMessage.timestamp > sentMessageMeta.timestamp) { this.initialMessage.timestamp = sentMessageMeta.timestamp - 1; } this.dispatchEvent(new CustomEvent('on-client-send-message', { bubbles: true, composed: true, detail: { message: text, }, })); } handleSurfaceChatCloseClick() { this.isSurfaceChatOpen = false; document.body.style.overflow = 'visible'; } handleChatInputSubmit(e) { if (!this.userId) { return; } this.sendMessage(e.detail.value); // Reset the input box and scroll to bottom if (this.onChatWindowEl) { this.onChatWindowEl.inputValue = ''; this.onChatWindowEl.scrollToBottom(); } // Reset the input value if (this.displayMode === DisplayMode.SURFACE) { this.surfaceChatInputValue = ''; this.isSurfaceChatOpen = true; document.body.style.overflow = 'hidden'; } } hasAutoOpenedThisSession(key) { if (!window.sessionStorage.getItem(key)) { // Set the session storage window.sessionStorage.setItem(key, 'true'); return false; } // It has been opened this seesion so don't open it again return true; } async connectToFirestore() { var _a; if (!this.webChannelUserId) { if (this.debug) { console.log('Connecting to Firestore'); } this.initializeFirestoreConversation(this.userId, this.clientId, this.getConversationId(this.clientId, this.userId), this.webChannelApiBaseUrl, (_a = this.startingContent) !== null && _a !== void 0 ? _a : []); } } renderChatWindow(shouldHideDisplayInputBar = false) { var _a; return html ` <on-chat-window .conversationMessages="${this.messages}" .conversationPrimarySpeakerId="${(_a = this.webChannelUserId) !== null && _a !== void 0 ? _a : ''}" .conversationSpeakers="${this.speakers}" ?shouldDisplayLoadingIndicator="${this.usersTyping.size > 0}" ?shouldHideDisplayInputBar="${shouldHideDisplayInputBar}" @on-chat-input-submit="${this.handleChatInputSubmit}" @on-chat-message-quick-reply-click="${this.handleChatInputSubmit}" ></on-chat-window> <style> :host { ${Array.from(this.customStyles.entries()).map((keyValuePair) => `${keyValuePair[0]}: ${keyValuePair[1]};`)}; } </style> <on-button class="surface-chat-window-close-button" .icon="${'x'}" .iconPlacement="${'only'}" @click="${this.handleSurfaceChatCloseClick}" ></on-button> `; } renderSurface() { return html ` <div class="surface-backdrop"></div> ${this.renderChatWindow(true)} <on-chat-input class="surface-chat-input" .value="${this.surfaceChatInputValue}" @on-chat-input-change="${({ detail, }) => (this.surfaceChatInputValue = detail.value)}" @on-chat-input-submit="${this.handleChatInputSubmit}" ></on-chat-input> `; } renderChatNotifications() { var _a; if (((_a = this.onChatWidgetEl) === null || _a === void 0 ? void 0 : _a.isOpen) || !this.lastSeenMessageProvider.value) return nothing; const handleNotificationOpenWidget = () => { if (this.onChatWidgetEl) { this.onChatWidgetEl.isOpen = true; this.resetLastSeenMessage(); } }; const primarySpeaker = this.speakers.find((speaker) => speaker.id === this.getWebChannelBotId()); return html ` <on-chat-bot-notifications .speaker=${primarySpeaker} @on-notification-reset=${this.resetLastSeenMessage} @on-notification-open-message=${handleNotificationOpenWidget} ></on-chat-bot-notifications> `; } renderCustomButton(type, src) { const slot = type === 'OPEN' ? 'open-chat-button' : 'close-chat-button'; const classes = classMap({ 'chat-button-image': true, 'open-chat-button': type === 'OPEN', 'close-chat-button': type === 'CLOSE', }); const isLottieAnimation = src.endsWith('.json'); return isLottieAnimation ? html ` <lottie-player slot="${slot}" class="${classes}" autoplay loop mode="normal" src="${src}" @ready="${this.handleLottieLoad}" > </lottie-player> ` : html ` <img slot="${slot}" class="${classes}" src="${src}" /> `; } render() { if (!this.botId) { return; } switch (this.displayMode) { case DisplayMode.WIDGET: case DisplayMode.WIDGET_WITHOUT_BUTTON: return this.widgetVisibility !== WidgetVisibility.HIDDEN ? html ` ${this.renderChatNotifications()} <on-chat-widget .avatarUrl="${this.botAvatarUrl}" .shouldHideWidgetButton="${this.displayMode === DisplayMode.WIDGET_WITHOUT_BUTTON}" .windowTitle="${this.botName}" > ${this.renderChatWindow()} ${this.chatOpenImageUrl ? this.renderCustomButton('OPEN', this.chatOpenImageUrl) : nothing} ${this.chatCloseImageUrl ? this.renderCustomButton('CLOSE', this.chatCloseImageUrl) : nothing} </on-chat-widget> ` : nothing; case DisplayMode.SURFACE: return this.renderSurface(); default: return this.renderChatWindow(); } } }; OnChatBotClient.styles = css ` :host { display: block; } :host([display-mode='FULL_SCREEN']) on-chat-window { height: 100%; } :host([display-mode='WIDGET']) on-chat-window, :host([display-mode='WIDGET_WITHOUT_BUTTON']) on-chat-window { width: 100%; } :host([display-mode='SURFACE']) on-chat-window { --on-chat-bubble-background-color: transparent; --on-chat-bubble-border: none; --on-chat-bubble-max-width: 80%; --on-chat-conversation-primary-background-color: transparent; --on-chat-conversation-primary-bubble-border: none; --on-chat-conversation-primary-color: var( --on-chat-surface-primary-color, var(--on-chat-widget-primary-color, black) ); bottom: 8rem; left: 50%; opacity: 0; pointer-events: 'none'; position: fixed; top: 0; transition: 300ms opacity ease-in-out; transform: translateX(-50%); width: 80%; z-index: ${SURFACE_WINDOW_Z_INDEX}; mask-image: linear-gradient(transparent 0, #000 20%); } :host([is-surface-chat-open]) .surface-backdrop, :host([is-surface-chat-open]) on-chat-window, :host([is-surface-chat-open]) .surface-chat-window-close-button { opacity: 1; pointer-events: 'auto'; } .chat-button-image.open-chat-button { height: var( --on-chat-widget-button-open-size, var(--on-chat-widget-button-size, 4rem) ); } .chat-button-image.close-chat-button { height: var( --on-chat-widget-button-close-size, var(--on-chat-widget-button-size, 4rem) ); } .surface-backdrop { background-color: var( --on-chat-surface-backdrop-color, rgba(0, 0, 0, 0.75) ); backdrop-filter: blur(50px); height: 100%; left: 0; opacity: 0; pointer-events: 'none'; position: fixed; top: 0; transition: 300ms opacity ease-in-out; width: 100%; z-index: ${SURFACE_BACKDROP_Z_INDEX}; } .surface-chat-input { --on-chat-input-background-color: transparent; --on-chat-input-border-width: 0; background: linear-gradient(white, white) padding-box, linear-gradient( to right, var( --on-chat-surface-input-border-color-a, var(--on-chat-input-border-color, #000) ), var( --on-chat-surface-input-border-color-b, var(--on-chat-input-border-color, #000) ) ) border-box; border: 8px solid transparent; border-radius: var(--on-chat-input-border-radius, 8px); bottom: 2rem; left: 50%; max-width: 420px; padding: 8px; position: fixed; transform: translateX(-50%); width: 80%; z-index: ${SURFACE_INPUT_Z_INDEX}; } .surface-chat-window-close-button { opacity: 0; pointer-events: 'none'; position: fixed; right: 2rem; top: 2rem; transition: 300ms opacity ease-in-out; z-index: ${SURFACE_WINDOW_CLOSE_BUTTON_Z_INDEX}; } `; __decorate([ query('on-chat-window') ], OnChatBotClient.prototype, "onChatWindowEl", void 0); __decorate([ query('on-chat-widget') ], OnChatBotClient.prototype, "onChatWidgetEl", void 0); __decorate([ property({ attribute: 'chat-close-image-url' }) ], OnChatBotClient.prototype, "chatCloseImageUrl", void 0); __decorate([ property({ attribute: 'chat-open-image-url' }) ], OnChatBotClient.prototype, "chatOpenImageUrl", void 0); __decorate([ property({ attribute: 'client-id' }) ], OnChatBotClient.prototype, "clientId", void 0); __decorate([ property({ type: Boolean }) ], OnChatBotClient.prototype, "debug", void 0); __decorate([ property({ attribute: 'message-history-limit', type: Number }) ], OnChatBotClient.prototype, "messageHistoryLimit", void 0); __decorate([ property({ attribute: 'display-mode', reflect: true }) ], OnChatBotClient.prototype, "displayMode", void 0); __decorate([ property() ], OnChatBotClient.prototype, "env", void 0); __decorate([ property({ attribute: 'initial-prompt' }) ], OnChatBotClient.prototype, "initialPrompt", void 0); __decorate([ property({ attribute: 'is-surface-chat-open', reflect: true, type: Boolean }) ], OnChatBotClient.prototype, "isSurfaceChatOpen", void 0); __decorate([ property({ attribute: 'persist-messages-across-sessions', type: Boolean }) ], OnChatBotClient.prototype, "persistMessagesAcrossSessions", void 0); __decorate([ property({ attribute: 'should-auto-open', type: Boolean }) ], OnChatBotClient.prototype, "shouldAutoOpen", void 0); __decorate([ property({ attribute: 'should-auto-open-mobile', type: Boolean }) ], OnChatBotClient.prototype, "shouldAutoOpenMobile", void 0); __decorate([ state() ], OnChatBotClient.prototype, "botAvatarUrl", void 0); __decorate([ state() ], OnChatBotClient.prototype, "botId", void 0); __decorate([ state() ], OnChatBotClient.prototype, "botName", void 0); __decorate([ state() ], OnChatBotClient.prototype, "customStyles", void 0); __decorate([ state() ], OnChatBotClient.prototype, "initialMessage", void 0); __decorate([ state() ], OnChatBotClient.prototype, "messages", void 0); __decorate([ state() ], OnChatBotClient.prototype, "speakers", void 0); __decorate([ state() ], OnChatBotClient.prototype, "startingContent", void 0); __decorate([ state() ], OnChatBotClient.prototype, "surfaceChatInputValue", void 0); __decorate([ state() ], OnChatBotClient.prototype, "userId", void 0); __decorate([ state() ], OnChatBotClient.prototype, "usersTyping", void 0); __decorate([ state() ], OnChatBotClient.prototype, "webChannelParticipants", void 0); __decorate([ state() ], OnChatBotClient.prototype, "webChannelUserId", void 0); __decorate([ state() ], OnChatBotClient.prototype, "widgetVisibility", void 0); OnChatBotClient = __decorate([ customElement('on-chat-bot-client') ], OnChatBotClient); export { OnChatBotClient }; //# sourceMappingURL=bot-client.js.map