]> BookStack Code Mirror - bookstack/commitdiff
Lexical: Added more icons, made reflective text/bg color buttons
authorDan Brown <redacted>
Sun, 23 Jun 2024 14:50:41 +0000 (15:50 +0100)
committerDan Brown <redacted>
Sun, 23 Jun 2024 14:50:41 +0000 (15:50 +0100)
resources/icons/editor/highlighter.svg [new file with mode: 0644]
resources/icons/editor/list-check.svg
resources/icons/editor/list-numbered.svg
resources/icons/editor/table.svg [new file with mode: 0644]
resources/icons/editor/text-color.svg [new file with mode: 0644]
resources/js/wysiwyg/ui/defaults/button-definitions.ts
resources/js/wysiwyg/ui/framework/blocks/color-button.ts [new file with mode: 0644]
resources/js/wysiwyg/ui/framework/blocks/dropdown-button.ts
resources/js/wysiwyg/ui/framework/buttons.ts
resources/js/wysiwyg/ui/toolbars.ts

diff --git a/resources/icons/editor/highlighter.svg b/resources/icons/editor/highlighter.svg
new file mode 100644 (file)
index 0000000..b2eaacd
--- /dev/null
@@ -0,0 +1 @@
+<svg version="1.1" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"><path class="editor-icon-color-bar" d="m80-2e-6v-160h800v160z"/><path d="m584-480-104-104-160 160 103 104zm-47-160 103 103 160-159-104-104zm-84-29 216 216-189 190c-16 16-34.833 24-56.5 24s-40.5-8-56.5-24l-27 23h-200l126-125c-16-16-24.333-35.167-25-57.5s7-41.5 23-57.5zm0 0 187-187c16-16 34.833-24 56.5-24s40.5 8 56.5 24l104 103c16 16 24 34.833 24 56.5s-8 40.5-24 56.5l-188 187z"/></svg>
\ No newline at end of file
index f30266b27be0b529716f2a11514dc2bb17d975b7..4517d0d53119a66aa55389650c8abf1d9a419d68 100644 (file)
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#5f6368"><path d="M222-200 80-342l56-56 85 85 170-170 56 57-225 226Zm0-320L80-662l56-56 85 85 170-170 56 57-225 226Zm298 240v-80h360v80H520Zm0-320v-80h360v80H520Z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M222-200 80-342l56-56 85 85 170-170 56 57-225 226Zm0-320L80-662l56-56 85 85 170-170 56 57-225 226Zm298 240v-80h360v80H520Zm0-320v-80h360v80H520Z"/></svg>
\ No newline at end of file
index 92cdbf0aed83e60b3a251a96c8fdfb8e7a4cfadb..4bc0fc1babf34cb408699d9f6c3b8359a699c901 100644 (file)
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#5f6368"><path d="M120-80v-60h100v-30h-60v-60h60v-30H120v-60h120q17 0 28.5 11.5T280-280v40q0 17-11.5 28.5T240-200q17 0 28.5 11.5T280-160v40q0 17-11.5 28.5T240-80H120Zm0-280v-110q0-17 11.5-28.5T160-510h60v-30H120v-60h120q17 0 28.5 11.5T280-560v70q0 17-11.5 28.5T240-450h-60v30h100v60H120Zm60-280v-180h-60v-60h120v240h-60Zm180 440v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360Z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M120-80v-60h100v-30h-60v-60h60v-30H120v-60h120q17 0 28.5 11.5T280-280v40q0 17-11.5 28.5T240-200q17 0 28.5 11.5T280-160v40q0 17-11.5 28.5T240-80H120Zm0-280v-110q0-17 11.5-28.5T160-510h60v-30H120v-60h120q17 0 28.5 11.5T280-560v70q0 17-11.5 28.5T240-450h-60v30h100v60H120Zm60-280v-180h-60v-60h120v240h-60Zm180 440v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360Z"/></svg>
\ No newline at end of file
diff --git a/resources/icons/editor/table.svg b/resources/icons/editor/table.svg
new file mode 100644 (file)
index 0000000..1542506
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200Zm80-400h560v-160H200v160Zm213 200h134v-120H413v120Zm0 200h134v-120H413v120ZM200-400h133v-120H200v120Zm427 0h133v-120H627v120ZM200-200h133v-120H200v120Zm427 0h133v-120H627v120Z"/></svg>
\ No newline at end of file
diff --git a/resources/icons/editor/text-color.svg b/resources/icons/editor/text-color.svg
new file mode 100644 (file)
index 0000000..a862e19
--- /dev/null
@@ -0,0 +1 @@
+<svg version="1.1" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"><path class="editor-icon-color-bar" d="m80-3e-6v-160h800v160z"/><path d="m220-280 210-560h100l210 560h-96l-50-144h-226l-52 144zm176-224h168l-82-232h-4z"/></svg>
index 589567c031a01fb283bfa1e35aabfd7c93fe2ff3..5e5f0d40904e105a5ec4cc8c8f697c8865db2701 100644 (file)
@@ -34,6 +34,8 @@ import redoIcon from "@icons/editor/redo.svg"
 import boldIcon from "@icons/editor/bold.svg"
 import italicIcon from "@icons/editor/italic.svg"
 import underlinedIcon from "@icons/editor/underlined.svg"
