1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-07-30 04:23:11 +03:00

Lexical: Wired table properties, and other buttons

This commit is contained in:
Dan Brown
2024-08-10 13:14:55 +01:00
parent abbfd42a6c
commit ebf95f637a
9 changed files with 243 additions and 79 deletions

View File

@ -8,24 +8,27 @@ import insertColumnBeforeIcon from "@icons/editor/table-insert-column-before.svg
import insertRowAboveIcon from "@icons/editor/table-insert-row-above.svg";
import insertRowBelowIcon from "@icons/editor/table-insert-row-below.svg";
import {EditorUiContext} from "../../framework/core";
import {$createNodeSelection, $createRangeSelection, $getSelection, BaseSelection} from "lexical";
import {$getSelection, BaseSelection} from "lexical";
import {$isCustomTableNode} from "../../../nodes/custom-table";
import {
$deleteTableColumn__EXPERIMENTAL,
$deleteTableRow__EXPERIMENTAL,
$insertTableColumn__EXPERIMENTAL,
$insertTableRow__EXPERIMENTAL,
$isTableNode, $isTableRowNode, $isTableSelection, $unmergeCell, TableCellNode,
$isTableNode, $isTableSelection, $unmergeCell, TableCellNode,
} from "@lexical/table";
import {$getNodeFromSelection, $selectionContainsNodeType} from "../../../utils/selection";
import {$getParentOfType} from "../../../utils/nodes";
import {$isCustomTableCellNode} from "../../../nodes/custom-table-cell";
import {$showCellPropertiesForm, $showRowPropertiesForm} from "../forms/tables";
import {$getTableRowsFromSelection, $mergeTableCellsInSelection} from "../../../utils/tables";
import {$showCellPropertiesForm, $showRowPropertiesForm, $showTablePropertiesForm} from "../forms/tables";
import {
$clearTableFormatting,
$clearTableSizes, $getTableFromSelection,
$getTableRowsFromSelection,
$mergeTableCellsInSelection
} from "../../../utils/tables";
import {$isCustomTableRowNode, CustomTableRowNode} from "../../../nodes/custom-table-row";
import {NodeClipboard} from "../../../services/node-clipboard";
import {r} from "@codemirror/legacy-modes/mode/r";
import {$generateHtmlFromNodes} from "@lexical/html";
const neverActive = (): boolean => false;
const cellNotSelected = (selection: BaseSelection|null) => !$selectionContainsNodeType(selection, $isCustomTableCellNode);
@ -40,15 +43,10 @@ export const tableProperties: EditorButtonDefinition = {
icon: tableIcon,
action(context: EditorUiContext) {
context.editor.getEditorState().read(() => {
const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
if (!$isCustomTableCellNode(cell)) {
return;
const table = $getTableFromSelection($getSelection());
if ($isCustomTableNode(table)) {
$showTablePropertiesForm(table, context);
}
const table = $getParentOfType(cell, $isTableNode);
const modalForm = context.manager.createModal('table_properties');
modalForm.show({});
// TODO
});
},
isActive: neverActive,
@ -59,14 +57,16 @@ export const clearTableFormatting: EditorButtonDefinition = {
label: 'Clear table formatting',
format: 'long',
action(context: EditorUiContext) {
context.editor.getEditorState().read(() => {
context.editor.update(() => {
const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
if (!$isCustomTableCellNode(cell)) {
return;
}
const table = $getParentOfType(cell, $isTableNode);
// TODO
if ($isCustomTableNode(table)) {
$clearTableFormatting(table);
}
});
},
isActive: neverActive,
@ -77,22 +77,15 @@ export const resizeTableToContents: EditorButtonDefinition = {
label: 'Resize to contents',
format: 'long',
action(context: EditorUiContext) {
context.editor.getEditorState().read(() => {
context.editor.update(() => {
const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
if (!$isCustomTableCellNode(cell)) {
return;
}
const table = $getParentOfType(cell, $isCustomTableNode);
if (!$isCustomTableNode(table)) {
return;
}
for (const row of table.getChildren()) {
if ($isTableRowNode(row)) {
// TODO - Come back later as this may depend on if we
// are using a custom table row
}
if ($isCustomTableNode(table)) {
$clearTableSizes(table);
}
});
},
@ -165,14 +158,9 @@ export const rowProperties: EditorButtonDefinition = {
format: 'long',
action(context: EditorUiContext) {
context.editor.getEditorState().read(() => {
const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
if (!$isCustomTableCellNode(cell)) {
return;
}
const row = $getParentOfType(cell, $isCustomTableRowNode);
if ($isCustomTableRowNode(row)) {
$showRowPropertiesForm(row, context);
const rows = $getTableRowsFromSelection($getSelection());
if ($isCustomTableRowNode(rows[0])) {
$showRowPropertiesForm(rows[0], context);
}
});
},

View File

@ -9,13 +9,15 @@ import {CustomTableCellNode} from "../../../nodes/custom-table-cell";
import {EditorFormModal} from "../../framework/modals";
import {$getSelection, ElementFormatType} from "lexical";
import {
$forEachTableCell, $getCellPaddingForTable,
$getTableCellColumnWidth,
$getTableCellsFromSelection,
$getTableCellsFromSelection, $getTableFromSelection,
$getTableRowsFromSelection,
$setTableCellColumnWidth
} from "../../../utils/tables";
import {formatSizeValue} from "../../../utils/dom";
import {CustomTableRowNode} from "../../../nodes/custom-table-row";
import {CustomTableNode} from "../../../nodes/custom-table";
const borderStyleInput: EditorSelectFormFieldDefinition = {
label: 'Border style',
@ -213,10 +215,58 @@ export const rowProperties: EditorFormDefinition = {
backgroundColorInput, // style on tr: height
],
};
export function $showTablePropertiesForm(table: CustomTableNode, context: EditorUiContext): EditorFormModal {
const styles = table.getStyles();
const modalForm = context.manager.createModal('table_properties');
modalForm.show({
width: styles.get('width') || '',
height: styles.get('height') || '',
cell_spacing: styles.get('cell-spacing') || '',
cell_padding: $getCellPaddingForTable(table),
border_width: styles.get('border-width') || '',
border_style: styles.get('border-style') || '',
border_color: styles.get('border-color') || '',
background_color: styles.get('background-color') || '',
// caption: '', TODO
align: table.getFormatType(),
});
return modalForm;
}
export const tableProperties: EditorFormDefinition = {
submitText: 'Save',
async action(formData, context: EditorUiContext) {
// TODO
context.editor.update(() => {
const table = $getTableFromSelection($getSelection());
if (!table) {
return;
}
const styles = table.getStyles();
styles.set('width', formatSizeValue(formData.get('width')?.toString() || ''));
styles.set('height', formatSizeValue(formData.get('height')?.toString() || ''));
styles.set('cell-spacing', formatSizeValue(formData.get('cell_spacing')?.toString() || ''));
styles.set('border-width', formatSizeValue(formData.get('border_width')?.toString() || ''));
styles.set('border-style', formData.get('border_style')?.toString() || '');
styles.set('border-color', formData.get('border_color')?.toString() || '');
styles.set('background-color', formData.get('background_color')?.toString() || '');
table.setStyles(styles);
table.setFormat(formData.get('align') as ElementFormatType);
const cellPadding = (formData.get('cell_padding')?.toString() || '');
if (cellPadding) {
const cellPaddingFormatted = formatSizeValue(cellPadding);
$forEachTableCell(table, (cell: CustomTableCellNode) => {
const styles = cell.getStyles();
styles.set('padding', cellPaddingFormatted);
cell.setStyles(styles);
});
}
// TODO - cell caption
});
return true;
},
fields: [
@ -224,42 +274,42 @@ export const tableProperties: EditorFormDefinition = {
build() {
const generalFields: EditorFormFieldDefinition[] = [
{
label: 'Width',
label: 'Width', // Style - width
name: 'width',
type: 'text',
},
{
label: 'Height',
label: 'Height', // Style - height
name: 'height',
type: 'text',
},
{
label: 'Cell spacing',
label: 'Cell spacing', // Style - border-spacing
name: 'cell_spacing',
type: 'text',
},
{
label: 'Cell padding',
label: 'Cell padding', // Style - padding on child cells?
name: 'cell_padding',
type: 'text',
},
{
label: 'Border width',
label: 'Border width', // Style - border-width
name: 'border_width',
type: 'text',
},
{
label: 'caption',
name: 'height',
label: 'caption', // Caption element
name: 'caption',
type: 'text', // TODO -
},
alignmentInput,
alignmentInput, // alignment class
];
const advancedFields: EditorFormFieldDefinition[] = [
borderStyleInput,
borderColorInput,
backgroundColorInput,
borderStyleInput, // Style - border-style
borderColorInput, // Style - border-color
backgroundColorInput, // Style - background-color
];
return new EditorFormTabs([