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