@lobehub/editor 4.15.2 → 4.16.1

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.
Files changed (63) hide show
  1. package/es/editor-kernel/react/useDecorators.js +14 -8
  2. package/es/headless/index.d.ts +1 -1
  3. package/es/headless/index.js +1 -1
  4. package/es/headless.d.ts +3 -18
  5. package/es/headless.js +711 -52
  6. package/es/index.d.ts +5 -5
  7. package/es/index.js +5 -5
  8. package/es/locale/index.d.ts +2 -0
  9. package/es/locale/index.js +5 -1
  10. package/es/plugins/auto-complete/plugin/index.js +3 -3
  11. package/es/plugins/block/index.d.ts +1 -1
  12. package/es/plugins/block/plugin/index.js +78 -2
  13. package/es/plugins/block/react/ReactBlockPlugin.js +172 -16
  14. package/es/plugins/block/react/drag/drag-utils.js +37 -10
  15. package/es/plugins/block/service/i-block-menu-service.d.ts +18 -1
  16. package/es/plugins/block/service/i-block-menu-service.js +24 -0
  17. package/es/plugins/block/service/index.d.ts +1 -1
  18. package/es/plugins/codeblock/plugin/index.js +25 -1
  19. package/es/plugins/common/plugin/register.js +2 -2
  20. package/es/plugins/litexml/command/diffCommand.d.ts +2 -17
  21. package/es/plugins/litexml/command/diffCommand.js +3 -9
  22. package/es/plugins/litexml/command/index.d.ts +2 -38
  23. package/es/plugins/litexml/command/index.js +3 -6
  24. package/es/plugins/litexml/command/symbols.d.ts +67 -0
  25. package/es/plugins/litexml/command/symbols.js +34 -0
  26. package/es/plugins/litexml/index.d.ts +1 -2
  27. package/es/plugins/litexml/plugin/index.js +8 -2
  28. package/es/plugins/litexml/react/DiffNodeToolbar/index.js +1 -1
  29. package/es/plugins/slash/plugin/index.js +1 -1
  30. package/es/plugins/slash/react/ReactSlashPlugin.js +4 -4
  31. package/es/plugins/table/command/index.d.ts +13 -1
  32. package/es/plugins/table/command/index.js +220 -39
  33. package/es/plugins/table/index.d.ts +3 -2
  34. package/es/plugins/table/node/index.d.ts +2 -0
  35. package/es/plugins/table/node/index.js +130 -2
  36. package/es/plugins/table/plugin/index.d.ts +6 -0
  37. package/es/plugins/table/plugin/index.js +193 -4
  38. package/es/plugins/table/react/TableActionMenu/ActionMenu.js +82 -6
  39. package/es/plugins/table/react/TableActionMenu/index.js +9 -4
  40. package/es/plugins/table/react/TableColController.js +354 -0
  41. package/es/plugins/table/react/TableController/hooks.js +201 -0
  42. package/es/plugins/table/react/TableController/style.js +264 -0
  43. package/es/plugins/table/react/TableController/utils.js +25 -0
  44. package/es/plugins/table/react/TableControllerButton.js +81 -0
  45. package/es/plugins/table/react/TableControllerMenu.js +123 -0
  46. package/es/plugins/table/react/TableInsertButton.js +25 -0
  47. package/es/plugins/table/react/TableResize/index.js +153 -78
  48. package/es/plugins/table/react/TableRowController.js +349 -0
  49. package/es/plugins/table/react/hooks.js +77 -0
  50. package/es/plugins/table/react/index.js +139 -16
  51. package/es/plugins/table/react/style.js +89 -8
  52. package/es/plugins/table/react/type.d.ts +2 -0
  53. package/es/plugins/table/react/useAutoFitPastedTable.js +189 -0
  54. package/es/plugins/table/service/i-table-controller-menu-service.d.ts +44 -0
  55. package/es/plugins/table/service/i-table-controller-menu-service.js +31 -0
  56. package/es/plugins/table/service/index.d.ts +1 -0
  57. package/es/plugins/table/utils/autoFitColumnWidth.js +87 -0
  58. package/es/plugins/table/utils/distributeColumnWidth.js +37 -0
  59. package/es/plugins/table/utils/index.js +102 -2
  60. package/es/react/EditorProvider/index.d.ts +2 -2
  61. package/es/renderer/LexicalDiff.d.ts +2 -2
  62. package/es/symbols-DEEvsKq4.d.ts +67 -0
  63. package/package.json +5 -1
