diff --git a/demo/scripts/controls/ribbonButtons/contentModel/tableEditButtons.ts b/demo/scripts/controls/ribbonButtons/contentModel/tableEditButtons.ts index 4c5368d0d57..851ae1d33e3 100644 --- a/demo/scripts/controls/ribbonButtons/contentModel/tableEditButtons.ts +++ b/demo/scripts/controls/ribbonButtons/contentModel/tableEditButtons.ts @@ -1,5 +1,4 @@ -import { editTable, isContentModelEditor } from 'roosterjs-content-model-editor'; -import { TableOperation } from 'roosterjs-editor-types'; +import { editTable, isContentModelEditor, TableOperation } from 'roosterjs-content-model-editor'; import { RibbonButton, TableEditAlignMenuItemStringKey, @@ -12,29 +11,29 @@ import { } from 'roosterjs-react'; const TableEditOperationMap: Partial> = { - menuNameTableInsertAbove: TableOperation.InsertAbove, - menuNameTableInsertBelow: TableOperation.InsertBelow, - menuNameTableInsertLeft: TableOperation.InsertLeft, - menuNameTableInsertRight: TableOperation.InsertRight, - menuNameTableDeleteTable: TableOperation.DeleteTable, - menuNameTableDeleteColumn: TableOperation.DeleteColumn, - menuNameTableDeleteRow: TableOperation.DeleteRow, - menuNameTableMergeAbove: TableOperation.MergeAbove, - menuNameTableMergeBelow: TableOperation.MergeBelow, - menuNameTableMergeLeft: TableOperation.MergeLeft, - menuNameTableMergeRight: TableOperation.MergeRight, - menuNameTableMergeCells: TableOperation.MergeCells, - menuNameTableSplitHorizontally: TableOperation.SplitHorizontally, - menuNameTableSplitVertically: TableOperation.SplitVertically, - menuNameTableAlignLeft: TableOperation.AlignCellLeft, - menuNameTableAlignCenter: TableOperation.AlignCellCenter, - menuNameTableAlignRight: TableOperation.AlignCellRight, - menuNameTableAlignTop: TableOperation.AlignCellTop, - menuNameTableAlignMiddle: TableOperation.AlignCellMiddle, - menuNameTableAlignBottom: TableOperation.AlignCellBottom, - menuNameTableAlignTableLeft: TableOperation.AlignLeft, - menuNameTableAlignTableCenter: TableOperation.AlignCenter, - menuNameTableAlignTableRight: TableOperation.AlignRight, + menuNameTableInsertAbove: 'insertAbove', + menuNameTableInsertBelow: 'insertBelow', + menuNameTableInsertLeft: 'insertLeft', + menuNameTableInsertRight: 'insertRight', + menuNameTableDeleteTable: 'deleteTable', + menuNameTableDeleteColumn: 'deleteColumn', + menuNameTableDeleteRow: 'deleteRow', + menuNameTableMergeAbove: 'mergeAbove', + menuNameTableMergeBelow: 'mergeBelow', + menuNameTableMergeLeft: 'mergeLeft', + menuNameTableMergeRight: 'mergeRight', + menuNameTableMergeCells: 'mergeCells', + menuNameTableSplitHorizontally: 'splitHorizontally', + menuNameTableSplitVertically: 'splitVertically', + menuNameTableAlignLeft: 'alignCellLeft', + menuNameTableAlignCenter: 'alignCellCenter', + menuNameTableAlignRight: 'alignCellRight', + menuNameTableAlignTop: 'alignCellTop', + menuNameTableAlignMiddle: 'alignCellMiddle', + menuNameTableAlignBottom: 'alignCellBottom', + menuNameTableAlignTableLeft: 'alignLeft', + menuNameTableAlignTableCenter: 'alignCenter', + menuNameTableAlignTableRight: 'alignRight', }; export const tableInsertButton: RibbonButton< diff --git a/packages-content-model/roosterjs-content-model-editor/lib/index.ts b/packages-content-model/roosterjs-content-model-editor/lib/index.ts index fa10c2012f4..18da70422c4 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/index.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/index.ts @@ -34,6 +34,19 @@ export { InsertEntityOptions, InsertEntityPosition, } from './publicTypes/parameter/InsertEntityOptions'; +export { + TableOperation, + TableVerticalInsertOperation, + TableHorizontalInsertOperation, + TableDeleteOperation, + TableVerticalMergeOperation, + TableHorizontalMergeOperation, + TableCellMergeOperation, + TableSplitOperation, + TableAlignOperation, + TableCellHorizontalAlignOperation, + TableCellVerticalAlignOperation, +} from './publicTypes/parameter/TableOperation'; export { default as insertTable } from './publicApi/table/insertTable'; export { default as formatTable } from './publicApi/table/formatTable'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/block/setModelAlignment.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/block/setModelAlignment.ts index c90535cc35b..416f8dd6a57 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/block/setModelAlignment.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/block/setModelAlignment.ts @@ -1,6 +1,6 @@ import { alignTable } from '../table/alignTable'; import { getOperationalBlocks } from '../selection/collectSelections'; -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableAlignOperation } from '../../publicTypes/parameter/TableOperation'; import type { ContentModelDocument, ContentModelListItem } from 'roosterjs-content-model-types'; const ResultMap: Record< @@ -23,22 +23,19 @@ const ResultMap: Record< const TableAlignMap: Record< 'left' | 'center' | 'right', - Record< - 'ltr' | 'rtl', - TableOperation.AlignLeft | TableOperation.AlignCenter | TableOperation.AlignRight - > + Record<'ltr' | 'rtl', TableAlignOperation> > = { left: { - ltr: TableOperation.AlignLeft, - rtl: TableOperation.AlignRight, + ltr: 'alignLeft', + rtl: 'alignRight', }, center: { - ltr: TableOperation.AlignCenter, - rtl: TableOperation.AlignCenter, + ltr: 'alignCenter', + rtl: 'alignCenter', }, right: { - ltr: TableOperation.AlignRight, - rtl: TableOperation.AlignLeft, + ltr: 'alignRight', + rtl: 'alignLeft', }, }; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTable.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTable.ts index 22341edecca..ccf78d77a4a 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTable.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTable.ts @@ -1,22 +1,12 @@ -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableAlignOperation } from '../../publicTypes/parameter/TableOperation'; import type { ContentModelTable } from 'roosterjs-content-model-types'; -import type { CompatibleTableOperation } from 'roosterjs-editor-types/lib/compatibleTypes'; /** * @internal */ -export function alignTable( - table: ContentModelTable, - operation: - | TableOperation.AlignCenter - | TableOperation.AlignLeft - | TableOperation.AlignRight - | CompatibleTableOperation.AlignCenter - | CompatibleTableOperation.AlignLeft - | CompatibleTableOperation.AlignRight -) { - table.format.marginLeft = operation == TableOperation.AlignLeft ? '' : 'auto'; - table.format.marginRight = operation == TableOperation.AlignRight ? '' : 'auto'; +export function alignTable(table: ContentModelTable, operation: TableAlignOperation) { + table.format.marginLeft = operation == 'alignLeft' ? '' : 'auto'; + table.format.marginRight = operation == 'alignRight' ? '' : 'auto'; delete table.cachedElement; } diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts index 214ebc15efd..93b972ef13e 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts @@ -1,46 +1,66 @@ import { getSelectedCells } from './getSelectedCells'; -import { TableOperation } from 'roosterjs-editor-types'; import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; -import type { ContentModelTable } from 'roosterjs-content-model-types'; -import type { CompatibleTableOperation } from 'roosterjs-editor-types/lib/compatibleTypes'; +import type { + TableCellHorizontalAlignOperation, + TableCellVerticalAlignOperation, +} from '../../publicTypes/parameter/TableOperation'; +import type { ContentModelTable, ContentModelTableCell } from 'roosterjs-content-model-types'; -const TextAlignValueMap: Partial> = { - [TableOperation.AlignCellLeft]: 'start', - [TableOperation.AlignCellCenter]: 'center', - [TableOperation.AlignCellRight]: 'end', +const TextAlignValueMap: Partial> = { + alignCellLeft: 'start', + alignCellCenter: 'center', + alignCellRight: 'end', }; -const VerticalAlignValueMap: Partial> = { - [TableOperation.AlignCellTop]: 'top', - [TableOperation.AlignCellMiddle]: 'middle', - [TableOperation.AlignCellBottom]: 'bottom', +const VerticalAlignValueMap: Partial> = { + alignCellTop: 'top', + alignCellMiddle: 'middle', + alignCellBottom: 'bottom', }; /** * @internal */ -export function alignTableCell( +export function alignTableCellHorizontally( table: ContentModelTable, - operation: - | TableOperation.AlignCellCenter - | TableOperation.AlignCellLeft - | TableOperation.AlignCellRight - | TableOperation.AlignCellTop - | TableOperation.AlignCellMiddle - | TableOperation.AlignCellBottom - | CompatibleTableOperation.AlignCellCenter - | CompatibleTableOperation.AlignCellLeft - | CompatibleTableOperation.AlignCellRight - | CompatibleTableOperation.AlignCellTop - | CompatibleTableOperation.AlignCellMiddle - | CompatibleTableOperation.AlignCellBottom + operation: TableCellHorizontalAlignOperation +) { + alignTableCellInternal(table, cell => { + cell.format.textAlign = TextAlignValueMap[operation]; + }); +} + +/** + * @internal + */ +export function alignTableCellVertically( + table: ContentModelTable, + operation: TableCellVerticalAlignOperation +) { + alignTableCellInternal(table, cell => { + cell.format.verticalAlign = VerticalAlignValueMap[operation]; + + updateTableCellMetadata(cell, metadata => { + metadata = metadata || {}; + metadata.vAlignOverride = true; + return metadata; + }); + }); +} + +function alignTableCellInternal( + table: ContentModelTable, + callback: (cell: ContentModelTableCell) => void ) { const sel = getSelectedCells(table); if (sel) { - const textAlign = TextAlignValueMap[operation]; - const verticalAlign = VerticalAlignValueMap[operation]; - for (let rowIndex = sel.firstRow; rowIndex <= sel.lastRow; rowIndex++) { for (let colIndex = sel.firstCol; colIndex <= sel.lastCol; colIndex++) { const cell = table.rows[rowIndex]?.cells[colIndex]; @@ -49,16 +69,7 @@ export function alignTableCell( if (format) { delete cell.cachedElement; - format.textAlign = textAlign || format.textAlign; - format.verticalAlign = verticalAlign || format.verticalAlign; - - if (verticalAlign) { - updateTableCellMetadata(cell, metadata => { - metadata = metadata || {}; - metadata.vAlignOverride = true; - return metadata; - }); - } + callback(cell); cell.blocks.forEach(block => { if (block.blockType === 'Paragraph') { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableColumn.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableColumn.ts index 03256dd5636..fa83add604a 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableColumn.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableColumn.ts @@ -1,22 +1,17 @@ import { createTableCell } from 'roosterjs-content-model-dom'; import { getSelectedCells } from './getSelectedCells'; -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableHorizontalInsertOperation } from '../../publicTypes/parameter/TableOperation'; import type { ContentModelTable } from 'roosterjs-content-model-types'; -import type { CompatibleTableOperation } from 'roosterjs-editor-types/lib/compatibleTypes'; /** * @internal */ export function insertTableColumn( table: ContentModelTable, - operation: - | TableOperation.InsertLeft - | TableOperation.InsertRight - | CompatibleTableOperation.InsertLeft - | CompatibleTableOperation.InsertRight + operation: TableHorizontalInsertOperation ) { const sel = getSelectedCells(table); - const insertLeft = operation == TableOperation.InsertLeft; + const insertLeft = operation == 'insertLeft'; if (sel) { for (let i = sel?.firstCol; i <= sel.lastCol; i++) { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableRow.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableRow.ts index 1f7f6cfd7e0..b35cfe45390 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableRow.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/insertTableRow.ts @@ -1,22 +1,14 @@ import { createTableCell } from 'roosterjs-content-model-dom'; import { getSelectedCells } from './getSelectedCells'; -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableVerticalInsertOperation } from '../../publicTypes/parameter/TableOperation'; import type { ContentModelTable } from 'roosterjs-content-model-types'; -import type { CompatibleTableOperation } from 'roosterjs-editor-types/lib/compatibleTypes'; /** * @internal */ -export function insertTableRow( - table: ContentModelTable, - operation: - | TableOperation.InsertAbove - | TableOperation.InsertBelow - | CompatibleTableOperation.InsertAbove - | CompatibleTableOperation.InsertBelow -) { +export function insertTableRow(table: ContentModelTable, operation: TableVerticalInsertOperation) { const sel = getSelectedCells(table); - const insertAbove = operation == TableOperation.InsertAbove; + const insertAbove = operation == 'insertAbove'; if (sel) { for (let i = sel.firstRow; i <= sel.lastRow; i++) { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableColumn.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableColumn.ts index 9362b73f316..1344fee2d2a 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableColumn.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableColumn.ts @@ -1,22 +1,17 @@ import { canMergeCells } from './canMergeCells'; import { getSelectedCells } from './getSelectedCells'; -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableHorizontalMergeOperation } from '../../publicTypes/parameter/TableOperation'; import type { ContentModelTable } from 'roosterjs-content-model-types'; -import type { CompatibleTableOperation } from 'roosterjs-editor-types/lib/compatibleTypes'; /** * @internal */ export function mergeTableColumn( table: ContentModelTable, - operation: - | TableOperation.MergeLeft - | TableOperation.MergeRight - | CompatibleTableOperation.MergeLeft - | CompatibleTableOperation.MergeRight + operation: TableHorizontalMergeOperation ) { const sel = getSelectedCells(table); - const mergeLeft = operation == TableOperation.MergeLeft; + const mergeLeft = operation == 'mergeLeft'; if (sel) { const mergingColIndex = mergeLeft ? sel.firstCol : sel.lastCol + 1; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableRow.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableRow.ts index b2aad23fa8b..ff2532471ed 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableRow.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/mergeTableRow.ts @@ -1,22 +1,14 @@ import { canMergeCells } from './canMergeCells'; import { getSelectedCells } from './getSelectedCells'; -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableVerticalMergeOperation } from '../../publicTypes/parameter/TableOperation'; import type { ContentModelTable } from 'roosterjs-content-model-types'; -import type { CompatibleTableOperation } from 'roosterjs-editor-types/lib/compatibleTypes'; /** * @internal */ -export function mergeTableRow( - table: ContentModelTable, - operation: - | TableOperation.MergeAbove - | TableOperation.MergeBelow - | CompatibleTableOperation.MergeAbove - | CompatibleTableOperation.MergeBelow -) { +export function mergeTableRow(table: ContentModelTable, operation: TableVerticalMergeOperation) { const sel = getSelectedCells(table); - const mergeAbove = operation == TableOperation.MergeAbove; + const mergeAbove = operation == 'mergeAbove'; if (sel) { const mergingRowIndex = mergeAbove ? sel.firstRow : sel.lastRow + 1; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/editTable.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/editTable.ts index 71a71d72fe8..02e14bea43b 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/editTable.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/editTable.ts @@ -1,6 +1,5 @@ import hasSelectionInBlock from '../selection/hasSelectionInBlock'; import { alignTable } from '../../modelApi/table/alignTable'; -import { alignTableCell } from '../../modelApi/table/alignTableCell'; import { applyTableFormat } from '../../modelApi/table/applyTableFormat'; import { deleteTable } from '../../modelApi/table/deleteTable'; import { deleteTableColumn } from '../../modelApi/table/deleteTableColumn'; @@ -17,7 +16,11 @@ import { normalizeTable } from '../../modelApi/table/normalizeTable'; import { setSelection } from '../../modelApi/selection/setSelection'; import { splitTableCellHorizontally } from '../../modelApi/table/splitTableCellHorizontally'; import { splitTableCellVertically } from '../../modelApi/table/splitTableCellVertically'; -import { TableOperation } from 'roosterjs-editor-types'; +import type { TableOperation } from '../../publicTypes/parameter/TableOperation'; +import { + alignTableCellHorizontally, + alignTableCellVertically, +} from '../../modelApi/table/alignTableCell'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import { createSelectionMarker, @@ -38,63 +41,63 @@ export default function editTable(editor: IContentModelEditor, operation: TableO if (tableModel) { switch (operation) { - case TableOperation.AlignCellLeft: - case TableOperation.AlignCellCenter: - case TableOperation.AlignCellRight: - alignTableCell(tableModel, operation); + case 'alignCellLeft': + case 'alignCellCenter': + case 'alignCellRight': + alignTableCellHorizontally(tableModel, operation); break; - case TableOperation.AlignCellTop: - case TableOperation.AlignCellMiddle: - case TableOperation.AlignCellBottom: - alignTableCell(tableModel, operation); + case 'alignCellTop': + case 'alignCellMiddle': + case 'alignCellBottom': + alignTableCellVertically(tableModel, operation); break; - case TableOperation.AlignCenter: - case TableOperation.AlignLeft: - case TableOperation.AlignRight: + case 'alignCenter': + case 'alignLeft': + case 'alignRight': alignTable(tableModel, operation); break; - case TableOperation.DeleteColumn: + case 'deleteColumn': deleteTableColumn(tableModel); break; - case TableOperation.DeleteRow: + case 'deleteRow': deleteTableRow(tableModel); break; - case TableOperation.DeleteTable: + case 'deleteTable': deleteTable(tableModel); break; - case TableOperation.InsertAbove: - case TableOperation.InsertBelow: + case 'insertAbove': + case 'insertBelow': insertTableRow(tableModel, operation); break; - case TableOperation.InsertLeft: - case TableOperation.InsertRight: + case 'insertLeft': + case 'insertRight': insertTableColumn(tableModel, operation); break; - case TableOperation.MergeAbove: - case TableOperation.MergeBelow: + case 'mergeAbove': + case 'mergeBelow': mergeTableRow(tableModel, operation); break; - case TableOperation.MergeCells: + case 'mergeCells': mergeTableCells(tableModel); break; - case TableOperation.MergeLeft: - case TableOperation.MergeRight: + case 'mergeLeft': + case 'mergeRight': mergeTableColumn(tableModel, operation); break; - case TableOperation.SplitHorizontally: + case 'splitHorizontally': splitTableCellHorizontally(tableModel); break; - case TableOperation.SplitVertically: + case 'splitVertically': splitTableCellVertically(tableModel); break; } diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicTypes/parameter/TableOperation.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicTypes/parameter/TableOperation.ts new file mode 100644 index 00000000000..16ff0c84aec --- /dev/null +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicTypes/parameter/TableOperation.ts @@ -0,0 +1,169 @@ +/** + * Operations used by editTable() API for insert table cell vertically + */ +export type TableVerticalInsertOperation = + /** + * Insert a row above current row + */ + | 'insertAbove' + + /** + * Insert a row below current row + */ + | 'insertBelow'; + +/** + * Operations used by editTable() API for insert table cell horizontally + */ +export type TableHorizontalInsertOperation = + /** + * Insert a column on the left of current column + */ + | 'insertLeft' + + /** + * Insert a column on the right of current column + */ + | 'insertRight'; + +/** + * Operations used by editTable() API for delete table cells + */ +export type TableDeleteOperation = + /** + * Delete the whole table + */ + | 'deleteTable' + + /** + * Delete current column + */ + | 'deleteColumn' + + /** + * Delete current row + */ + | 'deleteRow'; + +/** + * Operations used by editTable() API for merge table cells vertically + */ +export type TableVerticalMergeOperation = + /** + * Merge current row with the row above + */ + | 'mergeAbove' + + /** + * Merge current row with the row below + */ + | 'mergeBelow'; + +/** + * Operations used by editTable() API for merge table cells horizontally + */ +export type TableHorizontalMergeOperation = + /** + * Merge current column with the column on the left + */ + | 'mergeLeft' + + /** + * Merge current column with the column on the right + */ + | 'mergeRight'; + +/** + * Operations used by editTable() API for merge selected table cells + */ +export type TableCellMergeOperation = + /** + * Merge all selected cells + */ + 'mergeCells'; + +/** + * Operations used by editTable() API for split table cells + */ +export type TableSplitOperation = + /** + * Split current table cell horizontally + */ + | 'splitHorizontally' + + /** + * Split current table cell vertically + */ + | 'splitVertically'; + +/** + * Operations used by editTable() API for align table + */ +export type TableAlignOperation = + /** + * Align current table at the center + */ + | 'alignCenter' + + /** + * Align current table at the left + */ + | 'alignLeft' + + /** + * Align current table at the right + */ + | 'alignRight'; + +/** + * Operations used by editTable() API for align table cell horizontally + */ +export type TableCellHorizontalAlignOperation = + /** + * Align current content table cell at the left + */ + | 'alignCellLeft' + + /** + * Align current content table cell at the center + */ + | 'alignCellCenter' + + /** + * Align current content table cell at the right + */ + | 'alignCellRight'; + +/** + * Operations used by editTable() API for align table cell vertically + */ +export type TableCellVerticalAlignOperation = + /** + * Align current content table cell at the top + */ + | 'alignCellTop' + + /** + * Align current table cell at the middle + */ + | 'alignCellMiddle' + + /** + * Align current table cell at the bottom + */ + | 'alignCellBottom'; + +/** + * Operations used by editTable() API + */ +export type TableOperation = + | TableVerticalInsertOperation + | TableHorizontalInsertOperation + | TableDeleteOperation + | TableVerticalMergeOperation + | TableHorizontalMergeOperation + | TableCellMergeOperation + | TableSplitOperation + | TableAlignOperation + | TableCellHorizontalAlignOperation + | TableCellVerticalAlignOperation; diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableCellTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableCellTest.ts index 4b37d305c22..d0773936966 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableCellTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableCellTest.ts @@ -1,17 +1,17 @@ -import { alignTableCell } from '../../../lib/modelApi/table/alignTableCell'; import { ContentModelTableCellFormat } from 'roosterjs-content-model-types'; import { createTable, createTableCell } from 'roosterjs-content-model-dom'; -import { TableOperation } from 'roosterjs-editor-types'; +import { + alignTableCellHorizontally, + alignTableCellVertically, +} from '../../../lib/modelApi/table/alignTableCell'; +import { + TableCellHorizontalAlignOperation, + TableCellVerticalAlignOperation, +} from '../../../lib/publicTypes/parameter/TableOperation'; -describe('alignTableCell', () => { +describe('alignTableCellHorizontally', () => { function runTest( - operation: - | TableOperation.AlignCellCenter - | TableOperation.AlignCellLeft - | TableOperation.AlignCellRight - | TableOperation.AlignCellTop - | TableOperation.AlignCellMiddle - | TableOperation.AlignCellBottom, + operation: TableCellHorizontalAlignOperation, expectedFormat: ContentModelTableCellFormat ) { const table = createTable(2); @@ -33,7 +33,7 @@ describe('alignTableCell', () => { table.rows[1].cells[1].cachedElement = {} as any; table.rows[1].cells[2].cachedElement = {} as any; - alignTableCell(table, operation); + alignTableCellHorizontally(table, operation); expect(table.rows[0].cells.map(c => c.format)).toEqual([ {}, @@ -59,7 +59,7 @@ describe('alignTableCell', () => { it('empty table', () => { const table = createTable(0); - alignTableCell(table, TableOperation.AlignCellLeft); + alignTableCellHorizontally(table, 'alignCellLeft'); expect(table).toEqual({ blockType: 'Table', @@ -71,43 +71,99 @@ describe('alignTableCell', () => { }); it('align to left', () => { - runTest(TableOperation.AlignCellLeft, { + runTest('alignCellLeft', { textAlign: 'start', - verticalAlign: undefined, }); }); it('align to center', () => { - runTest(TableOperation.AlignCellCenter, { + runTest('alignCellCenter', { textAlign: 'center', - verticalAlign: undefined, }); }); it('align to right', () => { - runTest(TableOperation.AlignCellRight, { + runTest('alignCellRight', { textAlign: 'end', - verticalAlign: undefined, + }); + }); +}); + +describe('alignTableCellVertically', () => { + function runTest( + operation: TableCellVerticalAlignOperation, + expectedFormat: ContentModelTableCellFormat + ) { + const table = createTable(2); + table.rows[0].cells.push(createTableCell(1, 1, false)); + table.rows[0].cells.push(createTableCell(1, 1, false)); + table.rows[0].cells.push(createTableCell(1, 1, false)); + table.rows[1].cells.push(createTableCell(1, 1, false)); + table.rows[1].cells.push(createTableCell(1, 1, false)); + table.rows[1].cells.push(createTableCell(1, 1, false)); + table.rows[0].cells[1].isSelected = true; + table.rows[0].cells[2].isSelected = true; + table.rows[1].cells[1].isSelected = true; + table.rows[1].cells[2].isSelected = true; + + table.rows[0].cells[0].cachedElement = {} as any; + table.rows[0].cells[1].cachedElement = {} as any; + table.rows[0].cells[2].cachedElement = {} as any; + table.rows[1].cells[0].cachedElement = {} as any; + table.rows[1].cells[1].cachedElement = {} as any; + table.rows[1].cells[2].cachedElement = {} as any; + + alignTableCellVertically(table, operation); + + expect(table.rows[0].cells.map(c => c.format)).toEqual([ + {}, + expectedFormat, + expectedFormat, + ]); + expect(table.rows[1].cells.map(c => c.format)).toEqual([ + {}, + expectedFormat, + expectedFormat, + ]); + expect(table.rows[0].cells[0].cachedElement).toEqual({} as any); + expect(table.rows[0].cells[1].cachedElement).toBeUndefined(); + expect(table.rows[0].cells[2].cachedElement).toBeUndefined(); + expect(table.rows[1].cells[0].cachedElement).toEqual({} as any); + expect(table.rows[1].cells[1].cachedElement).toBeUndefined(); + expect(table.rows[1].cells[2].cachedElement).toBeUndefined(); + table.rows[0].cells[1].blocks.forEach(block => { + expect(block.format.textAlign).toEqual(undefined); + }); + } + + it('empty table', () => { + const table = createTable(0); + + alignTableCellVertically(table, 'alignCellBottom'); + + expect(table).toEqual({ + blockType: 'Table', + format: {}, + rows: [], + widths: [], + dataset: {}, }); }); it('align to top', () => { - runTest(TableOperation.AlignCellTop, { - textAlign: undefined, + runTest('alignCellTop', { verticalAlign: 'top', }); }); it('align to middle', () => { - runTest(TableOperation.AlignCellMiddle, { - textAlign: undefined, + runTest('alignCellMiddle', { verticalAlign: 'middle', }); }); it('align to bottom', () => { - runTest(TableOperation.AlignCellBottom, { - textAlign: undefined, + runTest('alignCellBottom', { verticalAlign: 'bottom', }); }); diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableTest.ts index c4d9973e231..e7c729ad421 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/alignTableTest.ts @@ -1,12 +1,11 @@ import { alignTable } from '../../../lib/modelApi/table/alignTable'; import { createTable } from 'roosterjs-content-model-dom'; -import { TableOperation } from 'roosterjs-editor-types'; describe('alignTable', () => { it('Align table to left', () => { const table = createTable(1); - alignTable(table, TableOperation.AlignLeft); + alignTable(table, 'alignLeft'); expect(table.format).toEqual({ marginRight: 'auto', @@ -17,7 +16,7 @@ describe('alignTable', () => { it('Align table to center', () => { const table = createTable(1); - alignTable(table, TableOperation.AlignCenter); + alignTable(table, 'alignCenter'); expect(table.format).toEqual({ marginLeft: 'auto', @@ -28,7 +27,7 @@ describe('alignTable', () => { it('Align table to right', () => { const table = createTable(1); - alignTable(table, TableOperation.AlignRight); + alignTable(table, 'alignRight'); expect(table.format).toEqual({ marginLeft: 'auto', @@ -43,7 +42,7 @@ describe('alignTable', () => { table.format.marginBottom = '10px'; table.format.marginLeft = '10px'; - alignTable(table, TableOperation.AlignRight); + alignTable(table, 'alignRight'); expect(table.format).toEqual({ marginTop: '10px', @@ -62,7 +61,7 @@ describe('alignTable', () => { table.cachedElement = tableNode; - alignTable(table, TableOperation.AlignRight); + alignTable(table, 'alignRight'); expect(table.format).toEqual({ marginRight: '', diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableColumnTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableColumnTest.ts index 8af7373a366..814ab74aa62 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableColumnTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableColumnTest.ts @@ -1,11 +1,10 @@ import { createTable, createTableCell } from 'roosterjs-content-model-dom'; import { insertTableColumn } from '../../../lib/modelApi/table/insertTableColumn'; -import { TableOperation } from 'roosterjs-editor-types'; describe('insertTableColumn', () => { it('empty table', () => { const table = createTable(0); - insertTableColumn(table, TableOperation.InsertLeft); + insertTableColumn(table, 'insertLeft'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -14,7 +13,7 @@ describe('insertTableColumn', () => { dataset: {}, }); - insertTableColumn(table, TableOperation.InsertRight); + insertTableColumn(table, 'insertRight'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -29,7 +28,7 @@ describe('insertTableColumn', () => { const cell1 = createTableCell(); table.rows[0].cells.push(cell1); - insertTableColumn(table, TableOperation.InsertLeft); + insertTableColumn(table, 'insertLeft'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -38,7 +37,7 @@ describe('insertTableColumn', () => { dataset: {}, }); - insertTableColumn(table, TableOperation.InsertRight); + insertTableColumn(table, 'insertRight'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -59,7 +58,7 @@ describe('insertTableColumn', () => { const cell2 = { ...cell1 }; delete cell2.isSelected; - insertTableColumn(table, TableOperation.InsertLeft); + insertTableColumn(table, 'insertLeft'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -68,7 +67,7 @@ describe('insertTableColumn', () => { dataset: {}, }); - insertTableColumn(table, TableOperation.InsertRight); + insertTableColumn(table, 'insertRight'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -94,7 +93,7 @@ describe('insertTableColumn', () => { const cell4 = { ...cell2 }; delete cell4.isSelected; - insertTableColumn(table, TableOperation.InsertLeft); + insertTableColumn(table, 'insertLeft'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -103,7 +102,7 @@ describe('insertTableColumn', () => { dataset: {}, }); - insertTableColumn(table, TableOperation.InsertRight); + insertTableColumn(table, 'insertRight'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -132,7 +131,7 @@ describe('insertTableColumn', () => { const cell4 = { ...cell2 }; delete cell4.isSelected; - insertTableColumn(table, TableOperation.InsertLeft); + insertTableColumn(table, 'insertLeft'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -144,7 +143,7 @@ describe('insertTableColumn', () => { dataset: {}, }); - insertTableColumn(table, TableOperation.InsertRight); + insertTableColumn(table, 'insertRight'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -187,7 +186,7 @@ describe('insertTableColumn', () => { delete cell6Clone.isSelected; delete cell11Clone.isSelected; - insertTableColumn(table, TableOperation.InsertLeft); + insertTableColumn(table, 'insertLeft'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -204,7 +203,7 @@ describe('insertTableColumn', () => { dataset: {}, }); - insertTableColumn(table, TableOperation.InsertRight); + insertTableColumn(table, 'insertRight'); expect(table).toEqual({ blockType: 'Table', format: {}, diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableRowTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableRowTest.ts index 77179678f2a..35c49e4d7ea 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableRowTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/insertTableRowTest.ts @@ -1,11 +1,10 @@ import { createTable, createTableCell } from 'roosterjs-content-model-dom'; import { insertTableRow } from '../../../lib/modelApi/table/insertTableRow'; -import { TableOperation } from 'roosterjs-editor-types'; describe('insertTableRow', () => { it('empty table', () => { const table = createTable(0); - insertTableRow(table, TableOperation.InsertAbove); + insertTableRow(table, 'insertAbove'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -14,7 +13,7 @@ describe('insertTableRow', () => { dataset: {}, }); - insertTableRow(table, TableOperation.InsertBelow); + insertTableRow(table, 'insertBelow'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -29,7 +28,7 @@ describe('insertTableRow', () => { const cell1 = createTableCell(); table.rows[0].cells.push(cell1); - insertTableRow(table, TableOperation.InsertAbove); + insertTableRow(table, 'insertAbove'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -38,7 +37,7 @@ describe('insertTableRow', () => { dataset: {}, }); - insertTableRow(table, TableOperation.InsertBelow); + insertTableRow(table, 'insertBelow'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -59,7 +58,7 @@ describe('insertTableRow', () => { const cell2 = { ...cell1 }; delete cell2.isSelected; - insertTableRow(table, TableOperation.InsertAbove); + insertTableRow(table, 'insertAbove'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -71,7 +70,7 @@ describe('insertTableRow', () => { dataset: {}, }); - insertTableRow(table, TableOperation.InsertBelow); + insertTableRow(table, 'insertBelow'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -103,7 +102,7 @@ describe('insertTableRow', () => { const cell4 = { ...cell2 }; delete cell4.isSelected; - insertTableRow(table, TableOperation.InsertAbove); + insertTableRow(table, 'insertAbove'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -117,7 +116,7 @@ describe('insertTableRow', () => { dataset: {}, }); - insertTableRow(table, TableOperation.InsertBelow); + insertTableRow(table, 'insertBelow'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -151,7 +150,7 @@ describe('insertTableRow', () => { const cell4 = { ...cell2 }; delete cell4.isSelected; - insertTableRow(table, TableOperation.InsertAbove); + insertTableRow(table, 'insertAbove'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -163,7 +162,7 @@ describe('insertTableRow', () => { dataset: {}, }); - insertTableRow(table, TableOperation.InsertBelow); + insertTableRow(table, 'insertBelow'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -209,7 +208,7 @@ describe('insertTableRow', () => { delete cell5Clone.isSelected; delete cell9Clone.isSelected; - insertTableRow(table, TableOperation.InsertAbove); + insertTableRow(table, 'insertAbove'); expect(table).toEqual({ blockType: 'Table', format: {}, @@ -225,7 +224,7 @@ describe('insertTableRow', () => { dataset: {}, }); - insertTableRow(table, TableOperation.InsertBelow); + insertTableRow(table, 'insertBelow'); expect(table).toEqual({ blockType: 'Table', format: {}, diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableColumnTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableColumnTest.ts index 93adcf55d6e..a7682cad9ad 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableColumnTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableColumnTest.ts @@ -1,13 +1,12 @@ import { ContentModelTableCell } from 'roosterjs-content-model-types'; import { createTable, createTableCell } from 'roosterjs-content-model-dom'; import { mergeTableColumn } from '../../../lib/modelApi/table/mergeTableColumn'; -import { TableOperation } from 'roosterjs-editor-types'; describe('mergeTableColumn', () => { it('empty table', () => { const table = createTable(0); - mergeTableColumn(table, TableOperation.MergeLeft); + mergeTableColumn(table, 'mergeLeft'); expect(table).toEqual({ blockType: 'Table', @@ -17,7 +16,7 @@ describe('mergeTableColumn', () => { dataset: {}, }); - mergeTableColumn(table, TableOperation.MergeRight); + mergeTableColumn(table, 'mergeRight'); expect(table).toEqual({ blockType: 'Table', @@ -40,7 +39,7 @@ describe('mergeTableColumn', () => { table.rows[0].cells.push(cells[0], cells[1]); table.rows[1].cells.push(cells[2], cells[3]); - mergeTableColumn(table, TableOperation.MergeLeft); + mergeTableColumn(table, 'mergeLeft'); expect(table).toEqual({ blockType: 'Table', @@ -56,7 +55,7 @@ describe('mergeTableColumn', () => { expect(cells.map(c => c.spanLeft)).toEqual([false, false, false, false]); expect(cells.map(c => c.spanAbove)).toEqual([false, false, false, false]); - mergeTableColumn(table, TableOperation.MergeRight); + mergeTableColumn(table, 'mergeRight'); expect(table).toEqual({ blockType: 'Table', @@ -92,7 +91,7 @@ describe('mergeTableColumn', () => { cells[1].isSelected = true; cells[2].isSelected = true; - mergeTableColumn(table, TableOperation.MergeLeft); + mergeTableColumn(table, 'mergeLeft'); expect(table).toEqual({ blockType: 'Table', @@ -126,7 +125,7 @@ describe('mergeTableColumn', () => { false, ]); - mergeTableColumn(table, TableOperation.MergeRight); + mergeTableColumn(table, 'mergeRight'); expect(table).toEqual({ blockType: 'Table', @@ -180,7 +179,7 @@ describe('mergeTableColumn', () => { cells[1].isSelected = true; cells[5].isSelected = true; - mergeTableColumn(table, TableOperation.MergeLeft); + mergeTableColumn(table, 'mergeLeft'); expect(table).toEqual({ blockType: 'Table', @@ -219,7 +218,7 @@ describe('mergeTableColumn', () => { cells[2].isSelected = true; cells[6].isSelected = true; - mergeTableColumn(table, TableOperation.MergeRight); + mergeTableColumn(table, 'mergeRight'); expect(table).toEqual({ blockType: 'Table', @@ -272,7 +271,7 @@ describe('mergeTableColumn', () => { cells[1].isSelected = true; cells[5].isSelected = true; - mergeTableColumn(table, TableOperation.MergeLeft); + mergeTableColumn(table, 'mergeLeft'); expect(table).toEqual({ blockType: 'Table', @@ -322,7 +321,7 @@ describe('mergeTableColumn', () => { cells[2].isSelected = true; cells[6].isSelected = true; - mergeTableColumn(table, TableOperation.MergeRight); + mergeTableColumn(table, 'mergeRight'); expect(table).toEqual({ blockType: 'Table', diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableRowTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableRowTest.ts index 0a8e5a2b54e..6609b9cbfef 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableRowTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/table/mergeTableRowTest.ts @@ -1,13 +1,12 @@ import { ContentModelTableCell } from 'roosterjs-content-model-types'; import { createTable, createTableCell } from 'roosterjs-content-model-dom'; import { mergeTableRow } from '../../../lib/modelApi/table/mergeTableRow'; -import { TableOperation } from 'roosterjs-editor-types'; describe('mergeTableRow', () => { it('empty table', () => { const table = createTable(0); - mergeTableRow(table, TableOperation.MergeAbove); + mergeTableRow(table, 'mergeAbove'); expect(table).toEqual({ blockType: 'Table', @@ -17,7 +16,7 @@ describe('mergeTableRow', () => { dataset: {}, }); - mergeTableRow(table, TableOperation.MergeBelow); + mergeTableRow(table, 'mergeBelow'); expect(table).toEqual({ blockType: 'Table', @@ -40,7 +39,7 @@ describe('mergeTableRow', () => { table.rows[0].cells.push(cells[0], cells[1]); table.rows[1].cells.push(cells[2], cells[3]); - mergeTableRow(table, TableOperation.MergeAbove); + mergeTableRow(table, 'mergeAbove'); expect(table).toEqual({ blockType: 'Table', @@ -56,7 +55,7 @@ describe('mergeTableRow', () => { expect(cells.map(c => c.spanLeft)).toEqual([false, false, false, false]); expect(cells.map(c => c.spanAbove)).toEqual([false, false, false, false]); - mergeTableRow(table, TableOperation.MergeBelow); + mergeTableRow(table, 'mergeBelow'); expect(table).toEqual({ blockType: 'Table', @@ -94,7 +93,7 @@ describe('mergeTableRow', () => { cells[2].isSelected = true; cells[4].isSelected = true; - mergeTableRow(table, TableOperation.MergeAbove); + mergeTableRow(table, 'mergeAbove'); expect(table).toEqual({ blockType: 'Table', @@ -130,7 +129,7 @@ describe('mergeTableRow', () => { false, ]); - mergeTableRow(table, TableOperation.MergeBelow); + mergeTableRow(table, 'mergeBelow'); expect(table).toEqual({ blockType: 'Table', @@ -188,7 +187,7 @@ describe('mergeTableRow', () => { cells[2].isSelected = true; cells[3].isSelected = true; - mergeTableRow(table, TableOperation.MergeAbove); + mergeTableRow(table, 'mergeAbove'); expect(table).toEqual({ blockType: 'Table', @@ -229,7 +228,7 @@ describe('mergeTableRow', () => { cells[4].isSelected = true; cells[5].isSelected = true; - mergeTableRow(table, TableOperation.MergeBelow); + mergeTableRow(table, 'mergeBelow'); expect(table).toEqual({ blockType: 'Table', @@ -286,7 +285,7 @@ describe('mergeTableRow', () => { cells[2].isSelected = true; cells[3].isSelected = true; - mergeTableRow(table, TableOperation.MergeAbove); + mergeTableRow(table, 'mergeAbove'); expect(table).toEqual({ blockType: 'Table', @@ -338,7 +337,7 @@ describe('mergeTableRow', () => { cells[4].isSelected = true; cells[5].isSelected = true; - mergeTableRow(table, TableOperation.MergeBelow); + mergeTableRow(table, 'mergeBelow'); expect(table).toEqual({ blockType: 'Table',