1 import {BaseSelection, LexicalEditor} from "lexical";
2 import {EditorUIManager} from "./manager";
4 import {el} from "../../utils/dom";
6 export type EditorUiStateUpdate = {
8 selection: BaseSelection|null;
11 export type EditorUiContext = {
12 editor: LexicalEditor; // Lexical editor instance
13 editorDOM: HTMLElement; // DOM element the editor is bound to
14 containerDOM: HTMLElement; // DOM element which contains all editor elements
15 scrollDOM: HTMLElement; // DOM element which is the main content scroll container
16 translate: (text: string) => string; // Translate function
17 error: (text: string|Error) => void; // Error reporting function
18 manager: EditorUIManager; // UI Manager instance for this editor
19 options: Record<string, any>; // General user options which may be used by sub elements
22 export interface EditorUiBuilderDefinition {
23 build: () => EditorUiElement;
26 export function isUiBuilderDefinition(object: any): object is EditorUiBuilderDefinition {
27 return 'build' in object;
30 export abstract class EditorUiElement {
31 protected dom: HTMLElement|null = null;
32 private context: EditorUiContext|null = null;
34 protected abstract buildDOM(): HTMLElement;
36 setContext(context: EditorUiContext): void {
37 this.context = context;
40 getContext(): EditorUiContext {
41 if (this.context === null) {
42 throw new Error('Attempted to use EditorUIContext before it has been set');
48 getDOMElement(): HTMLElement {
50 this.dom = this.buildDOM();
56 rebuildDOM(): HTMLElement {
57 const newDOM = this.buildDOM();
58 this.dom?.replaceWith(newDOM);
64 return this.getContext().translate(text);
67 updateState(state: EditorUiStateUpdate): void {
72 export class EditorContainerUiElement extends EditorUiElement {
73 protected children : EditorUiElement[] = [];
75 constructor(children: EditorUiElement[]) {
77 this.children.push(...children);
80 protected buildDOM(): HTMLElement {
81 return el('div', {}, this.getChildren().map(child => child.getDOMElement()));
84 getChildren(): EditorUiElement[] {
88 protected addChildren(...children: EditorUiElement[]): void {
89 this.children.push(...children);
92 protected removeChildren(...children: EditorUiElement[]): void {
93 for (const child of children) {
94 this.removeChild(child);
98 protected removeChild(child: EditorUiElement) {
99 const index = this.children.indexOf(child);
101 this.children.splice(index, 1);
105 updateState(state: EditorUiStateUpdate): void {
106 for (const child of this.children) {
107 child.updateState(state);
111 setContext(context: EditorUiContext) {
112 super.setContext(context);
113 for (const child of this.getChildren()) {
114 child.setContext(context);
119 export class EditorSimpleClassContainer extends EditorContainerUiElement {
122 constructor(className: string, children: EditorUiElement[]) {
124 this.className = className;
127 protected buildDOM(): HTMLElement {
129 class: this.className,
130 }, this.getChildren().map(child => child.getDOMElement()));