fix(grid): keep canvas hover state across drawing surface flips

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-08-26 22:04:42 +08:00
1 parent 174f786483
commit aac09d3cb7
2 files changed
+21 -2

No files matched your search

@@ -6893,6 +6893,11 @@ function inactiveCanvasSurface(): HTMLCanvasElement | null {
return (canvasUsingBackSurface.value ? canvasRef.value : canvasBackRef.value) ?? null;
}
const canvasOverlayRef = ref<HTMLElement>();
function isCanvasGridInteractionTarget(target: Node): boolean {
return canvasOverlayRef.value?.contains(target) === true || canvasRef.value?.contains(target) === true || canvasBackRef.value?.contains(target) === true;
}
const canvasViewportWidth = ref(0);
const canvasViewportHeight = ref(0);
const canvasScrollTop = ref(0);
@@ -7247,7 +7252,9 @@ function onCanvasMouseMove(event: MouseEvent) {
function onCanvasMouseLeave(event?: MouseEvent) {
const relatedTarget = event?.relatedTarget;
if (relatedTarget instanceof Node && canvasOverlayRef.value?.contains(relatedTarget)) return;
// A draw swaps the visible canvas surface. Treat that as an in-grid move so
// the action overlay does not disappear between the two surfaces.
if (relatedTarget instanceof Node && isCanvasGridInteractionTarget(relatedTarget)) return;
const previous = canvasHoverCell.value;
if (previous) {
const previousActualColIdx = visibleColumnIndexes.value[previous.visibleColIdx];
@@ -7270,7 +7277,7 @@ function keepCanvasDetailHover() {
function clearCanvasDetailHover(event?: MouseEvent) {
const relatedTarget = event?.relatedTarget;
if (relatedTarget instanceof Node && (canvasOverlayRef.value?.contains(relatedTarget) || activeCanvasSurface()?.contains(relatedTarget) || canvasBackRef.value?.contains(relatedTarget))) {
if (relatedTarget instanceof Node && isCanvasGridInteractionTarget(relatedTarget)) {
return;
}
onCanvasMouseLeave();
@@ -4,6 +4,18 @@ import { describe, expect, it } from "vitest";
const dataGridSource = readFileSync(new URL("../DataGrid.vue", import.meta.url), "utf8");
describe("DataGrid cell detail selection", () => {
it("keeps Canvas hover state while the renderer swaps drawing surfaces", () => {
expect(dataGridSource).toContain("function isCanvasGridInteractionTarget(target: Node): boolean");
expect(dataGridSource).toContain("canvasOverlayRef.value?.contains(target) === true");
expect(dataGridSource).toContain("canvasRef.value?.contains(target) === true");
expect(dataGridSource).toContain("canvasBackRef.value?.contains(target) === true");
const canvasLeave = dataGridSource.match(/function onCanvasMouseLeave[\s\S]*?\n\}/)?.[0];
const detailLeave = dataGridSource.match(/function clearCanvasDetailHover[\s\S]*?\n\}/)?.[0];
expect(canvasLeave).toContain("isCanvasGridInteractionTarget(relatedTarget)");
expect(detailLeave).toContain("isCanvasGridInteractionTarget(relatedTarget)");
});
it("gates only the three hover Info buttons with the visibility setting", () => {
expect(dataGridSource).toContain("const cellDetailButtonEnabled = computed(() => settingsStore.editorSettings.dataGridCellDetailButtonVisible);");
expect(dataGridSource.match(/v-if="cellDetailButtonEnabled"/g)).toHaveLength(3);