Skip to content

Commit 6f709e7

Browse files
Fix table cell caret rendering
1 parent fa623f3 commit 6f709e7

2 files changed

Lines changed: 77 additions & 12 deletions

File tree

app/src/features/editor/extensions/markdown-decorations/builders/tables.ts

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,12 +1794,6 @@ class NestedTableEditorController {
17941794
break;
17951795
}
17961796
}
1797-
scheduleMainSelectionToLocalSelection(
1798-
initialSelection,
1799-
localText,
1800-
mainView,
1801-
resolved,
1802-
);
18031797
const state = EditorState.create({
18041798
doc: localText,
18051799
selection: EditorSelection.single(
@@ -2123,17 +2117,26 @@ class NestedTableEditorController {
21232117
parent: host,
21242118
state,
21252119
});
2126-
this.editor.contentDOM.focus({ preventScroll: true });
2120+
let openedSelection = initialSelection;
21272121

21282122
if (pendingOpen?.clickCoords) {
21292123
const pos = this.editor.posAtCoords(pendingOpen.clickCoords);
21302124
if (pos != null) {
2125+
openedSelection = { anchor: pos, head: pos };
21312126
this.editor.dispatch({
21322127
selection: EditorSelection.cursor(pos),
21332128
scrollIntoView: false,
21342129
});
21352130
}
21362131
}
2132+
2133+
scheduleMainSelectionToLocalSelection(
2134+
openedSelection,
2135+
localText,
2136+
mainView,
2137+
resolved,
2138+
);
2139+
this.editor.contentDOM.focus({ preventScroll: true });
21372140
}
21382141

21392142
handleMainEditorUpdate(mainView: EditorView) {
@@ -2539,7 +2542,11 @@ const nestedTableEditorPlugin = ViewPlugin.fromClass(
25392542
),
25402543
)
25412544
) {
2542-
this.sync();
2545+
this.sync({
2546+
deferOpen: !update.transactions.some((transaction) =>
2547+
transaction.annotation(normalizeBeforeEditAnnotation),
2548+
),
2549+
});
25432550
}
25442551
}
25452552

@@ -2549,7 +2556,7 @@ const nestedTableEditorPlugin = ViewPlugin.fromClass(
25492556
destroyTableCellMenu(this.view);
25502557
}
25512558

2552-
private sync() {
2559+
private sync({ deferOpen = true }: { deferOpen?: boolean } = {}) {
25532560
const activeCell = getActiveTableCell(this.view.state);
25542561
if (!activeCell) {
25552562
this.controller.close();
@@ -2608,12 +2615,45 @@ const nestedTableEditorPlugin = ViewPlugin.fromClass(
26082615
this.view,
26092616
resolved.activeCell,
26102617
);
2611-
requestAnimationFrame(() => {
2618+
const openIfStillActive = () => {
26122619
if (!this.view.dom.isConnected) {
26132620
return;
26142621
}
2615-
this.controller.open(this.view, resolved, cellElement, pendingOpen);
2616-
});
2622+
const latestActiveCell = getActiveTableCell(this.view.state);
2623+
if (
2624+
!latestActiveCell ||
2625+
!isSameActiveTableCell(latestActiveCell, resolved.activeCell)
2626+
) {
2627+
return;
2628+
}
2629+
const latestResolved = getResolvedActiveTableCell(this.view.state);
2630+
if (
2631+
!latestResolved ||
2632+
!isSameActiveTableCell(latestResolved.activeCell, resolved.activeCell)
2633+
) {
2634+
return;
2635+
}
2636+
const latestCellElement = findActiveCellElement(
2637+
this.view,
2638+
latestResolved.activeCell,
2639+
);
2640+
if (!latestCellElement) {
2641+
return;
2642+
}
2643+
this.controller.open(
2644+
this.view,
2645+
latestResolved,
2646+
latestCellElement,
2647+
pendingOpen,
2648+
);
2649+
};
2650+
2651+
if (!deferOpen) {
2652+
openIfStillActive();
2653+
return;
2654+
}
2655+
2656+
requestAnimationFrame(openIfStillActive);
26172657
}
26182658
},
26192659
);

app/src/features/editor/extensions/tables/tables-runtime.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from "@/features/editor/extensions/tables/cell-selection-state";
1717
import {
1818
activeTableCellField,
19+
clearActiveTableCellEffect,
1920
setActiveTableCellEffect,
2021
} from "@/features/editor/extensions/tables/state";
2122

@@ -155,6 +156,30 @@ describe("table runtime", () => {
155156
view.destroy();
156157
});
157158

159+
it("does not reopen a stale cell editor after the active cell is cleared", async () => {
160+
const { view } = createView(
161+
["| H1 | H2 |", "| --- | --- |", "| A1 | A2 |"].join("\n"),
162+
);
163+
164+
view.dispatch({
165+
effects: setActiveTableCellEffect.of({
166+
col: 0,
167+
row: 0,
168+
section: "header",
169+
tableFrom: 0,
170+
}),
171+
});
172+
view.dispatch({
173+
effects: clearActiveTableCellEffect.of(),
174+
});
175+
176+
await flush();
177+
178+
expect(view.dom.querySelector(".cm-md-table-cell-editor")).toBeNull();
179+
180+
view.destroy();
181+
});
182+
158183
it("keeps the active-cell field registered on the editor state", () => {
159184
const { view } = createView("| H |\n| --- |\n| A |");
160185

0 commit comments

Comments
 (0)