@lexical/table 0.26.0 → 0.27.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.
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { addClassNamesToElement, $descendantsMatching, $findMatchingParent, removeClassNamesFromElement, objectKlassEquals, isHTMLElement as isHTMLElement$1, $insertFirst as $insertFirst$1, mergeRegister, $insertNodeToNearestRoot, $unwrapAndFilterDescendants } from '@lexical/utils';
10
- import { ElementNode, isHTMLElement, $createParagraphNode, $isElementNode, $isLineBreakNode, $isTextNode, $applyNodeReplacement, createCommand, $createTextNode, $getSelection, $isRangeSelection, $createPoint, $isParagraphNode, $normalizeSelection__EXPERIMENTAL, isCurrentlyReadOnlyMode, TEXT_TYPE_TO_FORMAT, $getNodeByKey, $getEditor, $setSelection, SELECTION_CHANGE_COMMAND, getDOMSelection, $createRangeSelection, $isRootNode, INSERT_PARAGRAPH_COMMAND, COMMAND_PRIORITY_HIGH, KEY_ESCAPE_COMMAND, COMMAND_PRIORITY_CRITICAL, CUT_COMMAND, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, CONTROLLED_TEXT_INSERTION_COMMAND, KEY_TAB_COMMAND, FOCUS_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, $getPreviousSelection, $getNearestNodeFromDOMNode, $createRangeSelectionFromDom, $isRootOrShadowRoot, $isDecoratorNode, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, DELETE_WORD_COMMAND, DELETE_LINE_COMMAND, DELETE_CHARACTER_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, isDOMNode, setDOMUnmanaged, COMMAND_PRIORITY_EDITOR, CLICK_COMMAND } from 'lexical';
10
+ import { ElementNode, isHTMLElement, $createParagraphNode, $isElementNode, $isLineBreakNode, $isTextNode, $applyNodeReplacement, createCommand, $createTextNode, $getSelection, $isRangeSelection, $createPoint, $isParagraphNode, $normalizeSelection__EXPERIMENTAL, isCurrentlyReadOnlyMode, TEXT_TYPE_TO_FORMAT, $getNodeByKey, $getEditor, $setSelection, SELECTION_CHANGE_COMMAND, getDOMSelection, $createRangeSelection, $isRootNode, INSERT_PARAGRAPH_COMMAND, COMMAND_PRIORITY_HIGH, KEY_ESCAPE_COMMAND, COMMAND_PRIORITY_CRITICAL, CUT_COMMAND, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, CONTROLLED_TEXT_INSERTION_COMMAND, KEY_TAB_COMMAND, FOCUS_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, $getPreviousSelection, $getNearestNodeFromDOMNode, $createRangeSelectionFromDom, $isRootOrShadowRoot, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, DELETE_WORD_COMMAND, DELETE_LINE_COMMAND, DELETE_CHARACTER_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, isDOMNode, $caretFromPoint, $isExtendableTextPointCaret, $extendCaretToRange, $isSiblingCaret, $getSiblingCaret, $setPointFromCaret, $normalizeCaret, $getAdjacentChildCaret, $isChildCaret, $getChildCaret, setDOMUnmanaged, COMMAND_PRIORITY_EDITOR, CLICK_COMMAND } from 'lexical';
11
11
  import { copyToClipboard, $getClipboardDataFromSelection } from '@lexical/clipboard';
12
12
 
