@lexical/table 0.29.1-nightly.20250401.0 → 0.29.1-nightly.20250403.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -535,6 +535,10 @@ function $removeTableRowAtIndex(tableNode, indexToDelete) {
535
535
  targetRowNode.remove();
536
536
  return tableNode;
537
537
  }
538
+
539
+ /**
540
+ * @deprecated This function does not support merged cells. Use {@link $insertTableRowAtSelection} or {@link $insertTableRowAtNode} instead.
541
+ */
538
542
  function $insertTableRow(tableNode, targetIndex, shouldInsertAfter = true, rowCount, table) {
539
543
  const tableRows = tableNode.getChildren();
540
544
  if (targetIndex >= tableRows.length || targetIndex < 0) {
@@ -587,7 +591,7 @@ const getHeaderState = (currentState, possibleState) => {
587
591
  * taking into account any spans. If successful, returns the
588
592
  * inserted table row node.
589
593
  */
590
- function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
594
+ function $insertTableRowAtSelection(insertAfter = true) {
591
595
  const selection = lexical.$getSelection();
592
596
  if (!(lexical.$isRangeSelection(selection) || $isTableSelection(selection))) {
593
597
  formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
@@ -596,17 +600,40 @@ function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
596
600
  const focus = selection.focus.getNode();
597
601
  const [anchorCell] = $getNodeTriplet(anchor);
598
602
  const [focusCell,, grid] = $getNodeTriplet(focus);
599
- const [gridMap, focusCellMap, anchorCellMap] = $computeTableMap(grid, focusCell, anchorCell);
600
- const columnCount = gridMap[0].length;
603
+ const [, focusCellMap, anchorCellMap] = $computeTableMap(grid, focusCell, anchorCell);
601
604
  const {
602
605
  startRow: anchorStartRow
603
606
  } = anchorCellMap;
604
607
  const {
605
608
  startRow: focusStartRow
606
609
  } = focusCellMap;
610
+ if (insertAfter) {
611
+ return $insertTableRowAtNode(anchorStartRow + anchorCell.__rowSpan > focusStartRow + focusCell.__rowSpan ? anchorCell : focusCell, true);
612
+ } else {
613
+ return $insertTableRowAtNode(focusStartRow < anchorStartRow ? focusCell : anchorCell, false);
614
+ }
615
+ }
616
+
617
+ /**
618
+ * @deprecated renamed to {@link $insertTableRowAtSelection}
619
+ */
620
+ const $insertTableRow__EXPERIMENTAL = $insertTableRowAtSelection;
621
+
622
+ /**
623
+ * Inserts a table row before or after the given cell node,
624
+ * taking into account any spans. If successful, returns the
625
+ * inserted table row node.
626
+ */
627
+ function $insertTableRowAtNode(cellNode, insertAfter = true) {
628
+ const [,, grid] = $getNodeTriplet(cellNode);
629
+ const [gridMap, cellMap] = $computeTableMap(grid, cellNode, cellNode);
630
+ const columnCount = gridMap[0].length;
631
+ const {
632
+ startRow: cellStartRow
633
+ } = cellMap;
607
634
  let insertedRow = null;
608
635
  if (insertAfter) {
609
- const insertAfterEndRow = Math.max(focusStartRow + focusCell.__rowSpan, anchorStartRow + anchorCell.__rowSpan) - 1;
636
+ const insertAfterEndRow = cellStartRow + cellNode.__rowSpan - 1;
610
637
  const insertAfterEndRowMap = gridMap[insertAfterEndRow];
611
638
  const newRow = $createTableRowNode();
612
639
  for (let i = 0; i < columnCount; i++) {
@@ -630,7 +657,7 @@ function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
630
657
  insertAfterEndRowNode.insertAfter(newRow);
631
658
  insertedRow = newRow;
632
659
  } else {
633
- const insertBeforeStartRow = Math.min(focusStartRow, anchorStartRow);
660
+ const insertBeforeStartRow = cellStartRow;
634
661
  const insertBeforeStartRowMap = gridMap[insertBeforeStartRow];
635
662
  const newRow = $createTableRowNode();
636
663
  for (let i = 0; i < columnCount; i++) {
@@ -656,6 +683,10 @@ function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
656
683
  }
657
684
  return insertedRow;
658
685
  }
686
+
687
+ /**
688
+ * @deprecated This function does not support merged cells. Use {@link $insertTableColumnAtSelection} or {@link $insertTableColumnAtNode} instead.
689
+ */
659
690
  function $insertTableColumn(tableNode, targetIndex, shouldInsertAfter = true, columnCount, table) {
660
691
  const tableRows = tableNode.getChildren();
661
692
  const tableCellsToBeInserted = [];
@@ -706,7 +737,7 @@ function $insertTableColumn(tableNode, targetIndex, shouldInsertAfter = true, co
706
737
  * taking into account any spans. If successful, returns the
707
738
  * first inserted cell node.
708
739
  */
709
- function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
740
+ function $insertTableColumnAtSelection(insertAfter = true) {
710
741
  const selection = lexical.$getSelection();
711
742
  if (!(lexical.$isRangeSelection(selection) || $isTableSelection(selection))) {
712
743
  formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
@@ -715,10 +746,38 @@ function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
715
746
  const focus = selection.focus.getNode();
716
747
  const [anchorCell] = $getNodeTriplet(anchor);
717
748
  const [focusCell,, grid] = $getNodeTriplet(focus);
718
- const [gridMap, focusCellMap, anchorCellMap] = $computeTableMap(grid, focusCell, anchorCell);
749
+ const [, focusCellMap, anchorCellMap] = $computeTableMap(grid, focusCell, anchorCell);
750
+ const {
751
+ startColumn: anchorStartColumn
752
+ } = anchorCellMap;
753
+ const {
754
+ startColumn: focusStartColumn
755
+ } = focusCellMap;
756
+ if (insertAfter) {
757
+ return $insertTableColumnAtNode(anchorStartColumn + anchorCell.__colSpan > focusStartColumn + focusCell.__colSpan ? anchorCell : focusCell, true);
758
+ } else {
759
+ return $insertTableColumnAtNode(focusStartColumn < anchorStartColumn ? focusCell : anchorCell, false);
760
+ }
761
+ }
762
+
763
+ /**
764
+ * @deprecated renamed to {@link $insertTableColumnAtSelection}
765
+ */
766
+ const $insertTableColumn__EXPERIMENTAL = $insertTableColumnAtSelection;
767
+
768
+ /**
769
+ * Inserts a column before or after the given cell node,
770
+ * taking into account any spans. If successful, returns the
771
+ * first inserted cell node.
772
+ */
773
+ function $insertTableColumnAtNode(cellNode, insertAfter = true, shouldSetSelection = true) {
774
+ const [,, grid] = $getNodeTriplet(cellNode);
775
+ const [gridMap, cellMap] = $computeTableMap(grid, cellNode, cellNode);
719
776
  const rowCount = gridMap.length;
720
- const startColumn = insertAfter ? Math.max(focusCellMap.startColumn, anchorCellMap.startColumn) : Math.min(focusCellMap.startColumn, anchorCellMap.startColumn);
721
- const insertAfterColumn = insertAfter ? startColumn + focusCell.__colSpan - 1 : startColumn - 1;
777
+ const {
778
+ startColumn
779
+ } = cellMap;
780
+ const insertAfterColumn = insertAfter ? startColumn + cellNode.__colSpan - 1 : startColumn - 1;
722
781
  const gridFirstChild = grid.getFirstChild();
723
782
  if (!$isTableRowNode(gridFirstChild)) {
724
783
  formatDevErrorMessage(`Expected firstTable child to be a row`);
@@ -775,7 +834,7 @@ function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
775
834
  currentCell.setColSpan(currentCell.__colSpan + 1);
776
835
  }
777
836
  }
778
- if (firstInsertedCell !== null) {
837
+ if (firstInsertedCell !== null && shouldSetSelection) {
779
838
  $moveSelectionToCell(firstInsertedCell);
780
839
  }
781
840
  const colWidths = grid.getColWidths();
@@ -788,6 +847,10 @@ function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
788
847
  }
789
848
  return firstInsertedCell;
790
849
  }
850
+
851
+ /**
852
+ * @deprecated This function does not support merged cells. Use {@link $deleteTableColumnAtSelection} instead.
853
+ */
791
854
  function $deleteTableColumn(tableNode, targetIndex) {
792
855
  const tableRows = tableNode.getChildren();
793
856
  for (let i = 0; i < tableRows.length; i++) {
@@ -802,7 +865,7 @@ function $deleteTableColumn(tableNode, targetIndex) {
802
865
  }
803
866
  return tableNode;
804
867
  }
805
- function $deleteTableRow__EXPERIMENTAL() {
868
+ function $deleteTableRowAtSelection() {
806
869
  const selection = lexical.$getSelection();
807
870
  if (!(lexical.$isRangeSelection(selection) || $isTableSelection(selection))) {
808
871
  formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
@@ -887,7 +950,12 @@ function $deleteTableRow__EXPERIMENTAL() {
887
950
  $moveSelectionToCell(cell);
888
951
  }
889
952
  }
890
- function $deleteTableColumn__EXPERIMENTAL() {
953
+
954
+ /**
955
+ * @deprecated renamed to {@link $deleteTableRowAtSelection}
956
+ */
957
+ const $deleteTableRow__EXPERIMENTAL = $deleteTableRowAtSelection;
958
+ function $deleteTableColumnAtSelection() {
891
959
  const selection = lexical.$getSelection();
892
960
  if (!(lexical.$isRangeSelection(selection) || $isTableSelection(selection))) {
893
961
  formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
@@ -961,6 +1029,11 @@ function $deleteTableColumn__EXPERIMENTAL() {
961
1029
  grid.setColWidths(newColWidths);
962
1030
  }
963
1031
  }
1032
+
1033
+ /**
1034
+ * @deprecated renamed to {@link $deleteTableColumnAtSelection}
1035
+ */
1036
+ const $deleteTableColumn__EXPERIMENTAL = $deleteTableColumnAtSelection;
964
1037
  function $moveSelectionToCell(cell) {
965
1038
  const firstDescendant = cell.getFirstDescendant();
966
1039
  if (firstDescendant == null) {
@@ -977,13 +1050,122 @@ function $insertFirst(parent, node) {
977
1050
  parent.append(node);
978
1051
  }
979
1052
  }
1053
+ function $mergeCells(cellNodes) {
1054
+ if (cellNodes.length === 0) {
1055
+ return null;
1056
+ }
1057
+
1058
+ // Find the table node
1059
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(cellNodes[0]);
1060
+ const [gridMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
1061
+
1062
+ // Find the boundaries of the selection including merged cells
1063
+ let minRow = Infinity;
1064
+ let maxRow = -Infinity;
1065
+ let minCol = Infinity;
1066
+ let maxCol = -Infinity;
1067
+
1068
+ // First pass: find the actual boundaries considering merged cells
1069
+ const processedCells = new Set();
1070
+ for (const row of gridMap) {
1071
+ for (const mapCell of row) {
1072
+ if (!mapCell || !mapCell.cell) {
1073
+ continue;
1074
+ }
1075
+ const cellKey = mapCell.cell.getKey();
1076
+ if (processedCells.has(cellKey)) {
1077
+ continue;
1078
+ }
1079
+ if (cellNodes.some(cell => cell.is(mapCell.cell))) {
1080
+ processedCells.add(cellKey);
1081
+ // Get the actual position of this cell in the grid
1082
+ const cellStartRow = mapCell.startRow;
1083
+ const cellStartCol = mapCell.startColumn;
1084
+ const cellRowSpan = mapCell.cell.__rowSpan || 1;
1085
+ const cellColSpan = mapCell.cell.__colSpan || 1;
1086
+
1087
+ // Update boundaries considering the cell's actual position and span
1088
+ minRow = Math.min(minRow, cellStartRow);
1089
+ maxRow = Math.max(maxRow, cellStartRow + cellRowSpan - 1);
1090
+ minCol = Math.min(minCol, cellStartCol);
1091
+ maxCol = Math.max(maxCol, cellStartCol + cellColSpan - 1);
1092
+ }
1093
+ }
1094
+ }
1095
+
1096
+ // Validate boundaries
1097
+ if (minRow === Infinity || minCol === Infinity) {
1098
+ return null;
1099
+ }
1100
+
1101
+ // The total span of the merged cell
1102
+ const totalRowSpan = maxRow - minRow + 1;
1103
+ const totalColSpan = maxCol - minCol + 1;
1104
+
1105
+ // Use the top-left cell as the target cell
1106
+ const targetCellMap = gridMap[minRow][minCol];
1107
+ if (!targetCellMap.cell) {
1108
+ return null;
1109
+ }
1110
+ const targetCell = targetCellMap.cell;
1111
+
1112
+ // Set the spans for the target cell
1113
+ targetCell.setColSpan(totalColSpan);
1114
+ targetCell.setRowSpan(totalRowSpan);
1115
+
1116
+ // Move content from other cells to the target cell
1117
+ const seenCells = new Set([targetCell.getKey()]);
1118
+
1119
+ // Second pass: merge content and remove other cells
1120
+ for (let row = minRow; row <= maxRow; row++) {
1121
+ for (let col = minCol; col <= maxCol; col++) {
1122
+ const mapCell = gridMap[row][col];
1123
+ if (!mapCell.cell) {
1124
+ continue;
1125
+ }
1126
+ const currentCell = mapCell.cell;
1127
+ const key = currentCell.getKey();
1128
+ if (!seenCells.has(key)) {
1129
+ seenCells.add(key);
1130
+ const isEmpty = $cellContainsEmptyParagraph(currentCell);
1131
+ if (!isEmpty) {
1132
+ targetCell.append(...currentCell.getChildren());
1133
+ }
1134
+ currentCell.remove();
1135
+ }
1136
+ }
1137
+ }
1138
+
1139
+ // Ensure target cell has content
1140
+ if (targetCell.getChildrenSize() === 0) {
1141
+ targetCell.append(lexical.$createParagraphNode());
1142
+ }
1143
+ return targetCell;
1144
+ }
1145
+ function $cellContainsEmptyParagraph(cell) {
1146
+ if (cell.getChildrenSize() !== 1) {
1147
+ return false;
1148
+ }
1149
+ const firstChild = cell.getFirstChildOrThrow();
1150
+ if (!lexical.$isParagraphNode(firstChild) || !firstChild.isEmpty()) {
1151
+ return false;
1152
+ }
1153
+ return true;
1154
+ }
980
1155
  function $unmergeCell() {
981
1156
  const selection = lexical.$getSelection();
982
1157
  if (!(lexical.$isRangeSelection(selection) || $isTableSelection(selection))) {
983
1158
  formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
984
1159
  }
985
1160
  const anchor = selection.anchor.getNode();
986
- const [cell, row, grid] = $getNodeTriplet(anchor);
1161
+ const cellNode = utils.$findMatchingParent(anchor, $isTableCellNode);
1162
+ if (!$isTableCellNode(cellNode)) {
1163
+ formatDevErrorMessage(`Expected to find a parent TableCellNode`);
1164
+ }
1165
+ return $unmergeCellNode(cellNode);
1166
+ }
1167
+ function $unmergeCellNode(cellNode) {
1168
+ const [cell, row, grid] = $getNodeTriplet(cellNode);
987
1169
  const colSpan = cell.__colSpan;
988
1170
  const rowSpan = cell.__rowSpan;
989
1171
  if (colSpan === 1 && rowSpan === 1) {
@@ -2285,62 +2467,115 @@ function applyTableHandlers(tableNode, element, editor, hasTabHandler) {
2285
2467
  if (nodes.length !== 1 || !$isTableNode(nodes[0]) || !isSelectionInsideOfGrid || anchorAndFocus === null) {
2286
2468
  return false;
2287
2469
  }
2288
- const [anchor] = anchorAndFocus;
2289
- const newGrid = nodes[0];
2290
- const newGridRows = newGrid.getChildren();
2291
- const newColumnCount = newGrid.getFirstChildOrThrow().getChildrenSize();
2292
- const newRowCount = newGrid.getChildrenSize();
2293
- const gridCellNode = utils.$findMatchingParent(anchor.getNode(), n => $isTableCellNode(n));
2294
- const gridRowNode = gridCellNode && utils.$findMatchingParent(gridCellNode, n => $isTableRowNode(n));
2295
- const gridNode = gridRowNode && utils.$findMatchingParent(gridRowNode, n => $isTableNode(n));
2296
- if (!$isTableCellNode(gridCellNode) || !$isTableRowNode(gridRowNode) || !$isTableNode(gridNode)) {
2470
+ const [anchor, focus] = anchorAndFocus;
2471
+ const [anchorCellNode, anchorRowNode, gridNode] = $getNodeTriplet(anchor);
2472
+ const focusCellNode = utils.$findMatchingParent(focus.getNode(), n => $isTableCellNode(n));
2473
+ if (!$isTableCellNode(anchorCellNode) || !$isTableCellNode(focusCellNode) || !$isTableRowNode(anchorRowNode) || !$isTableNode(gridNode)) {
2297
2474
  return false;
2298
2475
  }
2299
- const startY = gridRowNode.getIndexWithinParent();
2300
- const stopY = Math.min(gridNode.getChildrenSize() - 1, startY + newRowCount - 1);
2301
- const startX = gridCellNode.getIndexWithinParent();
2302
- const stopX = Math.min(gridRowNode.getChildrenSize() - 1, startX + newColumnCount - 1);
2303
- const fromX = Math.min(startX, stopX);
2304
- const fromY = Math.min(startY, stopY);
2305
- const toX = Math.max(startX, stopX);
2306
- const toY = Math.max(startY, stopY);
2307
- const gridRowNodes = gridNode.getChildren();
2308
- let newRowIdx = 0;
2309
- for (let r = fromY; r <= toY; r++) {
2310
- const currentGridRowNode = gridRowNodes[r];
2311
- if (!$isTableRowNode(currentGridRowNode)) {
2312
- return false;
2313
- }
2314
- const newGridRowNode = newGridRows[newRowIdx];
2315
- if (!$isTableRowNode(newGridRowNode)) {
2316
- return false;
2476
+ const templateGrid = nodes[0];
2477
+ const [initialGridMap, anchorCellMap, focusCellMap] = $computeTableMap(gridNode, anchorCellNode, focusCellNode);
2478
+ const [templateGridMap] = $computeTableMapSkipCellCheck(templateGrid, null, null);
2479
+ const initialRowCount = initialGridMap.length;
2480
+ const initialColCount = initialRowCount > 0 ? initialGridMap[0].length : 0;
2481
+
2482
+ // If we have a range selection, we'll fit the template grid into the
2483
+ // table, growing the table if necessary.
2484
+ let startRow = anchorCellMap.startRow;
2485
+ let startCol = anchorCellMap.startColumn;
2486
+ let affectedRowCount = templateGridMap.length;
2487
+ let affectedColCount = affectedRowCount > 0 ? templateGridMap[0].length : 0;
2488
+ if (isTableSelection) {
2489
+ // If we have a table selection, we'll only modify the cells within
2490
+ // the selection boundary.
2491
+ const selectionBoundary = $computeTableCellRectBoundary(initialGridMap, anchorCellMap, focusCellMap);
2492
+ const selectionRowCount = selectionBoundary.maxRow - selectionBoundary.minRow + 1;
2493
+ const selectionColCount = selectionBoundary.maxColumn - selectionBoundary.minColumn + 1;
2494
+ startRow = selectionBoundary.minRow;
2495
+ startCol = selectionBoundary.minColumn;
2496
+ affectedRowCount = Math.min(affectedRowCount, selectionRowCount);
2497
+ affectedColCount = Math.min(affectedColCount, selectionColCount);
2498
+ }
2499
+
2500
+ // Step 1: Unmerge all merged cells within the affected area
2501
+ let didPerformMergeOperations = false;
2502
+ const lastRowForUnmerge = Math.min(initialRowCount, startRow + affectedRowCount) - 1;
2503
+ const lastColForUnmerge = Math.min(initialColCount, startCol + affectedColCount) - 1;
2504
+ const unmergedKeys = new Set();
2505
+ for (let row = startRow; row <= lastRowForUnmerge; row++) {
2506
+ for (let col = startCol; col <= lastColForUnmerge; col++) {
2507
+ const cellMap = initialGridMap[row][col];
2508
+ if (unmergedKeys.has(cellMap.cell.getKey())) {
2509
+ continue; // cell was a merged cell that was already handled
2510
+ }
2511
+ if (cellMap.cell.__rowSpan === 1 && cellMap.cell.__colSpan === 1) {
2512
+ continue; // cell is not a merged cell
2513
+ }
2514
+ $unmergeCellNode(cellMap.cell);
2515
+ unmergedKeys.add(cellMap.cell.getKey());
2516
+ didPerformMergeOperations = true;
2317
2517
  }
2318
- const gridCellNodes = currentGridRowNode.getChildren();
2319
- const newGridCellNodes = newGridRowNode.getChildren();
2320
- let newColumnIdx = 0;
2321
- for (let c = fromX; c <= toX; c++) {
2322
- const currentGridCellNode = gridCellNodes[c];
2323
- if (!$isTableCellNode(currentGridCellNode)) {
2324
- return false;
2518
+ }
2519
+ let [interimGridMap] = $computeTableMapSkipCellCheck(gridNode.getWritable(), null, null);
2520
+
2521
+ // Step 2: Expand current table (if needed)
2522
+ const rowsToInsert = affectedRowCount - initialRowCount + startRow;
2523
+ for (let i = 0; i < rowsToInsert; i++) {
2524
+ const cellMap = interimGridMap[initialRowCount - 1][0];
2525
+ $insertTableRowAtNode(cellMap.cell);
2526
+ }
2527
+ const colsToInsert = affectedColCount - initialColCount + startCol;
2528
+ for (let i = 0; i < colsToInsert; i++) {
2529
+ const cellMap = interimGridMap[0][initialColCount - 1];
2530
+ $insertTableColumnAtNode(cellMap.cell, true, false);
2531
+ }
2532
+ [interimGridMap] = $computeTableMapSkipCellCheck(gridNode.getWritable(), null, null);
2533
+
2534
+ // Step 3: Merge cells and set cell content, to match template grid
2535
+ for (let row = startRow; row < startRow + affectedRowCount; row++) {
2536
+ for (let col = startCol; col < startCol + affectedColCount; col++) {
2537
+ const templateRow = row - startRow;
2538
+ const templateCol = col - startCol;
2539
+ const templateCellMap = templateGridMap[templateRow][templateCol];
2540
+ if (templateCellMap.startRow !== templateRow || templateCellMap.startColumn !== templateCol) {
2541
+ continue; // cell is a merged cell that was already handled
2325
2542
  }
2326
- const newGridCellNode = newGridCellNodes[newColumnIdx];
2327
- if (!$isTableCellNode(newGridCellNode)) {
2328
- return false;
2543
+ const templateCell = templateCellMap.cell;
2544
+ if (templateCell.__rowSpan !== 1 || templateCell.__colSpan !== 1) {
2545
+ const cellsToMerge = [];
2546
+ const lastRowForMerge = Math.min(row + templateCell.__rowSpan, startRow + affectedRowCount) - 1;
2547
+ const lastColForMerge = Math.min(col + templateCell.__colSpan, startCol + affectedColCount) - 1;
2548
+ for (let r = row; r <= lastRowForMerge; r++) {
2549
+ for (let c = col; c <= lastColForMerge; c++) {
2550
+ const cellMap = interimGridMap[r][c];
2551
+ cellsToMerge.push(cellMap.cell);
2552
+ }
2553
+ }
2554
+ $mergeCells(cellsToMerge);
2555
+ didPerformMergeOperations = true;
2329
2556
  }
2330
- const originalChildren = currentGridCellNode.getChildren();
2331
- newGridCellNode.getChildren().forEach(child => {
2557
+ const {
2558
+ cell
2559
+ } = interimGridMap[row][col];
2560
+ const originalChildren = cell.getChildren();
2561
+ templateCell.getChildren().forEach(child => {
2332
2562
  if (lexical.$isTextNode(child)) {
2333
2563
  const paragraphNode = lexical.$createParagraphNode();
2334
2564
  paragraphNode.append(child);
2335
- currentGridCellNode.append(child);
2565
+ cell.append(child);
2336
2566
  } else {
2337
- currentGridCellNode.append(child);
2567
+ cell.append(child);
2338
2568
  }
2339
2569
  });
2340
2570
  originalChildren.forEach(n => n.remove());
2341
- newColumnIdx++;
2342
2571
  }
2343
- newRowIdx++;
2572
+ }
2573
+ if (isTableSelection && didPerformMergeOperations) {
2574
+ // reset the table selection in case the anchor or focus cell was
2575
+ // removed via merge operations
2576
+ const [finalGridMap] = $computeTableMapSkipCellCheck(gridNode.getWritable(), null, null);
2577
+ const newAnchorCellMap = finalGridMap[anchorCellMap.startRow][anchorCellMap.startColumn];
2578
+ newAnchorCellMap.cell.selectEnd();
2344
2579
  }
2345
2580
  return true;
2346
2581
  }, lexical.COMMAND_PRIORITY_CRITICAL));
@@ -3900,7 +4135,9 @@ exports.$createTableRowNode = $createTableRowNode;
3900
4135
  exports.$createTableSelection = $createTableSelection;
3901
4136
  exports.$createTableSelectionFrom = $createTableSelectionFrom;
3902
4137
  exports.$deleteTableColumn = $deleteTableColumn;
4138
+ exports.$deleteTableColumnAtSelection = $deleteTableColumnAtSelection;
3903
4139
  exports.$deleteTableColumn__EXPERIMENTAL = $deleteTableColumn__EXPERIMENTAL;
4140
+ exports.$deleteTableRowAtSelection = $deleteTableRowAtSelection;
3904
4141
  exports.$deleteTableRow__EXPERIMENTAL = $deleteTableRow__EXPERIMENTAL;
3905
4142
  exports.$findCellNode = $findCellNode;
3906
4143
  exports.$findTableNode = $findTableNode;
@@ -3914,14 +4151,17 @@ exports.$getTableNodeFromLexicalNodeOrThrow = $getTableNodeFromLexicalNodeOrThro
3914
4151
  exports.$getTableRowIndexFromTableCellNode = $getTableRowIndexFromTableCellNode;
3915
4152
  exports.$getTableRowNodeFromTableCellNodeOrThrow = $getTableRowNodeFromTableCellNodeOrThrow;
3916
4153
  exports.$insertTableColumn = $insertTableColumn;
4154
+ exports.$insertTableColumnAtSelection = $insertTableColumnAtSelection;
3917
4155
  exports.$insertTableColumn__EXPERIMENTAL = $insertTableColumn__EXPERIMENTAL;
3918
4156
  exports.$insertTableRow = $insertTableRow;
4157
+ exports.$insertTableRowAtSelection = $insertTableRowAtSelection;
3919
4158
  exports.$insertTableRow__EXPERIMENTAL = $insertTableRow__EXPERIMENTAL;
3920
4159
  exports.$isScrollableTablesActive = $isScrollableTablesActive;
3921
4160
  exports.$isTableCellNode = $isTableCellNode;
3922
4161
  exports.$isTableNode = $isTableNode;
3923
4162
  exports.$isTableRowNode = $isTableRowNode;
3924
4163
  exports.$isTableSelection = $isTableSelection;
4164
+ exports.$mergeCells = $mergeCells;
3925
4165
  exports.$removeTableRowAtIndex = $removeTableRowAtIndex;
3926
4166
  exports.$unmergeCell = $unmergeCell;
3927
4167
  exports.INSERT_TABLE_COMMAND = INSERT_TABLE_COMMAND;