@lobehub/editor 4.15.2 → 4.16.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.
Files changed (52) hide show
  1. package/es/editor-kernel/react/useDecorators.js +14 -8
  2. package/es/headless.d.ts +2 -0
  3. package/es/headless.js +710 -46
  4. package/es/index.d.ts +4 -3
  5. package/es/index.js +4 -3
  6. package/es/locale/index.d.ts +2 -0
  7. package/es/locale/index.js +5 -1
  8. package/es/plugins/auto-complete/plugin/index.js +3 -3
  9. package/es/plugins/block/index.d.ts +1 -1
  10. package/es/plugins/block/plugin/index.js +78 -2
  11. package/es/plugins/block/react/ReactBlockPlugin.js +172 -16
  12. package/es/plugins/block/react/drag/drag-utils.js +37 -10
  13. package/es/plugins/block/service/i-block-menu-service.d.ts +18 -1
  14. package/es/plugins/block/service/i-block-menu-service.js +24 -0
  15. package/es/plugins/block/service/index.d.ts +1 -1
  16. package/es/plugins/codeblock/plugin/index.js +25 -1
  17. package/es/plugins/common/plugin/register.js +2 -2
  18. package/es/plugins/litexml/plugin/index.js +8 -2
  19. package/es/plugins/slash/plugin/index.js +1 -1
  20. package/es/plugins/slash/react/ReactSlashPlugin.js +4 -4
  21. package/es/plugins/table/command/index.d.ts +13 -1
  22. package/es/plugins/table/command/index.js +220 -39
  23. package/es/plugins/table/index.d.ts +3 -2
  24. package/es/plugins/table/node/index.d.ts +2 -0
  25. package/es/plugins/table/node/index.js +130 -2
  26. package/es/plugins/table/plugin/index.d.ts +6 -0
  27. package/es/plugins/table/plugin/index.js +193 -4
  28. package/es/plugins/table/react/TableActionMenu/ActionMenu.js +82 -6
  29. package/es/plugins/table/react/TableActionMenu/index.js +9 -4
  30. package/es/plugins/table/react/TableColController.js +354 -0
  31. package/es/plugins/table/react/TableController/hooks.js +201 -0
  32. package/es/plugins/table/react/TableController/style.js +264 -0
  33. package/es/plugins/table/react/TableController/utils.js +25 -0
  34. package/es/plugins/table/react/TableControllerButton.js +81 -0
  35. package/es/plugins/table/react/TableControllerMenu.js +123 -0
  36. package/es/plugins/table/react/TableInsertButton.js +25 -0
  37. package/es/plugins/table/react/TableResize/index.js +153 -78
  38. package/es/plugins/table/react/TableRowController.js +349 -0
  39. package/es/plugins/table/react/hooks.js +77 -0
  40. package/es/plugins/table/react/index.js +139 -16
  41. package/es/plugins/table/react/style.js +89 -8
  42. package/es/plugins/table/react/type.d.ts +2 -0
  43. package/es/plugins/table/react/useAutoFitPastedTable.js +189 -0
  44. package/es/plugins/table/service/i-table-controller-menu-service.d.ts +44 -0
  45. package/es/plugins/table/service/i-table-controller-menu-service.js +31 -0
  46. package/es/plugins/table/service/index.d.ts +1 -0
  47. package/es/plugins/table/utils/autoFitColumnWidth.js +87 -0
  48. package/es/plugins/table/utils/distributeColumnWidth.js +37 -0
  49. package/es/plugins/table/utils/index.js +102 -2
  50. package/es/react/EditorProvider/index.d.ts +2 -2
  51. package/es/renderer/LexicalDiff.d.ts +2 -2
  52. package/package.json +1 -1
package/es/headless.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { createHeadlessEditor as createHeadlessEditor$1 } from "@lexical/headless";
2
2
  import { createEmptyHistoryState, registerHistory } from "@lexical/history";
3
- import { $createTableNodeWithDimensions, $createTableSelection, $findTableNode, $isTableCellNode, $isTableNode, $isTableSelection, TableCellNode, TableNode, TableNode as TableNode$1, TableRowNode, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive } from "@lexical/table";
3
+ import { $computeTableMapSkipCellCheck, $createTableNodeWithDimensions, $createTableSelection, $deleteTableColumnAtSelection, $deleteTableRowAtSelection, $findTableNode, $insertTableColumnAtSelection, $insertTableRowAtSelection, $isSimpleTable, $isTableCellNode, $isTableNode, $isTableRowNode, $isTableSelection, TableCellNode, TableNode, TableNode as TableNode$1, TableRowNode, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive } from "@lexical/table";
4
4
  import { get, merge, template, templateSettings } from "es-toolkit/compat";
5
5
  import EventEmitter from "eventemitter3";
6
- import { $applyNodeReplacement, $caretFromPoint, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createRangeSelection, $createTextNode, $getCaretRange, $getCharacterOffsets, $getChildCaret, $getNearestNodeFromDOMNode, $getNodeByKey, $getPreviousSelection, $getRoot, $getSelection, $insertNodes, $isBlockElementNode, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isNodeSelection, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isTextNode, $isTextPointCaret, $nodesOfType, $normalizeSelection__EXPERIMENTAL, $parseSerializedNode, $setSelection, COLLABORATION_TAG, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, DecoratorNode, ElementNode, FORMAT_TEXT_COMMAND, HISTORIC_TAG, HISTORY_MERGE_TAG, HISTORY_PUSH_TAG, INDENT_CONTENT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, IS_BOLD, IS_CODE, IS_ITALIC, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, REDO_COMMAND, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, createCommand, createEditor, getNearestEditorFromDOMNode, isHTMLElement, isModifierMatch, resetRandomKey } from "lexical";
6
+ import { $applyNodeReplacement, $caretFromPoint, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createRangeSelection, $createTextNode, $getCaretRange, $getCharacterOffsets, $getChildCaret, $getNearestNodeFromDOMNode, $getNodeByKey, $getPreviousSelection, $getRoot, $getSelection, $insertNodes, $isBlockElementNode, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isNodeSelection, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isTextNode, $isTextPointCaret, $nodesOfType, $normalizeSelection__EXPERIMENTAL, $parseSerializedNode, $setSelection, COLLABORATION_TAG, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, DecoratorNode, ElementNode, FORMAT_TEXT_COMMAND, HISTORIC_TAG, HISTORY_MERGE_TAG, HISTORY_PUSH_TAG, INDENT_CONTENT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, IS_BOLD, IS_CODE, IS_ITALIC, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, REDO_COMMAND, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, createCommand, createEditor, getNearestEditorFromDOMNode, isHTMLElement, isModifierMatch, resetRandomKey, setDOMUnmanaged } from "lexical";
7
7
  import { $createHeadingNode, $createQuoteNode, $isHeadingNode, $isQuoteNode, HeadingNode, QuoteNode, registerRichText } from "@lexical/rich-text";
