Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table - cell merging #4046

Merged
merged 8 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,13 @@ test.describe('CopyAndPaste', () => {
'text/html': `<meta charset='utf-8'><table class="PlaygroundEditorTheme__table"><colgroup><col><col><col><col><col></colgroup><tbody><tr><th class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader" style="border: 1px solid black; width: 140px; vertical-align: top; text-align: start; background-color: rgb(242, 243, 245);"><p class="PlaygroundEditorTheme__paragraph"><span>a</span></p></th><th class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader" style="border: 1px solid black; width: 140px; vertical-align: top; text-align: start; background-color: rgb(242, 243, 245);"><p class="PlaygroundEditorTheme__paragraph"><span>b</span></p></th></tr><tr><th class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader" style="border: 1px solid black; width: 140px; vertical-align: top; text-align: start; background-color: rgb(242, 243, 245);"><p class="PlaygroundEditorTheme__paragraph"><span>c</span></p></th><td class="PlaygroundEditorTheme__tableCell" style="border: 1px solid black; width: 140px; vertical-align: top; text-align: start;"><p class="PlaygroundEditorTheme__paragraph"><span>d</span></p></td></tr></tbody></table>`,
};

await selectCellsFromTableCords(page, {x: 0, y: 0}, {x: 3, y: 3});
await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 3, y: 3},
true,
false,
);

await pasteFromClipboard(page, clipboard);

