mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-31 15:24:31 +03:00
Lexical: Refined editor UI
- Cleaned up dropdown lists to look integrated - Added icons for color picker clear and menu list items
This commit is contained in:
@ -11,6 +11,7 @@
|
||||
## Secondary Todo
|
||||
|
||||
- Color picker support in table form color fields
|
||||
- Color picker for color controls
|
||||
- Table caption text support
|
||||
- Support media src conversions (https://github.com/tinymce/tinymce/blob/release/6.6/modules/tinymce/src/plugins/media/main/ts/core/UrlPatterns.ts)
|
||||
|
||||
|
@ -347,6 +347,7 @@ export const deleteColumn: EditorButtonDefinition = {
|
||||
|
||||
export const cellProperties: EditorButtonDefinition = {
|
||||
label: 'Cell properties',
|
||||
format: 'long',
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.getEditorState().read(() => {
|
||||
const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
|
||||
@ -361,6 +362,7 @@ export const cellProperties: EditorButtonDefinition = {
|
||||
|
||||
export const mergeCells: EditorButtonDefinition = {
|
||||
label: 'Merge cells',
|
||||
format: 'long',
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
@ -377,6 +379,7 @@ export const mergeCells: EditorButtonDefinition = {
|
||||
|
||||
export const splitCell: EditorButtonDefinition = {
|
||||
label: 'Split cell',
|
||||
format: 'long',
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.update(() => {
|
||||
$unmergeCell();
|
||||
|
@ -3,6 +3,8 @@ import {$getSelection} from "lexical";
|
||||
import {$patchStyleText} from "@lexical/selection";
|
||||
import {el} from "../../../utils/dom";
|
||||
|
||||
import removeIcon from "@icons/editor/color-clear.svg";
|
||||
|
||||
const colorChoices = [
|
||||
'#000000',
|
||||
'#ffffff',
|
||||
@ -52,11 +54,13 @@ export class EditorColorPicker extends EditorUiElement {
|
||||
});
|
||||
});
|
||||
|
||||
colorOptions.push(el('div', {
|
||||
const removeButton = el('div', {
|
||||
class: 'editor-color-select-option',
|
||||
'data-color': '',
|
||||
title: 'Clear color',
|
||||
}, ['x']));
|
||||
}, []);
|
||||
removeButton.innerHTML = removeIcon;
|
||||
colorOptions.push(removeButton);
|
||||
|
||||
const colorRows = [];
|
||||
for (let i = 0; i < colorOptions.length; i+=5) {
|
||||
|
@ -2,6 +2,7 @@ import {handleDropdown} from "../helpers/dropdowns";
|
||||
import {EditorContainerUiElement, EditorUiElement} from "../core";
|
||||
import {EditorBasicButtonDefinition, EditorButton} from "../buttons";
|
||||
import {el} from "../../../utils/dom";
|
||||
import {EditorMenuButton} from "./menu-button";
|
||||
|
||||
export type EditorDropdownButtonOptions = {
|
||||
showOnHover?: boolean;
|
||||
@ -29,7 +30,8 @@ export class EditorDropdownButton extends EditorContainerUiElement {
|
||||
if (options.button instanceof EditorButton) {
|
||||
this.button = options.button;
|
||||
} else {
|
||||
this.button = new EditorButton({
|
||||
const type = options.button.format === 'long' ? EditorMenuButton : EditorButton;
|
||||
this.button = new type({
|
||||
...options.button,
|
||||
action() {
|
||||
return false;
|
||||
|
15
resources/js/wysiwyg/ui/framework/blocks/menu-button.ts
Normal file
15
resources/js/wysiwyg/ui/framework/blocks/menu-button.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {EditorButton} from "../buttons";
|
||||
import {el} from "../../../utils/dom";
|
||||
import arrowIcon from "@icons/chevron-right.svg"
|
||||
|
||||
export class EditorMenuButton extends EditorButton {
|
||||
protected buildDOM(): HTMLButtonElement {
|
||||
const dom = super.buildDOM();
|
||||
|
||||
const icon = el('div', {class: 'editor-menu-button-icon'});
|
||||
icon.innerHTML = arrowIcon;
|
||||
dom.append(icon);
|
||||
|
||||
return dom;
|
||||
}
|
||||
}
|
10
resources/js/wysiwyg/ui/framework/blocks/separator.ts
Normal file
10
resources/js/wysiwyg/ui/framework/blocks/separator.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {EditorUiElement} from "../core";
|
||||
import {el} from "../../../utils/dom";
|
||||
|
||||
export class EditorSeparator extends EditorUiElement {
|
||||
buildDOM(): HTMLElement {
|
||||
return el('div', {
|
||||
class: 'editor-separator',
|
||||
});
|
||||
}
|
||||
}
|
@ -65,6 +65,7 @@ import {
|
||||
} from "./defaults/buttons/objects";
|
||||
import {el} from "../utils/dom";
|
||||
import {EditorButtonWithMenu} from "./framework/blocks/button-with-menu";
|
||||
import {EditorSeparator} from "./framework/blocks/separator";
|
||||
|
||||
export function getMainEditorFullToolbar(): EditorContainerUiElement {
|
||||
return new EditorSimpleClassContainer('editor-toolbar-main', [
|
||||
@ -83,7 +84,7 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
|
||||
new FormatPreviewButton(el('h5'), h5),
|
||||
new FormatPreviewButton(el('blockquote'), blockquote),
|
||||
new FormatPreviewButton(el('p'), paragraph),
|
||||
new EditorDropdownButton({button: {label: 'Callouts'}, showOnHover: true, direction: 'vertical'}, [
|
||||
new EditorDropdownButton({button: {label: 'Callouts', format: 'long'}, showOnHover: true, direction: 'vertical'}, [
|
||||
new FormatPreviewButton(el('p', {class: 'callout info'}), infoCallout),
|
||||
new FormatPreviewButton(el('p', {class: 'callout success'}), successCallout),
|
||||
new FormatPreviewButton(el('p', {class: 'callout warning'}), warningCallout),
|
||||
@ -125,37 +126,41 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
|
||||
]),
|
||||
|
||||
// Insert types
|
||||
new EditorOverflowContainer(8, [
|
||||
new EditorOverflowContainer(4, [
|
||||
new EditorButton(link),
|
||||
|
||||
new EditorDropdownButton({button: table, direction: 'vertical'}, [
|
||||
new EditorDropdownButton({button: {...table, format: 'long'}, showOnHover: true}, [
|
||||
new EditorDropdownButton({button: {label: 'Insert', format: 'long'}, showOnHover: true}, [
|
||||
new EditorTableCreator(),
|
||||
]),
|
||||
new EditorDropdownButton({button: {label: 'Cell'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorSeparator(),
|
||||
new EditorDropdownButton({button: {label: 'Cell', format: 'long'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorButton(cellProperties),
|
||||
new EditorButton(mergeCells),
|
||||
new EditorButton(splitCell),
|
||||
]),
|
||||
new EditorDropdownButton({button: {label: 'Row'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorDropdownButton({button: {label: 'Row', format: 'long'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorButton({...insertRowAbove, format: 'long'}),
|
||||
new EditorButton({...insertRowBelow, format: 'long'}),
|
||||
new EditorButton({...deleteRow, format: 'long'}),
|
||||
new EditorButton(rowProperties),
|
||||
new EditorSeparator(),
|
||||
new EditorButton(cutRow),
|
||||
new EditorButton(copyRow),
|
||||
new EditorButton(pasteRowBefore),
|
||||
new EditorButton(pasteRowAfter),
|
||||
]),
|
||||
new EditorDropdownButton({button: {label: 'Column'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorDropdownButton({button: {label: 'Column', format: 'long'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorButton({...insertColumnBefore, format: 'long'}),
|
||||
new EditorButton({...insertColumnAfter, format: 'long'}),
|
||||
new EditorButton({...deleteColumn, format: 'long'}),
|
||||
new EditorSeparator(),
|
||||
new EditorButton(cutColumn),
|
||||
new EditorButton(copyColumn),
|
||||
new EditorButton(pasteColumnBefore),
|
||||
new EditorButton(pasteColumnAfter),
|
||||
]),
|
||||
new EditorSeparator(),
|
||||
new EditorButton({...tableProperties, format: 'long'}),
|
||||
new EditorButton(clearTableFormatting),
|
||||
new EditorButton(resizeTableToContents),
|
||||
|
Reference in New Issue
Block a user