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
JavaScript
/**
* 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();
}
}