BookStack/resources/js/wysiwyg/ui/framework/toolbars.ts
Dan Brown 63f4b42453
Lexical: Added toolbar scroll/resize handling
Also added smarter above/below positioning to respond if toolbar would
be off the bottom of the editor, and added hide/show when they'd go
outside editor scroll bounds.
2024-07-19 18:12:51 +01:00

71 lines
2.2 KiB
TypeScript

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 target: HTMLElement;
constructor(target: HTMLElement, children: EditorUiElement[]) {
super(children);
this.target = target;
}
protected buildDOM(): HTMLElement {
return el('div', {
class: 'editor-context-toolbar',
}, this.getChildren().map(child => child.getDOMElement()));
}
updatePosition() {
const editorBounds = this.getContext().scrollDOM.getBoundingClientRect();
const targetBounds = this.target.getBoundingClientRect();
const dom = this.getDOMElement();
const domBounds = dom.getBoundingClientRect();
const showing = targetBounds.bottom > editorBounds.top
&& targetBounds.top < editorBounds.bottom;
dom.hidden = !showing;
if (!showing) {
return;
}
const showAbove: boolean = targetBounds.bottom + 6 + domBounds.height > editorBounds.bottom;
dom.classList.toggle('is-above', showAbove);
const targetMid = targetBounds.left + (targetBounds.width / 2);
const targetLeft = targetMid - (domBounds.width / 2);
if (showAbove) {
dom.style.top = (targetBounds.top - 6 - domBounds.height) + 'px';
} else {
dom.style.top = (targetBounds.bottom + 6) + 'px';
}
dom.style.left = targetLeft + 'px';
}
insert(children: EditorUiElement[]) {
this.addChildren(...children);
const dom = this.getDOMElement();
dom.append(...children.map(child => child.getDOMElement()));
}
protected empty() {
const children = this.getChildren();
for (const child of children) {
child.getDOMElement().remove();
}
this.removeChildren(...children);
}
destroy() {
this.empty();
this.getDOMElement().remove();
}
}