fix(grid): preserve contiguous row selection
This commit is contained in:
parent
15d392bc44
commit
8c8c48f9b1
|
|
@ -7437,7 +7437,6 @@ function onCellContext(rowId: number, rowIndex: number, colIdx: number, visibleC
|
|||
contextHeaderColumnIndex.value = null;
|
||||
contextCell.value = { rowId, rowIndex, col: colIdx };
|
||||
if (hasRowSelection.value && isRowSelected(rowId)) {
|
||||
clearCellSelection();
|
||||
void prefetchCopyStatements();
|
||||
return;
|
||||
}
|
||||
|
|
@ -7576,9 +7575,6 @@ function onRowContext(rowId: number, rowIndex: number) {
|
|||
contextHeaderColumn.value = null;
|
||||
contextHeaderColumnIndex.value = null;
|
||||
contextCell.value = { rowId, rowIndex, col: -1 };
|
||||
if (hasRowSelection.value && isRowSelected(rowId)) {
|
||||
clearCellSelection();
|
||||
}
|
||||
if (!isRowSelected(rowId)) {
|
||||
clearCellSelection();
|
||||
selectedRowIds.value = new Set([rowId]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import { computed, ref } from "vue";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { useDataGridSelection } from "@/composables/useDataGridSelection";
|
||||
|
||||
function createSelection() {
|
||||
const columns = computed(() => ["id", "name", "email"]);
|
||||
const displayItems = computed(() =>
|
||||
[1, 2, 3, 4].map((id, index) => ({
|
||||
id,
|
||||
sourceIndex: index,
|
||||
data: [id, `name-${id}`, `user-${id}@example.com`],
|
||||
isNew: false,
|
||||
isDraft: false,
|
||||
isDeleted: false,
|
||||
isDirtyCol: [false, false, false],
|
||||
status: "clean",
|
||||
})),
|
||||
);
|
||||
|
||||
return useDataGridSelection({
|
||||
columns,
|
||||
displayItems,
|
||||
editingCell: ref(null),
|
||||
showTranspose: ref(false),
|
||||
transposeRowIndex: ref(null),
|
||||
gridRef: ref(undefined),
|
||||
});
|
||||
}
|
||||
|
||||
function rowEvent(options: { meta?: boolean; shift?: boolean } = {}): MouseEvent {
|
||||
return {
|
||||
metaKey: !!options.meta,
|
||||
ctrlKey: !!options.meta,
|
||||
shiftKey: !!options.shift,
|
||||
} as MouseEvent;
|
||||
}
|
||||
|
||||
describe("useDataGridSelection", () => {
|
||||
it("creates a whole-row cell range for contiguous meta row selections", () => {
|
||||
const selection = createSelection();
|
||||
|
||||
selection.handleRowClick(1, 2, rowEvent({ meta: true }));
|
||||
selection.handleRowClick(2, 3, rowEvent({ meta: true }));
|
||||
selection.handleRowClick(3, 4, rowEvent({ meta: true }));
|
||||
|
||||
expect(selection.selectedRowIds.value).toEqual(new Set([2, 3, 4]));
|
||||
expect(selection.selectedRange.value).toEqual({
|
||||
startRow: 1,
|
||||
endRow: 3,
|
||||
startCol: 0,
|
||||
endCol: 2,
|
||||
});
|
||||
expect(selection.hasCellSelection.value).toBe(true);
|
||||
});
|
||||
|
||||
it("does not create a rectangular cell range for non-contiguous meta row selections", () => {
|
||||
const selection = createSelection();
|
||||
|
||||
selection.handleRowClick(0, 1, rowEvent({ meta: true }));
|
||||
selection.handleRowClick(2, 3, rowEvent({ meta: true }));
|
||||
|
||||
expect(selection.selectedRowIds.value).toEqual(new Set([1, 3]));
|
||||
expect(selection.selectedRange.value).toBeNull();
|
||||
expect(selection.hasCellSelection.value).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -213,6 +213,7 @@ export function useDataGridSelection(options: UseDataGridSelectionOptions) {
|
|||
next.add(rowId);
|
||||
}
|
||||
selectedRowIds.value = next;
|
||||
selectContiguousRowIds(next);
|
||||
lastClickedRowIndex.value = rowIndex;
|
||||
} else if (isShift && lastClickedRowIndex.value !== null) {
|
||||
const start = Math.min(lastClickedRowIndex.value, rowIndex);
|
||||
|
|
@ -231,6 +232,30 @@ export function useDataGridSelection(options: UseDataGridSelectionOptions) {
|
|||
}
|
||||
}
|
||||
|
||||
function selectContiguousRowIds(rowIds: Set<number>) {
|
||||
if (rowIds.size === 0) {
|
||||
clearCellSelection();
|
||||
return;
|
||||
}
|
||||
|
||||
const indexes = displayItems.value.reduce<number[]>((selectedIndexes, item, index) => {
|
||||
if (rowIds.has(item.id)) selectedIndexes.push(index);
|
||||
return selectedIndexes;
|
||||
}, []);
|
||||
if (indexes.length !== rowIds.size) {
|
||||
clearCellSelection();
|
||||
return;
|
||||
}
|
||||
|
||||
const start = Math.min(...indexes);
|
||||
const end = Math.max(...indexes);
|
||||
if (end - start + 1 !== indexes.length) {
|
||||
clearCellSelection();
|
||||
return;
|
||||
}
|
||||
selectRows(start, end);
|
||||
}
|
||||
|
||||
function finishCellSelection() {
|
||||
isSelectingCells.value = false;
|
||||
document.removeEventListener("mouseup", finishCellSelection);
|
||||
|
|
|
|||
Loading…
Reference in New Issue