Expand Down
231 changes: 227 additions & 4 deletions packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import {
moveDown,
moveRight,
pressBackspace,
selectAll,
Expand All @@ -23,6 +24,7 @@ import {
insertSampleImage,
insertTable,
IS_COLLAB,
mergeTableCells,
pasteFromClipboard,
SAMPLE_IMAGE_URL,
selectCellsFromTableCords,
Expand Down Expand Up @@ -396,7 +398,13 @@ test.describe('Tables', () => {
await insertTable(page);

await fillTablePartiallyWithText(page);
await selectCellsFromTableCords(page, {x: 0, y: 0}, {x: 1, y: 1});
await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 1, y: 1},
true,
false,
);

await assertHTML(
page,
Expand Down Expand Up @@ -1047,7 +1055,13 @@ test.describe('Tables', () => {
await insertTable(page);

await fillTablePartiallyWithText(page);
await selectCellsFromTableCords(page, {x: 0, y: 0}, {x: 1, y: 1});
await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 1, y: 1},
true,
false,
);

await clickSelectors(page, ['.bold', '.italic', '.underline']);

Expand Down Expand Up @@ -1268,7 +1282,13 @@ test.describe('Tables', () => {
await insertTable(page);

await fillTablePartiallyWithText(page);
await selectCellsFromTableCords(page, {x: 0, y: 0}, {x: 1, y: 1});
await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 1, y: 1},
true,
false,
);

const clipboard = await copyToClipboard(page);

Expand Down Expand Up @@ -1454,7 +1474,13 @@ test.describe('Tables', () => {
await insertTable(page);

await fillTablePartiallyWithText(page);
await selectCellsFromTableCords(page, {x: 0, y: 0}, {x: 1, y: 1});
await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 1, y: 1},
true,
false,
);

await page.keyboard.press('Backspace');

Expand Down Expand Up @@ -2416,4 +2442,201 @@ test.describe('Tables', () => {
`,
);
});

test('Merge cells', async ({page, isPlainText}) => {
test.skip(isPlainText);

await focusEditor(page);

await insertTable(page, 1, 3);

await click(page, '.PlaygroundEditorTheme__tableCell');
await moveRight(page, 1);
await page.keyboard.type('first');
await page.keyboard.press('Tab');
await page.keyboard.type('second');
await selectCellsFromTableCords(
page,
{x: 1, y: 0},
{x: 2, y: 0},
true,
true,
);
await mergeTableCells(page);

await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
<table class="PlaygroundEditorTheme__table disable-selection">
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
colspan="2">
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">first</span>
</p>
</th>
</tr>
</table>
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
`,
html`
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
<table class="PlaygroundEditorTheme__table">
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
colspan="2">
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">first</span>
</p>
</th>
</tr>
</table>
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
`,
);
});

test('Select multiple merged cells (selection expands to a rectangle)', async ({
page,
isPlainText,
}) => {
test.skip(isPlainText);

await focusEditor(page);

await insertTable(page, 3, 3);

await click(page, '.PlaygroundEditorTheme__tableCell');
await moveDown(page, 1);
await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 0, y: 1},
true,
true,
);
await mergeTableCells(page);
await page.pause();

await moveRight(page, 1);
await selectCellsFromTableCords(
page,
{x: 1, y: 0},
{x: 2, y: 0},
true,
true,
);
await mergeTableCells(page);
await page.pause();

await selectCellsFromTableCords(
page,
{x: 0, y: 0},
{x: 1, y: 0},
true,
true,
);
await page.pause();

await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
<table class="PlaygroundEditorTheme__table disable-selection">
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
rowspan="2"
style="background-color: rgb(172, 206, 247); caret-color: transparent">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
colspan="2"
style="background-color: rgb(172, 206, 247); caret-color: transparent">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
</tr>
<tr>
<td
class="PlaygroundEditorTheme__tableCell"
style="background-color: rgb(172, 206, 247); caret-color: transparent">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td
class="PlaygroundEditorTheme__tableCell"
style="background-color: rgb(172, 206, 247); caret-color: transparent">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
</table>
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
`,
html`
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
<table class="PlaygroundEditorTheme__table">
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
rowspan="2">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
colspan="2">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
</tr>
<tr>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
</table>
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
`,
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ export async function moveRight(page, numCharacters = 1, delayMs) {
}
}

export async function moveDown(page, numCharacters = 1, delayMs) {
for (let i = 0; i < numCharacters; i++) {
if (delayMs !== undefined) {
await sleep(delayMs);
}
await page.keyboard.press('ArrowDown');
}
}

export async function pressBackspace(page, numCharacters = 1, delayMs) {
for (let i = 0; i < numCharacters; i++) {
if (delayMs !== undefined) {
Expand Down
41 changes: 33 additions & 8 deletions packages/lexical-playground/__tests__/utils/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -712,30 +712,50 @@ export async function selectFromAlignDropdown(page, selector) {
await click(page, '.dropdown ' + selector);
}

export async function insertTable(page) {
export async function insertTable(page, rows = null, columns = null) {
let leftFrame = page;
if (IS_COLLAB) {
leftFrame = await page.frame('left');
}
await selectFromInsertDropdown(page, '.item .table');
if (rows !== null) {
await leftFrame
.locator('input[data-test-id="table-modal-rows"]')
.fill(String(rows));
}
if (columns !== null) {
await leftFrame
.locator('input[data-test-id="table-modal-columns"]')
.fill(String(columns));
}
await click(
page,
'div[data-test-id="table-model-confirm-insert"] > .Button__root',
);
}

export async function selectCellsFromTableCords(page, firstCords, secondCords) {
export async function selectCellsFromTableCords(
page,
firstCords,
secondCords,
isFirstHeader = false,
isSecondHeader = false,
) {
let leftFrame = page;
if (IS_COLLAB) {
await focusEditor(page);
leftFrame = await page.frame('left');
}

const firstRowFirstColumnCell = await leftFrame.locator(
`table:first-of-type > tr:nth-child(${firstCords.y + 1}) > th:nth-child(${
firstCords.x + 1
})`,
`table:first-of-type > tr:nth-child(${firstCords.y + 1}) > ${
isFirstHeader ? 'th' : 'td'
}:nth-child(${firstCords.x + 1})`,
);
const secondRowSecondCell = await leftFrame.locator(
`table:first-of-type > tr:nth-child(${secondCords.y + 1}) > td:nth-child(${
secondCords.x + 1
})`,
`table:first-of-type > tr:nth-child(${secondCords.y + 1}) > ${
isSecondHeader ? 'th' : 'td'
}:nth-child(${secondCords.x + 1})`,
);

// Focus on inside the iFrame or the boundingBox() below returns null.
Expand All @@ -752,6 +772,11 @@ export async function selectCellsFromTableCords(page, firstCords, secondCords) {
);
}

export async function mergeTableCells(page) {
await click(page, '.table-cell-action-button-container');
await click(page, '.item:text("Merge cells")');
}

export async function enableCompositionKeyEvents(page) {
const targetPage = IS_COLLAB ? await page.frame('left') : page;
await targetPage.evaluate(() => {
Expand Down
5 changes: 4 additions & 1 deletion packages/lexical-playground/src/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ export default function Editor(): JSX.Element {
<DraggableBlockPlugin anchorElem={floatingAnchorElem} />
<CodeActionMenuPlugin anchorElem={floatingAnchorElem} />
<FloatingLinkEditorPlugin anchorElem={floatingAnchorElem} />
<TableCellActionMenuPlugin anchorElem={floatingAnchorElem} />
<TableCellActionMenuPlugin
anchorElem={floatingAnchorElem}
cellMerge={true}
/>
<FloatingTextFormatToolbarPlugin
anchorElem={floatingAnchorElem}
/>
Expand Down
Loading