+import textColorIcon from "@icons/editor/text-color.svg";
+import highlightIcon from "@icons/editor/highlighter.svg";
 import strikethroughIcon from "@icons/editor/strikethrough.svg"
 import superscriptIcon from "@icons/editor/superscript.svg"
 import subscriptIcon from "@icons/editor/subscript.svg"
@@ -43,6 +45,7 @@ import listBulletIcon from "@icons/editor/list-bullet.svg"
 import listNumberedIcon from "@icons/editor/list-numbered.svg"
 import listCheckIcon from "@icons/editor/list-check.svg"
 import linkIcon from "@icons/editor/link.svg"
+import tableIcon from "@icons/editor/table.svg"
 import imageIcon from "@icons/editor/image.svg"
 import detailsIcon from "@icons/editor/details.svg"
 import sourceIcon from "@icons/editor/source-view.svg"
@@ -167,8 +170,8 @@ function buildFormatButton(label: string, format: TextFormatType, icon: string):
 export const bold: EditorButtonDefinition = buildFormatButton('Bold', 'bold', boldIcon);
 export const italic: EditorButtonDefinition = buildFormatButton('Italic', 'italic', italicIcon);
 export const underline: EditorButtonDefinition = buildFormatButton('Underline', 'underline', underlinedIcon);
-export const textColor: EditorBasicButtonDefinition = {label: 'Text color'};
-export const highlightColor: EditorBasicButtonDefinition = {label: 'Highlight color'};
+export const textColor: EditorBasicButtonDefinition = {label: 'Text color', icon: textColorIcon};
+export const highlightColor: EditorBasicButtonDefinition = {label: 'Highlight color', icon: highlightIcon};
 
 export const strikethrough: EditorButtonDefinition = buildFormatButton('Strikethrough', 'strikethrough', strikethroughIcon);
 export const superscript: EditorButtonDefinition = buildFormatButton('Superscript', 'superscript', superscriptIcon);
@@ -183,6 +186,7 @@ export const clearFormating: EditorButtonDefinition = {
             for (const node of selection?.getNodes() || []) {
                 if ($isTextNode(node)) {
                     node.setFormat(0);
+                    node.setStyle('');
                 }
             }
         });
