UNPKG

besper-frontend-site-dev-main

Version:

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

145 lines (117 loc) 3.62 kB
// Base component class for all B-esper UI components import { ComponentProps, WidgetState } from '../../types/components.types.js'; import { generateId } from '../../utils/helpers.js'; import { createElement } from '../../utils/dom.js'; export abstract class Component { protected element: HTMLElement; protected id: string; protected className: string; protected state: WidgetState; protected eventListeners: Map<string, EventListener[]>; constructor(props: ComponentProps = {}) { this.id = props.id || generateId(); this.className = props.className || ''; this.state = { isVisible: true, isLoading: false, isMinimized: false, }; this.eventListeners = new Map(); this.element = this.createElement(); } protected abstract createElement(): HTMLElement; protected abstract render(): string; public mount(parent: HTMLElement): void { parent.appendChild(this.element); this.onMount(); } public unmount(): void { this.onUnmount(); this.removeAllEventListeners(); if (this.element.parentNode) { this.element.parentNode.removeChild(this.element); } } protected onMount(): void { // Override in subclasses } protected onUnmount(): void { // Override in subclasses } protected addEventListener( element: HTMLElement, event: string, listener: EventListener ): void { element.addEventListener(event, listener); const elementListeners = this.eventListeners.get(element.id) || []; elementListeners.push(listener); this.eventListeners.set(element.id, elementListeners); } protected removeEventListener( element: HTMLElement, event: string, listener: EventListener ): void { element.removeEventListener(event, listener); const elementListeners = this.eventListeners.get(element.id) || []; const index = elementListeners.indexOf(listener); if (index > -1) { elementListeners.splice(index, 1); this.eventListeners.set(element.id, elementListeners); } } protected removeAllEventListeners(): void { this.eventListeners.clear(); } protected updateState(newState: Partial<WidgetState>): void { this.state = { ...this.state, ...newState }; this.onStateChange(); } protected onStateChange(): void { // Override in subclasses to react to state changes } protected addClass(className: string): void { this.element.classList.add(className); } protected removeClass(className: string): void { this.element.classList.remove(className); } protected toggleClass(className: string, force?: boolean): void { if (force !== undefined) { this.element.classList.toggle(className, force); } else { this.element.classList.toggle(className); } } protected setStyle(property: string, value: string): void { this.element.style.setProperty(property, value); } protected show(): void { this.updateState({ isVisible: true }); this.element.style.display = ''; } protected hide(): void { this.updateState({ isVisible: false }); this.element.style.display = 'none'; } protected setLoading(loading: boolean): void { this.updateState({ isLoading: loading }); this.toggleClass('loading', loading); } public getElement(): HTMLElement { return this.element; } public getId(): string { return this.id; } public getState(): WidgetState { return { ...this.state }; } public isVisible(): boolean { return this.state.isVisible; } public isLoading(): boolean { return this.state.isLoading; } }