Lexical: Linked table form to have caption toggle option

This commit is contained in:
Dan Brown 2025-01-22 20:39:15 +00:00
parent 8a66365d48
commit 958b537a49
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
4 changed files with 42 additions and 7 deletions

View File

@ -1,4 +1,5 @@
import {
$createTextNode,
DOMConversionMap,
DOMExportOutput,
EditorConfig,
@ -7,6 +8,7 @@ import {
LexicalNode,
SerializedElementNode
} from "lexical";
import {TableNode} from "@lexical/table/LexicalTableNode";
export class CaptionNode extends ElementNode {
@ -71,4 +73,20 @@ export function $createCaptionNode(): CaptionNode {
export function $isCaptionNode(node: LexicalNode | null | undefined): node is CaptionNode {
return node instanceof CaptionNode;
}
export function $tableHasCaption(table: TableNode): boolean {
for (const child of table.getChildren()) {
if ($isCaptionNode(child)) {
return true;
}
}
return false;
}
export function $addCaptionToTable(table: TableNode, text: string = ''): void {
const caption = $createCaptionNode();
const textNode = $createTextNode(text || ' ');
caption.append(textNode);
table.append(caption);
}

View File

@ -10,7 +10,6 @@
## Secondary Todo
- 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)
- Deep check of translation coverage

View File

@ -18,6 +18,7 @@ import {formatSizeValue} from "../../../utils/dom";
import {TableCellNode, TableNode, TableRowNode} from "@lexical/table";
import {CommonBlockAlignment} from "lexical/nodes/common";
import {colorFieldBuilder} from "../../framework/blocks/color-field";
import {$addCaptionToTable, $isCaptionNode, $tableHasCaption} from "@lexical/table/LexicalCaptionNode";
const borderStyleInput: EditorSelectFormFieldDefinition = {
label: 'Border style',
@ -219,6 +220,7 @@ export const rowProperties: EditorFormDefinition = {
export function $showTablePropertiesForm(table: TableNode, context: EditorUiContext): EditorFormModal {
const styles = table.getStyles();
const modalForm = context.manager.createModal('table_properties');
modalForm.show({
width: styles.get('width') || '',
height: styles.get('height') || '',
@ -228,7 +230,7 @@ export function $showTablePropertiesForm(table: TableNode, context: EditorUiCont
border_style: styles.get('border-style') || '',
border_color: styles.get('border-color') || '',
background_color: styles.get('background-color') || '',
// caption: '', TODO
caption: $tableHasCaption(table) ? 'true' : '',
align: table.getAlignment(),
});
return modalForm;
@ -265,7 +267,17 @@ export const tableProperties: EditorFormDefinition = {
});
}
// TODO - cell caption
const showCaption = Boolean(formData.get('caption')?.toString() || '');
const hasCaption = $tableHasCaption(table);
if (showCaption && !hasCaption) {
$addCaptionToTable(table, context.translate('Caption'));
} else if (!showCaption && hasCaption) {
for (const child of table.getChildren()) {
if ($isCaptionNode(child)) {
child.remove();
}
}
}
});
return true;
},
@ -299,9 +311,9 @@ export const tableProperties: EditorFormDefinition = {
type: 'text',
},
{
label: 'caption', // Caption element
label: 'Show caption', // Caption element
name: 'caption',
type: 'text', // TODO -
type: 'checkbox',
},
alignmentInput, // alignment class
];

View File

@ -11,7 +11,7 @@ import {el} from "../../utils/dom";
export interface EditorFormFieldDefinition {
label: string;
name: string;
type: 'text' | 'select' | 'textarea';
type: 'text' | 'select' | 'textarea' | 'checkbox';
}
export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefinition {
@ -42,7 +42,11 @@ export class EditorFormField extends EditorUiElement {
setValue(value: string) {
const input = this.getDOMElement().querySelector('input,select,textarea') as HTMLInputElement;
input.value = value;
if (this.definition.type === 'checkbox') {
input.checked = Boolean(value);
} else {
input.value = value;
}
input.dispatchEvent(new Event('change'));
}
@ -61,6 +65,8 @@ export class EditorFormField extends EditorUiElement {
input = el('select', {id, name: this.definition.name, class: 'editor-form-field-input'}, optionElems);
} else if (this.definition.type === 'textarea') {
input = el('textarea', {id, name: this.definition.name, class: 'editor-form-field-input'});
} else if (this.definition.type === 'checkbox') {
input = el('input', {id, name: this.definition.name, type: 'checkbox', class: 'editor-form-field-input-checkbox', value: 'true'});
} else {
input = el('input', {id, name: this.definition.name, class: 'editor-form-field-input'});
}