1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-07-30 04:23:11 +03:00

Lexical: Finished up core drawing insert/editing

Added new options that sits on the context, for things needed but not
for the core editor, which are defined out of the editor (drawio URL,
error message text, pageId etc...)
This commit is contained in:
Dan Brown
2024-07-19 12:09:41 +01:00
parent fb87fb5750
commit c7c0df0964
13 changed files with 128 additions and 30 deletions

View File

@ -1,7 +1,6 @@
import {EditorDecorator} from "../framework/decorator";
import {EditorUiContext} from "../framework/core";
import {$selectionContainsNode, $selectSingleNode} from "../../helpers";
import {$openCodeEditorForNode, CodeBlockNode} from "../../nodes/code-block";
import {BaseSelection} from "lexical";
import {$openDrawingEditorForNode, DiagramNode} from "../../nodes/diagram";
@ -11,6 +10,7 @@ export class DiagramDecorator extends EditorDecorator {
setup(context: EditorUiContext, element: HTMLElement) {
const diagramNode = this.getNode();
element.classList.add('editor-diagram');
element.addEventListener('click', event => {
context.editor.update(() => {
$selectSingleNode(this.getNode());
@ -19,7 +19,7 @@ export class DiagramDecorator extends EditorDecorator {
element.addEventListener('dblclick', event => {
context.editor.getEditorState().read(() => {
$openDrawingEditorForNode(context.editor, (this.getNode() as DiagramNode));
$openDrawingEditorForNode(context, (this.getNode() as DiagramNode));
});
});

View File

@ -67,12 +67,14 @@ import tableIcon from "@icons/editor/table.svg";
import imageIcon from "@icons/editor/image.svg";
import horizontalRuleIcon from "@icons/editor/horizontal-rule.svg";
import codeBlockIcon from "@icons/editor/code-block.svg";
import diagramIcon from "@icons/editor/diagram.svg";
import detailsIcon from "@icons/editor/details.svg";
import sourceIcon from "@icons/editor/source-view.svg";
import fullscreenIcon from "@icons/editor/fullscreen.svg";
import editIcon from "@icons/edit.svg";
import {$createHorizontalRuleNode, $isHorizontalRuleNode} from "../../nodes/horizontal-rule";
import {$createCodeBlockNode, $isCodeBlockNode, $openCodeEditorForNode, CodeBlockNode} from "../../nodes/code-block";
import {$createDiagramNode, $isDiagramNode, $openDrawingEditorForNode, DiagramNode} from "../../nodes/diagram";
export const undo: EditorButtonDefinition = {
label: 'Undo',
@ -445,6 +447,31 @@ export const editCodeBlock: EditorButtonDefinition = Object.assign({}, codeBlock
icon: editIcon,
});
export const diagram: EditorButtonDefinition = {
label: 'Insert/edit drawing',
icon: diagramIcon,
action(context: EditorUiContext) {
context.editor.getEditorState().read(() => {
const selection = $getSelection();
const diagramNode = $getNodeFromSelection(context.lastSelection, $isDiagramNode) as (DiagramNode|null);
if (diagramNode === null) {
context.editor.update(() => {
const diagram = $createDiagramNode();
$insertNewBlockNodeAtSelection(diagram, true);
$openDrawingEditorForNode(context, diagram);
diagram.selectStart();
});
} else {
$openDrawingEditorForNode(context, diagramNode);
}
});
},
isActive(selection: BaseSelection|null): boolean {
return $selectionContainsNodeType(selection, $isDiagramNode);
}
};
export const details: EditorButtonDefinition = {
label: 'Insert collapsible block',
icon: detailsIcon,

View File

@ -3,17 +3,18 @@ import {EditorUIManager} from "./manager";
import {el} from "../../helpers";
export type EditorUiStateUpdate = {
editor: LexicalEditor,
selection: BaseSelection|null,
editor: LexicalEditor;
selection: BaseSelection|null;
};
export type EditorUiContext = {
editor: LexicalEditor,
editorDOM: HTMLElement,
containerDOM: HTMLElement,
translate: (text: string) => string,
manager: EditorUIManager,
lastSelection: BaseSelection|null,
editor: LexicalEditor; // Lexical editor instance
editorDOM: HTMLElement; // DOM element the editor is bound to
containerDOM: HTMLElement; // DOM element which contains all editor elements
translate: (text: string) => string; // Translate function
manager: EditorUIManager; // UI Manager instance for this editor
lastSelection: BaseSelection|null; // The last tracked selection made by the user
options: Record<string, any>; // General user options which may be used by sub elements
};
export abstract class EditorUiElement {

View File

@ -12,7 +12,7 @@ import {EditorUiContext} from "./framework/core";
import {CodeBlockDecorator} from "./decorators/code-block";
import {DiagramDecorator} from "./decorators/diagram";
export function buildEditorUI(container: HTMLElement, element: HTMLElement, editor: LexicalEditor): EditorUiContext {
export function buildEditorUI(container: HTMLElement, element: HTMLElement, editor: LexicalEditor, options: Record<string, any>): EditorUiContext {
const manager = new EditorUIManager();
const context: EditorUiContext = {
editor,
@ -21,6 +21,7 @@ export function buildEditorUI(container: HTMLElement, element: HTMLElement, edit
manager,
translate: (text: string): string => text,
lastSelection: null,
options,
};
manager.setContext(context);
@ -43,7 +44,7 @@ export function buildEditorUI(container: HTMLElement, element: HTMLElement, edit
// Register context toolbars
manager.registerContextToolbar('image', {
selector: 'img',
selector: 'img:not([drawio-diagram] img)',
content: getImageToolbarContent(),
displayTargetLocator(originalTarget: HTMLElement) {
return originalTarget.closest('a') || originalTarget;

View File

@ -4,7 +4,7 @@ import {
alignLeft,
alignRight,
blockquote, bold, bulletList, clearFormating, code, codeBlock,
dangerCallout, details, editCodeBlock, fullscreen,
dangerCallout, details, diagram, editCodeBlock, fullscreen,
h2, h3, h4, h5, highlightColor, horizontalRule, image,
infoCallout, italic, link, numberList, paragraph,
redo, source, strikethrough, subscript,
@ -89,6 +89,7 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
new EditorButton(image),
new EditorButton(horizontalRule),
new EditorButton(codeBlock),
new EditorButton(diagram),
new EditorButton(details),
]),