]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/index.ts
8227dec6838f4cb23077db9c307ccd41a55d02f2
[bookstack] / resources / js / wysiwyg / ui / index.ts
1 import {
2     $getSelection,
3     COMMAND_PRIORITY_LOW,
4     LexicalEditor,
5     SELECTION_CHANGE_COMMAND
6 } from "lexical";
7 import {getMainEditorFullToolbar} from "./toolbars";
8 import {EditorUIManager} from "./framework/manager";
9 import {image as imageFormDefinition, link as linkFormDefinition} from "./defaults/form-definitions";
10 import {DecoratorListener} from "lexical/LexicalEditor";
11 import type {NodeKey} from "lexical/LexicalNode";
12 import {EditorDecoratorAdapter} from "./framework/decorator";
13 import {ImageDecorator} from "./decorators/image";
14 import {EditorUiContext} from "./framework/core";
15
16 export function buildEditorUI(element: HTMLElement, editor: LexicalEditor) {
17     const manager = new EditorUIManager();
18     const context: EditorUiContext = {
19         editor,
20         manager,
21         translate: (text: string): string => text,
22         lastSelection: null,
23     };
24     manager.setContext(context);
25
26     // Create primary toolbar
27     const toolbar = getMainEditorFullToolbar();
28     toolbar.setContext(context);
29     element.before(toolbar.getDOMElement());
30
31     // Register modals
32     manager.registerModal('link', {
33         title: 'Insert/Edit link',
34         form: linkFormDefinition,
35     });
36     manager.registerModal('image', {
37         title: 'Insert/Edit Image',
38         form: imageFormDefinition
39     })
40
41     // Register decorator listener
42     // Maybe move to manager?
43     manager.registerDecoratorType('image', ImageDecorator);
44     const domDecorateListener: DecoratorListener<EditorDecoratorAdapter> = (decorators: Record<NodeKey, EditorDecoratorAdapter>) => {
45         const keys = Object.keys(decorators);
46         for (const key of keys) {
47             const decoratedEl = editor.getElementByKey(key);
48             const adapter = decorators[key];
49             const decorator = manager.getDecorator(adapter.type, key);
50             decorator.setNode(adapter.getNode());
51             const decoratorEl = decorator.render(context);
52             if (decoratedEl) {
53                 decoratedEl.append(decoratorEl);
54             }
55         }
56     }
57     editor.registerDecoratorListener(domDecorateListener);
58
59     // Update button states on editor selection change
60     editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
61         const selection = $getSelection();
62         toolbar.updateState({editor, selection});
63         context.lastSelection = selection;
64         return false;
65     }, COMMAND_PRIORITY_LOW);
66 }