@@ -3,9 +3,13 @@ import { KernelPlugin, init_plugin } from "../../../editor-kernel/plugin.js";
3
3
  import { ILitexmlService } from "../../litexml/service/litexml-service.js";
4
4
  import { IMarkdownShortCutService } from "../../markdown/service/shortcut.js";
5
5
  import { cx } from "../../../utils/cx.js";
6
- import { registerTableCommand } from "../command/index.js";
6
+ import { IBlockMenuService } from "../../block/service/i-block-menu-service.js";
7
+ import { createDefaultTableColWidths } from "../utils/index.js";
8
+ import { AUTO_FIT_TABLE_COLUMN_WIDTH_COMMAND, DISTRIBUTE_TABLE_COLUMN_WIDTH_COMMAND, INSERT_TABLE_COLUMN_COMMAND, INSERT_TABLE_ROW_COMMAND, SYNC_TABLE_COLUMN_WIDTH_COMMAND, registerTableCommand } from "../command/index.js";
7
9
  import { TableNode as TableNode$1, patchTableNode } from "../node/index.js";
8
- import { $isTableNode, TableCellNode, TableRowNode, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive } from "@lexical/table";
10
+ import { ITableControllerMenuService, TableControllerMenuService } from "../service/i-table-controller-menu-service.js";
11
+ import { $computeTableMapSkipCellCheck, $createTableSelection, $deleteTableColumnAtSelection, $deleteTableRowAtSelection, $isTableNode, TableCellNode, TableRowNode, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive } from "@lexical/table";
12
+ import { $setSelection } from "lexical";
9
13
  //#region src/plugins/table/plugin/index.ts
10
14
  init_helper();
11
15
  init_plugin();
