]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/defaults/toolbars.ts
Comments: Switched to lexical editor
[bookstack] / resources / js / wysiwyg / ui / defaults / toolbars.ts
1 import {EditorButton} from "../framework/buttons";
2 import {EditorContainerUiElement, EditorSimpleClassContainer, EditorUiContext, EditorUiElement} from "../framework/core";
3 import {EditorFormatMenu} from "../framework/blocks/format-menu";
4 import {FormatPreviewButton} from "../framework/blocks/format-preview-button";
5 import {EditorDropdownButton} from "../framework/blocks/dropdown-button";
6 import {EditorColorPicker} from "../framework/blocks/color-picker";
7 import {EditorTableCreator} from "../framework/blocks/table-creator";
8 import {EditorColorButton} from "../framework/blocks/color-button";
9 import {EditorOverflowContainer} from "../framework/blocks/overflow-container";
10 import {
11     cellProperties, clearTableFormatting,
12     copyColumn,
13     copyRow,
14     cutColumn,
15     cutRow,
16     deleteColumn,
17     deleteRow,
18     deleteTable,
19     deleteTableMenuAction,
20     insertColumnAfter,
21     insertColumnBefore,
22     insertRowAbove,
23     insertRowBelow,
24     mergeCells,
25     pasteColumnAfter,
26     pasteColumnBefore,
27     pasteRowAfter,
28     pasteRowBefore, resizeTableToContents,
29     rowProperties,
30     splitCell,
31     table, tableProperties
32 } from "./buttons/tables";
33 import {about, fullscreen, redo, source, undo} from "./buttons/controls";
34 import {
35     blockquote, dangerCallout,
36     h2,
37     h3,
38     h4,
39     h5,
40     infoCallout,
41     paragraph,
42     successCallout,
43     warningCallout
44 } from "./buttons/block-formats";
45 import {
46     bold, clearFormating, code,
47     highlightColor, highlightColorAction,
48     italic,
49     strikethrough, subscript,
50     superscript,
51     textColor, textColorAction,
52     underline
53 } from "./buttons/inline-formats";
54 import {
55     alignCenter,
56     alignJustify,
57     alignLeft,
58     alignRight,
59     directionLTR,
60     directionRTL
61 } from "./buttons/alignments";
62 import {
63     bulletList,
64     indentDecrease,
65     indentIncrease,
66     numberList,
67     taskList
68 } from "./buttons/lists";
69 import {
70     codeBlock,
71     details, detailsEditLabel, detailsToggle, detailsUnwrap,
72     diagram, diagramManager,
73     editCodeBlock,
74     horizontalRule,
75     image,
76     link, media,
77     unlink
78 } from "./buttons/objects";
79 import {el} from "../../utils/dom";
80 import {EditorButtonWithMenu} from "../framework/blocks/button-with-menu";
81 import {EditorSeparator} from "../framework/blocks/separator";
82 import {EditorContextToolbarDefinition} from "../framework/toolbars";
83
84 export function getMainEditorFullToolbar(context: EditorUiContext): EditorContainerUiElement {
85
86     const inRtlMode = context.manager.getDefaultDirection() === 'rtl';
87
88     return new EditorSimpleClassContainer('editor-toolbar-main', [
89
90         // History state
91         new EditorOverflowContainer(2, [
92             new EditorButton(undo),
93             new EditorButton(redo),
94         ]),
95
96         // Block formats
97         new EditorFormatMenu([
98             new FormatPreviewButton(el('h2'), h2),
99             new FormatPreviewButton(el('h3'), h3),
100             new FormatPreviewButton(el('h4'), h4),
101             new FormatPreviewButton(el('h5'), h5),
102             new FormatPreviewButton(el('blockquote'), blockquote),
103             new FormatPreviewButton(el('p'), paragraph),
104             new EditorDropdownButton({button: {label: 'Callouts', format: 'long'}, showOnHover: true, direction: 'vertical'}, [
105                 new FormatPreviewButton(el('p', {class: 'callout info'}), infoCallout),
106                 new FormatPreviewButton(el('p', {class: 'callout success'}), successCallout),
107                 new FormatPreviewButton(el('p', {class: 'callout warning'}), warningCallout),
108                 new FormatPreviewButton(el('p', {class: 'callout danger'}), dangerCallout),
109             ]),
110         ]),
111
112         // Inline formats
113         new EditorOverflowContainer(6, [
114             new EditorButton(bold),
115             new EditorButton(italic),
116             new EditorButton(underline),
117             new EditorDropdownButton({ button: new EditorColorButton(textColor, 'color') }, [
118                 new EditorColorPicker(textColorAction),
119             ]),
120             new EditorDropdownButton({button: new EditorColorButton(highlightColor, 'background-color')}, [
121                 new EditorColorPicker(highlightColorAction),
122             ]),
123             new EditorButton(strikethrough),
124             new EditorButton(superscript),
125             new EditorButton(subscript),
126             new EditorButton(code),
127             new EditorButton(clearFormating),
128         ]),
129
130         // Alignment
131         new EditorOverflowContainer(6, [
132             new EditorButton(alignLeft),
133             new EditorButton(alignCenter),
134             new EditorButton(alignRight),
135             new EditorButton(alignJustify),
136             inRtlMode ? new EditorButton(directionLTR) : null,
137             inRtlMode ? new EditorButton(directionRTL) : null,
138         ].filter(x => x !== null)),
139
140         // Lists
141         new EditorOverflowContainer(3, [
142             new EditorButton(bulletList),
143             new EditorButton(numberList),
144             new EditorButton(taskList),
145             new EditorButton(indentDecrease),
146             new EditorButton(indentIncrease),
147         ]),
148
149         // Insert types
150         new EditorOverflowContainer(4, [
151             new EditorButton(link),
152
153             new EditorDropdownButton({button: table, direction: 'vertical', showAside: false}, [
154                 new EditorDropdownButton({button: {label: 'Insert', format: 'long'}, showOnHover: true, showAside: true}, [
155                     new EditorTableCreator(),
156                 ]),
157                 new EditorSeparator(),
158                 new EditorDropdownButton({button: {label: 'Cell', format: 'long'}, direction: 'vertical', showOnHover: true}, [
159                     new EditorButton(cellProperties),
160                     new EditorButton(mergeCells),
161                     new EditorButton(splitCell),
162                 ]),
163                 new EditorDropdownButton({button: {label: 'Row', format: 'long'}, direction: 'vertical', showOnHover: true}, [
164                     new EditorButton({...insertRowAbove, format: 'long'}),
165                     new EditorButton({...insertRowBelow, format: 'long'}),
166                     new EditorButton({...deleteRow, format: 'long'}),
167                     new EditorButton(rowProperties),
168                     new EditorSeparator(),
169                     new EditorButton(cutRow),
170                     new EditorButton(copyRow),
171                     new EditorButton(pasteRowBefore),
172                     new EditorButton(pasteRowAfter),
173                 ]),
174                 new EditorDropdownButton({button: {label: 'Column', format: 'long'}, direction: 'vertical', showOnHover: true}, [
175                     new EditorButton({...insertColumnBefore, format: 'long'}),
176                     new EditorButton({...insertColumnAfter, format: 'long'}),
177                     new EditorButton({...deleteColumn, format: 'long'}),
178                     new EditorSeparator(),
179                     new EditorButton(cutColumn),
180                     new EditorButton(copyColumn),
181                     new EditorButton(pasteColumnBefore),
182                     new EditorButton(pasteColumnAfter),
183                 ]),
184                 new EditorSeparator(),
185                 new EditorButton({...tableProperties, format: 'long'}),
186                 new EditorButton(clearTableFormatting),
187                 new EditorButton(resizeTableToContents),
188                 new EditorButton(deleteTableMenuAction),
189             ]),
190
191             new EditorButton(image),
192             new EditorButton(horizontalRule),
193             new EditorButton(codeBlock),
194             new EditorButtonWithMenu(
195                 new EditorButton(diagram),
196                 [new EditorButton(diagramManager)],
197             ),
198             new EditorButton(media),
199             new EditorButton(details),
200         ]),
201
202         // Meta elements
203         new EditorOverflowContainer(3, [
204             new EditorButton(source),
205             new EditorButton(about),
206             new EditorButton(fullscreen),
207
208             // Test
209             // new EditorButton({
210             //     label: 'Test button',
211             //     action(context: EditorUiContext) {
212             //         context.editor.update(() => {
213             //             // Do stuff
214             //         });
215             //     },
216             //     isActive() {
217             //         return false;
218             //     }
219             // })
220         ]),
221     ]);
222 }
223
224 export function getBasicEditorToolbar(context: EditorUiContext): EditorContainerUiElement {
225     return new EditorSimpleClassContainer('editor-toolbar-main', [
226         new EditorButton(bold),
227         new EditorButton(italic),
228         new EditorButton(link),
229         new EditorButton(bulletList),
230         new EditorButton(numberList),
231     ]);
232 }
233
234 export const contextToolbars: Record<string, EditorContextToolbarDefinition> = {
235     image: {
236         selector: 'img:not([drawio-diagram] img)',
237         content: () => [new EditorButton(image)],
238     },
239     media: {
240         selector: '.editor-media-wrap',
241         content: () => [new EditorButton(media)],
242     },
243     link: {
244         selector: 'a',
245         content() {
246             return [
247                 new EditorButton(link),
248                 new EditorButton(unlink),
249             ]
250         },
251         displayTargetLocator(originalTarget: HTMLElement): HTMLElement {
252             const image = originalTarget.querySelector('img');
253             return image || originalTarget;
254         }
255     },
256     code: {
257         selector: '.editor-code-block-wrap',
258         content: () => [new EditorButton(editCodeBlock)],
259     },
260     table: {
261         selector: 'td,th',
262         content() {
263             return [
264                 new EditorOverflowContainer(2, [
265                     new EditorButton(tableProperties),
266                     new EditorButton(deleteTable),
267                 ]),
268                 new EditorOverflowContainer(3, [
269                     new EditorButton(insertRowAbove),
270                     new EditorButton(insertRowBelow),
271                     new EditorButton(deleteRow),
272                 ]),
273                 new EditorOverflowContainer(3, [
274                     new EditorButton(insertColumnBefore),
275                     new EditorButton(insertColumnAfter),
276                     new EditorButton(deleteColumn),
277                 ]),
278             ];
279         },
280         displayTargetLocator(originalTarget: HTMLElement): HTMLElement {
281             return originalTarget.closest('table') as HTMLTableElement;
282         }
283     },
284     details: {
285         selector: 'details',
286         content() {
287             return [
288                 new EditorButton(detailsEditLabel),
289                 new EditorButton(detailsToggle),
290                 new EditorButton(detailsUnwrap),
291             ]
292         },
293     },
294 };