]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/core.ts
465765caa3181b4501d53d068c55e1b90809bc27
[bookstack] / resources / js / wysiwyg / ui / framework / core.ts
1 import {BaseSelection, LexicalEditor} from "lexical";
2 import {EditorUIManager} from "./manager";
3 import {el} from "../../helpers";
4
5 export type EditorUiStateUpdate = {
6     editor: LexicalEditor,
7     selection: BaseSelection|null,
8 };
9
10 export type EditorUiContext = {
11     editor: LexicalEditor,
12     editorDOM: HTMLElement,
13     containerDOM: HTMLElement,
14     translate: (text: string) => string,
15     manager: EditorUIManager,
16     lastSelection: BaseSelection|null,
17 };
18
19 export abstract class EditorUiElement {
20     protected dom: HTMLElement|null = null;
21     private context: EditorUiContext|null = null;
22
23     protected abstract buildDOM(): HTMLElement;
24
25     setContext(context: EditorUiContext): void {
26         this.context = context;
27     }
28
29     getContext(): EditorUiContext {
30         if (this.context === null) {
31             throw new Error('Attempted to use EditorUIContext before it has been set');
32         }
33
34         return this.context;
35     }
36
37     getDOMElement(): HTMLElement {
38         if (!this.dom) {
39             this.dom = this.buildDOM();
40         }
41
42         return this.dom;
43     }
44
45     trans(text: string) {
46         return this.getContext().translate(text);
47     }
48
49     updateState(state: EditorUiStateUpdate): void {
50         return;
51     }
52 }
53
54 export class EditorContainerUiElement extends EditorUiElement {
55     protected children : EditorUiElement[] = [];
56
57     constructor(children: EditorUiElement[]) {
58         super();
59         this.children.push(...children);
60     }
61
62     protected buildDOM(): HTMLElement {
63         return el('div', {}, this.getChildren().map(child => child.getDOMElement()));
64     }
65
66     getChildren(): EditorUiElement[] {
67         return this.children;
68     }
69
70     protected addChildren(...children: EditorUiElement[]): void {
71         this.children.push(...children);
72     }
73
74     protected removeChildren(...children: EditorUiElement[]): void {
75         for (const child of children) {
76             this.removeChild(child);
77         }
78     }
79
80     protected removeChild(child: EditorUiElement) {
81         const index = this.children.indexOf(child);
82         if (index !== -1) {
83             this.children.splice(index, 1);
84         }
85     }
86
87     updateState(state: EditorUiStateUpdate): void {
88         for (const child of this.children) {
89             child.updateState(state);
90         }
91     }
92
93     setContext(context: EditorUiContext) {
94         super.setContext(context);
95         for (const child of this.getChildren()) {
96             child.setContext(context);
97         }
98     }
99 }
100
101 export class EditorSimpleClassContainer extends EditorContainerUiElement {
102     protected className;
103
104     constructor(className: string, children: EditorUiElement[]) {
105         super(children);
106         this.className = className;
107     }
108
109     protected buildDOM(): HTMLElement {
110         return el('div', {
111             class: this.className,
112         }, this.getChildren().map(child => child.getDOMElement()));
113     }
114 }
115