import {
+ $createTextNode,
DOMConversionMap,
DOMExportOutput,
EditorConfig,
LexicalNode,
SerializedElementNode
} from "lexical";
+import {TableNode} from "@lexical/table/LexicalTableNode";
export class CaptionNode extends ElementNode {
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);
}
\ No newline at end of file
## 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
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',
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') || '',
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;
});
}
- // 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;
},
type: 'text',
},
{
- label: 'caption', // Caption element
+ label: 'Show caption', // Caption element
name: 'caption',
- type: 'text', // TODO -
+ type: 'checkbox',
},
alignmentInput, // alignment class
];
export interface EditorFormFieldDefinition {
label: string;
name: string;
- type: 'text' | 'select' | 'textarea';
+ type: 'text' | 'select' | 'textarea' | 'checkbox';
}
export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefinition {
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'));
}
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'});
}