Skip to content

Commit 2a4f6d1

Browse files
committed
fix(YfmTable): fixed dragging a row in horizontally scrolled table
1 parent 113c6ba commit 2a4f6d1

File tree

4 files changed

+60
-9
lines changed

4 files changed

+60
-9
lines changed

src/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-drop-cursor.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {findParentNodeClosestToPos} from '#pm/utils';
22
import type {EditorView} from '#pm/view';
3-
import {isTableCellNode, isTableNode} from 'src/table-utils';
3+
import {isTableCellNode, isTableNode, isTableRowNode} from 'src/table-utils';
44

55
/** Same as `DropCursorOptions` from _prosemirror-dropcursor_ package */
66
export type DropCursorParams = {
@@ -131,6 +131,45 @@ export class DropCursor {
131131
}
132132
}
133133

134+
export class TableRowDropCursor extends DropCursor {
135+
update() {
136+
const cursorPos = this.getPos();
137+
if (cursorPos === null) return;
138+
139+
const $cursorPos = this.editorView.state.doc.resolve(cursorPos);
140+
const parentTable = findParentNodeClosestToPos($cursorPos, isTableNode);
141+
if (!parentTable) return;
142+
143+
let side: 'top' | 'bottom';
144+
let trowPos: number;
145+
if ($cursorPos.nodeAfter && isTableRowNode($cursorPos.nodeAfter)) {
146+
side = 'top';
147+
trowPos = cursorPos;
148+
} else if ($cursorPos.nodeBefore && isTableRowNode($cursorPos.nodeBefore)) {
149+
side = 'bottom';
150+
trowPos = cursorPos - $cursorPos.nodeBefore.nodeSize;
151+
} else {
152+
this.cursorElem?.remove();
153+
this.cursorElem = null;
154+
return;
155+
}
156+
157+
const trElem = this.editorView.nodeDOM(trowPos);
158+
const tableElem = this.editorView.nodeDOM(parentTable.pos);
159+
160+
const trRect = (trElem as HTMLElement).getBoundingClientRect();
161+
const tableRect = (tableElem as HTMLElement).getBoundingClientRect();
162+
163+
const rect: Rect = {
164+
top: trRect[side] - this.width / 2,
165+
bottom: trRect[side] + this.width / 2,
166+
left: tableRect.left,
167+
right: tableRect.right,
168+
};
169+
this.render(rect, {isBlock: true});
170+
}
171+
}
172+
134173
export class TableColumnDropCursor extends DropCursor {
135174
update() {
136175
const cursorPos = this.getPos();

src/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-ghost.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export class YfmTableDnDGhost {
114114
): BuildGhostResult {
115115
let shiftX = 0;
116116
let shiftY = 0;
117+
let isHorizontallyScrolled = false;
117118

118119
const document = view.dom.ownerDocument;
119120
const container = this._buildGhostContainer(view);
@@ -122,10 +123,12 @@ export class YfmTableDnDGhost {
122123
const tbody = table.appendChild(document.createElement('tbody'));
123124

124125
{
125-
const tablePos = tableDesc.pos;
126-
const tableNode = view.domAtPos(tablePos + 1).node;
127-
const rect = (tableNode as Element).getBoundingClientRect();
128-
table.style.width = rect.width + 'px';
126+
const tableNode = view.domAtPos(tableDesc.pos + 1).node;
127+
isHorizontallyScrolled = (tableNode as Element).scrollLeft > 0;
128+
129+
const tbodyNode = view.domAtPos(tableDesc.bodyPos + 1).node;
130+
const tbodyRect = (tbodyNode as Element).getBoundingClientRect();
131+
tbody.style.width = tbodyRect.width + 'px';
129132
}
130133

131134
const range = tableDesc.base.getRowRanges()[rangeIdx];
@@ -150,6 +153,10 @@ export class YfmTableDnDGhost {
150153
}
151154
}
152155

156+
if (isHorizontallyScrolled) {
157+
shiftX = 0;
158+
}
159+
153160
removeIdAttributes(table);
154161

155162
return {domElement: container, shiftX, shiftY};

src/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import {hideHoverDecos} from '../plugins/focus-plugin';
2020
import {getSelectedCellsForColumns, getSelectedCellsForRows} from '../utils';
2121

2222
import {
23+
type DropCursor,
2324
type DropCursorParams,
24-
DropCursor as RowDropCursor,
2525
TableColumnDropCursor,
26+
TableRowDropCursor,
2627
} from './dnd-drop-cursor';
2728
import {YfmTableDnDGhost} from './dnd-ghost';
2829

@@ -85,7 +86,7 @@ abstract class YfmTableDnDAbstractHandler implements TableHandler, DnDControlHan
8586
protected readonly _cellGetPos: () => number | undefined;
8687
protected readonly _editorView: EditorView;
8788
protected readonly _logger: Logger2.ILogger;
88-
protected readonly _dropCursor: RowDropCursor;
89+
protected readonly _dropCursor: DropCursor;
8990

9091
private __cellNode: Node;
9192
private __dragging = false;
@@ -94,7 +95,7 @@ abstract class YfmTableDnDAbstractHandler implements TableHandler, DnDControlHan
9495

9596
constructor(
9697
view: EditorView,
97-
params: Omit<YfmTableDnDHandlerParams, 'dropCursor'> & {dropCursor: RowDropCursor},
98+
params: Omit<YfmTableDnDHandlerParams, 'dropCursor'> & {dropCursor: DropCursor},
9899
) {
99100
this._editorView = view;
100101
this.__cellNode = params.cellNode;
@@ -192,7 +193,7 @@ class YfmTableRowDnDHandler extends YfmTableDnDAbstractHandler {
192193
super(view, {
193194
...params,
194195
logger: params.logger.nested({component: 'row-dnd-handler'}),
195-
dropCursor: new RowDropCursor(view, params.dropCursor),
196+
dropCursor: new TableRowDropCursor(view, params.dropCursor),
196197
});
197198
}
198199

src/table-utils/table-desc.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ class TableDescBinded {
380380
readonly pos: number;
381381
readonly base: TableDesc;
382382

383+
get bodyPos(): number {
384+
return this.pos + 1;
385+
}
386+
383387
get rows(): number {
384388
return this.base.rows;
385389
}

0 commit comments

Comments
 (0)