fix(grid): scope header generate-value to the clicked column

This commit is contained in:
Melody Ruch
2026-09-04 12:28:38 +08:00
committed by GitHub
parent 560e1c2c0c
commit 057c04d306
3 changed files with 47 additions and 1 deletions
@@ -5784,6 +5784,7 @@ const {
restoreCellSelectionState,
cellIsSelected,
columnIsSelected,
columnIsExclusivelySelected,
selectedRangeStart,
selectedRowIds,
selectedColumnIndexes,
@@ -10543,7 +10544,7 @@ watch(
function onHeaderContext(col: string, columnIndex: number) {
invalidateContextMenuTarget();
const visibleColIdx = visibleColumnIndexes.value.indexOf(columnIndex);
if (visibleColIdx >= 0 && !columnIsSelected(visibleColIdx)) {
if (visibleColIdx >= 0 && !columnIsExclusivelySelected(visibleColIdx)) {
selectColumn(visibleColIdx);
}
contextHeaderColumn.value = col;
@@ -122,6 +122,38 @@ describe("useDataGridSelection", () => {
expect(selection.selectedColumnIndexes.value).toEqual(new Set([0, 1, 2]));
});
it("distinguishes a column merely covered by a wider full-height range from one exclusively selected", () => {
const selection = createSelection();
// Full-height rectangle spanning columns 1-2 (e.g. dragged across two columns).
selection.selectSingleCell(0, 1);
selection.extendCellSelectionTo(3, 2);
expect(selection.columnIsSelected(1)).toBe(true);
expect(selection.columnIsSelected(2)).toBe(true);
expect(selection.columnIsExclusivelySelected(1)).toBe(false);
expect(selection.columnIsExclusivelySelected(2)).toBe(false);
// Narrowing to just column 1 (what a header click/selectColumn does) makes it exclusive.
selection.selectColumn(1);
expect(selection.columnIsExclusivelySelected(1)).toBe(true);
expect(selection.columnIsExclusivelySelected(2)).toBe(false);
});
it("treats an explicit multi-column header selection as exclusive for every column it contains", () => {
const selection = createSelection();
// Deliberate multi-column selection via header click + shift-click (not a stray cell range).
selection.selectColumn(0);
selection.selectColumn(1, rowEvent({ shift: true }));
expect(selection.hasColumnSelection.value).toBe(true);
expect(selection.columnIsExclusivelySelected(0)).toBe(true);
expect(selection.columnIsExclusivelySelected(1)).toBe(true);
expect(selection.columnIsExclusivelySelected(2)).toBe(false);
});
it("moves a single-column rectangular cell selection with its column after reordering", () => {
const selection = createSelection();
@@ -694,6 +694,18 @@ export function useDataGridSelection(options: UseDataGridSelectionOptions) {
return range.startCol <= colIndex && range.endCol >= colIndex && range.startRow === 0 && range.endRow >= displayItems.value.length - 1;
}
// Unlike columnIsSelected (used for header highlighting, where any column touched by a
// wider selection should light up), this requires the selected cell RANGE to cover this
// column only. An explicit multi-column header selection (hasColumnSelection) is left as-is:
// that's a deliberate user gesture (click/shift-click/ctrl-click headers), not a stray
// full-height cell range left over from selecting a block in the grid body.
function columnIsExclusivelySelected(colIndex: number): boolean {
if (hasColumnSelection.value) return selectedColumnIndexes.value.has(colIndex);
const range = selectedRange.value;
if (!range) return false;
return range.startCol === colIndex && range.endCol === colIndex && range.startRow === 0 && range.endRow >= displayItems.value.length - 1;
}
function selectedRangeStart(): CellPosition | null {
const range = selectedRange.value;
if (!range) return null;
@@ -727,6 +739,7 @@ export function useDataGridSelection(options: UseDataGridSelectionOptions) {
isCellSelectionDragConfirmed,
cellIsSelected,
columnIsSelected,
columnIsExclusivelySelected,
selectedRangeStart,
selectedRowIds,
selectedColumnIndexes,