8
8
  import createDebug from "debug";
9
9
  import { $filter, $findMatchingParent, $getNearestBlockElementAncestorOrThrow, $getNearestNodeOfType, $insertNodeToNearestRoot, CAN_USE_DOM, IS_APPLE as isApple, addClassNamesToElement, calculateZoomLevel, isHTMLAnchorElement, isHTMLElement as isHTMLElement$1, mergeRegister } from "@lexical/utils";
@@ -20,7 +20,11 @@ import { $isCodeHighlightNode, $isCodeNode, CodeHighlightNode, CodeNode } from "
20
20
  import { bundledLanguagesInfo } from "shiki";
21
21
  //#region src/locale/index.ts
22
22
  var locale_default = {
23
- block: { delete: "Delete block" },
23
+ block: {
24
+ copy: "Copy",
25
+ delete: "Delete block",
26
+ select: "Select"
27
+ },
24
28
  cancel: "Cancel",
25
29
  codemirror: {
26
30
  copySuccess: "Code copied to clipboard",
@@ -3815,8 +3819,14 @@ const LitexmlPlugin = class extends KernelPlugin {
3815
3819
  this.register(editor.registerNodeTransform(DiffNode, (node) => {
3816
3820
  if (node.diffType === "modify" && node.getChildrenSize() === 1) node.setDiffType("remove");
3817
3821
  }));
3818
- this.register(editor.registerUpdateListener(({ editorState, prevEditorState }) => {
3822
+ this.register(editor.registerUpdateListener(({ editorState, prevEditorState, tags }) => {
3819
3823
  if (editorState === prevEditorState) return;
3824
+ if (tags.has(HISTORIC_TAG)) return;
3825
+ let shouldNormalize = false;
3826
+ editorState.read(() => {
3827
+ shouldNormalize = $nodesOfType(DiffNode).some((node) => node.diffType === "modify" && node.getChildrenSize() === 1);
3828
+ });
3829
+ if (!shouldNormalize) return;
3820
3830
  editor.update(() => {
3821
3831
  const diffNodes = $nodesOfType(DiffNode);
3822
3832
  for (const node of diffNodes) if (node.diffType === "modify" && node.getChildrenSize() === 1) node.setDiffType("remove");
@@ -4648,7 +4658,7 @@ function registerLastElement(editor) {
4648
4658
  root.append(paragraph);
4649
4659
  }
4650
4660
  isProcessing = false;
4651
- });
4661
+ }, { tag: HISTORIC_TAG });
4652
4662
  });
4653
4663
  }
4654
4664
  });
@@ -6395,75 +6405,544 @@ const ListPlugin = class extends KernelPlugin {
6395
6405
  }
6396
6406
  };
6397
6407
  //#endregion
6408
+ //#region src/plugins/block/service/i-block-menu-service.ts
6409
+ const IBlockMenuService = genServiceId("BlockMenuService");
6410
+ function createDefaultTableColWidths(columnCount, tableWidth = 750) {
6411
+ const safeColumnCount = Math.max(1, columnCount);
6412
+ const columnWidth = Math.floor(tableWidth / safeColumnCount);
6413
+ const colWidths = Array.from({ length: safeColumnCount }, () => columnWidth);
6414
+ colWidths[safeColumnCount - 1] = tableWidth - columnWidth * (safeColumnCount - 1);
6415
+ return colWidths;
6416
+ }
6417
+ function syncTableWidthDOM(editor, tableKey, colWidths) {
6418
+ const tableElement = editor.getElementByKey(tableKey);
6419
+ const table = tableElement instanceof HTMLTableElement ? tableElement : tableElement?.querySelector("table.editor_table, table");
6420
+ if (!(table instanceof HTMLTableElement)) return;
6421
+ table.style.width = `${colWidths.reduce((total, width) => total + width, 0)}px`;
6422
+ }
6423
+ //#endregion
6424
+ //#region src/plugins/table/utils/autoFitColumnWidth.ts
6425
+ const AUTO_FIT_MIN_COLUMN_WIDTH = 75;
6426
+ const MEASURE_CONTAINER_CLASS = "lobe-editor-table-auto-fit-measure";
6427
+ const getTableElement$1 = (editor, tableKey) => {
6428
+ const tableElement = editor.getElementByKey(tableKey);
6429
+ return tableElement instanceof HTMLTableElement ? tableElement : tableElement?.querySelector("table.editor_table, table");
6430
+ };
6431
+ const applyNoWrapMeasureStyle = (element) => {
6432
+ element.style.whiteSpace = "nowrap";
6433
+ element.style.wordBreak = "normal";
6434
+ element.style.overflowWrap = "normal";
6435
+ element.style.setProperty("text-wrap", "nowrap");
6436
+ };
6437
+ const createMeasureContainer = (tableElement) => {
6438
+ const container = document.createElement("div");
6439
+ container.className = MEASURE_CONTAINER_CLASS;
6440
+ container.style.insetBlockStart = "0";
6441
+ container.style.insetInlineStart = "-100000px";
6442
+ container.style.pointerEvents = "none";
6443
+ container.style.position = "absolute";
6444
+ container.style.visibility = "hidden";
6445
+ container.style.zIndex = "-1";
6446
+ (tableElement.parentElement ?? document.body).append(container);
6447
+ return container;
6448
+ };
6449
+ const measureCellNoWrapWidth = (cellElement, measureContainer) => {
6450
+ const table = document.createElement("table");
6451
+ const tbody = document.createElement("tbody");
6452
+ const row = document.createElement("tr");
6453
+ const clone = cellElement.cloneNode(true);
6454
+ table.className = "editor_table";
6455
+ table.style.borderCollapse = "collapse";
6456
+ table.style.borderSpacing = "0";
6457
+ table.style.tableLayout = "auto";
6458
+ table.style.width = "max-content";
6459
+ delete clone.dataset.lexicalKey;
6460
+ clone.style.blockSize = "auto";
6461
+ clone.style.display = "table-cell";
6462
+ clone.style.inlineSize = "max-content";
6463
+ clone.style.maxInlineSize = "none";
6464
+ clone.style.minInlineSize = "0";
6465
+ clone.style.overflow = "visible";
6466
+ clone.style.position = "static";
6467
+ clone.style.width = "max-content";
6468
+ applyNoWrapMeasureStyle(table);
6469
+ applyNoWrapMeasureStyle(clone);
6470
+ clone.querySelectorAll("*").forEach(applyNoWrapMeasureStyle);
6471
+ row.append(clone);
6472
+ tbody.append(row);
6473
+ table.append(tbody);
6474
+ measureContainer.append(table);
6475
+ const width = Math.ceil(Math.max(table.getBoundingClientRect().width, clone.getBoundingClientRect().width));
6476
+ table.remove();
6477
+ return width;
6478
+ };
6479
+ const getAutoFitTableColumnWidths = (editor, tableNode, columnIndexes) => {
6480
+ const tableElement = getTableElement$1(editor, tableNode.getKey());
6481
+ if (!tableElement || columnIndexes.length === 0) return null;
6482
+ const columnCount = tableNode.getColumnCount();
6483
+ const targetColumnIndexes = [...new Set(columnIndexes)].filter((index) => index >= 0 && index < columnCount);
6484
+ if (targetColumnIndexes.length === 0) return null;
6485
+ const measureContainer = createMeasureContainer(tableElement);
6486
+ try {
6487
+ const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
6488
+ const nextColWidths = [...tableNode.getColWidths() || createDefaultTableColWidths(columnCount)];
6489
+ for (const columnIndex of targetColumnIndexes) {
6490
+ const measuredCellKeys = /* @__PURE__ */ new Set();
6491
+ let columnWidth = AUTO_FIT_MIN_COLUMN_WIDTH;
6492
+ for (const row of tableMap) {
6493
+ const cell = row[columnIndex]?.cell;
6494
+ if (!cell || cell.getColSpan() > 1 || measuredCellKeys.has(cell.getKey())) continue;
6495
+ const cellElement = editor.getElementByKey(cell.getKey());
6496
+ if (!(cellElement instanceof HTMLElement)) continue;
6497
+ measuredCellKeys.add(cell.getKey());
6498
+ columnWidth = Math.max(columnWidth, measureCellNoWrapWidth(cellElement, measureContainer));
6499
+ }
6500
+ nextColWidths[columnIndex] = columnWidth;
6501
+ }
6502
+ return nextColWidths;
6503
+ } finally {
6504
+ measureContainer.remove();
6505
+ }
6506
+ };
6507
+ //#endregion
6508
+ //#region src/plugins/table/utils/distributeColumnWidth.ts
6509
+ const DISTRIBUTE_MIN_COLUMN_WIDTH = 75;
6510
+ const getTableElement = (editor, tableKey) => {
6511
+ const tableElement = editor.getElementByKey(tableKey);
6512
+ return tableElement instanceof HTMLTableElement ? tableElement : tableElement?.querySelector("table.editor_table, table");
6513
+ };
6514
+ const getScrollContainerWidth = (tableElement) => {
6515
+ const container = tableElement.closest(".lobe-editor-table-scroll-wrapper") ?? tableElement.parentElement;
6516
+ if (!container) return 0;
6517
+ return container.clientWidth || container.getBoundingClientRect().width;
6518
+ };
6519
+ const getHorizontalBorderWidth = (tableElement) => {
6520
+ const firstRow = tableElement.rows[0];
6521
+ if (!firstRow) return 0;
6522
+ const cells = Array.from(firstRow.cells);
6523
+ if (cells.length === 0) return 0;
6524
+ return cells.reduce((total, cell, index) => {
6525
+ const style = getComputedStyle(cell);
6526
+ const borderInlineStartWidth = index === 0 ? Number.parseFloat(style.borderInlineStartWidth) || 0 : 0;
6527
+ const borderInlineEndWidth = Number.parseFloat(style.borderInlineEndWidth) || 0;
6528
+ return total + borderInlineStartWidth + borderInlineEndWidth;
6529
+ }, 0);
6530
+ };
6531
+ const getDistributedTableColumnWidths = (editor, tableNode) => {
6532
+ const columnCount = tableNode.getColumnCount();
6533
+ if (columnCount === 0) return null;
6534
+ const tableElement = getTableElement(editor, tableNode.getKey());
6535
+ if (!tableElement) return null;
6536
+ const minTableWidth = DISTRIBUTE_MIN_COLUMN_WIDTH * columnCount;
6537
+ const targetTableWidth = Math.max(getScrollContainerWidth(tableElement) - getHorizontalBorderWidth(tableElement), minTableWidth);
6538
+ const columnWidth = Math.floor(targetTableWidth / columnCount);
6539
+ const colWidths = Array.from({ length: columnCount }, () => columnWidth);
6540
+ colWidths[columnCount - 1] = targetTableWidth - columnWidth * (columnCount - 1);
6541
+ return colWidths;
6542
+ };
6543
+ //#endregion
6398
6544
  //#region src/plugins/table/command/index.ts
6399
6545
  const INSERT_TABLE_COMMAND = createCommand();
6400
6546
  const SELECT_TABLE_COMMAND = createCommand();
6547
+ const INSERT_TABLE_COLUMN_COMMAND = createCommand();
6548
+ const INSERT_TABLE_ROW_COMMAND = createCommand();
6549
+ const SYNC_TABLE_COLUMN_WIDTH_COMMAND = createCommand();
6550
+ const AUTO_FIT_TABLE_COLUMN_WIDTH_COMMAND = createCommand();
6551
+ const DISTRIBUTE_TABLE_COLUMN_WIDTH_COMMAND = createCommand();
6552
+ const MOVE_TABLE_COLUMN_COMMAND = createCommand();
6553
+ const MOVE_TABLE_ROW_COMMAND = createCommand();
6554
+ const resetTableScrollLeft = (editor, tableKey) => {
6555
+ const tableElement = editor.getElementByKey(tableKey);
6556
+ const scrollWrapper = (tableElement instanceof HTMLTableElement ? tableElement : tableElement?.querySelector("table.editor_table, table"))?.closest(".lobe-editor-table-scroll-wrapper");
6557
+ if (scrollWrapper) scrollWrapper.scrollLeft = 0;
6558
+ };
6559
+ const $selectFirstDescendant = (node) => {
6560
+ const firstDescendant = node.getFirstDescendant();
6561
+ if ($isTextNode(firstDescendant)) firstDescendant.select();
6562
+ else node.selectStart();
6563
+ };
6564
+ const getMoveRange = (selectedIndexes, targetIndex, insertAfter = false) => {
6565
+ if (selectedIndexes.length === 0) return null;
6566
+ const sortedIndexes = [...selectedIndexes].sort((a, b) => a - b);
6567
+ const from = sortedIndexes[0];
6568
+ const to = sortedIndexes.at(-1) ?? from;
6569
+ const count = to - from + 1;
6570
+ const insertionIndex = insertAfter ? targetIndex + 1 : targetIndex;
6571
+ if (insertionIndex >= from && insertionIndex <= to + 1) return null;
6572
+ return {
6573
+ count,
6574
+ from,
6575
+ target: insertionIndex > to ? insertionIndex - count : insertionIndex,
6576
+ to
6577
+ };
6578
+ };
6579
+ const $selectTableRows = (tableNode, from, to) => {
6580
+ const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
6581
+ const firstRow = tableMap[from];
6582
+ const lastRow = tableMap[to];
6583
+ const firstCell = firstRow?.[0]?.cell;
6584
+ const lastCell = lastRow?.[lastRow.length - 1]?.cell;
6585
+ if (!firstCell || !lastCell) return false;
6586
+ const tableSelection = $createTableSelection();
6587
+ tableSelection.set(tableNode.getKey(), firstCell.getKey(), lastCell.getKey());
6588
+ $setSelection(tableSelection);
6589
+ return true;
6590
+ };
6591
+ const $selectTableColumns = (tableNode, from, to) => {
6592
+ const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
6593
+ const firstCell = tableMap.find((row) => row[from])?.[from]?.cell;
6594
+ const lastCell = [...tableMap].reverse().find((row) => row[to])?.[to]?.cell;
6595
+ if (!firstCell || !lastCell) return false;
6596
+ const tableSelection = $createTableSelection();
6597
+ tableSelection.set(tableNode.getKey(), firstCell.getKey(), lastCell.getKey());
6598
+ $setSelection(tableSelection);
6599
+ return true;
6600
+ };
6601
+ const getRangeFromSelection = (selection, table, targetIndex, direction, crossAxisLength, anchorIndex) => {
6602
+ if (anchorIndex !== void 0) return {
6603
+ from: Math.min(anchorIndex, targetIndex),
6604
+ to: Math.max(anchorIndex, targetIndex)
6605
+ };
6606
+ if (!$isTableSelection(selection) || selection.tableKey !== table) return {
6607
+ from: 0,
6608
+ to: targetIndex
6609
+ };
6610
+ const shape = selection.getShape();
6611
+ if (!(direction === "row" ? shape.fromX === 0 && shape.toX === crossAxisLength - 1 : shape.fromY === 0 && shape.toY === crossAxisLength - 1)) return {
6612
+ from: 0,
6613
+ to: targetIndex
6614
+ };
6615
+ const from = direction === "row" ? shape.fromY : shape.fromX;
6616
+ const to = direction === "row" ? shape.toY : shape.toX;
6617
+ return {
6618
+ from: Math.min(from, targetIndex),
6619
+ to: Math.max(to, targetIndex)
6620
+ };
6621
+ };
6401
6622
  function registerTableCommand(editor) {
6402
6623
  return mergeRegister(editor.registerCommand(INSERT_TABLE_COMMAND, ({ rows, columns, includeHeaders }) => {
6403
6624
  const selection = $getSelection() || $getPreviousSelection();
6404
6625
  if (!selection || !$isRangeSelection(selection)) return false;
6405
- if ($findTableNode(selection.anchor.getNode())) return false;
6406
- const anchorNode = selection.anchor.getNode();
6407
- const tableNode = $createTableNodeWithDimensions(Number(rows), Number(columns), includeHeaders);
6626
+ const anchorNode = $getNodeByKey(selection.anchor.key);
6627
+ if (!anchorNode) return false;
6628
+ if ($findTableNode(anchorNode)) return false;
6629
+ const rowCount = Number(rows);
6630
+ const columnCount = Number(columns);
6631
+ const tableNode = $createTableNodeWithDimensions(rowCount, columnCount, includeHeaders);
6632
+ tableNode.setColWidths(createDefaultTableColWidths(columnCount));
6408
6633
  if ($isElementNode(anchorNode) && anchorNode.isEmpty()) anchorNode.replace(tableNode);
6409
6634
  else $insertNodeToNearestRoot(tableNode);
6410
6635
  const firstDescendant = tableNode.getFirstDescendant();
6411
6636
  if ($isTextNode(firstDescendant)) firstDescendant.select();
6412
6637
  return true;
6413
- }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(SELECT_TABLE_COMMAND, ({ table, columnIndex, rowIndex }) => {
6414
- editor.update(() => {
6415
- const prevSelection = $getSelection();
6416
- const tableNode = $getNodeByKey(table);
6417
- if (!tableNode || !$isTableNode(tableNode)) return;
6418
- const tableSelection = $isTableSelection(prevSelection) ? prevSelection : $createTableSelection();
6419
- if (rowIndex !== void 0) {
6420
- const firstRow = tableNode.getChildren()[rowIndex];
6421
- if (!firstRow) return;
6422
- const firstCell = firstRow.getFirstChild();
6423
- const lastCell = firstRow.getLastChild();
6424
- if (!firstCell || !lastCell) return;
6425
- tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6426
- $setSelection(tableSelection);
6427
- } else if (columnIndex !== void 0) {
6428
- const firstRow = tableNode.getFirstChild();
6429
- const lastRow = tableNode.getLastChild();
6430
- if (!firstRow || !lastRow) return;
6431
- const firstCell = firstRow.getChildren()[columnIndex];
6432
- const lastCell = lastRow.getChildren()[columnIndex];
6433
- if (!firstCell || !lastCell) return;
6434
- tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6435
- $setSelection(tableSelection);
6436
- } else {
6437
- const firstRow = tableNode.getFirstChild();
6438
- const lastRow = tableNode.getLastChild();
6439
- if (!firstRow || !lastRow) return;
6440
- const firstCell = firstRow.getFirstChild();
6441
- const lastCell = lastRow.getLastChild();
6442
- if (!firstCell || !lastCell) return;
6443
- tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6444
- $setSelection(tableSelection);
6445
- }
6638
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(INSERT_TABLE_COLUMN_COMMAND, ({ table, columnIndex, insertAfter = true }) => {
6639
+ const tableNode = $getNodeByKey(table);
6640
+ if (!tableNode || !$isTableNode(tableNode)) return false;
6641
+ const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
6642
+ const firstCell = tableMap.find((row) => row[columnIndex])?.[columnIndex]?.cell;
6643
+ const lastCell = [...tableMap].reverse().find((row) => row[columnIndex])?.[columnIndex]?.cell;
6644
+ if (!firstCell || !lastCell) return false;
6645
+ const tableSelection = $createTableSelection();
6646
+ tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6647
+ $setSelection(tableSelection);
6648
+ $insertTableColumnAtSelection(insertAfter);
6649
+ return true;
6650
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(INSERT_TABLE_ROW_COMMAND, ({ table, rowIndex, insertAfter = true }) => {
6651
+ const tableNode = $getNodeByKey(table);
6652
+ if (!tableNode || !$isTableNode(tableNode)) return false;
6653
+ const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
6654
+ const row = tableMap[rowIndex];
6655
+ const firstCell = row?.[0]?.cell;
6656
+ const lastCell = row?.[row.length - 1]?.cell;
6657
+ if (!firstCell || !lastCell) return false;
6658
+ const tableSelection = $createTableSelection();
6659
+ tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6660
+ $setSelection(tableSelection);
6661
+ const insertedRow = $insertTableRowAtSelection(insertAfter);
6662
+ if (insertedRow) $selectFirstDescendant(insertedRow);
6663
+ return true;
6664
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(SYNC_TABLE_COLUMN_WIDTH_COMMAND, ({ table, columnIndex }) => {
6665
+ const tableNode = $getNodeByKey(table);
6666
+ if (!tableNode || !$isTableNode(tableNode)) return false;
6667
+ const columnCount = tableNode.getColumnCount();
6668
+ const selectedWidth = (tableNode.getColWidths() || createDefaultTableColWidths(columnCount))[columnIndex];
6669
+ if (selectedWidth === void 0) return false;
6670
+ const nextColWidths = Array.from({ length: columnCount }, () => selectedWidth);
6671
+ tableNode.setColWidths(nextColWidths);
6672
+ requestAnimationFrame(() => {
6673
+ syncTableWidthDOM(editor, table, nextColWidths);
6446
6674
  });
6447
- return false;
6675
+ return true;
6676
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(AUTO_FIT_TABLE_COLUMN_WIDTH_COMMAND, ({ table, columnIndexes }) => {
6677
+ const tableNode = $getNodeByKey(table);
6678
+ if (!tableNode || !$isTableNode(tableNode)) return false;
6679
+ const nextColWidths = getAutoFitTableColumnWidths(editor, tableNode, columnIndexes);
6680
+ if (!nextColWidths) return false;
6681
+ tableNode.setColWidths(nextColWidths);
6682
+ requestAnimationFrame(() => {
6683
+ syncTableWidthDOM(editor, table, nextColWidths);
6684
+ });
6685
+ return true;
6686
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(DISTRIBUTE_TABLE_COLUMN_WIDTH_COMMAND, ({ table }) => {
6687
+ const tableNode = $getNodeByKey(table);
6688
+ if (!tableNode || !$isTableNode(tableNode)) return false;
6689
+ const nextColWidths = getDistributedTableColumnWidths(editor, tableNode);
6690
+ if (!nextColWidths) return false;
6691
+ tableNode.setColWidths(nextColWidths);
6692
+ requestAnimationFrame(() => {
6693
+ syncTableWidthDOM(editor, table, nextColWidths);
6694
+ resetTableScrollLeft(editor, table);
6695
+ });
6696
+ return true;
6697
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(MOVE_TABLE_COLUMN_COMMAND, ({ table, selectedColumns, columnIndex, insertAfter = false }) => {
6698
+ const tableNode = $getNodeByKey(table);
6699
+ if (!tableNode || !$isTableNode(tableNode) || !$isSimpleTable(tableNode)) return false;
6700
+ const moveRange = getMoveRange(selectedColumns, columnIndex, insertAfter);
6701
+ if (!moveRange) return false;
6702
+ const { count, from, target, to } = moveRange;
6703
+ tableNode.getChildren().filter($isTableRowNode).forEach((row) => {
6704
+ const cells = row.getChildren();
6705
+ const movedCells = cells.slice(from, to + 1);
6706
+ const nextCells = [...cells.slice(0, from), ...cells.slice(to + 1)];
6707
+ nextCells.splice(target, 0, ...movedCells);
6708
+ row.splice(0, cells.length, nextCells);
6709
+ });
6710
+ const colWidths = tableNode.getColWidths();
6711
+ if (colWidths && colWidths.length === tableNode.getColumnCount()) {
6712
+ const movedWidths = colWidths.slice(from, to + 1);
6713
+ const nextWidths = [...colWidths.slice(0, from), ...colWidths.slice(to + 1)];
6714
+ nextWidths.splice(target, 0, ...movedWidths);
6715
+ tableNode.setColWidths(nextWidths);
6716
+ }
6717
+ $selectTableColumns(tableNode, target, target + count - 1);
6718
+ return true;
6719
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(MOVE_TABLE_ROW_COMMAND, ({ table, selectedRows, rowIndex, insertAfter = false }) => {
6720
+ const tableNode = $getNodeByKey(table);
6721
+ if (!tableNode || !$isTableNode(tableNode) || !$isSimpleTable(tableNode)) return false;
6722
+ const moveRange = getMoveRange(selectedRows, rowIndex, insertAfter);
6723
+ if (!moveRange) return false;
6724
+ const { count, from, target, to } = moveRange;
6725
+ const rows = tableNode.getChildren();
6726
+ const movedRows = rows.slice(from, to + 1);
6727
+ const nextRows = [...rows.slice(0, from), ...rows.slice(to + 1)];
6728
+ nextRows.splice(target, 0, ...movedRows);
6729
+ tableNode.splice(0, rows.length, nextRows);
6730
+ $selectTableRows(tableNode, target, target + count - 1);
6731
+ return true;
6732
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(SELECT_TABLE_COMMAND, ({ table, anchorIndex, columnIndex, extend, rowIndex }) => {
6733
+ const prevSelection = $getSelection();
6734
+ const tableNode = $getNodeByKey(table);
6735
+ if (!tableNode || !$isTableNode(tableNode)) return false;
6736
+ const tableSelection = $isTableSelection(prevSelection) ? prevSelection : $createTableSelection();
6737
+ const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
6738
+ if (rowIndex !== void 0) {
6739
+ const { from, to } = extend ? getRangeFromSelection(prevSelection, table, rowIndex, "row", tableNode.getColumnCount(), anchorIndex) : {
6740
+ from: rowIndex,
6741
+ to: rowIndex
6742
+ };
6743
+ const firstRow = tableMap[from];
6744
+ const lastRow = tableMap[to];
6745
+ const firstCell = firstRow?.[0]?.cell;
6746
+ const lastCell = lastRow?.[lastRow.length - 1]?.cell;
6747
+ if (!firstCell || !lastCell) return false;
6748
+ tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6749
+ $setSelection(tableSelection);
6750
+ return true;
6751
+ }
6752
+ if (columnIndex !== void 0) {
6753
+ const { from, to } = extend ? getRangeFromSelection(prevSelection, table, columnIndex, "column", tableMap.length, anchorIndex) : {
6754
+ from: columnIndex,
6755
+ to: columnIndex
6756
+ };
6757
+ const firstCell = tableMap.find((row) => row[from])?.[from]?.cell;
6758
+ const lastCell = [...tableMap].reverse().find((row) => row[to])?.[to]?.cell;
6759
+ if (!firstCell || !lastCell) return false;
6760
+ tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6761
+ $setSelection(tableSelection);
6762
+ return true;
6763
+ }
6764
+ const firstRow = tableMap[0];
6765
+ const lastRow = tableMap.at(-1);
6766
+ const firstCell = firstRow?.[0]?.cell;
6767
+ const lastCell = lastRow?.[lastRow.length - 1]?.cell;
6768
+ if (!firstCell || !lastCell) return false;
6769
+ tableSelection.set(table, firstCell.getKey(), lastCell.getKey());
6770
+ $setSelection(tableSelection);
6771
+ return true;
6448
6772
  }, COMMAND_PRIORITY_EDITOR));
6449
6773
  }
6450
6774
  //#endregion
6451
6775
  //#region src/plugins/table/node/index.ts
6452
6776
  const OriginalCreateDOM = TableNode.prototype.createDOM;
6777
+ const OriginalUpdateDOM = TableNode.prototype.updateDOM;
6778
+ const SCROLL_INDICATOR_WIDTH = 24;
6779
+ function markTableControllerHost(element, withDecorator = false) {
6780
+ setDOMUnmanaged(element);
6781
+ if (withDecorator) element.dataset.lexicalDecorator = "true";
6782
+ }
6783
+ function updateTableScrollIndicators(scrollWrapper) {
6784
+ const maxScrollLeft = scrollWrapper.scrollWidth - scrollWrapper.clientWidth;
6785
+ const scrollLeft = scrollWrapper.scrollLeft;
6786
+ const hasOverflow = maxScrollLeft > 1;
6787
+ const showStart = hasOverflow && scrollLeft > 1;
6788
+ const showEnd = hasOverflow && scrollLeft < maxScrollLeft - 1;
6789
+ const startIndicator = scrollWrapper.querySelector(":scope > .lobe-editor-table-scroll-indicator-start");
6790
+ const endIndicator = scrollWrapper.querySelector(":scope > .lobe-editor-table-scroll-indicator-end");
6791
+ startIndicator?.classList.toggle("lobe-editor-table-scroll-indicator-visible", showStart);
6792
+ endIndicator?.classList.toggle("lobe-editor-table-scroll-indicator-visible", showEnd);
6793
+ if (startIndicator) startIndicator.style.transform = `translateX(${scrollLeft}px)`;
6794
+ if (endIndicator) endIndicator.style.transform = `translateX(${Math.max(scrollLeft + scrollWrapper.clientWidth - SCROLL_INDICATOR_WIDTH, 0)}px)`;
6795
+ }
6796
+ function ensureTableScrollIndicators(scrollWrapper) {
6797
+ const ensureIndicator = (className) => {
6798
+ const existingIndicator = scrollWrapper.querySelector(`:scope > .${className}`);
6799
+ if (existingIndicator instanceof HTMLElement) {
6800
+ setDOMUnmanaged(existingIndicator);
6801
+ return;
6802
+ }
6803
+ const indicator = document.createElement("span");
6804
+ indicator.className = `lobe-editor-table-scroll-indicator ${className}`;
6805
+ setDOMUnmanaged(indicator);
6806
+ scrollWrapper.append(indicator);
6807
+ };
6808
+ ensureIndicator("lobe-editor-table-scroll-indicator-start");
6809
+ ensureIndicator("lobe-editor-table-scroll-indicator-end");
6810
+ if (scrollWrapper.dataset.scrollIndicatorsReady === "true") {
6811
+ updateTableScrollIndicators(scrollWrapper);
6812
+ return;
6813
+ }
6814
+ scrollWrapper.dataset.scrollIndicatorsReady = "true";
6815
+ scrollWrapper.addEventListener("scroll", () => updateTableScrollIndicators(scrollWrapper), { passive: true });
6816
+ const resizeObserver = new ResizeObserver(() => updateTableScrollIndicators(scrollWrapper));
6817
+ resizeObserver.observe(scrollWrapper);
6818
+ resizeObserver.observe(scrollWrapper.querySelector("table") ?? scrollWrapper);
6819
+ requestAnimationFrame(() => updateTableScrollIndicators(scrollWrapper));
6820
+ }
6821
+ function ensureTableControllerDOM(element) {
6822
+ const table = element instanceof HTMLTableElement ? element : element.querySelector("table");
6823
+ if (!table) return;
6824
+ let scrollWrapper = table.closest(".lobe-editor-table-scroll-wrapper");
6825
+ if (!table.closest(".lobe-editor-table-scroll-wrapper")) {
6826
+ scrollWrapper = document.createElement("div");
6827
+ scrollWrapper.className = "lobe-editor-table-scroll-wrapper";
6828
+ table.parentElement?.insertBefore(scrollWrapper, table);
6829
+ scrollWrapper.append(table);
6830
+ }
6831
+ if (!scrollWrapper) return;
6832
+ const legacyToolbar = element.querySelector(":scope > .toolbar");
6833
+ if (legacyToolbar instanceof HTMLElement) {
6834
+ legacyToolbar.className = "toolbar-col";
6835
+ markTableControllerHost(legacyToolbar, true);
6836
+ scrollWrapper.append(legacyToolbar);
6837
+ }
6838
+ const ensureToolbar = (parent, className, withDecorator = false) => {
6839
+ const existingToolbar = parent.querySelector(`:scope > .${className}`);
6840
+ if (existingToolbar instanceof HTMLElement) {
6841
+ markTableControllerHost(existingToolbar, withDecorator);
6842
+ return;
6843
+ }
6844
+ if (!existingToolbar) {
6845
+ const toolbar = document.createElement("div");
6846
+ toolbar.className = className;
6847
+ markTableControllerHost(toolbar, withDecorator);
6848
+ parent.append(toolbar);
6849
+ }
6850
+ };
6851
+ const legacyDecoratedToolbar = scrollWrapper.querySelector(":scope > .toolbar[data-lexical-decorator]");
6852
+ if (legacyDecoratedToolbar instanceof HTMLElement) {
6853
+ legacyDecoratedToolbar.className = "toolbar-col";
6854
+ markTableControllerHost(legacyDecoratedToolbar, true);
6855
+ }
6856
+ const legacyPlainToolbar = scrollWrapper.querySelector(":scope > .toolbar:not([data-lexical-decorator])");
6857
+ if (legacyPlainToolbar instanceof HTMLElement) {
6858
+ legacyPlainToolbar.className = "toolbar-row";
6859
+ markTableControllerHost(legacyPlainToolbar, true);
6860
+ element.append(legacyPlainToolbar);
6861
+ }
6862
+ ensureToolbar(scrollWrapper, "toolbar-col", true);
6863
+ ensureToolbar(element, "toolbar-row", true);
6864
+ ensureTableScrollIndicators(scrollWrapper);
6865
+ }
6866
+ function reconcileTableDecorator(editor, node, decorator) {
6867
+ if (!decorator) return;
6868
+ if (typeof decorator === "function") {
6869
+ reconcileDecorator(editor, node.getKey(), decorator(node, editor));
6870
+ return;
6871
+ }
6872
+ if ("multi" in decorator) {
6873
+ const decorators = decorator.multi.map((item) => ({
6874
+ queryDOM: item.queryDOM,
6875
+ render: item.render(node, editor)
6876
+ }));
6877
+ reconcileDecorator(editor, node.getKey(), { multi: decorators });
6878
+ return;
6879
+ }
6880
+ reconcileDecorator(editor, node.getKey(), {
6881
+ queryDOM: decorator.queryDOM,
6882
+ render: decorator.render(node, editor)
6883
+ });
6884
+ }
6453
6885
  function patchTableNode() {
6886
+ if (TableNode.prototype.createDOM !== OriginalCreateDOM) return;
6454
6887
  Object.defineProperty(TableNode.prototype, "createDOM", {
6455
6888
  configurable: true,
6456
6889
  enumerable: false,
6457
6890
  value: function(config, editor) {
6458
6891
  const table = OriginalCreateDOM.call(this, config, editor);
6459
- const controller = document.createElement("div");
6460
- table.append(controller);
6892
+ ensureTableControllerDOM(table);
6893
+ const decorator = getKernelFromEditor(editor)?.getDecorator(TableNode.getType()) || null;
6894
+ reconcileTableDecorator(editor, this, decorator);
6895
+ return table;
6896
+ },
6897
+ writable: true
6898
+ });
6899
+ Object.defineProperty(TableNode.prototype, "updateDOM", {
6900
+ configurable: true,
6901
+ enumerable: false,
6902
+ value: function(_prevNode, _dom, _config) {
6903
+ const table = OriginalUpdateDOM.call(this, _prevNode, _dom, _config);
6904
+ ensureTableControllerDOM(_dom);
6905
+ const kernel = getKernelFromEditorConfig(_config);
6906
+ const editor = kernel?.getLexicalEditor();
6907
+ if (editor) {
6908
+ const decorator = kernel?.getDecorator(TableNode.getType()) || null;
6909
+ reconcileTableDecorator(editor, this, decorator);
6910
+ }
6461
6911
  return table;
6462
6912
  },
6463
6913
  writable: true
6464
6914
  });
6465
6915
  }
6466
6916
  //#endregion
6917
+ //#region src/plugins/table/service/i-table-controller-menu-service.ts
6918
+ const ITableControllerMenuService = genServiceId("TableControllerMenuService");
6919
+ var TableControllerMenuService = class {
6920
+ constructor() {
6921
+ this.items = /* @__PURE__ */ new Map();
6922
+ this.listeners = /* @__PURE__ */ new Set();
6923
+ }
6924
+ getItems(context) {
6925
+ return Array.from(this.items.values()).filter((item) => item.when ? item.when(context) : true).sort((a, b) => (a.order || 0) - (b.order || 0));
6926
+ }
6927
+ registerItem(item) {
6928
+ this.items.set(item.key, item);
6929
+ this.notify();
6930
+ return () => {
6931
+ this.items.delete(item.key);
6932
+ this.notify();
6933
+ };
6934
+ }
6935
+ subscribe(listener) {
6936
+ this.listeners.add(listener);
6937
+ return () => {
6938
+ this.listeners.delete(listener);
6939
+ };
6940
+ }
6941
+ notify() {
6942
+ for (const listener of this.listeners) listener();
6943
+ }
6944
+ };
6945
+ //#endregion
6467
6946
  //#region src/plugins/table/plugin/index.ts
6468
6947
  const tableCellProcessor = (before, content, after) => {
6469
6948
  return before + content.replace(/\n+$/, "").replaceAll(/\n+/g, "<br />") + after;
@@ -6471,6 +6950,13 @@ const tableCellProcessor = (before, content, after) => {
6471
6950
  function isHeadlessEditor(editor) {
6472
6951
  return editor._headless === true;
6473
6952
  }
6953
+ const getSelectedRange = (selectedIndexes) => {
6954
+ const sortedIndexes = [...selectedIndexes].sort((a, b) => a - b);
6955
+ return {
6956
+ end: sortedIndexes.at(-1) ?? 0,
6957
+ start: sortedIndexes[0] ?? 0
6958
+ };
6959
+ };
6474
6960
  const TablePlugin = class extends KernelPlugin {
6475
6961
  static {
6476
6962
  this.pluginName = "TablePlugin";
@@ -6479,11 +6965,26 @@ const TablePlugin = class extends KernelPlugin {
6479
6965
  super();
6480
6966
  this.kernel = kernel;
6481
6967
  patchTableNode();
6968
+ kernel.registerServiceHotReload(ITableControllerMenuService, new TableControllerMenuService());
6482
6969
  kernel.registerNodes([
6483
6970
  TableNode$1,
6484
6971
  TableRowNode,
6485
6972
  TableCellNode
6486
6973
  ]);
6974
+ if (options?.decoratorCol || options?.decoratorRow) {
6975
+ kernel.registerDecorator(TableNode$1.getType(), { multi: [...options.decoratorCol ? [{
6976
+ queryDOM: (el) => el.querySelector(".toolbar-col"),
6977
+ render: (node, editor) => {
6978
+ return options.decoratorCol?.(node, editor) || null;
6979
+ }
6980
+ }] : [], ...options.decoratorRow ? [{
6981
+ queryDOM: (el) => el.querySelector(".toolbar-row"),
6982
+ render: (node, editor) => {
6983
+ return options.decoratorRow?.(node, editor) || null;
6984
+ }
6985
+ }] : []] });
6986
+ this.registeredDecorators.add(TableNode$1.getType());
6987
+ }
6487
6988
  kernel.registerThemes({
6488
6989
  table: "editor_table",
6489
6990
  tableCell: "editor_table_cell",
@@ -6502,6 +7003,169 @@ const TablePlugin = class extends KernelPlugin {
6502
7003
  }
6503
7004
  this.registerMarkdown();
6504
7005
  this.registerLiteXml();
7006
+ this.registerControllerMenu();
7007
+ this.registerBlockSelect();
7008
+ }
7009
+ registerBlockSelect() {
7010
+ const blockMenuService = this.kernel.requireService(IBlockMenuService);
7011
+ if (!blockMenuService) return;
7012
+ this.register(blockMenuService.registerSelectHandler({
7013
+ key: "__table_block_select_handler",
7014
+ onSelect: (node) => {
7015
+ if (!$isTableNode(node)) return false;
7016
+ const [tableMap] = $computeTableMapSkipCellCheck(node, null, null);
7017
+ const firstCell = tableMap[0]?.[0]?.cell;
7018
+ const lastRow = [...tableMap].reverse().find((row) => row.length > 0);
7019
+ const lastCell = lastRow?.[lastRow.length - 1]?.cell;
7020
+ if (!firstCell || !lastCell) return false;
7021
+ const tableSelection = $createTableSelection();
7022
+ tableSelection.set(node.getKey(), firstCell.getKey(), lastCell.getKey());
7023
+ $setSelection(tableSelection);
7024
+ return true;
7025
+ },
7026
+ order: 100
7027
+ }));
7028
+ }
7029
+ registerControllerMenu() {
7030
+ const tableControllerMenuService = this.kernel.requireService(ITableControllerMenuService);
7031
+ if (!tableControllerMenuService) return;
7032
+ [
7033
+ tableControllerMenuService.registerItem({
7034
+ key: "__table_column_insert_before",
7035
+ label: "Insert before",
7036
+ onClick: ({ editor, node, selectedIndexes }) => {
7037
+ const { start } = getSelectedRange(selectedIndexes);
7038
+ editor.dispatchCommand(INSERT_TABLE_COLUMN_COMMAND, {
7039
+ columnIndex: start,
7040
+ insertAfter: false,
7041
+ table: node.getKey()
7042
+ });
7043
+ },
7044
+ order: 10,
7045
+ preview: "insert-before",
7046
+ when: ({ axis }) => axis === "column"
7047
+ }),
7048
+ tableControllerMenuService.registerItem({
7049
+ key: "__table_column_insert_after",
7050
+ label: "Insert after",
7051
+ onClick: ({ editor, node, selectedIndexes }) => {
7052
+ const { end } = getSelectedRange(selectedIndexes);
7053
+ editor.dispatchCommand(INSERT_TABLE_COLUMN_COMMAND, {
7054
+ columnIndex: end,
7055
+ insertAfter: true,
7056
+ table: node.getKey()
7057
+ });
7058
+ },
7059
+ order: 20,
7060
+ preview: "insert-after",
7061
+ when: ({ axis }) => axis === "column"
7062
+ }),
7063
+ tableControllerMenuService.registerItem({
7064
+ key: "__table_column_separator_delete",
7065
+ order: 40,
7066
+ type: "separator",
7067
+ when: ({ axis }) => axis === "column"
7068
+ }),
7069
+ tableControllerMenuService.registerItem({
7070
+ key: "__table_column_sync_width",
7071
+ label: "Sync width to all columns",
7072
+ onClick: ({ editor, node, selectedIndexes }) => {
7073
+ const columnIndex = selectedIndexes[0];
7074
+ if (columnIndex === void 0) return;
7075
+ editor.dispatchCommand(SYNC_TABLE_COLUMN_WIDTH_COMMAND, {
7076
+ columnIndex,
7077
+ table: node.getKey()
7078
+ });
7079
+ },
7080
+ order: 30,
7081
+ when: ({ axis, selectedIndexes }) => axis === "column" && selectedIndexes.length > 0
7082
+ }),
7083
+ tableControllerMenuService.registerItem({
7084
+ key: "__table_column_auto_fit_width",
7085
+ label: "Auto fit width",
7086
+ onClick: ({ editor, node, selectedIndexes }) => {
7087
+ editor.dispatchCommand(AUTO_FIT_TABLE_COLUMN_WIDTH_COMMAND, {
7088
+ columnIndexes: selectedIndexes,
7089
+ table: node.getKey()
7090
+ });
7091
+ },
7092
+ order: 35,
7093
+ when: ({ axis, selectedIndexes }) => axis === "column" && selectedIndexes.length > 0
7094
+ }),
7095
+ tableControllerMenuService.registerItem({
7096
+ key: "__table_column_distribute_width",
7097
+ label: "Distribute width",
7098
+ onClick: ({ editor, node }) => {
7099
+ editor.dispatchCommand(DISTRIBUTE_TABLE_COLUMN_WIDTH_COMMAND, { table: node.getKey() });
7100
+ },
7101
+ order: 36,
7102
+ when: ({ axis }) => axis === "column"
7103
+ }),
7104
+ tableControllerMenuService.registerItem({
7105
+ danger: true,
7106
+ key: "__table_column_delete",
7107
+ label: "Delete",
7108
+ onClick: ({ editor }) => {
7109
+ editor.update(() => {
7110
+ $deleteTableColumnAtSelection();
7111
+ });
7112
+ },
7113
+ order: 40,
7114
+ preview: "delete",
7115
+ when: ({ axis }) => axis === "column"
7116
+ }),
7117
+ tableControllerMenuService.registerItem({
7118
+ key: "__table_row_insert_above",
7119
+ label: "Insert above",
7120
+ onClick: ({ editor, node, selectedIndexes }) => {
7121
+ const { start } = getSelectedRange(selectedIndexes);
7122
+ editor.dispatchCommand(INSERT_TABLE_ROW_COMMAND, {
7123
+ insertAfter: false,
7124
+ rowIndex: start,
7125
+ table: node.getKey()
7126
+ });
7127
+ },
7128
+ order: 10,
7129
+ preview: "insert-before",
7130
+ when: ({ axis }) => axis === "row"
7131
+ }),
7132
+ tableControllerMenuService.registerItem({
7133
+ key: "__table_row_insert_below",
7134
+ label: "Insert below",
7135
+ onClick: ({ editor, node, selectedIndexes }) => {
7136
+ const { end } = getSelectedRange(selectedIndexes);
7137
+ editor.dispatchCommand(INSERT_TABLE_ROW_COMMAND, {
7138
+ insertAfter: true,
7139
+ rowIndex: end,
7140
+ table: node.getKey()
7141
+ });
7142
+ },
7143
+ order: 20,
7144
+ preview: "insert-after",
7145
+ when: ({ axis }) => axis === "row"
7146
+ }),
7147
+ tableControllerMenuService.registerItem({
7148
+ key: "__table_row_separator_delete",
7149
+ order: 30,
7150
+ type: "separator",
7151
+ when: ({ axis }) => axis === "row"
7152
+ }),
7153
+ tableControllerMenuService.registerItem({
7154
+ danger: true,
7155
+ key: "__table_row_delete",
7156
+ label: "Delete",
7157
+ onClick: ({ editor }) => {
7158
+ editor.update(() => {
7159
+ $deleteTableRowAtSelection();
7160
+ });
7161
+ },
7162
+ order: 40,
7163
+ preview: "delete",
7164
+ when: ({ axis }) => axis === "row"
7165
+ })
7166
+ ].forEach((unregister) => {
7167
+ this.register(unregister);
7168
+ });
6505
7169
  }
6506
7170
  registerLiteXml() {
6507
7171
  const litexmlService = this.kernel.requireService(ILitexmlService);
@@ -6536,7 +7200,7 @@ const TablePlugin = class extends KernelPlugin {
6536
7200
  for (const child of children) if ((child.children?.length || -1) > maxTdlen) maxTdlen = child.children.length;
6537
7201
  return INodeHelper.createElementNode(TableNode$1.getType(), {
6538
7202
  children,
6539
- colWidths: colWidths.length > 0 ? colWidths : new Array(maxTdlen).fill(750 / maxTdlen),
7203
+ colWidths: colWidths.length > 0 ? colWidths : createDefaultTableColWidths(maxTdlen),
6540
7204
  direction: null,
6541
7205
  format: "",
6542
7206
  indent: 0,
@@ -6592,7 +7256,7 @@ const TablePlugin = class extends KernelPlugin {
6592
7256
  const colLen = node.children[0]?.children.length || 1;
6593
7257
  return INodeHelper.createElementNode("table", {
6594
7258
  children,
6595
- colWidths: new Array(colLen).fill(750 / colLen),
7259
+ colWidths: createDefaultTableColWidths(colLen),
6596
7260
  direction: null,
6597
7261
  format: "",
6598
7262
  indent: 0,