import m from 'mithril'; import { IdType } from './Types'; import { generateId } from './Tools'; import { EventEmitter, ValidEventTypes } from '../event-emitter/EventEmitter'; declare type ViewType = { view: () => m.Vnode | m.Children; } export declare type ComponentAttributes = { id?: IdType; events?: ValidEventTypes; } export abstract class Component implements ViewType { private readonly id: IdType; protected readonly attrs: A; protected node?: HTMLElement; protected modal = false; events: EventEmitter; fitContainer: boolean = false; parent?: Component; constructor(attrs?: A) { this.attrs = attrs || {} as A; this.id = this.attrs.id || generateId(); this.events = new EventEmitter(this); if (this.attrs.events) { for (const name in this.attrs.events) { (this.events as EventEmitter).on(name, this.attrs.events[name]); } } } getId(): IdType { return this.id; } mount(el: HTMLElement | string = document.body): void { if (typeof el === 'string') { el = document.querySelector(el) as HTMLElement; } if (!this.node) { this.node = document.createElement('div'); this.node.classList.add('webcraft'); if (this.modal) { this.node.classList.add('webcraft--modal'); } } m.mount(this.node, { view: () => this.view(), oncreate: () => { (el as HTMLElement).appendChild(this.node!); }, onremove: () => { (el as HTMLElement).removeChild(this.node!); }, }); } unmount() { if (this.node) { m.mount(this.node, null); } } abstract view(): m.Vnode | m.Children; }