13
13
  /**
@@ -89,6 +89,7 @@ class TableCellNode extends ElementNode {
89
89
  this.__headerState = headerState;
90
90
  this.__width = width;
91
91
  this.__backgroundColor = null;
92
+ this.__verticalAlign = undefined;
92
93
  }
93
94
  createDOM(config) {
94
95
  const element = document.createElement(this.getTag());
@@ -304,6 +305,20 @@ function $isTableCellNode(node) {
304
305
 
305
306
  const INSERT_TABLE_COMMAND = createCommand('INSERT_TABLE_COMMAND');
306
307
 
308
+ /**
309
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
310
+ *
311
+ * This source code is licensed under the MIT license found in the
312
+ * LICENSE file in the root directory of this source tree.
313
+ *
314
+ */
315
+
316
+ // Do not require this module directly! Use normal `invariant` calls.
317
+
318
+ function formatDevErrorMessage(message) {
319
+ throw new Error(message);
320
+ }
321
+
307
322
  /**
308
323
  * Copyright (c) Meta Platforms, Inc. and affiliates.
309
324
  *
@@ -421,14 +436,6 @@ const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.docume
421
436
  const IS_FIREFOX = CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
422
437
  CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
423
438
 
424
- /**
425
- * Copyright (c) Meta Platforms, Inc. and affiliates.
426
- *
427
- * This source code is licensed under the MIT license found in the
428
- * LICENSE file in the root directory of this source tree.
429
- *
430
- */
431
-
432
439
  function $createTableNodeWithDimensions(rowCount, columnCount, includeHeaders = true) {
433
440
  const tableNode = $createTableNode();
434
441
  for (let iRow = 0; iRow < rowCount; iRow++) {
@@ -526,7 +533,7 @@ function $insertTableRow(tableNode, targetIndex, shouldInsertAfter = true, rowCo
526
533
  for (let c = 0; c < tableColumnCount; c++) {
527
534
  const tableCellFromTargetRow = tableRowCells[c];
528
535
  if (!$isTableCellNode(tableCellFromTargetRow)) {
529
- throw Error(`Expected table cell`);
536
+ formatDevErrorMessage(`Expected table cell`);
530
537
  }
531
538
  const {
532
539
  above,
@@ -567,7 +574,7 @@ const getHeaderState = (currentState, possibleState) => {
567
574
  function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
568
575
  const selection = $getSelection();
569
576
  if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
570
- throw Error(`Expected a RangeSelection or TableSelection`);
577
+ formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
571
578
  }
572
579
  const anchor = selection.anchor.getNode();
573
580
  const focus = selection.focus.getNode();
@@ -602,7 +609,7 @@ function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
602
609
  }
603
610
  const insertAfterEndRowNode = grid.getChildAtIndex(insertAfterEndRow);
604
611
  if (!$isTableRowNode(insertAfterEndRowNode)) {
605
- throw Error(`insertAfterEndRow is not a TableRowNode`);
612
+ formatDevErrorMessage(`insertAfterEndRow is not a TableRowNode`);
606
613
  }
607
614
  insertAfterEndRowNode.insertAfter(newRow);
608
615
  insertedRow = newRow;
@@ -626,7 +633,7 @@ function $insertTableRow__EXPERIMENTAL(insertAfter = true) {
626
633
  }
627
634
  const insertBeforeStartRowNode = grid.getChildAtIndex(insertBeforeStartRow);
628
635
  if (!$isTableRowNode(insertBeforeStartRowNode)) {
629
- throw Error(`insertBeforeStartRow is not a TableRowNode`);
636
+ formatDevErrorMessage(`insertBeforeStartRow is not a TableRowNode`);
630
637
  }
631
638
  insertBeforeStartRowNode.insertBefore(newRow);
632
639
  insertedRow = newRow;
@@ -646,7 +653,7 @@ function $insertTableColumn(tableNode, targetIndex, shouldInsertAfter = true, co
646
653
  }
647
654
  const targetCell = tableRowChildren[targetIndex];
648
655
  if (!$isTableCellNode(targetCell)) {
649
- throw Error(`Expected table cell`);
656
+ formatDevErrorMessage(`Expected table cell`);
650
657
  }
651
658
  const {
652
659
  left,
@@ -686,7 +693,7 @@ function $insertTableColumn(tableNode, targetIndex, shouldInsertAfter = true, co
686
693
  function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
687
694
  const selection = $getSelection();
688
695
  if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
689
- throw Error(`Expected a RangeSelection or TableSelection`);
696
+ formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
690
697
  }
691
698
  const anchor = selection.anchor.getNode();
692
699
  const focus = selection.focus.getNode();
@@ -698,7 +705,7 @@ function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
698
705
  const insertAfterColumn = insertAfter ? startColumn + focusCell.__colSpan - 1 : startColumn - 1;
699
706
  const gridFirstChild = grid.getFirstChild();
700
707
  if (!$isTableRowNode(gridFirstChild)) {
701
- throw Error(`Expected firstTable child to be a row`);
708
+ formatDevErrorMessage(`Expected firstTable child to be a row`);
702
709
  }
703
710
  let firstInsertedCell = null;
704
711
  function $createTableCellNodeForInsertTableColumn(headerState = TableCellHeaderStates.NO_STATUS) {
@@ -713,7 +720,7 @@ function $insertTableColumn__EXPERIMENTAL(insertAfter = true) {
713
720
  if (i !== 0) {
714
721
  const currentRow = loopRow.getNextSibling();
715
722
  if (!$isTableRowNode(currentRow)) {
716
- throw Error(`Expected row nextSibling to be a row`);
723
+ formatDevErrorMessage(`Expected row nextSibling to be a row`);
717
724
  }
718
725
  loopRow = currentRow;
719
726
  }
@@ -782,7 +789,7 @@ function $deleteTableColumn(tableNode, targetIndex) {
782
789
  function $deleteTableRow__EXPERIMENTAL() {
783
790
  const selection = $getSelection();
784
791
  if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
785
- throw Error(`Expected a RangeSelection or TableSelection`);
792
+ formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
786
793
  }
787
794
  const [anchor, focus] = selection.isBackward() ? [selection.focus.getNode(), selection.anchor.getNode()] : [selection.anchor.getNode(), selection.focus.getNode()];
788
795
  const [anchorCell,, grid] = $getNodeTriplet(anchor);
@@ -824,7 +831,7 @@ function $deleteTableRow__EXPERIMENTAL() {
824
831
  if (cellStartRow >= anchorStartRow && cellStartRow + cell.__rowSpan - 1 > focusEndRow) {
825
832
  cell.setRowSpan(cell.__rowSpan - (focusEndRow - cellStartRow + 1));
826
833
  if (!(nextRowNode !== null)) {
827
- throw Error(`Expected nextRowNode not to be null`);
834
+ formatDevErrorMessage(`Expected nextRowNode not to be null`);
828
835
  }
829
836
  let insertAfterCell = null;
830
837
  for (let columnIndex = 0; columnIndex < column; columnIndex++) {
@@ -847,7 +854,7 @@ function $deleteTableRow__EXPERIMENTAL() {
847
854
  }
848
855
  const rowNode = grid.getChildAtIndex(row);
849
856
  if (!$isTableRowNode(rowNode)) {
850
- throw Error(`Expected TableNode childAtIndex(${String(row)}) to be RowNode`);
857
+ formatDevErrorMessage(`Expected TableNode childAtIndex(${String(row)}) to be RowNode`);
851
858
  }
852
859
  rowNode.remove();
853
860
  }
@@ -867,7 +874,7 @@ function $deleteTableRow__EXPERIMENTAL() {
867
874
  function $deleteTableColumn__EXPERIMENTAL() {
868
875
  const selection = $getSelection();
869
876
  if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
870
- throw Error(`Expected a RangeSelection or TableSelection`);
877
+ formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
871
878
  }
872
879
  const anchor = selection.anchor.getNode();
873
880
  const focus = selection.focus.getNode();
@@ -957,7 +964,7 @@ function $insertFirst(parent, node) {
957
964
  function $unmergeCell() {
958
965
  const selection = $getSelection();
959
966
  if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
960
- throw Error(`Expected a RangeSelection or TableSelection`);
967
+ formatDevErrorMessage(`Expected a RangeSelection or TableSelection`);
961
968
  }
962
969
  const anchor = selection.anchor.getNode();
963
970
  const [cell, row, grid] = $getNodeTriplet(anchor);
@@ -1007,7 +1014,7 @@ function $unmergeCell() {
1007
1014
  const currentRowMap = map[currentRow];
1008
1015
  currentRowNode = (currentRowNode || row).getNextSibling();
1009
1016
  if (!$isTableRowNode(currentRowNode)) {
1010
- throw Error(`Expected row next sibling to be a row`);
1017
+ formatDevErrorMessage(`Expected row next sibling to be a row`);
1011
1018
  }
1012
1019
  let insertAfterCell = null;
1013
1020
  for (let column = 0; column < startColumn; column++) {
@@ -1036,10 +1043,10 @@ function $unmergeCell() {
1036
1043
  function $computeTableMap(tableNode, cellA, cellB) {
1037
1044
  const [tableMap, cellAValue, cellBValue] = $computeTableMapSkipCellCheck(tableNode, cellA, cellB);
1038
1045
  if (!(cellAValue !== null)) {
1039
- throw Error(`Anchor not found in Table`);
1046
+ formatDevErrorMessage(`Anchor not found in Table`);
1040
1047
  }
1041
1048
  if (!(cellBValue !== null)) {
1042
- throw Error(`Focus not found in Table`);
1049
+ formatDevErrorMessage(`Focus not found in Table`);
1043
1050
  }
1044
1051
  return [tableMap, cellAValue, cellBValue];
1045
1052
  }
@@ -1058,12 +1065,12 @@ function $computeTableMapSkipCellCheck(tableNode, cellA, cellB) {
1058
1065
  for (let rowIdx = 0; rowIdx < gridChildren.length; rowIdx++) {
1059
1066
  const row = gridChildren[rowIdx];
1060
1067
  if (!$isTableRowNode(row)) {
1061
- throw Error(`Expected TableNode children to be TableRowNode`);
1068
+ formatDevErrorMessage(`Expected TableNode children to be TableRowNode`);
1062
1069
  }
1063
1070
  const startMapRow = getMapRow(rowIdx);
1064
1071
  for (let cell = row.getFirstChild(), colIdx = 0; cell != null; cell = cell.getNextSibling()) {
1065
1072
  if (!$isTableCellNode(cell)) {
1066
- throw Error(`Expected TableRowNode children to be TableCellNode`);
1073
+ formatDevErrorMessage(`Expected TableRowNode children to be TableCellNode`);
1067
1074
  } // Skip past any columns that were merged from a higher row
1068
1075
  while (startMapRow[colIdx] !== undefined) {
1069
1076
  colIdx++;
@@ -1110,23 +1117,23 @@ function $getNodeTriplet(source) {
1110
1117
  } else if ('__type' in source) {
1111
1118
  const cell_ = $findMatchingParent(source, $isTableCellNode);
1112
1119
  if (!$isTableCellNode(cell_)) {
1113
- throw Error(`Expected to find a parent TableCellNode`);
1120
+ formatDevErrorMessage(`Expected to find a parent TableCellNode`);
1114
1121
  }
1115
1122
  cell = cell_;
1116
1123
  } else {
1117
1124
  const cell_ = $findMatchingParent(source.getNode(), $isTableCellNode);
1118
1125
  if (!$isTableCellNode(cell_)) {
1119
- throw Error(`Expected to find a parent TableCellNode`);
1126
+ formatDevErrorMessage(`Expected to find a parent TableCellNode`);
1120
1127
  }
1121
1128
  cell = cell_;
1122
1129
  }
1123
1130
  const row = cell.getParent();
1124
1131
  if (!$isTableRowNode(row)) {
1125
- throw Error(`Expected TableCellNode to have a parent TableRowNode`);
1132
+ formatDevErrorMessage(`Expected TableCellNode to have a parent TableRowNode`);
1126
1133
  }
1127
1134
  const grid = row.getParent();
1128
1135
  if (!$isTableNode(grid)) {
1129
- throw Error(`Expected TableRowNode to have a parent TableNode`);
1136
+ formatDevErrorMessage(`Expected TableRowNode to have a parent TableNode`);
1130
1137
  }
1131
1138
  return [cell, row, grid];
1132
1139
  }
@@ -1257,34 +1264,26 @@ function $getTableCellNodeRect(tableCellNode) {
1257
1264
  return null;
1258
1265
  }
1259
1266
 
1260
- /**
1261
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1262
- *
1263
- * This source code is licensed under the MIT license found in the
1264
- * LICENSE file in the root directory of this source tree.
1265
- *
1266
- */
1267
-
1268
1267
  function $getCellNodes(tableSelection) {
1269
1268
  const [[anchorNode, anchorCell, anchorRow, anchorTable], [focusNode, focusCell, focusRow, focusTable]] = ['anchor', 'focus'].map(k => {
1270
1269
  const node = tableSelection[k].getNode();
1271
1270
  const cellNode = $findMatchingParent(node, $isTableCellNode);
1272
1271
  if (!$isTableCellNode(cellNode)) {
1273
- throw Error(`Expected TableSelection ${k} to be (or a child of) TableCellNode, got key ${node.getKey()} of type ${node.getType()}`);
1272
+ formatDevErrorMessage(`Expected TableSelection ${k} to be (or a child of) TableCellNode, got key ${node.getKey()} of type ${node.getType()}`);
1274
1273
  }
1275
1274
  const rowNode = cellNode.getParent();
1276
1275
  if (!$isTableRowNode(rowNode)) {
1277
- throw Error(`Expected TableSelection ${k} cell parent to be a TableRowNode`);
1276
+ formatDevErrorMessage(`Expected TableSelection ${k} cell parent to be a TableRowNode`);
1278
1277
  }
1279
1278
  const tableNode = rowNode.getParent();
1280
1279
  if (!$isTableNode(tableNode)) {
1281
- throw Error(`Expected TableSelection ${k} row parent to be a TableNode`);
1280
+ formatDevErrorMessage(`Expected TableSelection ${k} row parent to be a TableNode`);
1282
1281
  }
1283
1282
  return [node, cellNode, rowNode, tableNode];
1284
1283
  });
1285
1284
  // TODO: nested tables may violate this
1286
1285
  if (!anchorTable.is(focusTable)) {
1287
- throw Error(`Expected TableSelection anchor and focus to be in the same table`);
1286
+ formatDevErrorMessage(`Expected TableSelection anchor and focus to be in the same table`);
1288
1287
  }
1289
1288
  return {
1290
1289
  anchorCell,
@@ -1385,7 +1384,7 @@ class TableSelection {
1385
1384
  insertNodes(nodes) {
1386
1385
  const focusNode = this.focus.getNode();
1387
1386
  if (!$isElementNode(focusNode)) {
1388
- throw Error(`Expected TableSelection focus to be an ElementNode`);
1387
+ formatDevErrorMessage(`Expected TableSelection focus to be an ElementNode`);
1389
1388
  }
1390
1389
  const selection = $normalizeSelection__EXPERIMENTAL(focusNode.select(0, focusNode.getChildrenSize()));
1391
1390
  selection.insertNodes(nodes);
@@ -1399,11 +1398,11 @@ class TableSelection {
1399
1398
  } = $getCellNodes(this);
1400
1399
  const anchorCellNodeRect = $getTableCellNodeRect(anchorCell);
1401
1400
  if (!(anchorCellNodeRect !== null)) {
1402
- throw Error(`getCellRect: expected to find AnchorNode`);
1401
+ formatDevErrorMessage(`getCellRect: expected to find AnchorNode`);
1403
1402
  }
1404
1403
  const focusCellNodeRect = $getTableCellNodeRect(focusCell);
1405
1404
  if (!(focusCellNodeRect !== null)) {
1406
- throw Error(`getCellRect: expected to find focusCellNode`);
1405
+ formatDevErrorMessage(`getCellRect: expected to find focusCellNode`);
1407
1406
  }
1408
1407
  const startX = Math.min(anchorCellNodeRect.columnIndex, focusCellNodeRect.columnIndex);
1409
1408
  const stopX = Math.max(anchorCellNodeRect.columnIndex + anchorCellNodeRect.colSpan - 1, focusCellNodeRect.columnIndex + focusCellNodeRect.colSpan - 1);
@@ -1435,14 +1434,14 @@ class TableSelection {
1435
1434
  // focus is on higher Grid level than anchor
1436
1435
  const gridParent = tableNode.getParent();
1437
1436
  if (!(gridParent != null)) {
1438
- throw Error(`Expected gridParent to have a parent`);
1437
+ formatDevErrorMessage(`Expected gridParent to have a parent`);
1439
1438
  }
1440
1439
  this.set(this.tableKey, gridParent.getKey(), focusCell.getKey());
1441
1440
  } else {
1442
1441
  // anchor is on higher Grid level than focus
1443
1442
  const focusCellParent = focusCellGrid.getParent();
1444
1443
  if (!(focusCellParent != null)) {
1445
- throw Error(`Expected focusCellParent to have a parent`);
1444
+ formatDevErrorMessage(`Expected focusCellParent to have a parent`);
1446
1445
  }
1447
1446
  this.set(this.tableKey, focusCell.getKey(), focusCellParent.getKey());
1448
1447
  }
@@ -1472,7 +1471,7 @@ class TableSelection {
1472
1471
  } = map[i][j];
1473
1472
  const currentRow = cell.getParent();
1474
1473
  if (!$isTableRowNode(currentRow)) {
1475
- throw Error(`Expected TableCellNode parent to be a TableRowNode`);
1474
+ formatDevErrorMessage(`Expected TableCellNode parent to be a TableRowNode`);
1476
1475
  }
1477
1476
  if (currentRow !== lastRow) {
1478
1477
  nodeMap.set(currentRow.getKey(), currentRow);
@@ -1522,13 +1521,13 @@ function $createTableSelectionFrom(tableNode, anchorCell, focusCell) {
1522
1521
  const focusCellKey = focusCell.getKey();
1523
1522
  {
1524
1523
  if (!tableNode.isAttached()) {
1525
- throw Error(`$createTableSelectionFrom: tableNode ${tableNodeKey} is not attached`);
1524
+ formatDevErrorMessage(`$createTableSelectionFrom: tableNode ${tableNodeKey} is not attached`);
1526
1525
  }
1527
1526
  if (!tableNode.is($findTableNode(anchorCell))) {
1528
- throw Error(`$createTableSelectionFrom: anchorCell ${anchorCellKey} is not in table ${tableNodeKey}`);
1527
+ formatDevErrorMessage(`$createTableSelectionFrom: anchorCell ${anchorCellKey} is not in table ${tableNodeKey}`);
1529
1528
  }
1530
1529
  if (!tableNode.is($findTableNode(focusCell))) {
1531
- throw Error(`$createTableSelectionFrom: focusCell ${focusCellKey} is not in table ${tableNodeKey}`);
1530
+ formatDevErrorMessage(`$createTableSelectionFrom: focusCell ${focusCellKey} is not in table ${tableNodeKey}`);
1532
1531
  } // TODO: Check for rectangular grid
1533
1532
  }
1534
1533
  const prevSelection = $getSelection();
@@ -1554,22 +1553,14 @@ function $visitRecursively(node, $visit) {
1554
1553
  }
1555
1554
  }
1556
1555
 
1557
- /**
1558
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1559
- *
1560
- * This source code is licensed under the MIT license found in the
1561
- * LICENSE file in the root directory of this source tree.
1562
- *
1563
- */
1564
-
1565
1556
  function $getTableAndElementByKey(tableNodeKey, editor = $getEditor()) {
1566
1557
  const tableNode = $getNodeByKey(tableNodeKey);
1567
1558
  if (!$isTableNode(tableNode)) {
1568
- throw Error(`TableObserver: Expected tableNodeKey ${tableNodeKey} to be a TableNode`);
1559
+ formatDevErrorMessage(`TableObserver: Expected tableNodeKey ${tableNodeKey} to be a TableNode`);
1569
1560
  }
1570
1561
  const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNodeKey));
1571
1562
  if (!(tableElement !== null)) {
1572
- throw Error(`TableObserver: Expected to find TableElement in DOM for key ${tableNodeKey}`);
1563
+ formatDevErrorMessage(`TableObserver: Expected to find TableElement in DOM for key ${tableNodeKey}`);
1573
1564
  }
1574
1565
  return {
1575
1566
  tableElement,
@@ -1701,7 +1692,7 @@ class TableObserver {
1701
1692
  $updateTableTableSelection(selection) {
1702
1693
  if (selection !== null) {
1703
1694
  if (!(selection.tableKey === this.tableNodeKey)) {
1704
- throw Error(`TableObserver.$updateTableTableSelection: selection.tableKey !== this.tableNodeKey ('${selection.tableKey}' !== '${this.tableNodeKey}')`);
1695
+ formatDevErrorMessage(`TableObserver.$updateTableTableSelection: selection.tableKey !== this.tableNodeKey ('${selection.tableKey}' !== '${this.tableNodeKey}')`);
1705
1696
  }
1706
1697
  const editor = this.editor;
1707
1698
  this.tableSelection = selection;
@@ -1808,7 +1799,7 @@ class TableObserver {
1808
1799
  $getAnchorTableCellOrThrow() {
1809
1800
  const anchorTableCell = this.$getAnchorTableCell();
1810
1801
  if (!(anchorTableCell !== null)) {
1811
- throw Error(`TableObserver anchorTableCell is null`);
1802
+ formatDevErrorMessage(`TableObserver anchorTableCell is null`);
1812
1803
  }
1813
1804
  return anchorTableCell;
1814
1805
  }
@@ -1818,7 +1809,7 @@ class TableObserver {
1818
1809
  $getFocusTableCellOrThrow() {
1819
1810
  const focusTableCell = this.$getFocusTableCell();
1820
1811
  if (!(focusTableCell !== null)) {
1821
- throw Error(`TableObserver focusTableCell is null`);
1812
+ formatDevErrorMessage(`TableObserver focusTableCell is null`);
1822
1813
  }
1823
1814
  return focusTableCell;
1824
1815
  }
@@ -1840,14 +1831,14 @@ class TableObserver {
1840
1831
  $formatCells(type) {
1841
1832
  const selection = $getSelection();
1842
1833
  if (!$isTableSelection(selection)) {
1843
- throw Error(`Expected Table selection`);
1834
+ formatDevErrorMessage(`Expected Table selection`);
1844
1835
  }
1845
1836
  const formatSelection = $createRangeSelection();
1846
1837
  const anchor = formatSelection.anchor;
1847
1838
  const focus = formatSelection.focus;
1848
1839
  const cellNodes = selection.getNodes().filter($isTableCellNode);
1849
1840
  if (!(cellNodes.length > 0)) {
1850
- throw Error(`No table cells present`);
1841
+ formatDevErrorMessage(`No table cells present`);
1851
1842
  }
1852
1843
  const paragraph = cellNodes[0].getFirstChild();
1853
1844
  const alignFormatWith = $isParagraphNode(paragraph) ? paragraph.getFormatFlags(type, null) : null;
@@ -1869,7 +1860,7 @@ class TableObserver {
1869
1860
  }
1870
1861
  const selection = $getSelection();
1871
1862
  if (!$isTableSelection(selection)) {
1872
- throw Error(`Expected TableSelection`);
1863
+ formatDevErrorMessage(`Expected TableSelection`);
1873
1864
  }
1874
1865
  const selectedNodes = selection.getNodes().filter($isTableCellNode);
1875
1866
  if (selectedNodes.length === this.table.columns * this.table.rows) {
@@ -1902,14 +1893,6 @@ class TableObserver {
1902
1893
  }
1903
1894
  }
1904
1895
 
1905
- /**
1906
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1907
- *
1908
- * This source code is licensed under the MIT license found in the
1909
- * LICENSE file in the root directory of this source tree.
1910
- *
1911
- */
1912
-
1913
1896
  const LEXICAL_ELEMENT_KEY = '__lexicalTableSelection';
1914
1897
  const isMouseDownOnEvent = event => {
1915
1898
  return (event.buttons & 1) === 1;
@@ -1920,7 +1903,7 @@ function getTableElement(tableNode, dom) {
1920
1903
  }
1921
1904
  const element = dom.nodeName === 'TABLE' ? dom : tableNode.getDOMSlot(dom).element;
1922
1905
  if (!(element.nodeName === 'TABLE')) {
1923
- throw Error(`getTableElement: Expecting table in as DOM node for TableNode, not ${dom.nodeName}`);
1906
+ formatDevErrorMessage(`getTableElement: Expecting table in as DOM node for TableNode, not ${dom.nodeName}`);
1924
1907
  }
1925
1908
  return element;
1926
1909
  }
@@ -1944,7 +1927,7 @@ function applyTableHandlers(tableNode, element, editor, hasTabHandler) {
1944
1927
  const rootElement = editor.getRootElement();
1945
1928
  const editorWindow = getEditorWindow(editor);
1946
1929
  if (!(rootElement !== null && editorWindow !== null)) {
1947
- throw Error(`applyTableHandlers: editor has no root element set`);
1930
+ formatDevErrorMessage(`applyTableHandlers: editor has no root element set`);
1948
1931
  }
1949
1932
  const tableObserver = new TableObserver(editor, tableNode.getKey());
1950
1933
  const tableElement = getTableElement(tableNode, element);
@@ -2476,7 +2459,7 @@ function detatchTableObserverFromTableElement(tableElement, tableObserver) {
2476
2459
  }
2477
2460
  function attachTableObserverToTableElement(tableElement, tableObserver) {
2478
2461
  if (!(getTableObserverFromTableElement(tableElement) === null)) {
2479
- throw Error(`tableElement already has an attached TableObserver`);
2462
+ formatDevErrorMessage(`tableElement already has an attached TableObserver`);
2480
2463
  }
2481
2464
  tableElement[LEXICAL_ELEMENT_KEY] = tableObserver;
2482
2465
  }
@@ -2625,7 +2608,7 @@ function $selectAdjacentCell(tableCellNode, direction) {
2625
2608
  }
2626
2609
  const parentRow = $findMatchingParent(tableCellNode, $isTableRowNode);
2627
2610
  if (!(parentRow !== null)) {
2628
- throw Error(`selectAdjacentCell: Cell not in table row`);
2611
+ formatDevErrorMessage(`selectAdjacentCell: Cell not in table row`);
2629
2612
  }
2630
2613
  for (let nextRow = parentRow[siblingMethod](); $isTableRowNode(nextRow); nextRow = nextRow[siblingMethod]()) {
2631
2614
  const child = nextRow[childMethod]();
@@ -2635,7 +2618,7 @@ function $selectAdjacentCell(tableCellNode, direction) {
2635
2618
  }
2636
2619
  const parentTable = $findMatchingParent(parentRow, $isTableNode);
2637
2620
  if (!(parentTable !== null)) {
2638
- throw Error(`selectAdjacentCell: Row not in table`);
2621
+ formatDevErrorMessage(`selectAdjacentCell: Row not in table`);
2639
2622
  }
2640
2623
  return direction === 'next' ? parentTable.selectNext() : parentTable.selectPrevious();
2641
2624
  }
@@ -2696,7 +2679,7 @@ function getCorner(rect, cellValue) {
2696
2679
  function getCornerOrThrow(rect, cellValue) {
2697
2680
  const corner = getCorner(rect, cellValue);
2698
2681
  if (!(corner !== null)) {
2699
- throw Error(`getCornerOrThrow: cell ${cellValue.cell.getKey()} is not at a corner of rect`);
2682
+ formatDevErrorMessage(`getCornerOrThrow: cell ${cellValue.cell.getKey()} is not at a corner of rect`);
2700
2683
  }
2701
2684
  return corner;
2702
2685
  }
@@ -2707,12 +2690,12 @@ function cellAtCornerOrThrow(tableMap, rect, [colName, rowName]) {
2707
2690
  const rowNum = rect[rowName];
2708
2691
  const rowMap = tableMap[rowNum];
2709
2692
  if (!(rowMap !== undefined)) {
2710
- throw Error(`cellAtCornerOrThrow: ${rowName} = ${String(rowNum)} missing in tableMap`);
2693
+ formatDevErrorMessage(`cellAtCornerOrThrow: ${rowName} = ${String(rowNum)} missing in tableMap`);
2711
2694
  }
2712
2695
  const colNum = rect[colName];
2713
2696
  const cell = rowMap[colNum];
2714
2697
  if (!(cell !== undefined)) {
2715
- throw Error(`cellAtCornerOrThrow: ${colName} = ${String(colNum)} missing in tableMap`);
2698
+ formatDevErrorMessage(`cellAtCornerOrThrow: ${colName} = ${String(colNum)} missing in tableMap`);
2716
2699
  }
2717
2700
  return cell;
2718
2701
  }
@@ -2775,6 +2758,9 @@ function $adjustFocusInDirection(tableObserver, tableMap, anchorCellValue, focus
2775
2758
  }
2776
2759
  function $isSelectionInTable(selection, tableNode) {
2777
2760
  if ($isRangeSelection(selection) || $isTableSelection(selection)) {
2761
+ // TODO this should probably return false if there's an unrelated
2762
+ // shadow root between the node and the table (e.g. another table,
2763
+ // collapsible, etc.)
2778
2764
  const isAnchorInside = tableNode.isParentOf(selection.anchor.getNode());
2779
2765
  const isFocusInside = tableNode.isParentOf(selection.focus.getNode());
2780
2766
  return isAnchorInside && isFocusInside;
@@ -2804,7 +2790,7 @@ function $addHighlightToDOM(editor, cell) {
2804
2790
  const editorThemeClasses = editor._config.theme;
2805
2791
  const node = $getNearestNodeFromDOMNode(element);
2806
2792
  if (!$isTableCellNode(node)) {
2807
- throw Error(`Expected to find LexicalNode from Table Cell DOMNode`);
2793
+ formatDevErrorMessage(`Expected to find LexicalNode from Table Cell DOMNode`);
2808
2794
  }
2809
2795
  addClassNamesToElement(element, editorThemeClasses.tableCellSelected);
2810
2796
  }
@@ -2812,7 +2798,7 @@ function $removeHighlightFromDOM(editor, cell) {
2812
2798
  const element = cell.elem;
2813
2799
  const node = $getNearestNodeFromDOMNode(element);
2814
2800
  if (!$isTableCellNode(node)) {
2815
- throw Error(`Expected to find LexicalNode from Table Cell DOMNode`);
2801
+ formatDevErrorMessage(`Expected to find LexicalNode from Table Cell DOMNode`);
2816
2802
  }
2817
2803
  const editorThemeClasses = editor._config.theme;
2818
2804
  removeClassNamesFromElement(element, editorThemeClasses.tableCellSelected);
@@ -2838,6 +2824,85 @@ function $getBlockParentIfFirstNode(node) {
2838
2824
  }
2839
2825
  return null;
2840
2826
  }
2827
+ function $handleHorizontalArrowKeyRangeSelection(editor, event, selection, alter, isBackward, tableNode, tableObserver) {
2828
+ const initialFocus = $caretFromPoint(selection.focus, isBackward ? 'previous' : 'next');
2829
+ if ($isExtendableTextPointCaret(initialFocus)) {
2830
+ return false;
2831
+ }
2832
+ let lastCaret = initialFocus;
2833
+ // TableCellNode is the only shadow root we are interested in piercing so
2834
+ // we find the last internal caret and then check its parent
2835
+ for (const nextCaret of $extendCaretToRange(initialFocus).iterNodeCarets('shadowRoot')) {
2836
+ if (!($isSiblingCaret(nextCaret) && $isElementNode(nextCaret.origin))) {
2837
+ return false;
2838
+ }
2839
+ lastCaret = nextCaret;
2840
+ }
2841
+ const lastCaretParent = lastCaret.getParentAtCaret();
2842
+ if (!$isTableCellNode(lastCaretParent)) {
2843
+ return false;
2844
+ }
2845
+ const anchorCell = lastCaretParent;
2846
+ const focusCaret = $findNextTableCell($getSiblingCaret(anchorCell, lastCaret.direction));
2847
+ const anchorCellTable = $findMatchingParent(anchorCell, $isTableNode);
2848
+ if (!(anchorCellTable && anchorCellTable.is(tableNode))) {
2849
+ return false;
2850
+ }
2851
+ const anchorCellDOM = editor.getElementByKey(anchorCell.getKey());
2852
+ const anchorDOMCell = getDOMCellFromTarget(anchorCellDOM);
2853
+ if (!anchorCellDOM || !anchorDOMCell) {
2854
+ return false;
2855
+ }
2856
+ const anchorCellTableElement = $getElementForTableNode(editor, anchorCellTable);
2857
+ tableObserver.table = anchorCellTableElement;
2858
+ if (!focusCaret) {
2859
+ if (alter === 'extend') {
2860
+ // extend the selection from a range inside the cell to a table selection of the cell
2861
+ tableObserver.$setAnchorCellForSelection(anchorDOMCell);
2862
+ tableObserver.$setFocusCellForSelection(anchorDOMCell, true);
2863
+ } else {
2864
+ // exit the table
2865
+ const outerFocusCaret = $getTableExitCaret($getSiblingCaret(anchorCellTable, initialFocus.direction));
2866
+ $setPointFromCaret(selection.anchor, outerFocusCaret);
2867
+ $setPointFromCaret(selection.focus, outerFocusCaret);
2868
+ }
2869
+ } else if (alter === 'extend') {
2870
+ const focusDOMCell = getDOMCellFromTarget(editor.getElementByKey(focusCaret.origin.getKey()));
2871
+ if (!focusDOMCell) {
2872
+ return false;
2873
+ }
2874
+ tableObserver.$setAnchorCellForSelection(anchorDOMCell);
2875
+ tableObserver.$setFocusCellForSelection(focusDOMCell, true);
2876
+ } else {
2877
+ // alter === 'move'
2878
+ const innerFocusCaret = $normalizeCaret(focusCaret);
2879
+ $setPointFromCaret(selection.anchor, innerFocusCaret);
2880
+ $setPointFromCaret(selection.focus, innerFocusCaret);
2881
+ }
2882
+ stopEvent(event);
2883
+ return true;
2884
+ }
2885
+ function $getTableExitCaret(initialCaret) {
2886
+ const adjacent = $getAdjacentChildCaret(initialCaret);
2887
+ return $isChildCaret(adjacent) ? $normalizeCaret(adjacent) : initialCaret;
2888
+ }
2889
+ function $findNextTableCell(initialCaret) {
2890
+ for (const nextCaret of $extendCaretToRange(initialCaret).iterNodeCarets('root')) {
2891
+ const {
2892
+ origin
2893
+ } = nextCaret;
2894
+ if ($isTableCellNode(origin)) {
2895
+ // not sure why ts isn't narrowing here (even if the guard is on nextCaret.origin)
2896
+ // but returning a new caret is fine
2897
+ if ($isChildCaret(nextCaret)) {
2898
+ return $getChildCaret(origin, initialCaret.direction);
2899
+ }
2900
+ } else if (!$isTableRowNode(origin)) {
2901
+ break;
2902
+ }
2903
+ }
2904
+ return null;
2905
+ }
2841
2906
  function $handleArrowKey(editor, event, direction, tableNode, tableObserver) {
2842
2907
  if ((direction === 'up' || direction === 'down') && isTypeaheadMenuInView(editor)) {
2843
2908
  return false;
@@ -2955,77 +3020,67 @@ function $handleArrowKey(editor, event, direction, tableNode, tableObserver) {
2955
3020
  }
2956
3021
  return false;
2957
3022
  }
2958
- if ($isRangeSelection(selection) && selection.isCollapsed()) {
2959
- const {
2960
- anchor,
2961
- focus
2962
- } = selection;
2963
- const anchorCellNode = $findMatchingParent(anchor.getNode(), $isTableCellNode);
2964
- const focusCellNode = $findMatchingParent(focus.getNode(), $isTableCellNode);
2965
- if (!$isTableCellNode(anchorCellNode) || !anchorCellNode.is(focusCellNode)) {
2966
- return false;
2967
- }
2968
- const anchorCellTable = $findTableNode(anchorCellNode);
2969
- if (anchorCellTable !== tableNode && anchorCellTable != null) {
2970
- const anchorCellTableElement = getTableElement(anchorCellTable, editor.getElementByKey(anchorCellTable.getKey()));
2971
- if (anchorCellTableElement != null) {
2972
- tableObserver.table = getTable(anchorCellTable, anchorCellTableElement);
2973
- return $handleArrowKey(editor, event, direction, anchorCellTable, tableObserver);
2974
- }
2975
- }
3023
+ if ($isRangeSelection(selection)) {
2976
3024
  if (direction === 'backward' || direction === 'forward') {
2977
- const anchorType = anchor.type;
2978
- const anchorOffset = anchor.offset;
2979
- const anchorNode = anchor.getNode();
2980
- if (!anchorNode) {
3025
+ const alter = event.shiftKey ? 'extend' : 'move';
3026
+ return $handleHorizontalArrowKeyRangeSelection(editor, event, selection, alter, direction === 'backward', tableNode, tableObserver);
3027
+ }
3028
+ if (selection.isCollapsed()) {
3029
+ const {
3030
+ anchor,
3031
+ focus
3032
+ } = selection;
3033
+ const anchorCellNode = $findMatchingParent(anchor.getNode(), $isTableCellNode);
3034
+ const focusCellNode = $findMatchingParent(focus.getNode(), $isTableCellNode);
3035
+ if (!$isTableCellNode(anchorCellNode) || !anchorCellNode.is(focusCellNode)) {
2981
3036
  return false;
2982
3037
  }
2983
- const selectedNodes = selection.getNodes();
2984
- if (selectedNodes.length === 1 && $isDecoratorNode(selectedNodes[0])) {
3038
+ const anchorCellTable = $findTableNode(anchorCellNode);
3039
+ if (anchorCellTable !== tableNode && anchorCellTable != null) {
3040
+ const anchorCellTableElement = getTableElement(anchorCellTable, editor.getElementByKey(anchorCellTable.getKey()));
3041
+ if (anchorCellTableElement != null) {
3042
+ tableObserver.table = getTable(anchorCellTable, anchorCellTableElement);
3043
+ return $handleArrowKey(editor, event, direction, anchorCellTable, tableObserver);
3044
+ }
3045
+ }
3046
+ const anchorCellDom = editor.getElementByKey(anchorCellNode.__key);
3047
+ const anchorDOM = editor.getElementByKey(anchor.key);
3048
+ if (anchorDOM == null || anchorCellDom == null) {
2985
3049
  return false;
2986
3050
  }
2987
- if (isExitingTableAnchor(anchorType, anchorOffset, anchorNode, direction)) {
2988
- return $handleTableExit(event, anchorNode, anchorCellNode, tableNode, direction);
3051
+ let edgeSelectionRect;
3052
+ if (anchor.type === 'element') {
3053
+ edgeSelectionRect = anchorDOM.getBoundingClientRect();
3054
+ } else {
3055
+ const domSelection = getDOMSelection(getEditorWindow(editor));
3056
+ if (domSelection === null || domSelection.rangeCount === 0) {
3057
+ return false;
3058
+ }
3059
+ const range = domSelection.getRangeAt(0);
3060
+ edgeSelectionRect = range.getBoundingClientRect();
2989
3061
  }
2990
- return false;
2991
- }
2992
- const anchorCellDom = editor.getElementByKey(anchorCellNode.__key);
2993
- const anchorDOM = editor.getElementByKey(anchor.key);
2994
- if (anchorDOM == null || anchorCellDom == null) {
2995
- return false;
2996
- }
2997
- let edgeSelectionRect;
2998
- if (anchor.type === 'element') {
2999
- edgeSelectionRect = anchorDOM.getBoundingClientRect();
3000
- } else {
3001
- const domSelection = getDOMSelection(getEditorWindow(editor));
3002
- if (domSelection === null || domSelection.rangeCount === 0) {
3062
+ const edgeChild = direction === 'up' ? anchorCellNode.getFirstChild() : anchorCellNode.getLastChild();
3063
+ if (edgeChild == null) {
3003
3064
  return false;
3004
3065
  }
3005
- const range = domSelection.getRangeAt(0);
3006
- edgeSelectionRect = range.getBoundingClientRect();
3007
- }
3008
- const edgeChild = direction === 'up' ? anchorCellNode.getFirstChild() : anchorCellNode.getLastChild();
3009
- if (edgeChild == null) {
3010
- return false;
3011
- }
3012
- const edgeChildDOM = editor.getElementByKey(edgeChild.__key);
3013
- if (edgeChildDOM == null) {
3014
- return false;
3015
- }
3016
- const edgeRect = edgeChildDOM.getBoundingClientRect();
3017
- const isExiting = direction === 'up' ? edgeRect.top > edgeSelectionRect.top - edgeSelectionRect.height : edgeSelectionRect.bottom + edgeSelectionRect.height > edgeRect.bottom;
3018
- if (isExiting) {
3019
- stopEvent(event);
3020
- const cords = tableNode.getCordsFromCellNode(anchorCellNode, tableObserver.table);
3021
- if (event.shiftKey) {
3022
- const cell = tableNode.getDOMCellFromCordsOrThrow(cords.x, cords.y, tableObserver.table);
3023
- tableObserver.$setAnchorCellForSelection(cell);
3024
- tableObserver.$setFocusCellForSelection(cell, true);
3025
- } else {
3026
- return selectTableNodeInDirection(tableObserver, tableNode, cords.x, cords.y, direction);
3066
+ const edgeChildDOM = editor.getElementByKey(edgeChild.__key);
3067
+ if (edgeChildDOM == null) {
3068
+ return false;
3069
+ }
3070
+ const edgeRect = edgeChildDOM.getBoundingClientRect();
3071
+ const isExiting = direction === 'up' ? edgeRect.top > edgeSelectionRect.top - edgeSelectionRect.height : edgeSelectionRect.bottom + edgeSelectionRect.height > edgeRect.bottom;
3072
+ if (isExiting) {
3073
+ stopEvent(event);
3074
+ const cords = tableNode.getCordsFromCellNode(anchorCellNode, tableObserver.table);
3075
+ if (event.shiftKey) {
3076
+ const cell = tableNode.getDOMCellFromCordsOrThrow(cords.x, cords.y, tableObserver.table);
3077
+ tableObserver.$setAnchorCellForSelection(cell);
3078
+ tableObserver.$setFocusCellForSelection(cell, true);
3079
+ } else {
3080
+ return selectTableNodeInDirection(tableObserver, tableNode, cords.x, cords.y, direction);
3081
+ }
3082
+ return true;
3027
3083
  }
3028
- return true;
3029
3084
  }
3030
3085
  } else if ($isTableSelection(selection)) {
3031
3086
  const {
@@ -3036,7 +3091,7 @@ function $handleArrowKey(editor, event, direction, tableNode, tableObserver) {
3036
3091
  const focusCellNode = $findMatchingParent(focus.getNode(), $isTableCellNode);
3037
3092
  const [tableNodeFromSelection] = selection.getNodes();
3038
3093
  if (!$isTableNode(tableNodeFromSelection)) {
3039
- throw Error(`$handleArrowKey: TableSelection.getNodes()[0] expected to be TableNode`);
3094
+ formatDevErrorMessage(`$handleArrowKey: TableSelection.getNodes()[0] expected to be TableNode`);
3040
3095
  }
3041
3096
  const tableElement = getTableElement(tableNodeFromSelection, editor.getElementByKey(tableNodeFromSelection.getKey()));
3042
3097
  if (!$isTableCellNode(anchorCellNode) || !$isTableCellNode(focusCellNode) || !$isTableNode(tableNodeFromSelection) || tableElement == null) {
@@ -3072,54 +3127,6 @@ function isTypeaheadMenuInView(editor) {
3072
3127
  }
3073
3128
  return root.hasAttribute('aria-controls') && root.getAttribute('aria-controls') === 'typeahead-menu';
3074
3129
  }
3075
- function isExitingTableAnchor(type, offset, anchorNode, direction) {
3076
- return isExitingTableElementAnchor(type, anchorNode, direction) || $isExitingTableTextAnchor(type, offset, anchorNode, direction);
3077
- }
3078
- function isExitingTableElementAnchor(type, anchorNode, direction) {
3079
- return type === 'element' && (direction === 'backward' ? anchorNode.getPreviousSibling() === null : anchorNode.getNextSibling() === null);
3080
- }
3081
- function $isExitingTableTextAnchor(type, offset, anchorNode, direction) {
3082
- const parentNode = $findMatchingParent(anchorNode, n => $isElementNode(n) && !n.isInline());
3083
- if (!parentNode) {
3084
- return false;
3085
- }
3086
- const hasValidOffset = direction === 'backward' ? offset === 0 : offset === anchorNode.getTextContentSize();
3087
- return type === 'text' && hasValidOffset && (direction === 'backward' ? parentNode.getPreviousSibling() === null : parentNode.getNextSibling() === null);
3088
- }
3089
- function $handleTableExit(event, anchorNode, anchorCellNode, tableNode, direction) {
3090
- const [tableMap, cellValue] = $computeTableMap(tableNode, anchorCellNode, anchorCellNode);
3091
- if (!isExitingCell(tableMap, cellValue, direction)) {
3092
- return false;
3093
- }
3094
- const toNode = $getExitingToNode(anchorNode, direction, tableNode);
3095
- if (!toNode || $isTableNode(toNode)) {
3096
- return false;
3097
- }
3098
- stopEvent(event);
3099
- if (direction === 'backward') {
3100
- toNode.selectEnd();
3101
- } else {
3102
- toNode.selectStart();
3103
- }
3104
- return true;
3105
- }
3106
- function isExitingCell(tableMap, cellValue, direction) {
3107
- const firstCell = tableMap[0][0];
3108
- const lastCell = tableMap[tableMap.length - 1][tableMap[0].length - 1];
3109
- const {
3110
- startColumn,
3111
- startRow
3112
- } = cellValue;
3113
- return direction === 'backward' ? startColumn === firstCell.startColumn && startRow === firstCell.startRow : startColumn === lastCell.startColumn && startRow === lastCell.startRow;
3114
- }
3115
- function $getExitingToNode(anchorNode, direction, tableNode) {
3116
- const parentNode = $findMatchingParent(anchorNode, n => $isElementNode(n) && !n.isInline());
3117
- if (!parentNode) {
3118
- return undefined;
3119
- }
3120
- const anchorSibling = direction === 'backward' ? parentNode.getPreviousSibling() : parentNode.getNextSibling();
3121
- return anchorSibling && $isTableNode(anchorSibling) ? anchorSibling : direction === 'backward' ? tableNode.getPreviousSibling() : tableNode.getNextSibling();
3122
- }
3123
3130
  function $insertParagraphAtTableEdge(edgePosition, tableNode, children) {
3124
3131
  const paragraphNode = $createParagraphNode();
3125
3132
  if (edgePosition === 'first') {
@@ -3188,14 +3195,6 @@ function $getNearestTableCellInTableFromDOMNode(tableNode, startingDOM, editorSt
3188
3195
  return $findParentTableCellNodeInTable(tableNode, $getNearestNodeFromDOMNode(startingDOM, editorState));
3189
3196
  }
3190
3197
 
3191
- /**
3192
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3193
- *
3194
- * This source code is licensed under the MIT license found in the
3195
- * LICENSE file in the root directory of this source tree.
3196
- *
3197
- */
3198
-
3199
3198
  function updateColgroup(dom, config, colCount, colWidths) {
3200
3199
  const colGroup = dom.querySelector('colgroup');
3201
3200
  if (!colGroup) {
@@ -3332,7 +3331,7 @@ class TableNode extends ElementNode {
3332
3331
  getDOMSlot(element) {
3333
3332
  const tableElement = element.nodeName !== 'TABLE' && element.querySelector('table') || element;
3334
3333
  if (!(tableElement.nodeName === 'TABLE')) {
3335
- throw Error(`TableNode.getDOMSlot: createDOM() did not return a table`);
3334
+ formatDevErrorMessage(`TableNode.getDOMSlot: createDOM() did not return a table`);
3336
3335
  }
3337
3336
  return super.getDOMSlot(tableElement).withAfter(tableElement.querySelector('colgroup'));
3338
3337
  }
@@ -3582,7 +3581,7 @@ class TableNode extends ElementNode {
3582
3581
  function $getElementForTableNode(editor, tableNode) {
3583
3582
  const tableElement = editor.getElementByKey(tableNode.getKey());
3584
3583
  if (!(tableElement !== null)) {
3585
- throw Error(`$getElementForTableNode: Table Element Not Found`);
3584
+ formatDevErrorMessage(`$getElementForTableNode: Table Element Not Found`);
3586
3585
  }
3587
3586
  return getTable(tableNode, tableElement);
3588
3587
  }
@@ -3622,14 +3621,6 @@ function $isTableNode(node) {
3622
3621
  return node instanceof TableNode;
3623
3622
  }
3624
3623
 
3625
- /**
3626
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3627
- *
3628
- * This source code is licensed under the MIT license found in the
3629
- * LICENSE file in the root directory of this source tree.
3630
- *
3631
- */
3632
-
3633
3624
  function $insertTableCommandListener({
3634
3625
  rows,
3635
3626
  columns,
@@ -3685,7 +3676,7 @@ function $tableTransform(node) {
3685
3676
  continue;
3686
3677
  }
3687
3678
  if (!$isTableRowNode(rowNode)) {
3688
- throw Error(`TablePlugin: Expecting all children of TableNode to be TableRowNode, found ${rowNode.constructor.name} (type ${rowNode.getType()})`);
3679
+ formatDevErrorMessage(`TablePlugin: Expecting all children of TableNode to be TableRowNode, found ${rowNode.constructor.name} (type ${rowNode.getType()})`);
3689
3680
  }
3690
3681
  const rowLength = gridMap[i].reduce((acc, cell) => cell ? 1 + acc : acc, 0);
3691
3682
  if (rowLength === maxRowLength) {
@@ -3738,14 +3729,14 @@ function registerTableCellUnmergeTransform(editor) {
3738
3729
  const columnsCount = gridMap[0].length;
3739
3730
  let row = gridNode.getFirstChild();
3740
3731
  if (!$isTableRowNode(row)) {
3741
- throw Error(`Expected TableNode first child to be a RowNode`);
3732
+ formatDevErrorMessage(`Expected TableNode first child to be a RowNode`);
3742
3733
  }
3743
3734
  const unmerged = [];
3744
3735
  for (let i = 0; i < rowsCount; i++) {
3745
3736
  if (i !== 0) {
3746
3737
  row = row.getNextSibling();
3747
3738
  if (!$isTableRowNode(row)) {
3748
- throw Error(`Expected TableNode first child to be a RowNode`);
3739
+ formatDevErrorMessage(`Expected TableNode first child to be a RowNode`);
3749
3740
  }
3750
3741
  }
3751
3742
  let lastRowCell = null;
@@ -3757,7 +3748,7 @@ function registerTableCellUnmergeTransform(editor) {
3757
3748
  unmerged.push(cell);
3758
3749
  } else if (cell.getColSpan() > 1 || cell.getRowSpan() > 1) {
3759
3750
  if (!$isTableCellNode(cell)) {
3760
- throw Error(`Expected TableNode cell to be a TableCellNode`);
3751
+ formatDevErrorMessage(`Expected TableNode cell to be a TableCellNode`);
3761
3752
  }
3762
3753
  const newCell = $createTableCellNode(cell.__headerState);
3763
3754
  if (lastRowCell !== null) {
@@ -3833,7 +3824,7 @@ function registerTableSelectionObserver(editor, hasTabHandler = true) {
3833
3824
  function registerTablePlugin(editor) {
3834
3825
  if (!editor.hasNodes([TableNode])) {
3835
3826
  {
3836
- throw Error(`TablePlugin: TableNode is not registered on editor`);
3827
+ formatDevErrorMessage(`TablePlugin: TableNode is not registered on editor`);
3837
3828
  }
3838
3829
  }
3839
3830
  return mergeRegister(editor.registerCommand(INSERT_TABLE_COMMAND, $insertTableCommandListener, COMMAND_PRIORITY_EDITOR), editor.registerCommand(SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, ({