fix: Table row selection logic with merged cells (#10142)

closes #10128
This commit is contained in:
Tom Moor
2025-09-10 03:28:06 +02:00
committed by GitHub
parent 1da18c3101
commit 19f9245e17
4 changed files with 47 additions and 7 deletions

View File

@@ -203,7 +203,7 @@
"prosemirror-model": "^1.25.2",
"prosemirror-schema-list": "^1.5.1",
"prosemirror-state": "^1.4.3",
"prosemirror-tables": "^1.7.1",
"prosemirror-tables": "^1.8.1",
"prosemirror-transform": "1.10.0",
"prosemirror-view": "^1.40.1",
"proxy-from-env": "^1.1.0",

View File

@@ -6,6 +6,7 @@ import { addRowBefore, selectRow, selectTable } from "../commands/table";
import { getCellAttrs, setCellAttrs } from "../lib/table";
import {
getCellsInColumn,
getRowIndexInMap,
isRowSelected,
isTableSelected,
} from "../queries/table";
@@ -155,7 +156,10 @@ export default class TableCell extends Node {
const rows = getCellsInColumn(0)(state);
if (rows) {
rows.forEach((pos, index) => {
rows.forEach((pos, visualIndex) => {
const actualRowIndex = getRowIndexInMap(visualIndex, state);
const index =
actualRowIndex !== -1 ? actualRowIndex : visualIndex;
if (index === 0) {
const className = cn(EditorStyleHelper.tableGrip, {
selected: isTableSelected(state),
@@ -180,7 +184,7 @@ export default class TableCell extends Node {
const className = cn(EditorStyleHelper.tableGripRow, {
selected: isRowSelected(index)(state),
first: index === 0,
last: index === rows.length - 1,
last: visualIndex === rows.length - 1,
});
decorations.push(

View File

@@ -52,6 +52,42 @@ export function getRowIndex(state: EditorState): number | undefined {
return undefined;
}
/**
* Get the actual row index in the table map for a given visual row index
* when merged cells are present.
*
* @param visualRowIndex The visual row index (0-based)
* @param state The editor state
* @returns The actual row index in the table map, or -1 if not found
*/
export function getRowIndexInMap(
visualRowIndex: number,
state: EditorState
): number {
if (!isInTable(state)) {
return -1;
}
const rect = selectedRect(state);
const cells = getCellsInColumn(0)(state);
if (visualRowIndex >= 0 && visualRowIndex < cells.length) {
const cellPos = cells[visualRowIndex] - rect.tableStart;
// Find the row index in the table map for this cell position
for (let row = 0; row < rect.map.height; row++) {
const rowStart = row * rect.map.width;
for (let col = 0; col < rect.map.width; col++) {
if (rect.map.map[rowStart + col] === cellPos) {
return row;
}
}
}
}
return -1;
}
export function getCellsInColumn(index: number) {
return (state: EditorState): number[] => {
if (!isInTable(state)) {

View File

@@ -12309,10 +12309,10 @@ prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.4.3:
prosemirror-transform "^1.0.0"
prosemirror-view "^1.27.0"
prosemirror-tables@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.7.1.tgz#df2507f285c6c7563097b4904cb7c4b9e0cd724b"
integrity sha512-eRQ97Bf+i9Eby99QbyAiyov43iOKgWa7QCGly+lrDt7efZ1v8NWolhXiB43hSDGIXT1UXgbs4KJN3a06FGpr1Q==
prosemirror-tables@^1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.8.1.tgz#896a234e3e18240b629b747a871369dae78c8a9a"
integrity sha512-DAgDoUYHCcc6tOGpLVPSU1k84kCUWTWnfWX3UDy2Delv4ryH0KqTD6RBI6k4yi9j9I8gl3j8MkPpRD/vWPZbug==
dependencies:
prosemirror-keymap "^1.2.2"
prosemirror-model "^1.25.0"