@@ -254,6 +258,7 @@ export const link: EditorButtonDefinition = {
 
 export const table: EditorBasicButtonDefinition = {
     label: 'Table',
+    icon: tableIcon,
 };
 
 export const image: EditorButtonDefinition = {
diff --git a/resources/js/wysiwyg/ui/framework/blocks/color-button.ts b/resources/js/wysiwyg/ui/framework/blocks/color-button.ts
new file mode 100644 (file)
index 0000000..e81521a
--- /dev/null
@@ -0,0 +1,35 @@
+import {EditorBasicButtonDefinition, EditorButton} from "../buttons";
+import {EditorUiStateUpdate} from "../core";
+import {$isRangeSelection} from "lexical";
+import {$getSelectionStyleValueForProperty} from "@lexical/selection";
+
+export class EditorColorButton extends EditorButton {
+    protected style: string;
+
+    constructor(definition: EditorBasicButtonDefinition, style: string) {
+        super(definition);
+
+        this.style = style;
+    }
+
+    getColorBar(): HTMLElement {
+        const colorBar = this.getDOMElement().querySelector('svg .editor-icon-color-bar');
+
+        if (!colorBar) {
+            throw new Error(`Could not find expected color bar in the icon for this ${this.definition.label} button`);
+        }
+
+        return (colorBar as HTMLElement);
+    }
+
+    updateState(state: EditorUiStateUpdate): void {
+        super.updateState(state);
+
+        if ($isRangeSelection(state.selection)) {
+            const value = $getSelectionStyleValueForProperty(state.selection, this.style);
+            const colorBar = this.getColorBar();
+            colorBar.setAttribute('fill', value);
+        }
+    }
+
+}
\ No newline at end of file
index 199c7728d8ac13f20cc79cb0f3db71c657fd54de..a419b92b28eff5bb4829972ccd259714c38234fd 100644 (file)
@@ -8,19 +8,23 @@ export class EditorDropdownButton extends EditorContainerUiElement {
     protected childItems: EditorUiElement[];
     protected open: boolean = false;
 
-    constructor(buttonDefinition: EditorBasicButtonDefinition, children: EditorUiElement[]) {
+    constructor(button: EditorBasicButtonDefinition|EditorButton, children: EditorUiElement[]) {
         super(children);
         this.childItems = children
 
-        this.button = new EditorButton({
-            ...buttonDefinition,
-            action() {
-                return false;
-            },
-            isActive: () => {
-                return this.open;
-            }
-        });
+        if (button instanceof EditorButton) {
+            this.button = button;
+        } else {
+            this.button = new EditorButton({
+                ...button,
+                action() {
+                    return false;
+                },
+                isActive: () => {
+                    return this.open;
+                }
+            });
+        }
 
         this.children.push(this.button);
     }
index 02f88dac8d4f5ff63edd87a765461986ecea3021..7e8df076a601eb311ade221409bab8fb775511e1 100644 (file)
@@ -1,7 +1,6 @@
 import {BaseSelection} from "lexical";
 import {EditorUiContext, EditorUiElement, EditorUiStateUpdate} from "./core";
 import {el} from "../../helpers";
-import {context} from "esbuild";
 
 export interface EditorBasicButtonDefinition {
     label: string;
@@ -20,9 +19,22 @@ export class EditorButton extends EditorUiElement {
     protected completedSetup: boolean = false;
     protected disabled: boolean = false;
 
-    constructor(definition: EditorButtonDefinition) {
+    constructor(definition: EditorButtonDefinition|EditorBasicButtonDefinition) {
         super();
-        this.definition = definition;
+
+        if ((definition as EditorButtonDefinition).action !== undefined) {
+            this.definition = definition as EditorButtonDefinition;
+        } else {
+            this.definition = {
+                ...definition,
+                action() {
+                    return false;
+                },
+                isActive: () => {
+                    return false;
+                }
+            };
+        }
     }
 
     setContext(context: EditorUiContext) {
index 4dbf9bb7e3bb685e2ef764b8fe4485626afa5b06..821c9f9cfea9e86cd6501758c2989f108b1380b3 100644 (file)
@@ -16,6 +16,7 @@ import {FormatPreviewButton} from "./framework/blocks/format-preview-button";
 import {EditorDropdownButton} from "./framework/blocks/dropdown-button";
 import {EditorColorPicker} from "./framework/blocks/color-picker";
 import {EditorTableCreator} from "./framework/blocks/table-creator";
+import {EditorColorButton} from "./framework/blocks/color-button";
 
 export function getMainEditorFullToolbar(): EditorContainerUiElement {
     return new EditorSimpleClassContainer('editor-toolbar-main', [
@@ -41,10 +42,10 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
         new EditorButton(bold),
         new EditorButton(italic),
         new EditorButton(underline),
-        new EditorDropdownButton(textColor, [
+        new EditorDropdownButton(new EditorColorButton(textColor, 'color'), [
             new EditorColorPicker('color'),
         ]),
-        new EditorDropdownButton(highlightColor, [
+        new EditorDropdownButton(new EditorColorButton(highlightColor, 'background-color'), [
             new EditorColorPicker('background-color'),
         ]),
         new EditorButton(strikethrough),