@@ -15,6 +19,13 @@ const tableCellProcessor = (before, content, after) => {
15
19
  function isHeadlessEditor(editor) {
16
20
  return editor._headless === true;
17
21
  }
22
+ const getSelectedRange = (selectedIndexes) => {
23
+ const sortedIndexes = [...selectedIndexes].sort((a, b) => a - b);
24
+ return {
25
+ end: sortedIndexes.at(-1) ?? 0,
26
+ start: sortedIndexes[0] ?? 0
27
+ };
28
+ };
18
29
  const TablePlugin = class extends KernelPlugin {
19
30
  static {
20
31
  this.pluginName = "TablePlugin";
@@ -23,11 +34,26 @@ const TablePlugin = class extends KernelPlugin {
23
34
  super();
24
35
  this.kernel = kernel;
25
36
  patchTableNode();
37
+ kernel.registerServiceHotReload(ITableControllerMenuService, new TableControllerMenuService());
26
38
  kernel.registerNodes([
27
39
  TableNode$1,
28
40
  TableRowNode,
29
41
  TableCellNode
30
42
  ]);
43
+ if (options?.decoratorCol || options?.decoratorRow) {
44
+ kernel.registerDecorator(TableNode$1.getType(), { multi: [...options.decoratorCol ? [{
45
+ queryDOM: (el) => el.querySelector(".toolbar-col"),
46
+ render: (node, editor) => {
47
+ return options.decoratorCol?.(node, editor) || null;
48
+ }
49
+ }] : [], ...options.decoratorRow ? [{
50
+ queryDOM: (el) => el.querySelector(".toolbar-row"),
51
+ render: (node, editor) => {
52
+ return options.decoratorRow?.(node, editor) || null;
53
+ }
54
+ }] : []] });
55
+ this.registeredDecorators.add(TableNode$1.getType());
56
+ }
31
57
  kernel.registerThemes({
32
58
  table: "editor_table",
33
59
  tableCell: "editor_table_cell",
@@ -46,6 +72,169 @@ const TablePlugin = class extends KernelPlugin {
46
72
  }
47
73
  this.registerMarkdown();
48
74
  this.registerLiteXml();
75
+ this.registerControllerMenu();
76
+ this.registerBlockSelect();
77
+ }
78
+ registerBlockSelect() {
79
+ const blockMenuService = this.kernel.requireService(IBlockMenuService);
80
+ if (!blockMenuService) return;
81
+ this.register(blockMenuService.registerSelectHandler({
82
+ key: "__table_block_select_handler",
83
+ onSelect: (node) => {
84
+ if (!$isTableNode(node)) return false;
85
+ const [tableMap] = $computeTableMapSkipCellCheck(node, null, null);
86
+ const firstCell = tableMap[0]?.[0]?.cell;
87
+ const lastRow = [...tableMap].reverse().find((row) => row.length > 0);
88
+ const lastCell = lastRow?.[lastRow.length - 1]?.cell;
89
+ if (!firstCell || !lastCell) return false;
90
+ const tableSelection = $createTableSelection();
91
+ tableSelection.set(node.getKey(), firstCell.getKey(), lastCell.getKey());
92
+ $setSelection(tableSelection);
93
+ return true;
94
+ },
95
+ order: 100
96
+ }));
97
+ }
98
+ registerControllerMenu() {
99
+ const tableControllerMenuService = this.kernel.requireService(ITableControllerMenuService);
100
+ if (!tableControllerMenuService) return;
101
+ [
102
+ tableControllerMenuService.registerItem({
103
+ key: "__table_column_insert_before",
104
+ label: "Insert before",
105
+ onClick: ({ editor, node, selectedIndexes }) => {
106
+ const { start } = getSelectedRange(selectedIndexes);
107
+ editor.dispatchCommand(INSERT_TABLE_COLUMN_COMMAND, {
108
+ columnIndex: start,
109
+ insertAfter: false,
110
+ table: node.getKey()
111
+ });
112
+ },
113
+ order: 10,
114
+ preview: "insert-before",
115
+ when: ({ axis }) => axis === "column"
116
+ }),
117
+ tableControllerMenuService.registerItem({
118
+ key: "__table_column_insert_after",
119
+ label: "Insert after",
120
+ onClick: ({ editor, node, selectedIndexes }) => {
121
+ const { end } = getSelectedRange(selectedIndexes);
122
+ editor.dispatchCommand(INSERT_TABLE_COLUMN_COMMAND, {
123
+ columnIndex: end,
124
+ insertAfter: true,
125
+ table: node.getKey()
126
+ });
127
+ },
128
+ order: 20,
129
+ preview: "insert-after",
130
+ when: ({ axis }) => axis === "column"
131
+ }),
132
+ tableControllerMenuService.registerItem({
133
+ key: "__table_column_separator_delete",
134
+ order: 40,
135
+ type: "separator",
136
+ when: ({ axis }) => axis === "column"
137
+ }),
138
+ tableControllerMenuService.registerItem({
139
+ key: "__table_column_sync_width",
140
+ label: "Sync width to all columns",
141
+ onClick: ({ editor, node, selectedIndexes }) => {
142
+ const columnIndex = selectedIndexes[0];
143
+ if (columnIndex === void 0) return;
144
+ editor.dispatchCommand(SYNC_TABLE_COLUMN_WIDTH_COMMAND, {
145
+ columnIndex,
146
+ table: node.getKey()
147
+ });
148
+ },
149
+ order: 30,
150
+ when: ({ axis, selectedIndexes }) => axis === "column" && selectedIndexes.length > 0
151
+ }),
152
+ tableControllerMenuService.registerItem({
153
+ key: "__table_column_auto_fit_width",
154
+ label: "Auto fit width",
155
+ onClick: ({ editor, node, selectedIndexes }) => {
156
+ editor.dispatchCommand(AUTO_FIT_TABLE_COLUMN_WIDTH_COMMAND, {
157
+ columnIndexes: selectedIndexes,
158
+ table: node.getKey()
159
+ });
160
+ },
161
+ order: 35,
162
+ when: ({ axis, selectedIndexes }) => axis === "column" && selectedIndexes.length > 0
163
+ }),
164
+ tableControllerMenuService.registerItem({
165
+ key: "__table_column_distribute_width",
166
+ label: "Distribute width",
167
+ onClick: ({ editor, node }) => {
168
+ editor.dispatchCommand(DISTRIBUTE_TABLE_COLUMN_WIDTH_COMMAND, { table: node.getKey() });
169
+ },
170
+ order: 36,
171
+ when: ({ axis }) => axis === "column"
172
+ }),
173
+ tableControllerMenuService.registerItem({
174
+ danger: true,
175
+ key: "__table_column_delete",
176
+ label: "Delete",
177
+ onClick: ({ editor }) => {
178
+ editor.update(() => {
179
+ $deleteTableColumnAtSelection();
180
+ });
181
+ },
182
+ order: 40,
183
+ preview: "delete",
184
+ when: ({ axis }) => axis === "column"
185
+ }),
186
+ tableControllerMenuService.registerItem({
187
+ key: "__table_row_insert_above",
188
+ label: "Insert above",
189
+ onClick: ({ editor, node, selectedIndexes }) => {
190
+ const { start } = getSelectedRange(selectedIndexes);
191
+ editor.dispatchCommand(INSERT_TABLE_ROW_COMMAND, {
192
+ insertAfter: false,
193
+ rowIndex: start,
194
+ table: node.getKey()
195
+ });
196
+ },
197
+ order: 10,
198
+ preview: "insert-before",
199
+ when: ({ axis }) => axis === "row"
200
+ }),
201
+ tableControllerMenuService.registerItem({
202
+ key: "__table_row_insert_below",
203
+ label: "Insert below",
204
+ onClick: ({ editor, node, selectedIndexes }) => {
205
+ const { end } = getSelectedRange(selectedIndexes);
206
+ editor.dispatchCommand(INSERT_TABLE_ROW_COMMAND, {
207
+ insertAfter: true,
208
+ rowIndex: end,
209
+ table: node.getKey()
210
+ });
211
+ },
212
+ order: 20,
213
+ preview: "insert-after",
214
+ when: ({ axis }) => axis === "row"
215
+ }),
216
+ tableControllerMenuService.registerItem({
217
+ key: "__table_row_separator_delete",
218
+ order: 30,
219
+ type: "separator",
220
+ when: ({ axis }) => axis === "row"
221
+ }),
222
+ tableControllerMenuService.registerItem({
223
+ danger: true,
224
+ key: "__table_row_delete",
225
+ label: "Delete",
226
+ onClick: ({ editor }) => {
227
+ editor.update(() => {
228
+ $deleteTableRowAtSelection();
229
+ });
230
+ },
231
+ order: 40,
232
+ preview: "delete",
233
+ when: ({ axis }) => axis === "row"
234
+ })
235
+ ].forEach((unregister) => {
236
+ this.register(unregister);
237
+ });
49
238
  }
50
239
  registerLiteXml() {
51
240
  const litexmlService = this.kernel.requireService(ILitexmlService);
@@ -80,7 +269,7 @@ const TablePlugin = class extends KernelPlugin {
80
269
  for (const child of children) if ((child.children?.length || -1) > maxTdlen) maxTdlen = child.children.length;
81
270
  return INodeHelper.createElementNode(TableNode$1.getType(), {
82
271
  children,
83
- colWidths: colWidths.length > 0 ? colWidths : new Array(maxTdlen).fill(750 / maxTdlen),
272
+ colWidths: colWidths.length > 0 ? colWidths : createDefaultTableColWidths(maxTdlen),
84
273
  direction: null,
85
274
  format: "",
86
275
  indent: 0,
@@ -136,7 +325,7 @@ const TablePlugin = class extends KernelPlugin {
136
325
  const colLen = node.children[0]?.children.length || 1;
137
326
  return INodeHelper.createElementNode("table", {
138
327
  children,
139
- colWidths: new Array(colLen).fill(750 / colLen),
328
+ colWidths: createDefaultTableColWidths(colLen),
140
329
  direction: null,
141
330
  format: "",
142
331
  indent: 0,
@@ -2,7 +2,7 @@ import { useTranslation } from "../../../../editor-kernel/react/useTranslation.j
2
2
  import { $canUnmerge, $selectLastDescendant, computeSelectionCount, currentCellBackgroundColor } from "./utils.js";
3
3
  import { Dropdown } from "@lobehub/ui";
4
4
  import { Grid2X2XIcon, PanelBottomCloseIcon, PanelLeftCloseIcon, PanelRightCloseIcon, PanelTopCloseIcon, TableColumnsSplitIcon, TableRowsSplitIcon } from "lucide-react";
5
- import { memo, useCallback, useEffect, useMemo, useState } from "react";
5
+ import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { $computeTableMapSkipCellCheck, $deleteTableColumnAtSelection, $deleteTableRowAtSelection, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $insertTableColumnAtSelection, $insertTableRowAtSelection, $isTableCellNode, $isTableSelection, $mergeCells, $unmergeCell, TableCellHeaderStates, TableCellNode, getTableElement, getTableObserverFromTableElement } from "@lexical/table";
8
8
  import { $getSelection, $setSelection } from "lexical";
@@ -14,8 +14,13 @@ import { $getSelection, $setSelection } from "lexical";
14
14
  * LICENSE file in the root directory of this source tree.
15
15
  *
16
16
  */
17
+ const TABLE_DELETE_PREVIEW_CLASS = "lobe-editor-table-delete-preview";
18
+ const range = (from, to) => {
19
+ return Array.from({ length: to - from + 1 }, (_, index) => from + index);
20
+ };
17
21
  const TableActionMenu = memo(({ editor, tableCellNode: _tableCellNode, cellMerge, children }) => {
18
22
  const [tableCellNode, updateTableCellNode] = useState(_tableCellNode);
23
+ const deletePreviewElementsRef = useRef([]);
19
24
  const [selectionCounts, updateSelectionCounts] = useState({
20
25
  columns: 1,
21
26
  rows: 1
@@ -24,6 +29,62 @@ const TableActionMenu = memo(({ editor, tableCellNode: _tableCellNode, cellMerge
24
29
  const [canUnmergeCell, setCanUnmergeCell] = useState(false);
25
30
  const [, setBackgroundColor] = useState(() => currentCellBackgroundColor(editor) || "");
26
31
  const t = useTranslation();
32
+ const clearDeletePreview = useCallback(() => {
33
+ deletePreviewElementsRef.current.forEach((element) => {
34
+ element.classList.remove(TABLE_DELETE_PREVIEW_CLASS);
35
+ });
36
+ document.querySelectorAll(`.${TABLE_DELETE_PREVIEW_CLASS}`).forEach((element) => {
37
+ element.classList.remove(TABLE_DELETE_PREVIEW_CLASS);
38
+ });
39
+ deletePreviewElementsRef.current = [];
40
+ }, []);
41
+ const showDeletePreview = useCallback((target) => {
42
+ clearDeletePreview();
43
+ editor.getEditorState().read(() => {
44
+ if (!tableCellNode.isAttached()) return;
45
+ const latestTableCellNode = tableCellNode.getLatest();
46
+ if (!$isTableCellNode(latestTableCellNode)) return;
47
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(latestTableCellNode);
48
+ const [gridMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
49
+ const selection = $getSelection();
50
+ const previewCellKeys = /* @__PURE__ */ new Set();
51
+ if (target === "columns") {
52
+ const selectedColumns = $isTableSelection(selection) && selection.tableKey === tableNode.getKey() ? range(selection.getShape().fromX, selection.getShape().toX) : [];
53
+ const columnIndexes = selectedColumns.length > 0 ? selectedColumns : [$getTableColumnIndexFromTableCellNode(latestTableCellNode)];
54
+ for (const row of gridMap) for (const columnIndex of columnIndexes) {
55
+ const cell = row[columnIndex]?.cell;
56
+ if (cell) previewCellKeys.add(cell.getKey());
57
+ }
58
+ } else if (target === "rows") {
59
+ const selectedRows = $isTableSelection(selection) && selection.tableKey === tableNode.getKey() ? range(selection.getShape().fromY, selection.getShape().toY) : [];
60
+ const rowIndexes = selectedRows.length > 0 ? selectedRows : [$getTableRowIndexFromTableCellNode(latestTableCellNode)];
61
+ for (const rowIndex of rowIndexes) {
62
+ const row = gridMap[rowIndex];
63
+ if (!row) continue;
64
+ for (const mapCell of row) if (mapCell?.cell) previewCellKeys.add(mapCell.cell.getKey());
65
+ }
66
+ } else for (const row of gridMap) for (const mapCell of row) if (mapCell?.cell) previewCellKeys.add(mapCell.cell.getKey());
67
+ for (const cellKey of previewCellKeys) {
68
+ const element = editor.getElementByKey(cellKey);
69
+ if (element instanceof HTMLElement) {
70
+ element.classList.add(TABLE_DELETE_PREVIEW_CLASS);
71
+ deletePreviewElementsRef.current.push(element);
72
+ }
73
+ }
74
+ });
75
+ }, [
76
+ clearDeletePreview,
77
+ editor,
78
+ tableCellNode
79
+ ]);
80
+ const renderDeleteMenuLabel = useCallback((label, target) => {
81
+ return /* @__PURE__ */ jsx("span", {
82
+ onMouseEnter: () => showDeletePreview(target),
83
+ onMouseLeave: clearDeletePreview,
84
+ style: { display: "block" },
85
+ children: label
86
+ });
87
+ }, [clearDeletePreview, showDeletePreview]);
27
88
  useEffect(() => {
28
89
  return editor.registerMutationListener(TableCellNode, (nodeMutations) => {
29
90
  if (nodeMutations.get(tableCellNode.getKey()) === "updated") {
@@ -45,6 +106,16 @@ const TableActionMenu = memo(({ editor, tableCellNode: _tableCellNode, cellMerge
45
106
  setCanUnmergeCell($canUnmerge());
46
107
  });
47
108
  }, [editor]);
109
+ useEffect(() => {
110
+ return () => {
111
+ clearDeletePreview();
112
+ };
113
+ }, [clearDeletePreview]);
114
+ useEffect(() => {
115
+ return editor.registerUpdateListener(() => {
116
+ clearDeletePreview();
117
+ });
118
+ }, [clearDeletePreview, editor]);
48
119
  const clearTableSelection = useCallback(() => {
49
120
  editor.update(() => {
50
121
  if (tableCellNode.isAttached()) {
@@ -83,25 +154,29 @@ const TableActionMenu = memo(({ editor, tableCellNode: _tableCellNode, cellMerge
83
154
  });
84
155
  }, [editor, selectionCounts.columns]);
85
156
  const deleteTableRowAtSelection = useCallback(() => {
157
+ clearDeletePreview();
86
158
  editor.update(() => {
87
159
  $deleteTableRowAtSelection();
88
160
  });
89
- }, [editor]);
161
+ }, [clearDeletePreview, editor]);
90
162
  const deleteTableAtSelection = useCallback(() => {
163
+ clearDeletePreview();
91
164
  editor.update(() => {
92
165
  $getTableNodeFromLexicalNodeOrThrow(tableCellNode).remove();
93
166
  clearTableSelection();
94
167
  });
95
168
  }, [
169
+ clearDeletePreview,
96
170
  editor,
97
171
  tableCellNode,
98
172
  clearTableSelection
99
173
  ]);
100
174
  const deleteTableColumnAtSelection = useCallback(() => {
175
+ clearDeletePreview();
101
176
  editor.update(() => {
102
177
  $deleteTableColumnAtSelection();
103
178
  });
104
- }, [editor]);
179
+ }, [clearDeletePreview, editor]);
105
180
  const toggleTableRowIsHeader = useCallback(() => {
106
181
  editor.update(() => {
107
182
  const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
@@ -178,20 +253,20 @@ const TableActionMenu = memo(({ editor, tableCellNode: _tableCellNode, cellMerge
178
253
  {
179
254
  icon: TableColumnsSplitIcon,
180
255
  key: "table-delete-columns",
181
- label: t(`table.deleteColumn`),
256
+ label: renderDeleteMenuLabel(t(`table.deleteColumn`), "columns"),
182
257
  onClick: () => deleteTableColumnAtSelection()
183
258
  },
184
259
  {
185
260
  icon: TableRowsSplitIcon,
186
261
  key: "table-delete-rows",
187
- label: t(`table.deleteRow`),
262
+ label: renderDeleteMenuLabel(t(`table.deleteRow`), "rows"),
188
263
  onClick: () => deleteTableRowAtSelection()
189
264
  },
190
265
  { type: "divider" },
191
266
  {
192
267
  icon: Grid2X2XIcon,
193
268
  key: "table-delete",
194
- label: t(`table.delete`),
269
+ label: renderDeleteMenuLabel(t(`table.delete`), "table"),
195
270
  onClick: () => deleteTableAtSelection()
196
271
  }
197
272
  ];
@@ -209,6 +284,7 @@ const TableActionMenu = memo(({ editor, tableCellNode: _tableCellNode, cellMerge
209
284
  deleteTableColumnAtSelection,
210
285
  deleteTableRowAtSelection,
211
286
  deleteTableAtSelection,
287
+ renderDeleteMenuLabel,
212
288
  toggleTableRowIsHeader,
213
289
  toggleTableColumnIsHeader
214
290
  ]) },
@@ -7,7 +7,7 @@ import { ChevronDown } from "lucide-react";
7
7
  import { memo, useCallback, useEffect, useRef, useState } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
9
9
  import { $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, $isTableCellNode, $isTableSelection, getTableElement, getTableObserverFromTableElement } from "@lexical/table";
10
- import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_CRITICAL, SELECTION_CHANGE_COMMAND, getDOMSelection } from "lexical";
10
+ import { $getNodeByKey, $getSelection, $isRangeSelection, COMMAND_PRIORITY_CRITICAL, SELECTION_CHANGE_COMMAND, getDOMSelection } from "lexical";
11
11
  import { mergeRegister } from "@lexical/utils";
12
12
  //#region src/plugins/table/react/TableActionMenu/index.tsx
13
13
  /**
@@ -48,7 +48,9 @@ const TableActionMenu = memo(({ cellMerge, editor }) => {
48
48
  let tableObserver = null;
49
49
  let tableCellParentNodeDOM = null;
50
50
  if ($isRangeSelection(selection) && rootElement !== null && nativeSelection !== null && rootElement.contains(nativeSelection.anchorNode)) {
51
- const tableCellNodeFromSelection = $getTableCellNodeFromLexicalNode(selection.anchor.getNode());
51
+ const anchorNode = $getNodeByKey(selection.anchor.key);
52
+ if (!anchorNode) return disable();
53
+ const tableCellNodeFromSelection = $getTableCellNodeFromLexicalNode(anchorNode);
52
54
  if (!tableCellNodeFromSelection) return disable();
53
55
  tableCellParentNodeDOM = editor.getElementByKey(tableCellNodeFromSelection.getKey());
54
56
  if (!tableCellParentNodeDOM || !tableCellNodeFromSelection.isAttached()) return disable();
@@ -59,8 +61,10 @@ const TableActionMenu = memo(({ cellMerge, editor }) => {
59
61
  tableObserver = getTableObserverFromTableElement(tableElement);
60
62
  setTableMenuCellNode(tableCellNodeFromSelection);
61
63
  } else if ($isTableSelection(selection)) {
62
- const anchorNode = $getTableCellNodeFromLexicalNode(selection.anchor.getNode());
63
- if (!$isTableCellNode(anchorNode)) throw new Error("TableSelection anchorNode must be a TableCellNode");
64
+ const selectionAnchorNode = $getNodeByKey(selection.anchor.key);
65
+ if (!selectionAnchorNode) return disable();
66
+ const anchorNode = $getTableCellNodeFromLexicalNode(selectionAnchorNode);
67
+ if (!$isTableCellNode(anchorNode)) return disable();
64
68
  const tableNode = $getTableNodeFromLexicalNodeOrThrow(anchorNode);
65
69
  const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNode.getKey()));
66
70
  if (tableElement === null) throw new Error("TableActionMenu: Expected to find tableElement in DOM");
@@ -68,6 +72,7 @@ const TableActionMenu = memo(({ cellMerge, editor }) => {
68
72
  tableCellParentNodeDOM = editor.getElementByKey(anchorNode.getKey());
69
73
  if (tableCellParentNodeDOM === null) return disable();
70
74
  if (checkTableCellOverflow(tableCellParentNodeDOM)) return disable();
75
+ setTableMenuCellNode(anchorNode);
71
76
  } else if (!activeElement) return disable();
72
77
  if (tableObserver === null || tableCellParentNodeDOM === null) return disable();
73
78
  const enabled = !tableObserver || !tableObserver.isSelecting;