| 15 | * event / command is executed in all components - by simply awaiting the `triggerEvent()`. |
| 16 | */ |
| 17 | export class TypedComponent<ChildT extends TypedComponent<ChildT>> { |
| 18 | $widget!: JQuery<HTMLElement>; |
| 19 | componentId: string; |
| 20 | children: ChildT[]; |
| 21 | initialized: Promise<void> | null; |
| 22 | parent?: TypedComponent<any>; |
| 23 | _position!: number; |
| 24 | private listeners: Record<string, EventHandler[]> | null = {}; |
| 25 | |
| 26 | constructor() { |
| 27 | this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`; |
| 28 | this.children = []; |
| 29 | this.initialized = null; |
| 30 | } |
| 31 | |
| 32 | get sanitizedClassName() { |
| 33 | // webpack mangles names and sometimes uses unsafe characters |
| 34 | return this.constructor.name.replace(/[^A-Z0-9]/gi, "_"); |
| 35 | } |
| 36 | |
| 37 | get position() { |
| 38 | return this._position; |
| 39 | } |
| 40 | |
| 41 | set position(newPosition: number) { |
| 42 | this._position = newPosition; |
| 43 | } |
| 44 | |
| 45 | setParent(parent: TypedComponent<any>) { |
| 46 | this.parent = parent; |
| 47 | return this; |
| 48 | } |
| 49 | |
| 50 | child(...components: ChildT[]) { |
| 51 | for (const component of components) { |
| 52 | component.setParent(this); |
| 53 | |
| 54 | this.children.push(component); |
| 55 | } |
| 56 | |
| 57 | return this; |
| 58 | } |
| 59 | |
| 60 | /** |
| 61 | * Removes a child component from this component's children array. |
| 62 | * This is used for cleanup when a widget is unmounted to prevent event listener accumulation. |
| 63 | */ |
| 64 | removeChild(component: ChildT) { |
| 65 | const index = this.children.indexOf(component); |
| 66 | if (index !== -1) { |
| 67 | this.children.splice(index, 1); |
| 68 | component.parent = undefined; |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | handleEvent<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | null | undefined { |
| 73 | try { |
| 74 | const callMethodPromise = this.initialized ? this.initialized.then(() => this.callMethod((this as any)[`${name}Event`], data)) : this.callMethod((this as any)[`${name}Event`], data); |
nothing calls this directly
no outgoing calls
no test coverage detected