Lexical: Added more icons, made reflective text/bg color buttons
|  | @ -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> | ||||
| After Width: | Height: | Size: 465 B | 
|  | @ -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> | ||||
| <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> | ||||
| Before Width: | Height: | Size: 242 B After Width: | Height: | Size: 227 B | 
|  | @ -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> | ||||
| <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> | ||||
| Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 453 B | 
|  | @ -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> | ||||
| After Width: | Height: | Size: 377 B | 
|  | @ -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> | ||||
| After Width: | Height: | Size: 240 B | 
|  | @ -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 = { | ||||
|  |  | |||
|  | @ -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); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -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); | ||||
|     } | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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), | ||||
|  |  | |||