Skip to content

Commit

Permalink
Lexical: Added base context toolbar logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ssddanbrown committed Jun 30, 2024
1 parent 517c578 commit c9a03c5
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 6 deletions.
59 changes: 55 additions & 4 deletions resources/js/wysiwyg/ui/framework/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {EditorDecorator, EditorDecoratorAdapter} from "./decorator";
import {$getSelection, 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 class EditorUIManager {

Expand All @@ -13,6 +13,8 @@ export class EditorUIManager {
protected decoratorInstancesByNodeKey: Record<string, EditorDecorator> = {};
protected context: EditorUiContext|null = null;
protected toolbar: EditorContainerUiElement|null = null;
protected contextToolbarDefinitionsByKey: Record<string, EditorContextToolbarDefinition> = {};
protected activeContextToolbars: EditorContextToolbar[] = [];

setContext(context: EditorUiContext) {
this.context = context;
Expand Down Expand Up @@ -80,10 +82,59 @@ export class EditorUIManager {
this.getContext().editorDOM.before(toolbar.getDOMElement());
}

protected triggerStateUpdate(state: EditorUiStateUpdate): void {
registerContextToolbar(key: string, definition: EditorContextToolbarDefinition) {
this.contextToolbarDefinitionsByKey[key] = definition;
}

protected triggerStateUpdate(update: EditorUiStateUpdate): void {
const context = this.getContext();
context.lastSelection = state.selection;
this.toolbar?.updateState(state);
context.lastSelection = update.selection;
this.toolbar?.updateState(update);
this.updateContextToolbars(update);
for (const toolbar of this.activeContextToolbars) {
toolbar.updateState(update);
}
}

protected updateContextToolbars(update: EditorUiStateUpdate): void {
for (const toolbar of this.activeContextToolbars) {
toolbar.empty();
toolbar.getDOMElement().remove();
}

const node = (update.selection?.getNodes() || [])[0] || null;
if (!node) {
return;
}

const element = update.editor.getElementByKey(node.getKey());
if (!element) {
return;
}

const toolbarKeys = Object.keys(this.contextToolbarDefinitionsByKey);
const contentByTarget = new Map<HTMLElement, EditorUiElement[]>();
for (const key of toolbarKeys) {
const definition = this.contextToolbarDefinitionsByKey[key];
const matchingElem = ((element.closest(definition.selector)) || (element.querySelector(definition.selector))) as HTMLElement|null;
if (matchingElem) {
const targetEl = definition.displayTargetLocator ? definition.displayTargetLocator(matchingElem) : matchingElem;
if (!contentByTarget.has(targetEl)) {
contentByTarget.set(targetEl, [])
}
// @ts-ignore
contentByTarget.get(targetEl).push(...definition.content);
}
}

for (const [target, contents] of contentByTarget) {
const toolbar = new EditorContextToolbar(contents);
toolbar.setContext(this.getContext());
this.activeContextToolbars.push(toolbar);

this.getContext().editorDOM.after(toolbar.getDOMElement());
toolbar.attachTo(target);
}
}

protected setupEditor(editor: LexicalEditor) {
Expand Down
36 changes: 36 additions & 0 deletions resources/js/wysiwyg/ui/framework/toolbars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {EditorContainerUiElement, EditorUiElement} from "./core";
import {el} from "../../helpers";

export type EditorContextToolbarDefinition = {
selector: string;
content: EditorUiElement[],
displayTargetLocator?: (originalTarget: HTMLElement) => HTMLElement;
};

export class EditorContextToolbar extends EditorContainerUiElement {

protected buildDOM(): HTMLElement {
return el('div', {
class: 'editor-context-toolbar',
}, this.getChildren().map(child => child.getDOMElement()));
}

attachTo(target: HTMLElement) {
// Todo - attach to target position
console.log('attaching context toolbar to', target);
}

insert(children: EditorUiElement[]) {
this.addChildren(...children);
const dom = this.getDOMElement();
dom.append(...children.map(child => child.getDOMElement()));
}

empty() {
const children = this.getChildren();
for (const child of children) {
child.getDOMElement().remove();
}
this.removeChildren(...children);
}
}
11 changes: 10 additions & 1 deletion resources/js/wysiwyg/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {LexicalEditor} from "lexical";
import {getMainEditorFullToolbar} from "./toolbars";
import {getImageToolbarContent, getMainEditorFullToolbar} from "./toolbars";
import {EditorUIManager} from "./framework/manager";
import {image as imageFormDefinition, link as linkFormDefinition, source as sourceFormDefinition} from "./defaults/form-definitions";
import {ImageDecorator} from "./decorators/image";
Expand Down Expand Up @@ -33,6 +33,15 @@ export function buildEditorUI(element: HTMLElement, editor: LexicalEditor) {
form: sourceFormDefinition,
});

// Register context toolbars
manager.registerContextToolbar('image', {
selector: 'img',
content: getImageToolbarContent(),
displayTargetLocator(originalTarget: HTMLElement) {
return originalTarget.closest('a') || originalTarget;
}
});

// Register image decorator listener
manager.registerDecoratorType('image', ImageDecorator);
}
6 changes: 5 additions & 1 deletion resources/js/wysiwyg/ui/toolbars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
undo,
warningCallout
} from "./defaults/button-definitions";
import {EditorContainerUiElement, EditorSimpleClassContainer, EditorUiContext} from "./framework/core";
import {EditorContainerUiElement, EditorSimpleClassContainer, EditorUiContext, EditorUiElement} from "./framework/core";
import {el} from "../helpers";
import {EditorFormatMenu} from "./framework/blocks/format-menu";
import {FormatPreviewButton} from "./framework/blocks/format-preview-button";
Expand Down Expand Up @@ -87,4 +87,8 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
}
})
]);
}

export function getImageToolbarContent(): EditorUiElement[] {
return [new EditorButton(image)];
}

0 comments on commit c9a03c5

Please sign in to comment.