]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/blocks/dropdown-button.ts
ZIP Exports: Built out initial import view
[bookstack] / resources / js / wysiwyg / ui / framework / blocks / dropdown-button.ts
1 import {handleDropdown} from "../helpers/dropdowns";
2 import {EditorContainerUiElement, EditorUiElement} from "../core";
3 import {EditorBasicButtonDefinition, EditorButton} from "../buttons";
4 import {el} from "../../../utils/dom";
5 import {EditorMenuButton} from "./menu-button";
6
7 export type EditorDropdownButtonOptions = {
8     showOnHover?: boolean;
9     direction?: 'vertical'|'horizontal';
10     button: EditorBasicButtonDefinition|EditorButton;
11 };
12
13 const defaultOptions: EditorDropdownButtonOptions = {
14     showOnHover: false,
15     direction: 'horizontal',
16     button: {label: 'Menu'},
17 }
18
19 export class EditorDropdownButton extends EditorContainerUiElement {
20     protected button: EditorButton;
21     protected childItems: EditorUiElement[];
22     protected open: boolean = false;
23     protected options: EditorDropdownButtonOptions;
24
25     constructor(options: EditorDropdownButtonOptions, children: EditorUiElement[]) {
26         super(children);
27         this.childItems = children;
28         this.options = Object.assign({}, defaultOptions, options);
29
30         if (options.button instanceof EditorButton) {
31             this.button = options.button;
32         } else {
33             const type = options.button.format === 'long' ? EditorMenuButton : EditorButton;
34             this.button = new type({
35                 ...options.button,
36                 action() {
37                     return false;
38                 },
39                 isActive: () => {
40                     return this.open;
41                 }
42             });
43         }
44
45         this.addChildren(this.button);
46     }
47
48     insertItems(...items: EditorUiElement[]) {
49         this.addChildren(...items);
50         this.childItems.push(...items);
51     }
52
53     protected buildDOM(): HTMLElement {
54         const button = this.button.getDOMElement();
55
56         const childElements: HTMLElement[] = this.childItems.map(child => child.getDOMElement());
57         const menu = el('div', {
58             class: `editor-dropdown-menu editor-dropdown-menu-${this.options.direction}`,
59             hidden: 'true',
60         }, childElements);
61
62         const wrapper = el('div', {
63             class: 'editor-dropdown-menu-container',
64         }, [button, menu]);
65
66         handleDropdown({toggle: button, menu : menu,
67             showOnHover: this.options.showOnHover,
68             onOpen : () => {
69             this.open = true;
70             this.getContext().manager.triggerStateUpdateForElement(this.button);
71         }, onClose : () => {
72             this.open = false;
73             this.getContext().manager.triggerStateUpdateForElement(this.button);
74         }});
75
76         return wrapper;
77     }
78 }