From 0cbb68357b27b56663941297e93fbac97df89970 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 00:30:08 +0300 Subject: [PATCH 01/19] Support for vertical cell writing --- .../plugins/TableActionMenuPlugin/index.tsx | 11 +++++ .../lexical-table/src/LexicalTableCellNode.ts | 46 ++++++++++++++++++- .../lexical-table/src/LexicalTableUtils.ts | 11 ++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx index 0796241e5e1..79e3b944a27 100644 --- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx @@ -501,6 +501,17 @@ function TableActionMenu({ [editor], ); + const toggleTextDirection = useCallback(() => { + editor.update(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection) || $isTableSelection(selection)) { + const [cell] = $getNodeTriplet(selection.anchor); + const currentTextDirection = cell.getWritingMode(); + cell.setWritingMode(!currentTextDirection ? 'vertical-lr' : null); + } + }); + }, [editor]); + let mergeCellButton: null | JSX.Element = null; if (cellMerge) { if (canMergeCells) { diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 455d39bf6c9..21d1d8bdb12 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -11,6 +11,7 @@ import type { DOMConversionOutput, DOMExportOutput, EditorConfig, + ElementFormatType, LexicalEditor, LexicalNode, NodeKey, @@ -26,9 +27,11 @@ import { $isLineBreakNode, $isTextNode, ElementNode, + ParagraphNode, } from 'lexical'; import {COLUMN_WIDTH, PIXEL_VALUE_REG_EXP} from './constants'; +import {computeVerticalFormat} from './LexicalTableUtils'; export const TableCellHeaderStates = { BOTH: 3, @@ -47,6 +50,7 @@ export type SerializedTableCellNode = Spread< headerState: TableCellHeaderState; width?: number; backgroundColor?: null | string; + writingMode?: null | string; }, SerializedElementNode >; @@ -63,6 +67,8 @@ export class TableCellNode extends ElementNode { __width?: number; /** @internal */ __backgroundColor: null | string; + /** @internal */ + __writingMode: null | string; static getType(): string { return 'tablecell'; @@ -77,6 +83,7 @@ export class TableCellNode extends ElementNode { ); cellNode.__rowSpan = node.__rowSpan; cellNode.__backgroundColor = node.__backgroundColor; + cellNode.__writingMode = node.__writingMode; return cellNode; } @@ -103,6 +110,7 @@ export class TableCellNode extends ElementNode { ); cellNode.__rowSpan = rowSpan; cellNode.__backgroundColor = serializedNode.backgroundColor || null; + cellNode.__writingMode = serializedNode.writingMode || null; return cellNode; } @@ -118,6 +126,7 @@ export class TableCellNode extends ElementNode { this.__headerState = headerState; this.__width = width; this.__backgroundColor = null; + this.__writingMode = null; } createDOM(config: EditorConfig): HTMLElement { @@ -137,6 +146,16 @@ export class TableCellNode extends ElementNode { if (this.__backgroundColor !== null) { element.style.backgroundColor = this.__backgroundColor; } + if (this.__writingMode !== null) { + element.style.writingMode = this.__writingMode; + element.style.verticalAlign = computeVerticalFormat( + this.getChildFormatType(), + ); + element.style.transform = 'rotate(180deg)'; + } else { + element.style.verticalAlign = ''; + element.style.transform = ''; + } addClassNamesToElement( element, @@ -164,6 +183,11 @@ export class TableCellNode extends ElementNode { element_.style.verticalAlign = 'top'; element_.style.textAlign = 'start'; + const writingMode = this.getWritingMode(); + if (writingMode !== null) { + element_.style.writingMode = writingMode; + } + const backgroundColor = this.getBackgroundColor(); if (backgroundColor !== null) { element_.style.backgroundColor = backgroundColor; @@ -186,6 +210,7 @@ export class TableCellNode extends ElementNode { rowSpan: this.__rowSpan, type: 'tablecell', width: this.getWidth(), + writingMode: this.getWritingMode(), }; } @@ -231,6 +256,18 @@ export class TableCellNode extends ElementNode { return this.getLatest().__width; } + getChildFormatType(): ElementFormatType { + return this.getFirstChild().getFormatType(); + } + + getWritingMode(): null | string { + return this.getLatest().__writingMode; + } + + setWritingMode(newWritingMode: null | string): void { + this.getWritable().__writingMode = newWritingMode; + } + getBackgroundColor(): null | string { return this.getLatest().__backgroundColor; } @@ -265,7 +302,10 @@ export class TableCellNode extends ElementNode { prevNode.__width !== this.__width || prevNode.__colSpan !== this.__colSpan || prevNode.__rowSpan !== this.__rowSpan || - prevNode.__backgroundColor !== this.__backgroundColor + prevNode.__backgroundColor !== this.__backgroundColor || + prevNode.__writingMode !== this.__writingMode || + prevNode.__format !== this.__format || + this.getFormatType() !== this.getChildFormatType() ); } @@ -311,6 +351,10 @@ export function $convertTableCellNodeElement( if (backgroundColor !== '') { tableCellNode.__backgroundColor = backgroundColor; } + const writingMode = domNode_.style.writingMode; + if (writingMode !== '') { + tableCellNode.__writingMode = writingMode; + } const style = domNode_.style; const textDecoration = style.textDecoration.split(' '); diff --git a/packages/lexical-table/src/LexicalTableUtils.ts b/packages/lexical-table/src/LexicalTableUtils.ts index 3293881e823..ad91305c18a 100644 --- a/packages/lexical-table/src/LexicalTableUtils.ts +++ b/packages/lexical-table/src/LexicalTableUtils.ts @@ -7,7 +7,7 @@ */ import type {TableMapType, TableMapValueType} from './LexicalTableSelection'; -import type {ElementNode, PointType} from 'lexical'; +import type {ElementFormatType, ElementNode, PointType} from 'lexical'; import {$findMatchingParent} from '@lexical/utils'; import { @@ -892,3 +892,12 @@ export function $getTableCellNodeRect(tableCellNode: TableCellNode): { return null; } + +export const computeVerticalFormat = (format?: ElementFormatType) => { + if (format === 'center') { + return 'middle'; + } else if (format === 'right' || format === 'end') { + return 'top'; + } + return 'bottom'; +}; From 1dd6f3fe4b77a2129af48bb0a4ef22cb24cb9735 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 00:37:29 +0300 Subject: [PATCH 02/19] Support for vertical cell writing --- packages/lexical-table/src/LexicalTableCellNode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 21d1d8bdb12..5f76af92ab6 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -257,7 +257,7 @@ export class TableCellNode extends ElementNode { } getChildFormatType(): ElementFormatType { - return this.getFirstChild().getFormatType(); + return this.getFirstChild()!.getFormatType(); } getWritingMode(): null | string { From 87befee06bec24c7effcab448ca2741cdc4d2867 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 00:45:49 +0300 Subject: [PATCH 03/19] Support for vertical cell writing --- .../__tests__/unit/LexicalTableCellNode.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index 9c56db63bf3..797eea6da4e 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -7,6 +7,7 @@ */ import {$createTableCellNode, TableCellHeaderStates} from '@lexical/table'; +import {$createParagraphNode, $createTextNode} from 'lexical'; import {initializeUnitTest} from 'lexical/src/__tests__/utils'; const editorConfig = Object.freeze({ @@ -66,5 +67,21 @@ describe('LexicalTableCellNode tests', () => { ); }); }); + + test('TableCellNode Toggle Writing Direction', async () => { + const {editor} = testEnv; + + await editor.update(() => { + const cellNode = $createTableCellNode(TableCellHeaderStates.NO_STATUS); + const p = $createParagraphNode(); + p.append($createTextNode('abc')); + cellNode.append(p); + cellNode.setWritingMode('lr-vertical'); + + expect(cellNode.createDOM(editorConfig).outerHTML).toBe( + ``, + ); + }); + }); }); }); From 3c317cc30533a94c56292db3f3b24b2a948d86ff Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 11:16:47 +0300 Subject: [PATCH 04/19] Support for vertical cell writing --- .../src/plugins/TableActionMenuPlugin/index.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx index 79e3b944a27..73016230162 100644 --- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx @@ -507,7 +507,19 @@ function TableActionMenu({ if ($isRangeSelection(selection) || $isTableSelection(selection)) { const [cell] = $getNodeTriplet(selection.anchor); const currentTextDirection = cell.getWritingMode(); - cell.setWritingMode(!currentTextDirection ? 'vertical-lr' : null); + const newTextDirection = !currentTextDirection ? 'vertical-lr' : null; + cell.setWritingMode(newTextDirection); + + if ($isTableSelection(selection)) { + const nodes = selection.getNodes(); + + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if ($isTableCellNode(node)) { + node.setWritingMode(newTextDirection); + } + } + } } }); }, [editor]); From 7fb89b4abe0d12a8d3d95a501d6d52a649dc935a Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 11:35:06 +0300 Subject: [PATCH 05/19] Tests --- .../src/__tests__/unit/LexicalSelection.test.tsx | 2 +- .../lexical/src/__tests__/unit/LexicalSerialization.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx b/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx index 121d13fe3ec..4a6ce1386f8 100644 --- a/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx +++ b/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx @@ -2946,7 +2946,7 @@ describe('LexicalSelection tests', () => { return $createHeadingNode('h1'); }); expect(JSON.stringify(testEditor._pendingEditorState?.toJSON())).toBe( - '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"children":[{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1}],"direction":null,"format":"","indent":0,"type":"tablerow","version":1}],"direction":null,"format":"","indent":0,"type":"table","version":1},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"root","version":1}}', + '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"children":[{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1,"writingMode:null},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode:null}],"direction":null,"format":"","indent":0,"type":"tablerow","version":1}],"direction":null,"format":"","indent":0,"type":"table","version":1},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"root","version":1}}', ); }); }); diff --git a/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts b/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts index 9237bc9d3dd..927411213da 100644 --- a/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts +++ b/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts @@ -110,7 +110,7 @@ describe('LexicalSerialization tests', () => { }); const stringifiedEditorState = JSON.stringify(editor.getEditorState()); - const expectedStringifiedEditorState = `{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Welcome to the playground","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"In case you were wondering what the black box at the bottom is – it's the debug view, showing the current state of the editor. You can disable it by pressing on the settings control in the bottom-left of your screen and toggling the debug view setting.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"The playground is a demo environment built with ","type":"text","version":1},{"detail":0,"format":16,"mode":"normal","style":"","text":"@lexical/react","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":". Try typing in ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"some text","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" with ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"different","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" formats.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Make sure to check out the various plugins in the toolbar. You can also use #hashtags or @-mentions too!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"If you'd like to find out more about Lexical, you can:","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Visit the ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lexical website","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://lexical.dev/"},{"detail":0,"format":0,"mode":"normal","style":"","text":" for documentation and more information.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Check out the code on our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"GitHub repository","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Playground code can be found ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"here","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical/tree/main/packages/lexical-playground"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Join our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Discord Server","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://discord.com/invite/KmG4wQnnD9"},{"detail":0,"format":0,"mode":"normal","style":"","text":" and chat with the team.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lastly, we're constantly adding cool new features to this playground. So make sure you check back here when you next get a chance :).","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"const lexical = \\"awesome\\"","type":"code-highlight","version":1}],"direction":"ltr","format":"","indent":0,"type":"code","version":1,"language":"javascript"},{"children":[{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1}],"direction":"ltr","format":"","indent":0,"type":"table","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}`; + const expectedStringifiedEditorState = `{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Welcome to the playground","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"In case you were wondering what the black box at the bottom is – it's the debug view, showing the current state of the editor. You can disable it by pressing on the settings control in the bottom-left of your screen and toggling the debug view setting.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"The playground is a demo environment built with ","type":"text","version":1},{"detail":0,"format":16,"mode":"normal","style":"","text":"@lexical/react","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":". Try typing in ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"some text","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" with ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"different","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" formats.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Make sure to check out the various plugins in the toolbar. You can also use #hashtags or @-mentions too!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"If you'd like to find out more about Lexical, you can:","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Visit the ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lexical website","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://lexical.dev/"},{"detail":0,"format":0,"mode":"normal","style":"","text":" for documentation and more information.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Check out the code on our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"GitHub repository","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Playground code can be found ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"here","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical/tree/main/packages/lexical-playground"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Join our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Discord Server","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://discord.com/invite/KmG4wQnnD9"},{"detail":0,"format":0,"mode":"normal","style":"","text":" and chat with the team.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lastly, we're constantly adding cool new features to this playground. So make sure you check back here when you next get a chance :).","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"const lexical = \\"awesome\\"","type":"code-highlight","version":1}],"direction":"ltr","format":"","indent":0,"type":"code","version":1,"language":"javascript"},{"children":[{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1}],"direction":"ltr","format":"","indent":0,"type":"table","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}`; expect(stringifiedEditorState).toBe(expectedStringifiedEditorState); From 1f62e4fc255dd5391ef0afb87481b9794b18bd86 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 11:45:23 +0300 Subject: [PATCH 06/19] Tests --- .../src/__tests__/unit/LexicalSelection.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx b/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx index 4a6ce1386f8..0400a98311c 100644 --- a/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx +++ b/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx @@ -2946,7 +2946,7 @@ describe('LexicalSelection tests', () => { return $createHeadingNode('h1'); }); expect(JSON.stringify(testEditor._pendingEditorState?.toJSON())).toBe( - '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"children":[{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1,"writingMode:null},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode:null}],"direction":null,"format":"","indent":0,"type":"tablerow","version":1}],"direction":null,"format":"","indent":0,"type":"table","version":1},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"root","version":1}}', + '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"children":[{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1,"writingMode":null},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null}],"direction":null,"format":"","indent":0,"type":"tablerow","version":1}],"direction":null,"format":"","indent":0,"type":"table","version":1},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"root","version":1}}', ); }); }); From 91aabc28a5a84dd824786112cf96b41870796391 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 11:50:32 +0300 Subject: [PATCH 07/19] Tests --- packages/lexical-table/src/LexicalTableCellNode.ts | 2 +- .../src/__tests__/unit/LexicalTableCellNode.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 5f76af92ab6..c73aff26370 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -305,7 +305,7 @@ export class TableCellNode extends ElementNode { prevNode.__backgroundColor !== this.__backgroundColor || prevNode.__writingMode !== this.__writingMode || prevNode.__format !== this.__format || - this.getFormatType() !== this.getChildFormatType() + prevNode.getFormatType() !== this.getChildFormatType() ); } diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index 797eea6da4e..3c8a942bfae 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -76,10 +76,10 @@ describe('LexicalTableCellNode tests', () => { const p = $createParagraphNode(); p.append($createTextNode('abc')); cellNode.append(p); - cellNode.setWritingMode('lr-vertical'); + cellNode.setWritingMode('vertical-rl'); expect(cellNode.createDOM(editorConfig).outerHTML).toBe( - ``, + ``, ); }); }); From c96524f3783db216150fa4947f82d976e1f5fc4b Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sat, 24 Aug 2024 11:53:02 +0300 Subject: [PATCH 08/19] Tests --- packages/lexical-table/src/LexicalTableCellNode.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index c73aff26370..f12c9868297 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -304,8 +304,8 @@ export class TableCellNode extends ElementNode { prevNode.__rowSpan !== this.__rowSpan || prevNode.__backgroundColor !== this.__backgroundColor || prevNode.__writingMode !== this.__writingMode || - prevNode.__format !== this.__format || - prevNode.getFormatType() !== this.getChildFormatType() + prevNode.__format !== this.__format //|| + // prevNode.getFormatType() !== this.getChildFormatType() ); } From d2d9bc834c8d98b0687e2b893ea5ccb7bbc87798 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Fri, 30 Aug 2024 00:56:02 +0300 Subject: [PATCH 09/19] writingMode internals --- .../plugins/TableActionMenuPlugin/index.tsx | 10 +++-- .../__tests__/unit/LexicalSelection.test.tsx | 2 +- .../lexical-table/src/LexicalTableCellNode.ts | 38 ++++++++++++------- .../unit/LexicalTableCellNode.test.ts | 2 +- .../unit/LexicalSerialization.test.ts | 2 +- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx index 73016230162..46fab8d3eeb 100644 --- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx @@ -506,9 +506,11 @@ function TableActionMenu({ const selection = $getSelection(); if ($isRangeSelection(selection) || $isTableSelection(selection)) { const [cell] = $getNodeTriplet(selection.anchor); - const currentTextDirection = cell.getWritingMode(); - const newTextDirection = !currentTextDirection ? 'vertical-lr' : null; - cell.setWritingMode(newTextDirection); + const currentTextDirection = cell.getCellDirection(); + const newTextDirection = !currentTextDirection + ? 'vertical' + : 'horizontal'; + cell.setCellDirection(newTextDirection); if ($isTableSelection(selection)) { const nodes = selection.getNodes(); @@ -516,7 +518,7 @@ function TableActionMenu({ for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if ($isTableCellNode(node)) { - node.setWritingMode(newTextDirection); + node.setCellDirection(newTextDirection); } } } diff --git a/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx b/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx index 0400a98311c..121d13fe3ec 100644 --- a/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx +++ b/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsx @@ -2946,7 +2946,7 @@ describe('LexicalSelection tests', () => { return $createHeadingNode('h1'); }); expect(JSON.stringify(testEditor._pendingEditorState?.toJSON())).toBe( - '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"children":[{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1,"writingMode":null},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null}],"direction":null,"format":"","indent":0,"type":"tablerow","version":1}],"direction":null,"format":"","indent":0,"type":"table","version":1},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"root","version":1}}', + '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"children":[{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"","type":"text","version":1}],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1}],"direction":null,"format":"","indent":0,"type":"tablerow","version":1}],"direction":null,"format":"","indent":0,"type":"table","version":1},{"children":[],"direction":null,"format":"","indent":0,"type":"heading","version":1,"tag":"h1"}],"direction":null,"format":"","indent":0,"type":"root","version":1}}', ); }); }); diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index f12c9868297..fd31f834563 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -50,7 +50,7 @@ export type SerializedTableCellNode = Spread< headerState: TableCellHeaderState; width?: number; backgroundColor?: null | string; - writingMode?: null | string; + writingMode?: string; }, SerializedElementNode >; @@ -68,7 +68,7 @@ export class TableCellNode extends ElementNode { /** @internal */ __backgroundColor: null | string; /** @internal */ - __writingMode: null | string; + __writingMode?: string; static getType(): string { return 'tablecell'; @@ -110,7 +110,7 @@ export class TableCellNode extends ElementNode { ); cellNode.__rowSpan = rowSpan; cellNode.__backgroundColor = serializedNode.backgroundColor || null; - cellNode.__writingMode = serializedNode.writingMode || null; + cellNode.__writingMode = serializedNode.writingMode; return cellNode; } @@ -126,7 +126,6 @@ export class TableCellNode extends ElementNode { this.__headerState = headerState; this.__width = width; this.__backgroundColor = null; - this.__writingMode = null; } createDOM(config: EditorConfig): HTMLElement { @@ -146,7 +145,7 @@ export class TableCellNode extends ElementNode { if (this.__backgroundColor !== null) { element.style.backgroundColor = this.__backgroundColor; } - if (this.__writingMode !== null) { + if (this.__writingMode) { element.style.writingMode = this.__writingMode; element.style.verticalAlign = computeVerticalFormat( this.getChildFormatType(), @@ -183,7 +182,7 @@ export class TableCellNode extends ElementNode { element_.style.verticalAlign = 'top'; element_.style.textAlign = 'start'; - const writingMode = this.getWritingMode(); + const writingMode = this.getCellDirection(); if (writingMode !== null) { element_.style.writingMode = writingMode; } @@ -210,7 +209,7 @@ export class TableCellNode extends ElementNode { rowSpan: this.__rowSpan, type: 'tablecell', width: this.getWidth(), - writingMode: this.getWritingMode(), + writingMode: this.__writingMode, }; } @@ -260,12 +259,25 @@ export class TableCellNode extends ElementNode { return this.getFirstChild()!.getFormatType(); } - getWritingMode(): null | string { - return this.getLatest().__writingMode; + getChildTextDirection(): 'ltr' | 'rtl' | null { + return this.getFirstChild()!.getDirection(); } - setWritingMode(newWritingMode: null | string): void { - this.getWritable().__writingMode = newWritingMode; + getCellDirection(): null | string { + return this.getLatest().__writingMode || null; + } + + setCellDirection(direction: 'horizontal' | 'vertical'): void { + if (direction === 'vertical') { + const childTextDirection = this.getChildTextDirection(); + if (childTextDirection === 'rtl') { + this.getWritable().__writingMode = 'vertical-rl'; + } else { + this.getWritable().__writingMode = 'vertical-lr'; + } + } else { + this.getWritable().__writingMode = undefined; + } } getBackgroundColor(): null | string { @@ -304,8 +316,8 @@ export class TableCellNode extends ElementNode { prevNode.__rowSpan !== this.__rowSpan || prevNode.__backgroundColor !== this.__backgroundColor || prevNode.__writingMode !== this.__writingMode || - prevNode.__format !== this.__format //|| - // prevNode.getFormatType() !== this.getChildFormatType() + prevNode.__format !== this.__format || + this.getFormatType() !== this.getChildFormatType() ); } diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index 3c8a942bfae..9339027859f 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -76,7 +76,7 @@ describe('LexicalTableCellNode tests', () => { const p = $createParagraphNode(); p.append($createTextNode('abc')); cellNode.append(p); - cellNode.setWritingMode('vertical-rl'); + cellNode.setCellDirection('vertical'); expect(cellNode.createDOM(editorConfig).outerHTML).toBe( ``, diff --git a/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts b/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts index 927411213da..9237bc9d3dd 100644 --- a/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts +++ b/packages/lexical/src/__tests__/unit/LexicalSerialization.test.ts @@ -110,7 +110,7 @@ describe('LexicalSerialization tests', () => { }); const stringifiedEditorState = JSON.stringify(editor.getEditorState()); - const expectedStringifiedEditorState = `{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Welcome to the playground","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"In case you were wondering what the black box at the bottom is – it's the debug view, showing the current state of the editor. You can disable it by pressing on the settings control in the bottom-left of your screen and toggling the debug view setting.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"The playground is a demo environment built with ","type":"text","version":1},{"detail":0,"format":16,"mode":"normal","style":"","text":"@lexical/react","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":". Try typing in ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"some text","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" with ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"different","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" formats.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Make sure to check out the various plugins in the toolbar. You can also use #hashtags or @-mentions too!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"If you'd like to find out more about Lexical, you can:","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Visit the ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lexical website","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://lexical.dev/"},{"detail":0,"format":0,"mode":"normal","style":"","text":" for documentation and more information.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Check out the code on our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"GitHub repository","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Playground code can be found ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"here","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical/tree/main/packages/lexical-playground"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Join our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Discord Server","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://discord.com/invite/KmG4wQnnD9"},{"detail":0,"format":0,"mode":"normal","style":"","text":" and chat with the team.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lastly, we're constantly adding cool new features to this playground. So make sure you check back here when you next get a chance :).","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"const lexical = \\"awesome\\"","type":"code-highlight","version":1}],"direction":"ltr","format":"","indent":0,"type":"code","version":1,"language":"javascript"},{"children":[{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1,"writingMode":null}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1}],"direction":"ltr","format":"","indent":0,"type":"table","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}`; + const expectedStringifiedEditorState = `{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Welcome to the playground","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"heading","version":1,"tag":"h1"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"In case you were wondering what the black box at the bottom is – it's the debug view, showing the current state of the editor. You can disable it by pressing on the settings control in the bottom-left of your screen and toggling the debug view setting.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"The playground is a demo environment built with ","type":"text","version":1},{"detail":0,"format":16,"mode":"normal","style":"","text":"@lexical/react","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":". Try typing in ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"some text","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" with ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"different","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" formats.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Make sure to check out the various plugins in the toolbar. You can also use #hashtags or @-mentions too!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"If you'd like to find out more about Lexical, you can:","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Visit the ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lexical website","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://lexical.dev/"},{"detail":0,"format":0,"mode":"normal","style":"","text":" for documentation and more information.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Check out the code on our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"GitHub repository","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Playground code can be found ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"here","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://github.com/facebook/lexical/tree/main/packages/lexical-playground"},{"detail":0,"format":0,"mode":"normal","style":"","text":".","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Join our ","type":"text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Discord Server","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":null,"target":null,"title":null,"url":"https://discord.com/invite/KmG4wQnnD9"},{"detail":0,"format":0,"mode":"normal","style":"","text":" and chat with the team.","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Lastly, we're constantly adding cool new features to this playground. So make sure you check back here when you next get a chance :).","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"const lexical = \\"awesome\\"","type":"code-highlight","version":1}],"direction":"ltr","format":"","indent":0,"type":"code","version":1,"language":"javascript"},{"children":[{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":3,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":1,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1},{"children":[{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":2,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1},{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1,"textFormat":0,"textStyle":""}],"direction":"ltr","format":"","indent":0,"type":"tablecell","version":1,"backgroundColor":null,"colSpan":1,"headerState":0,"rowSpan":1}],"direction":"ltr","format":"","indent":0,"type":"tablerow","version":1}],"direction":"ltr","format":"","indent":0,"type":"table","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}`; expect(stringifiedEditorState).toBe(expectedStringifiedEditorState); From 561d2146fe1ed57f74cf7df00ed01cff988a5018 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Fri, 30 Aug 2024 01:03:25 +0300 Subject: [PATCH 10/19] writingMode internals --- .../src/__tests__/unit/LexicalTableCellNode.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index 9339027859f..0657d3c042b 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -79,7 +79,7 @@ describe('LexicalTableCellNode tests', () => { cellNode.setCellDirection('vertical'); expect(cellNode.createDOM(editorConfig).outerHTML).toBe( - ``, + ``, ); }); }); From 6e086f7bbd877137a9e04ac24e208008cea9dd3f Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Fri, 30 Aug 2024 01:18:19 +0300 Subject: [PATCH 11/19] writingMode internals --- .../src/plugins/TableActionMenuPlugin/index.tsx | 16 +++++++++++++--- .../lexical-table/src/LexicalTableCellNode.ts | 10 +++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx index 46fab8d3eeb..6011258a0e2 100644 --- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx @@ -507,9 +507,8 @@ function TableActionMenu({ if ($isRangeSelection(selection) || $isTableSelection(selection)) { const [cell] = $getNodeTriplet(selection.anchor); const currentTextDirection = cell.getCellDirection(); - const newTextDirection = !currentTextDirection - ? 'vertical' - : 'horizontal'; + const newTextDirection = + currentTextDirection === 'horizontal' ? 'vertical' : 'horizontal'; cell.setCellDirection(newTextDirection); if ($isTableSelection(selection)) { @@ -581,6 +580,17 @@ function TableActionMenu({ data-test-id="table-row-striping"> Toggle Row Striping +

diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 70b1bf73c83..56d7c980ba1 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -176,8 +176,8 @@ export class TableCellNode extends ElementNode { element_.style.verticalAlign = 'top'; element_.style.textAlign = 'start'; - const writingMode = this.getCellDirection(); - if (writingMode !== null) { + const writingMode = this.getWritingMode(); + if (writingMode) { element_.style.writingMode = writingMode; } @@ -249,19 +249,22 @@ export class TableCellNode extends ElementNode { return this.getLatest().__width; } - getCellDirection(): 'horizontal' | 'vertical' { - if (this.getLatest().__writingMode) { - return 'vertical'; - } else { - return 'horizontal'; - } + /** + * Returns the currently set cell writing direction + * @returns undefined for horizontal, string value for vertical + */ + getCellDirection(): string | undefined { + return this.getLatest().__writingMode; } - setCellDirection(direction: 'horizontal' | 'vertical'): void { - if (direction === 'vertical') { - this.getWritable().__writingMode = 'vertical-lr'; - } else { + toggleCellDirection(): void { + if ( + this.getLatest().__writingMode === 'vertical-rl' || + this.getLatest().__writingMode === 'vertical-lr' + ) { this.getWritable().__writingMode = undefined; + } else { + this.getWritable().__writingMode = 'vertical-rl'; } } @@ -348,7 +351,7 @@ export function $convertTableCellNodeElement( tableCellNode.__backgroundColor = backgroundColor; } const writingMode = domNode_.style.writingMode; - if (writingMode) { + if (writingMode && writingMode !== 'horizontal-tb') { tableCellNode.__writingMode = writingMode; } diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index f86e0b1697d..82e07e8710c 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -79,7 +79,7 @@ describe('LexicalTableCellNode tests', () => { cellNode.setCellDirection('vertical'); expect(cellNode.createDOM(editorConfig).outerHTML).toBe( - ``, + ``, ); }); }); From dbbee5c88411445aa11d5109d589710c5248bc2b Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sun, 1 Sep 2024 00:54:59 +0300 Subject: [PATCH 16/19] clean up --- packages/lexical-table/src/LexicalTableCellNode.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 56d7c980ba1..535c989d629 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -176,7 +176,7 @@ export class TableCellNode extends ElementNode { element_.style.verticalAlign = 'top'; element_.style.textAlign = 'start'; - const writingMode = this.getWritingMode(); + const writingMode = this.getCellDirection(); if (writingMode) { element_.style.writingMode = writingMode; } @@ -250,7 +250,7 @@ export class TableCellNode extends ElementNode { } /** - * Returns the currently set cell writing direction + * Returns the current cell writing direction * @returns undefined for horizontal, string value for vertical */ getCellDirection(): string | undefined { From bac145a015a507f6f394c964b70a8843f407ede7 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sun, 1 Sep 2024 00:59:42 +0300 Subject: [PATCH 17/19] clean up 2 --- packages/lexical-table/src/LexicalTableCellNode.ts | 2 +- .../src/__tests__/unit/LexicalTableCellNode.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 535c989d629..62c992af9bd 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -351,7 +351,7 @@ export function $convertTableCellNodeElement( tableCellNode.__backgroundColor = backgroundColor; } const writingMode = domNode_.style.writingMode; - if (writingMode && writingMode !== 'horizontal-tb') { + if (writingMode === 'vertical-lr' || writingMode === 'vertical-rl') { tableCellNode.__writingMode = writingMode; } diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index 82e07e8710c..9ea198367dd 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -76,7 +76,7 @@ describe('LexicalTableCellNode tests', () => { const p = $createParagraphNode(); p.append($createTextNode('abc')); cellNode.append(p); - cellNode.setCellDirection('vertical'); + cellNode.toggleCellDirection(); expect(cellNode.createDOM(editorConfig).outerHTML).toBe( ``, From fa367df4727cd6832274d666af89d5237c3cbb32 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sun, 1 Sep 2024 10:05:10 +0300 Subject: [PATCH 18/19] tsdoc --- .../src/plugins/TableActionMenuPlugin/index.tsx | 7 +++++-- .../lexical-table/src/LexicalTableCellNode.ts | 16 +++++++++------- .../__tests__/unit/LexicalTableCellNode.test.ts | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx index b1df6de2281..b79a90ef0cd 100644 --- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx @@ -506,7 +506,10 @@ function TableActionMenu({ const selection = $getSelection(); if ($isRangeSelection(selection) || $isTableSelection(selection)) { const [cell] = $getNodeTriplet(selection.anchor); - cell.toggleCellDirection(); + const newDirection = cell.getCellDirection() + ? 'vertical-rl' + : undefined; + cell.setCellDirection(newDirection); if ($isTableSelection(selection)) { const nodes = selection.getNodes(); @@ -514,7 +517,7 @@ function TableActionMenu({ for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if ($isTableCellNode(node)) { - node.toggleCellDirection(); + node.setCellDirection(newDirection); } } } diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 62c992af9bd..0f68f80a4cc 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -251,20 +251,22 @@ export class TableCellNode extends ElementNode { /** * Returns the current cell writing direction - * @returns undefined for horizontal, string value for vertical + * @returns undefined for horizontal, string value if vertical */ getCellDirection(): string | undefined { return this.getLatest().__writingMode; } - toggleCellDirection(): void { - if ( - this.getLatest().__writingMode === 'vertical-rl' || - this.getLatest().__writingMode === 'vertical-lr' - ) { + /** + * Update cell writing direction, set to null or undefined for horizontal (default) + * Set to 'vertical-rl' or 'vertical-lr' for vertical and paragraph order preference. + * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode} + */ + setCellDirection(direction?: null | 'vertical-rl' | 'vertical-lr'): void { + if (!direction) { this.getWritable().__writingMode = undefined; } else { - this.getWritable().__writingMode = 'vertical-rl'; + this.getLatest().__writingMode = direction; } } diff --git a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts index 9ea198367dd..bc664a63a51 100644 --- a/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts +++ b/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.ts @@ -76,7 +76,7 @@ describe('LexicalTableCellNode tests', () => { const p = $createParagraphNode(); p.append($createTextNode('abc')); cellNode.append(p); - cellNode.toggleCellDirection(); + cellNode.setCellDirection('vertical-rl'); expect(cellNode.createDOM(editorConfig).outerHTML).toBe( ``, From 4fd91d2d027bfe12702eab250995d3182ab4d567 Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Sun, 1 Sep 2024 10:08:42 +0300 Subject: [PATCH 19/19] rename --- .../src/plugins/TableActionMenuPlugin/index.tsx | 12 +++++------- packages/lexical-table/src/LexicalTableCellNode.ts | 6 +++--- .../src/__tests__/unit/LexicalTableCellNode.test.ts | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx index b79a90ef0cd..fb941f84e3f 100644 --- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx @@ -501,15 +501,13 @@ function TableActionMenu({ [editor], ); - const toggleCellDirection = useCallback(() => { + const toggleWritingMode = useCallback(() => { editor.update(() => { const selection = $getSelection(); if ($isRangeSelection(selection) || $isTableSelection(selection)) { const [cell] = $getNodeTriplet(selection.anchor); - const newDirection = cell.getCellDirection() - ? 'vertical-rl' - : undefined; - cell.setCellDirection(newDirection); + const newDirection = cell.getWritingMode() ? 'vertical-rl' : undefined; + cell.setWritingMode(newDirection); if ($isTableSelection(selection)) { const nodes = selection.getNodes(); @@ -517,7 +515,7 @@ function TableActionMenu({ for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if ($isTableCellNode(node)) { - node.setCellDirection(newDirection); + node.setWritingMode(newDirection); } } } @@ -583,7 +581,7 @@ function TableActionMenu({