UNPKG

besper-frontend-site-dev-main

Version:

Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment

140 lines (122 loc) 3.19 kB
/** * Typing Indicator Component * Handles the typing indicator display in the chat widget */ export class TypingIndicator { constructor(widget, state, options = {}) { this.widget = widget; this.state = state; this.options = options; this.isVisible = false; } /** * Generate the HTML for the typing indicator * @returns {string} Typing indicator HTML string */ getHTML() { const config = this.state.botConfig; const shouldHideAvatar = !config?.logoUrl; return ` <div class="besper-typing-indicator" id="besper-typing"> <div class="besper-message besper-bot"> <div class="besper-message-avatar besper-bot" ${shouldHideAvatar ? 'style="display: none;"' : ''}> ${ config?.logoUrl ? `<img src="${config.logoUrl}" alt="Bot Logo" class="besper-avatar-image">` : '' } </div> <div class="besper-message-content"> <div class="besper-typing-dots"> <span></span> <span></span> <span></span> </div> </div> </div> </div> `; } /** * Show the typing indicator */ show() { if (this.isVisible) return; const messagesContainer = this.widget.querySelector('#besper-messages'); if (!messagesContainer) return; // Remove any existing typing indicator first this.hide(); // Add the typing indicator messagesContainer.insertAdjacentHTML('beforeend', this.getHTML()); this.isVisible = true; // Auto-scroll to show the typing indicator this.scrollToBottom(); } /** * Hide the typing indicator */ hide() { const typingIndicator = this.widget.querySelector('#besper-typing'); if (typingIndicator) { typingIndicator.remove(); this.isVisible = false; } } /** * Toggle the typing indicator visibility */ toggle() { if (this.isVisible) { this.hide(); } else { this.show(); } } /** * Check if the typing indicator is currently visible * @returns {boolean} Whether the typing indicator is visible */ isShowing() { return this.isVisible; } /** * Scroll to the bottom of the messages container */ scrollToBottom() { const messagesContainer = this.widget.querySelector('#besper-messages'); if (messagesContainer) { messagesContainer.scrollTop = messagesContainer.scrollHeight; } } /** * Show typing indicator with automatic hide after timeout * @param {number} timeout - Timeout in milliseconds (default: 5000) */ showWithTimeout(timeout = 5000) { this.show(); // Clear any existing timeout if (this.hideTimeout) { clearTimeout(this.hideTimeout); } // Set new timeout this.hideTimeout = setTimeout(() => { this.hide(); }, timeout); } /** * Clear any pending hide timeout */ clearTimeout() { if (this.hideTimeout) { clearTimeout(this.hideTimeout); this.hideTimeout = null; } } /** * Cleanup method for component destruction */ destroy() { this.hide(); this.clearTimeout(); } }