1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2026-01-03 23:42:28 +03:00

Lexical: Added color picker/indicator to form fields

This commit is contained in:
Dan Brown
2025-01-18 11:12:43 +00:00
parent c091f67db3
commit 04cca77ae6
10 changed files with 125 additions and 36 deletions

View File

@@ -0,0 +1,56 @@
import {EditorContainerUiElement, EditorUiBuilderDefinition, EditorUiContext} from "../core";
import {EditorFormField, EditorFormFieldDefinition} from "../forms";
import {EditorColorPicker} from "./color-picker";
import {EditorDropdownButton} from "./dropdown-button";
import colorDisplayIcon from "@icons/editor/color-display.svg"
export class EditorColorField extends EditorContainerUiElement {
protected input: EditorFormField;
protected pickerButton: EditorDropdownButton;
constructor(input: EditorFormField) {
super([]);
this.input = input;
this.pickerButton = new EditorDropdownButton({
button: { icon: colorDisplayIcon, label: 'Select color'}
}, [
new EditorColorPicker(this.onColorSelect.bind(this))
]);
this.addChildren(this.pickerButton, this.input);
}
protected buildDOM(): HTMLElement {
const dom = this.input.getDOMElement();
dom.append(this.pickerButton.getDOMElement());
dom.classList.add('editor-color-field-container');
const field = dom.querySelector('input') as HTMLInputElement;
field.addEventListener('change', () => {
this.setIconColor(field.value);
});
return dom;
}
onColorSelect(color: string, context: EditorUiContext): void {
this.input.setValue(color);
}
setIconColor(color: string) {
const icon = this.getDOMElement().querySelector('svg .editor-icon-color-display');
if (icon) {
icon.setAttribute('fill', color || 'url(#pattern2)');
}
}
}
export function colorFieldBuilder(field: EditorFormFieldDefinition): EditorUiBuilderDefinition {
return {
build() {
return new EditorColorField(new EditorFormField(field));
}
}
}

View File

@@ -1,6 +1,4 @@
import {EditorUiElement} from "../core";
import {$getSelection} from "lexical";
import {$patchStyleText} from "@lexical/selection";
import {EditorUiContext, EditorUiElement} from "../core";
import {el} from "../../../utils/dom";
import removeIcon from "@icons/editor/color-clear.svg";
@@ -38,13 +36,15 @@ const colorChoices = [
const storageKey = 'bs-lexical-custom-colors';
export type EditorColorPickerCallback = (color: string, context: EditorUiContext) => void;
export class EditorColorPicker extends EditorUiElement {
protected styleProperty: string;
protected callback: EditorColorPickerCallback;
constructor(styleProperty: string) {
constructor(callback: EditorColorPickerCallback) {
super();
this.styleProperty = styleProperty;
this.callback = callback;
}
buildDOM(): HTMLElement {
@@ -131,11 +131,6 @@ export class EditorColorPicker extends EditorUiElement {
}
setColor(color: string) {
this.getContext().editor.update(() => {
const selection = $getSelection();
if (selection) {
$patchStyleText(selection, {[this.styleProperty]: color || null});
}
});
this.callback(color, this.getContext());
}
}

View File

@@ -44,7 +44,6 @@ export class LinkField extends EditorContainerUiElement {
updateFormFromHeader(header: HeadingNode) {
this.getHeaderIdAndText(header).then(({id, text}) => {
console.log('updating form', id, text);
const modal = this.getContext().manager.getActiveModal('link');
if (modal) {
modal.getForm().setValues({
@@ -60,7 +59,6 @@ export class LinkField extends EditorContainerUiElement {
return new Promise((res) => {
this.getContext().editor.update(() => {
let id = header.getId();
console.log('header', id, header.__id);
if (!id) {
id = 'header-' + uniqueIdSmall();
header.setId(id);

View File

@@ -19,15 +19,17 @@ export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefiniti
valuesByLabel: Record<string, string>
}
export type EditorFormFields = (EditorFormFieldDefinition|EditorUiBuilderDefinition)[];
interface EditorFormTabDefinition {
label: string;
contents: EditorFormFieldDefinition[];
contents: EditorFormFields;
}
export interface EditorFormDefinition {
submitText: string;
action: (formData: FormData, context: EditorUiContext) => Promise<boolean>;
fields: (EditorFormFieldDefinition|EditorUiBuilderDefinition)[];
fields: EditorFormFields;
}
export class EditorFormField extends EditorUiElement {
@@ -41,6 +43,7 @@ export class EditorFormField extends EditorUiElement {
setValue(value: string) {
const input = this.getDOMElement().querySelector('input,select,textarea') as HTMLInputElement;
input.value = value;
input.dispatchEvent(new Event('change'));
}
getName(): string {
@@ -155,11 +158,17 @@ export class EditorForm extends EditorContainerUiElement {
export class EditorFormTab extends EditorContainerUiElement {
protected definition: EditorFormTabDefinition;
protected fields: EditorFormField[];
protected fields: EditorUiElement[];
protected id: string;
constructor(definition: EditorFormTabDefinition) {
const fields = definition.contents.map(fieldDef => new EditorFormField(fieldDef));
const fields = definition.contents.map(fieldDef => {
if (isUiBuilderDefinition(fieldDef)) {
return fieldDef.build();
}
return new EditorFormField(fieldDef)
});
super(fields);
this.definition = definition;