]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/toolbars.ts
Lexical: Added toolbar scroll/resize handling
[bookstack] / resources / js / wysiwyg / ui / framework / toolbars.ts
1 import {EditorContainerUiElement, EditorUiElement} from "./core";
2 import {el} from "../../helpers";
3
4 export type EditorContextToolbarDefinition = {
5     selector: string;
6     content: EditorUiElement[],
7     displayTargetLocator?: (originalTarget: HTMLElement) => HTMLElement;
8 };
9
10 export class EditorContextToolbar extends EditorContainerUiElement {
11
12     protected target: HTMLElement;
13
14     constructor(target: HTMLElement, children: EditorUiElement[]) {
15         super(children);
16         this.target = target;
17     }
18
19     protected buildDOM(): HTMLElement {
20         return el('div', {
21             class: 'editor-context-toolbar',
22         }, this.getChildren().map(child => child.getDOMElement()));
23     }
24
25     updatePosition() {
26         const editorBounds = this.getContext().scrollDOM.getBoundingClientRect();
27         const targetBounds = this.target.getBoundingClientRect();
28         const dom = this.getDOMElement();
29         const domBounds = dom.getBoundingClientRect();
30
31         const showing = targetBounds.bottom > editorBounds.top
32             && targetBounds.top < editorBounds.bottom;
33
34         dom.hidden = !showing;
35
36         if (!showing) {
37             return;
38         }
39
40         const showAbove: boolean = targetBounds.bottom + 6 + domBounds.height > editorBounds.bottom;
41         dom.classList.toggle('is-above', showAbove);
42
43         const targetMid = targetBounds.left + (targetBounds.width / 2);
44         const targetLeft = targetMid - (domBounds.width / 2);
45         if (showAbove) {
46             dom.style.top = (targetBounds.top - 6 - domBounds.height) + 'px';
47         } else {
48             dom.style.top = (targetBounds.bottom + 6) + 'px';
49         }
50         dom.style.left = targetLeft + 'px';
51     }
52
53     insert(children: EditorUiElement[]) {
54         this.addChildren(...children);
55         const dom = this.getDOMElement();
56         dom.append(...children.map(child => child.getDOMElement()));
57     }
58
59     protected empty() {
60         const children = this.getChildren();
61         for (const child of children) {
62             child.getDOMElement().remove();
63         }
64         this.removeChildren(...children);
65     }
66
67     destroy() {
68         this.empty();
69         this.getDOMElement().remove();
70     }
71 }