1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2026-01-03 23:42:28 +03:00

Lexical: Added code block selection & edit features

Also added extra lifecycle handling for decorators to things can be
properly cleaned up after node destruction.
This commit is contained in:
Dan Brown
2024-07-16 16:36:08 +01:00
parent 51d8044a54
commit ea4c50c2c2
11 changed files with 156 additions and 19 deletions

View File

@@ -1,11 +1,13 @@
import {EditorFormModal, EditorFormModalDefinition} from "./modals";
import {EditorContainerUiElement, EditorUiContext, EditorUiElement, EditorUiStateUpdate} from "./core";
import {EditorDecorator, EditorDecoratorAdapter} from "./decorator";
import {$getSelection, COMMAND_PRIORITY_LOW, LexicalEditor, SELECTION_CHANGE_COMMAND} from "lexical";
import {$getSelection, BaseSelection, COMMAND_PRIORITY_LOW, LexicalEditor, SELECTION_CHANGE_COMMAND} from "lexical";
import {DecoratorListener} from "lexical/LexicalEditor";
import type {NodeKey} from "lexical/LexicalNode";
import {EditorContextToolbar, EditorContextToolbarDefinition} from "./toolbars";
export type SelectionChangeHandler = (selection: BaseSelection|null) => void;
export class EditorUIManager {
protected modalDefinitionsByKey: Record<string, EditorFormModalDefinition> = {};
@@ -15,6 +17,7 @@ export class EditorUIManager {
protected toolbar: EditorContainerUiElement|null = null;
protected contextToolbarDefinitionsByKey: Record<string, EditorContextToolbarDefinition> = {};
protected activeContextToolbars: EditorContextToolbar[] = [];
protected selectionChangeHandlers: Set<SelectionChangeHandler> = new Set();
setContext(context: EditorUiContext) {
this.context = context;
@@ -72,6 +75,10 @@ export class EditorUIManager {
return decorator;
}
getDecoratorByNodeKey(nodeKey: string): EditorDecorator|null {
return this.decoratorInstancesByNodeKey[nodeKey] || null;
}
setToolbar(toolbar: EditorContainerUiElement) {
if (this.toolbar) {
this.toolbar.getDOMElement().remove();
@@ -94,7 +101,7 @@ export class EditorUIManager {
for (const toolbar of this.activeContextToolbars) {
toolbar.updateState(update);
}
// console.log('selection update', update.selection);
this.triggerSelectionChange(update.selection);
}
triggerStateRefresh(): void {
@@ -104,6 +111,24 @@ export class EditorUIManager {
});
}
protected triggerSelectionChange(selection: BaseSelection|null): void {
if (!selection) {
return;
}
for (const handler of this.selectionChangeHandlers) {
handler(selection);
}
}
onSelectionChange(handler: SelectionChangeHandler): void {
this.selectionChangeHandlers.add(handler);
}
offSelectionChange(handler: SelectionChangeHandler): void {
this.selectionChangeHandlers.delete(handler);
}
protected updateContextToolbars(update: EditorUiStateUpdate): void {
for (const toolbar of this.activeContextToolbars) {
toolbar.empty();