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
text/typescript
// 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;
}
}