Skip to content

Commit 83a72b8

Browse files
committed
[FIX] Selection: Ignore keyboard events when selecting range in the grid
Currently, users can modify the input of a composer/selection input while selecting a range in the grid. Those inputs can have side-effect that are difficult to account for as the selection is managed in a hook which is not aware of the related feature that it handles (selection, cell reference, pivot reference, selection input). A recent work to fix that: #7400 Overall, there is no added value to be able to mix writing text while selecting ranges inside the grid so we simply disable that possibility altogether. Task: 5347297
1 parent 06263d9 commit 83a72b8

File tree

4 files changed

+36
-28
lines changed

4 files changed

+36
-28
lines changed

src/components/helpers/drag_and_drop_grid_hook.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export function useDragAndDropBeyondTheViewport(env: SpreadsheetChildEnv) {
2626
let scrollDirection: DnDDirection = "all";
2727
const getters = env.model.getters;
2828

29+
const blockKeyboard = (ev: KeyboardEvent) => ev.preventDefault();
30+
const cleanUpBlockKeyboard = () =>
31+
removeEventListener("keydown", blockKeyboard, { capture: true });
32+
2933
let cleanUpFns: (() => void)[] = [];
3034

3135
const cleanUp = () => {
@@ -156,7 +160,9 @@ export function useDragAndDropBeyondTheViewport(env: SpreadsheetChildEnv) {
156160
pointerMoveCallback = onPointerMove;
157161
pointerUpCallback = onPointerUp;
158162

159-
cleanUpFns.push(startDnd(pointerMoveHandler, pointerUpHandler));
163+
// block keyboard events during pointer interaction to avoid conflicts
164+
addEventListener("keydown", blockKeyboard, { capture: true });
165+
cleanUpFns.push(startDnd(pointerMoveHandler, pointerUpHandler), cleanUpBlockKeyboard);
160166
};
161167

162168
onWillUnmount(() => {

tests/composer/composer_integration_component.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,16 @@ describe("Composer interactions", () => {
577577
createTable(model, "A1");
578578
expect(getTable(model, "A1")).toBeTruthy();
579579
});
580+
581+
test("keyboard inputs are disabled when selecting a range for the composer", async () => {
582+
await typeInComposerGrid("=");
583+
gridMouseEvent(model, "pointerdown", "C8");
584+
gridMouseEvent(model, "pointermove", "B8");
585+
await keyDown({ key: "A" });
586+
gridMouseEvent(model, "pointerup", "B8");
587+
await nextTick();
588+
expect(composerStore.currentContent).toBe("=B8:C8");
589+
});
580590
});
581591

582592
describe("Grid composer", () => {

tests/grid/grid_drag_and_drop_component.test.ts

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ import {
99
addColumns,
1010
addRows,
1111
createSheet,
12-
deleteSheet,
1312
freezeColumns,
1413
freezeRows,
1514
hideColumns,
1615
hideRows,
1716
setViewportOffset,
1817
} from "../test_helpers/commands_helpers";
19-
import { edgeScrollDelay, triggerMouseEvent } from "../test_helpers/dom_helper";
18+
import {
19+
edgeScrollDelay,
20+
triggerKeyboardEvent,
21+
triggerMouseEvent,
22+
} from "../test_helpers/dom_helper";
2023
import { mountComponent, nextTick } from "../test_helpers/helpers";
2124

2225
// As we test an isolated component, grid and gridOverlay won't exist
@@ -416,7 +419,7 @@ test("Drag&drop is stopped when the calling component is unmounted", async () =>
416419
jest.advanceTimersByTime(advanceTimer);
417420
expect(selectedCol).toEqual(1);
418421
expect(mouseUpFn).toHaveBeenCalledTimes(1);
419-
expect(spyRemoveEventListener).toHaveBeenCalledTimes(4);
422+
expect(spyRemoveEventListener).toHaveBeenCalledTimes(5);
420423
});
421424

422425
test("Drag&drop is stopped when mouseup is called on an element that stops pointer events", async () => {
@@ -454,27 +457,15 @@ test("drag And Drop is based on the current active sheet", async () => {
454457
});
455458
});
456459

457-
test("drag And Drop is stopped if the current sheet is deleted", async () => {
458-
setViewportOffset(model, 6 * DEFAULT_CELL_WIDTH, 6 * DEFAULT_CELL_HEIGHT);
459-
createSheet(model, { sheetId: "sh2", activate: true });
460-
setViewportOffset(model, 6 * DEFAULT_CELL_WIDTH, 6 * DEFAULT_CELL_HEIGHT);
461-
await nextTick();
462-
463-
expect(model.getters.getActiveMainViewport()).toMatchObject({
464-
left: 6,
465-
right: 16,
466-
});
467-
const { height } = model.getters.getSheetViewDimension();
468-
triggerMouseEvent(".o-fake-grid", "pointerdown", DEFAULT_CELL_WIDTH, 0.5 * height);
469-
deleteSheet(model, "sh2");
470-
await nextTick();
471-
triggerMouseEvent(".o-fake-grid", "pointermove", -0.5 * DEFAULT_CELL_WIDTH, 0.5 * height);
472-
const advanceTimer = edgeScrollDelay(0.5 * DEFAULT_CELL_WIDTH, 1);
473-
474-
jest.advanceTimersByTime(advanceTimer);
475-
triggerMouseEvent(".o-fake-grid", "pointerup", -0.5 * DEFAULT_CELL_WIDTH, 0.5 * height);
476-
expect(model.getters.getActiveMainViewport()).toMatchObject({
477-
left: 6,
478-
right: 16,
479-
});
460+
test("keyboard inputs are blocked during Drag And Drop", async () => {
461+
const target = document.querySelector(".o-fake-grid")!;
462+
triggerMouseEvent(".o-fake-grid", "pointerdown");
463+
let ev = triggerKeyboardEvent(target, "keydown", { key: "A" });
464+
expect(ev.defaultPrevented).toBeTruthy();
465+
triggerMouseEvent(".o-fake-grid", "pointermove");
466+
ev = triggerKeyboardEvent(target, "keydown", { key: "A" });
467+
expect(ev.defaultPrevented).toBeTruthy();
468+
triggerMouseEvent(".o-fake-grid", "pointerup");
469+
ev = triggerKeyboardEvent(target, "keydown", { key: "A" });
470+
expect(ev.defaultPrevented).toBeFalsy();
480471
});

tests/test_helpers/dom_helper.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ export function getGridIconEventPosition(model: Model, xc: string) {
218218

219219
export async function clickGridIcon(model: Model, xc: string) {
220220
const { x, y } = getGridIconEventPosition(model, xc);
221-
triggerMouseEvent(".o-grid-overlay", "pointerdown", x, y);
221+
simulateClick(".o-grid-overlay", x, y);
222222
await nextTick();
223223
}
224224

@@ -297,6 +297,7 @@ export function triggerKeyboardEvent(
297297
) {
298298
const ev = new KeyboardEvent(type, { bubbles: true, cancelable: true, ...eventArgs });
299299
dispatchEvent(selector, ev);
300+
return ev;
300301
}
301302

302303
function dispatchEvent(selector: string | EventTarget, ev: Event) {

0 commit comments

Comments
 (0)