]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/defaults/buttons/inline-formats.ts
Lexical: Added color picker/indicator to form fields
[bookstack] / resources / js / wysiwyg / ui / defaults / buttons / inline-formats.ts
1 import {$getSelection, $isTextNode, BaseSelection, FORMAT_TEXT_COMMAND, TextFormatType} from "lexical";
2 import {EditorBasicButtonDefinition, EditorButtonDefinition} from "../../framework/buttons";
3 import {EditorUiContext} from "../../framework/core";
4 import boldIcon from "@icons/editor/bold.svg";
5 import italicIcon from "@icons/editor/italic.svg";
6 import underlinedIcon from "@icons/editor/underlined.svg";
7 import textColorIcon from "@icons/editor/text-color.svg";
8 import highlightIcon from "@icons/editor/highlighter.svg";
9 import strikethroughIcon from "@icons/editor/strikethrough.svg";
10 import superscriptIcon from "@icons/editor/superscript.svg";
11 import subscriptIcon from "@icons/editor/subscript.svg";
12 import codeIcon from "@icons/editor/code.svg";
13 import formatClearIcon from "@icons/editor/format-clear.svg";
14 import {$selectionContainsTextFormat} from "../../../utils/selection";
15 import {$patchStyleText} from "@lexical/selection";
16 import {context} from "esbuild";
17
18 function buildFormatButton(label: string, format: TextFormatType, icon: string): EditorButtonDefinition {
19     return {
20         label: label,
21         icon,
22         action(context: EditorUiContext) {
23             context.editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
24         },
25         isActive(selection: BaseSelection|null): boolean {
26             return $selectionContainsTextFormat(selection, format);
27         }
28     };
29 }
30
31 export const bold: EditorButtonDefinition = buildFormatButton('Bold', 'bold', boldIcon);
32 export const italic: EditorButtonDefinition = buildFormatButton('Italic', 'italic', italicIcon);
33 export const underline: EditorButtonDefinition = buildFormatButton('Underline', 'underline', underlinedIcon);
34 export const textColor: EditorBasicButtonDefinition = {label: 'Text color', icon: textColorIcon};
35 export const highlightColor: EditorBasicButtonDefinition = {label: 'Background color', icon: highlightIcon};
36
37 function colorAction(context: EditorUiContext, property: string, color: string): void {
38     context.editor.update(() => {
39         const selection = $getSelection();
40         if (selection) {
41             $patchStyleText(selection, {[property]: color || null});
42         }
43     });
44 }
45
46 export const textColorAction = (color: string, context: EditorUiContext) => colorAction(context, 'color', color);
47 export const highlightColorAction = (color: string, context: EditorUiContext) => colorAction(context, 'color', color);
48
49 export const strikethrough: EditorButtonDefinition = buildFormatButton('Strikethrough', 'strikethrough', strikethroughIcon);
50 export const superscript: EditorButtonDefinition = buildFormatButton('Superscript', 'superscript', superscriptIcon);
51 export const subscript: EditorButtonDefinition = buildFormatButton('Subscript', 'subscript', subscriptIcon);
52 export const code: EditorButtonDefinition = buildFormatButton('Inline code', 'code', codeIcon);
53 export const clearFormating: EditorButtonDefinition = {
54     label: 'Clear formatting',
55     icon: formatClearIcon,
56     action(context: EditorUiContext) {
57         context.editor.update(() => {
58             const selection = $getSelection();
59             for (const node of selection?.getNodes() || []) {
60                 if ($isTextNode(node)) {
61                     node.setFormat(0);
62                     node.setStyle('');
63                 }
64             }
65         });
66     },
67     isActive() {
68         return false;
69     }
70 };