]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/index.ts
Lexical: Added basic list button/support
[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, source as sourceFormDefinition} 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     manager.registerModal('source', {
41         title: 'Source code',
42         form: sourceFormDefinition,
43     });
44
45     // Register decorator listener
46     // Maybe move to manager?
47     manager.registerDecoratorType('image', ImageDecorator);
48     const domDecorateListener: DecoratorListener<EditorDecoratorAdapter> = (decorators: Record<NodeKey, EditorDecoratorAdapter>) => {
49         const keys = Object.keys(decorators);
50         for (const key of keys) {
51             const decoratedEl = editor.getElementByKey(key);
52             const adapter = decorators[key];
53             const decorator = manager.getDecorator(adapter.type, key);
54             decorator.setNode(adapter.getNode());
55             const decoratorEl = decorator.render(context);
56             if (decoratedEl) {
57                 decoratedEl.append(decoratorEl);
58             }
59         }
60     }
61     editor.registerDecoratorListener(domDecorateListener);
62
63     // Update button states on editor selection change
64     editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
65         const selection = $getSelection();
66         toolbar.updateState({editor, selection});
67         context.lastSelection = selection;
68         return false;
69     }, COMMAND_PRIORITY_LOW);
70 }