diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts index 627af7b7f0..65827b8434 100644 --- a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts @@ -4,12 +4,11 @@ import { sleep, } from 'tests/util/helpers'; import type { Event as GEvent } from '@antv/g-canvas'; -import { getActiveHoverRowColCells } from '@antv/s2'; +import type { InteractionCellHighlight } from '@antv/s2'; import type { S2Options } from '@/common/interface'; import type { SpreadSheet } from '@/sheet-type'; import { HOVER_FOCUS_DURATION, - type InteractionCellSelectedHighlightType, InteractionName, InteractionStateName, InterceptType, @@ -204,7 +203,7 @@ describe('Interaction Data Cell Click Tests', () => { selectedCellHighlight: { colHeader: true, rowHeader: true, - } as InteractionCellSelectedHighlightType, + } as InteractionCellHighlight, }, }); diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts index 986b60d2b9..e88bb33ab7 100644 --- a/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts @@ -81,6 +81,15 @@ describe('Interaction Hover Tests', () => { }); test('should trigger data cell hover', async () => { + const interactionGetHoverHighlightSpy = jest + .spyOn(s2.interaction, 'getHoverHighlight') + .mockImplementationOnce(() => ({ + rowHeader: true, + colHeader: true, + currentRow: true, + currentCol: true, + })); + s2.emit(S2Event.DATA_CELL_HOVER, { target: {} } as GEvent); expect(s2.interaction.getState()).toEqual({ cells: [mockCellMeta], @@ -94,6 +103,37 @@ describe('Interaction Hover Tests', () => { stateName: InteractionStateName.HOVER_FOCUS, }); expect(s2.showTooltipWithInfo).toHaveBeenCalled(); + expect(interactionGetHoverHighlightSpy).toHaveBeenCalled(); + }); + + test('should trigger data cell hover depend on separate config', async () => { + s2.interaction.getAllColHeaderCells = jest.fn(); + s2.interaction.getAllRowHeaderCells = jest.fn(); + + s2.setOptions({ + interaction: { + hoverHighlight: { + colHeader: true, + rowHeader: false, + }, + }, + }); + + s2.emit(S2Event.DATA_CELL_HOVER, { target: {} } as GEvent); + expect(s2.interaction.getState()).toEqual({ + cells: [mockCellMeta], + stateName: InteractionStateName.HOVER, + }); + + await sleep(1000); + + expect(s2.interaction.getState()).toEqual({ + cells: [mockCellMeta], + stateName: InteractionStateName.HOVER_FOCUS, + }); + + expect(s2.interaction.getAllColHeaderCells).toHaveBeenCalled(); + expect(s2.interaction.getAllRowHeaderCells).not.toHaveBeenCalled(); }); test('should not trigger data cell hover when hover cell not change', () => { diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 65dc86bccf..b84db55a0e 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -118,14 +118,17 @@ export class DataCell extends BaseCell { return; } - if (this.spreadsheet.options.interaction.hoverHighlight) { + const { currentRow, currentCol } = + this.spreadsheet.interaction.getHoverHighlight(); + + if (currentRow || currentCol) { // 如果当前是hover,要绘制出十字交叉的行列样式 const currentColIndex = this.meta.colIndex; const currentRowIndex = this.meta.rowIndex; // 当视图内的 cell 行列 index 与 hover 的 cell 一致,绘制hover的十字样式 if ( - currentColIndex === currentHoverCell?.colIndex || - currentRowIndex === currentHoverCell?.rowIndex + (currentCol && currentColIndex === currentHoverCell?.colIndex) || + (currentRow && currentRowIndex === currentHoverCell?.rowIndex) ) { this.updateByState(InteractionStateName.HOVER); } else { diff --git a/packages/s2-core/src/common/constant/interaction.ts b/packages/s2-core/src/common/constant/interaction.ts index f95a7cb0c6..75a9650318 100644 --- a/packages/s2-core/src/common/constant/interaction.ts +++ b/packages/s2-core/src/common/constant/interaction.ts @@ -117,10 +117,3 @@ export enum ScrollDirectionRowIndexDiff { SCROLL_UP = -1, SCROLL_DOWN = 1, } - -export interface InteractionCellSelectedHighlightType { - rowHeader?: boolean; // 高亮行头 - colHeader?: boolean; // 高亮列头 - currentRow?: boolean; // 高亮选中单元格所在行 - currentCol?: boolean; // 高亮选中单元格所在列 -} diff --git a/packages/s2-core/src/common/interface/interaction.ts b/packages/s2-core/src/common/interface/interaction.ts index 95555293ad..4bba56f0ef 100644 --- a/packages/s2-core/src/common/interface/interaction.ts +++ b/packages/s2-core/src/common/interface/interaction.ts @@ -14,7 +14,6 @@ import type { BaseEvent } from '../../interaction/base-event'; import type { SpreadSheet } from '../../sheet-type'; import type { CellTypes, - InteractionCellSelectedHighlightType, InteractionStateName, InterceptType, ScrollbarPositionType, @@ -141,7 +140,7 @@ export interface InteractionOptions { // focus selected cell, like the spotlight selectedCellsSpotlight?: boolean; // highlight all row header cells and column header cells to which the hovered cell belongs - hoverHighlight?: boolean; + hoverHighlight?: boolean | InteractionCellHighlight; // keep cell hovered after 800ms duration hoverFocus?: boolean | HoverFocusOptions; // enable Command + C to copy spread data @@ -171,7 +170,7 @@ export interface InteractionOptions { // https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener eventListenerOptions?: boolean | AddEventListenerOptions; // highlight col and row header for selected cell - selectedCellHighlight?: boolean | InteractionCellSelectedHighlightType; + selectedCellHighlight?: boolean | InteractionCellHighlight; // https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior overscrollBehavior?: 'auto' | 'none' | 'contain'; // trigger hover after scroll @@ -180,3 +179,10 @@ export interface InteractionOptions { // register custom interactions customInteractions?: CustomInteraction[]; } + +export interface InteractionCellHighlight { + rowHeader?: boolean; // 高亮行头 + colHeader?: boolean; // 高亮列头 + currentRow?: boolean; // 高亮选中单元格所在行 + currentCol?: boolean; // 高亮选中单元格所在列 +} diff --git a/packages/s2-core/src/interaction/base-interaction/hover.ts b/packages/s2-core/src/interaction/base-interaction/hover.ts index ef84df2aa7..e326544168 100644 --- a/packages/s2-core/src/interaction/base-interaction/hover.ts +++ b/packages/s2-core/src/interaction/base-interaction/hover.ts @@ -35,13 +35,17 @@ export class HoverEvent extends BaseEvent implements BaseEventImplement { const { rowId, colId } = meta; const { interaction } = this.spreadsheet; - updateAllColHeaderCellState( - colId, - interaction.getAllColHeaderCells(), - InteractionStateName.HOVER, - ); + const { rowHeader, colHeader } = interaction.getHoverHighlight(); - if (rowId) { + if (colHeader) { + updateAllColHeaderCellState( + colId, + interaction.getAllColHeaderCells(), + InteractionStateName.HOVER, + ); + } + + if (rowHeader && rowId) { // update rowHeader cells const allRowHeaderCells = getActiveHoverRowColCells( rowId, @@ -86,7 +90,8 @@ export class HoverEvent extends BaseEvent implements BaseEventImplement { hideSummary: true, showSingleTips, }; - if (interactionOptions.hoverHighlight) { + const { rowHeader, colHeader } = interaction.getHoverHighlight(); + if (rowHeader || colHeader) { // highlight all the row and column cells which the cell belongs to this.updateRowColCells(meta); } @@ -201,7 +206,8 @@ export class HoverEvent extends BaseEvent implements BaseEventImplement { stateName: InteractionStateName.HOVER, }); - if (interactionOptions.hoverHighlight) { + const { rowHeader, colHeader } = interaction.getHoverHighlight(); + if (rowHeader || colHeader) { // highlight all the row and column cells which the cell belongs to this.updateRowColCells(meta); } diff --git a/packages/s2-core/src/interaction/root.ts b/packages/s2-core/src/interaction/root.ts index 80f16bc0ce..c0c5035e64 100644 --- a/packages/s2-core/src/interaction/root.ts +++ b/packages/s2-core/src/interaction/root.ts @@ -8,13 +8,13 @@ import { InteractionStateName, InterceptType, S2Event, - type InteractionCellSelectedHighlightType, } from '../common/constant'; import type { BrushSelection, BrushSelectionInfo, CellMeta, CustomInteraction, + InteractionCellHighlight, InteractionStateInfo, Intercept, MergedCellInfo, @@ -569,7 +569,7 @@ export class RootInteraction { return this.hoverTimer; } - public getSelectedCellHighlight(): InteractionCellSelectedHighlightType { + public getSelectedCellHighlight(): InteractionCellHighlight { const { selectedCellHighlight } = this.spreadsheet.options.interaction; if (isBoolean(selectedCellHighlight)) { @@ -599,4 +599,31 @@ export class RootInteraction { public getHoverAfterScroll(): boolean { return this.spreadsheet.options.interaction.hoverAfterScroll; } + + public getHoverHighlight(): InteractionCellHighlight { + const { hoverHighlight } = this.spreadsheet.options.interaction; + + if (isBoolean(hoverHighlight)) { + return { + rowHeader: hoverHighlight, + colHeader: hoverHighlight, + currentRow: hoverHighlight, + currentCol: hoverHighlight, + }; + } + + const { + rowHeader = false, + colHeader = false, + currentRow = false, + currentCol = false, + } = hoverHighlight ?? {}; + + return { + rowHeader, + colHeader, + currentRow, + currentCol, + }; + } } diff --git a/packages/s2-core/src/utils/cell/data-cell.ts b/packages/s2-core/src/utils/cell/data-cell.ts index e8291d84f8..e0859dd627 100644 --- a/packages/s2-core/src/utils/cell/data-cell.ts +++ b/packages/s2-core/src/utils/cell/data-cell.ts @@ -6,7 +6,6 @@ import { VALUE_FIELD, InteractionStateName, CellTypes, - type InteractionCellSelectedHighlightType, EMPTY_PLACEHOLDER, } from '../../common/constant'; import type { diff --git a/packages/s2-react/playground/index.tsx b/packages/s2-react/playground/index.tsx index a5028263c9..fd69cd6768 100644 --- a/packages/s2-react/playground/index.tsx +++ b/packages/s2-react/playground/index.tsx @@ -12,7 +12,7 @@ import { getPalette, type DataType, type HeaderActionIconProps, - type InteractionCellSelectedHighlightType, + type InteractionCellHighlight, type InteractionOptions, type S2DataConfig, type TargetCellInfo, @@ -909,7 +909,7 @@ function MainLayout() { onChange={(type) => { let selectedCellHighlight: | boolean - | InteractionCellSelectedHighlightType = false; + | InteractionCellHighlight = false; const oldIdx = type.findIndex((typeItem) => isBoolean(typeItem), ); @@ -953,18 +953,58 @@ function MainLayout() { - { +