1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2024-11-22 19:02:31 +01:00

Lexical: Integrated diagram manager, added menu split button

This commit is contained in:
Dan Brown 2024-08-17 10:48:34 +01:00
parent ad6b26ba97
commit 0039f893cc
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
8 changed files with 103 additions and 9 deletions

View File

@ -0,0 +1 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m2 6.9159 10 10.168 10-10.168z" stroke-width="2.0168"/></svg>

After

Width:  |  Height:  |  Size: 131 B

View File

@ -10,7 +10,6 @@
- Alignments: Handle inline block content (image, video)
- Image paste upload
- Keyboard shortcuts support
- Drawing gallery integration
- Support media src conversions (https://github.com/tinymce/tinymce/blob/release/6.6/modules/tinymce/src/plugins/media/main/ts/core/UrlPatterns.ts)
- Media resize support (like images)
- Table caption text support

View File

@ -30,7 +30,7 @@ import {
$insertNewBlockNodeAtSelection,
$selectionContainsNodeType
} from "../../../utils/selection";
import {$isDiagramNode, $openDrawingEditorForNode} from "../../../utils/diagrams";
import {$isDiagramNode, $openDrawingEditorForNode, showDiagramManagerForInsert} from "../../../utils/diagrams";
import {$createLinkedImageNodeFromImageData, showImageManager} from "../../../utils/images";
import {$showImageForm} from "../forms/objects";
@ -184,6 +184,16 @@ export const diagram: EditorButtonDefinition = {
}
};
export const diagramManager: EditorButtonDefinition = {
label: 'Drawing manager',
action(context: EditorUiContext) {
showDiagramManagerForInsert(context);
},
isActive(): boolean {
return false;
}
};
export const media: EditorButtonDefinition = {
label: 'Insert/edit Media',
icon: mediaIcon,

View File

@ -0,0 +1,31 @@
import {EditorContainerUiElement, EditorUiElement} from "../core";
import {el} from "../../../utils/dom";
import {EditorButton} from "../buttons";
import {EditorDropdownButton} from "./dropdown-button";
import caretDownIcon from "@icons/caret-down-large.svg";
export class EditorButtonWithMenu extends EditorContainerUiElement {
protected button: EditorButton;
protected dropdownButton: EditorDropdownButton;
constructor(button: EditorButton, menuItems: EditorUiElement[]) {
super([button]);
this.button = button;
this.dropdownButton = new EditorDropdownButton({
button: {label: 'Menu', icon: caretDownIcon},
showOnHover: false,
direction: 'vertical',
}, menuItems);
this.addChildren(this.dropdownButton);
}
buildDOM(): HTMLElement {
return el('div', {
class: 'editor-button-with-menu-container',
}, [
this.button.getDOMElement(),
this.dropdownButton.getDOMElement()
]);
}
}

View File

@ -56,16 +56,15 @@ import {bulletList, numberList, taskList} from "./defaults/buttons/lists";
import {
codeBlock,
details,
diagram,
diagram, diagramManager,
editCodeBlock,
horizontalRule,
image,
link, media,
unlink
} from "./defaults/buttons/objects";
import {$isTableNode} from "@lexical/table";
import {$selectionContainsNodeType} from "../utils/selection";
import {el} from "../utils/dom";
import {EditorButtonWithMenu} from "./framework/blocks/button-with-menu";
export function getMainEditorFullToolbar(): EditorContainerUiElement {
return new EditorSimpleClassContainer('editor-toolbar-main', [
@ -166,7 +165,10 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
new EditorButton(image),
new EditorButton(horizontalRule),
new EditorButton(codeBlock),
new EditorButton(diagram),
new EditorButtonWithMenu(
new EditorButton(diagram),
[new EditorButton(diagramManager)],
),
new EditorButton(media),
new EditorButton(details),
]),

View File

@ -1,8 +1,11 @@
import {LexicalEditor, LexicalNode} from "lexical";
import {$getSelection, $insertNodes, LexicalEditor, LexicalNode} from "lexical";
import {HttpError} from "../../services/http";
import {EditorUiContext} from "../ui/framework/core";
import * as DrawIO from "../../services/drawio";
import {DiagramNode} from "../nodes/diagram";
import {$createDiagramNode, DiagramNode} from "../nodes/diagram";
import {ImageManager} from "../../components";
import {EditorImageData} from "./images";
import {$getNodeFromSelection} from "./selection";
export function $isDiagramNode(node: LexicalNode | null | undefined): node is DiagramNode {
return node instanceof DiagramNode;
@ -67,4 +70,26 @@ export function $openDrawingEditorForNode(context: EditorUiContext, node: Diagra
}, async (pngData: string) => {
return updateDrawingNodeFromData(context, node, pngData, isNew);
});
}
export function showDiagramManager(callback: (image: EditorImageData) => any) {
const imageManager: ImageManager = window.$components.first('image-manager') as ImageManager;
imageManager.show((image: EditorImageData) => {
callback(image);
}, 'drawio');
}
export function showDiagramManagerForInsert(context: EditorUiContext) {
const selection = context.lastSelection;
showDiagramManager((image: EditorImageData) => {
context.editor.update(() => {
const diagramNode = $createDiagramNode(image.id, image.url);
const selectedDiagram = $getNodeFromSelection(selection, $isDiagramNode);
if ($isDiagramNode(selectedDiagram)) {
selectedDiagram.replace(diagramNode);
} else {
$insertNodes([diagramNode]);
}
});
});
}

View File

@ -2,7 +2,8 @@ import {ImageManager} from "../../components";
import {$createImageNode} from "../nodes/image";
import {$createLinkNode, LinkNode} from "@lexical/link";
type EditorImageData = {
export type EditorImageData = {
id: string;
url: string;
thumbs?: {display: string};
name: string;

View File

@ -82,6 +82,31 @@ body.editor-is-fullscreen {
fill: currentColor;
display: block;
}
.editor-button-with-menu-container {
display: flex;
flex-direction: row;
gap: 0;
align-items: stretch;
border-radius: 4px;
.editor-dropdown-menu-container {
display: flex;
}
.editor-dropdown-menu-container > .editor-dropdown-menu {
top: 100%;
}
.editor-dropdown-menu-container > .editor-button {
padding-inline: 4px;
margin-inline-start: -3px;
svg {
width: 12px;
height: 12px;
}
}
&:hover {
outline: 1px solid #DDD;
outline-offset: -3px;
}
}
// Containers
.editor-dropdown-menu-container {