Skip to content

Commit

Permalink
feat(tooltip): enhance tooltip (#862)
Browse files Browse the repository at this point in the history
* feat(tooltip): enhance tooltip

* feat(tooltip): update docs

* feat(tooltip): fix test

* feat(tooltip): fix test

* feat(tooltip): fix test

* feat(tooltip): update docs

* feat(tooltip): update demo

* feat(tooltip): update docs

* feat(tooltip): support config corner and rename cell => data

* feat(tooltip): update docs
  • Loading branch information
lijinke666 authored Dec 6, 2021
1 parent 3162549 commit 9e411b5
Show file tree
Hide file tree
Showing 49 changed files with 1,040 additions and 329 deletions.
10 changes: 6 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
2. 安装依赖:`yarn bootstrap` 或者 `yarn`
3. 提交你的改动,commit 请遵守 [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w)
4. 如果你的改动是修复 bug, 还可以在提交信息后面加上 `close #issue 号`, 这样可以在 pr 合并后,可以自动关闭对应的 issue, 比如 `fix: render bug close #123`
5. 确保加上了对应的单元测试
5. 确保加上了对应的单元测试和文档 (如有必要)
6. 所有 Lint 和 Test 检查通过后,并且 review 通过,我们会合并你的 pr.

![preview](https://gw.alipayobjects.com/zos/antfincdn/ssOxFrycD/86339514-5f9a-4101-8690-e47c97cd8af5.png)
Expand All @@ -54,6 +54,8 @@ npm i -g yarn
1. `yarn bootstrap` 安装依赖
2. `yarn site:bootstrap` 安装网站相关依赖
3. `yarn site:start` 启动本地的 `S2` 网站
4. `yarn core:start` 可视化的方式调试测试
5. `yarn build` 构建 `S2`, 输出 `umd`, `esm``lib` 目录
6. `yarn test` 运行单元格测试
4. `yarn core:start` 可视化的方式调试核心层测试 (基于 jest-electron)
5. `yarn react:start` 可视化的方式调试组件层测试 (基于 jest-electron)
6. `yarn react:playground` 启动本地的组件层demo (基于 vite)
7. `yarn build` 构建 `@antv/s2``@antv/s2-react` 两个包, 分别输出 `umd`, `esm``lib` 目录
8. `yarn test` 运行单元格测试
8 changes: 4 additions & 4 deletions README.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,14 @@ yarn site:bootstrap
yarn site:start
```

## 👬 Contributors

![https://github.com/antvis/s2/graphs/contributors](https://contrib.rocks/image?repo=antvis/s2)

## 📧 Contact Us

<img src="width: 100%; height: auto" href="https://gw.alipayobjects.com/zos/antfincdn/2zjO70QLdp/7939a108-930c-42a9-a0d3-fbfdc2cc44cf.jpg" alt="S2"></a>

## 👬 Contributors

![https://github.com/antvis/s2/graphs/contributors](https://contrib.rocks/image?repo=antvis/s2)

## 📄 License

MIT@[AntV](https://github.com/antvis).
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,26 @@ git clone [email protected]:antvis/S2.git

cd S2

yarn
# 安装依赖
yarn # 或者 yarn bootstrap

# 调试 s2-core
yarn core:start

# 本地启动官网
# 调试 s2-react
yarn react:playground

yarn site:bootstrap
# 单元测试
yarn test

# 打包
yarn build

# 代码风格和类型检测
yarn lint

# 本地启动官网
yarn site:bootstrap
yarn site:start
```

Expand Down
15 changes: 12 additions & 3 deletions packages/s2-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,23 @@ git clone [email protected]:antvis/S2.git

cd S2

yarn
# 安装依赖
yarn # 或者 yarn bootstrap

# 调试
yarn core:start

# 本地启动官网
# 单元测试
yarn test

yarn site:bootstrap
# 打包
yarn build

# 代码风格和类型检测
yarn lint

# 本地启动官网
yarn site:bootstrap
yarn site:start
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { createFakeSpreadSheet, createMockCellInfo } from 'tests/util/helpers';
import {
createFakeSpreadSheet,
createMockCellInfo,
sleep,
} from 'tests/util/helpers';
import { Event as GEvent } from '@antv/g-canvas';
import { DataCellClick } from '@/interaction/base-interaction/click';
import { S2Options } from '@/common/interface';
import { SpreadSheet } from '@/sheet-type';
import { InteractionStateName, S2Event } from '@/common/constant';
import {
HOVER_FOCUS_TIME,
InteractionStateName,
S2Event,
} from '@/common/constant';

jest.mock('@/interaction/event-controller');

Expand All @@ -22,6 +30,9 @@ describe('Interaction Data Cell Click Tests', () => {
trend: false,
},
},
interaction: {
hoverHighlight: true,
},
} as S2Options;
s2.isTableMode = jest.fn(() => true);
});
Expand Down Expand Up @@ -76,4 +87,32 @@ describe('Interaction Data Cell Click Tests', () => {
record: mockCellData.data,
});
});

test('should clear hover timer when data cell toggle click', async () => {
const showTooltipWithInfoSpy = jest
.spyOn(s2, 'showTooltipWithInfo')
.mockImplementation(() => {});

const event = {
stopPropagation() {},
} as unknown as GEvent;

// trigger hover
s2.emit(S2Event.DATA_CELL_HOVER, event);

// select
s2.emit(S2Event.DATA_CELL_CLICK, event);
// unselect
s2.emit(S2Event.DATA_CELL_CLICK, event);

// wait hover focus time trigger
await sleep(HOVER_FOCUS_TIME + 500);

expect(s2.interaction.getCurrentStateName()).not.toEqual(
InteractionStateName.HOVER_FOCUS,
);

// only call show tooltip once for cell clicked
expect(showTooltipWithInfoSpy).toHaveReturnedTimes(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,45 @@ describe('Interaction Brush Selection Tests', () => {
).toHaveBeenCalled();
});

// https://github.com/antvis/S2/issues/852
test('should clear brush selection state when mouse down and context menu clicked', () => {
const globalMouseUp = jest.fn();
mockSpreadSheetInstance.on(S2Event.GLOBAL_MOUSE_UP, globalMouseUp);

emitEvent(S2Event.DATA_CELL_MOUSE_DOWN, {
layerX: 10,
layerY: 20,
});
emitEvent(S2Event.DATA_CELL_MOUSE_MOVE, {
layerX: 12,
layerY: 22,
});

expect(brushSelectionInstance.brushSelectionStage).toEqual(
InteractionBrushSelectionStage.DRAGGED,
);

emitEvent(S2Event.GLOBAL_CONTEXT_MENU, {});

expect(globalMouseUp).not.toHaveBeenCalled();
expect(brushSelectionInstance.brushSelectionStage).toEqual(
InteractionBrushSelectionStage.UN_DRAGGED,
);
expect(
brushSelectionInstance.spreadsheet.interaction.hasIntercepts([
InterceptType.HOVER,
]),
).toBeFalsy();
expect(
brushSelectionInstance.spreadsheet.interaction.hasIntercepts([
InterceptType.BRUSH_SELECTION,
]),
).toBeFalsy();
expect(
brushSelectionInstance.hidePrepareSelectMaskShape,
).toHaveReturnedTimes(1);
});

test('should skip brush selection if mouse move less than valid distance', () => {
emitEvent(S2Event.DATA_CELL_MOUSE_MOVE, {});

Expand Down
112 changes: 73 additions & 39 deletions packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,36 @@ describe('PivotSheet Tests', () => {
return {
[CellTypes.ROW_CELL]: 'row',
[CellTypes.COL_CELL]: 'col',
[CellTypes.DATA_CELL]: 'cell',
[CellTypes.DATA_CELL]: 'data',
[CellTypes.CORNER_CELL]: 'corner',
}[cellType];
};

test('should support callback tooltip content for string', () => {
s2.showTooltip({
position: {
x: 10,
y: 10,
},
content: () => 'custom callback content',
});

expect(s2.tooltip.container.innerHTML).toEqual('custom callback content');
});

test('should support callback tooltip content for element', () => {
const content = document.createElement('div');
s2.showTooltip({
position: {
x: 10,
y: 10,
},
content: () => content,
});

expect(s2.tooltip.container.contains(content)).toBeTruthy();
});

test('should init tooltip', () => {
s2.showTooltip({ position: { x: 0, y: 0 } });

Expand Down Expand Up @@ -157,7 +183,12 @@ describe('PivotSheet Tests', () => {
expect(sheet.tooltip.container.innerHTML).toEqual(tooltipContent);
});

test.each([CellTypes.ROW_CELL, CellTypes.COL_CELL, CellTypes.DATA_CELL])(
test.each([
CellTypes.ROW_CELL,
CellTypes.COL_CELL,
CellTypes.DATA_CELL,
CellTypes.CORNER_CELL,
])(
'should use %o tooltip content from tooltip config first for string content',
(cellType) => {
const tooltipContent = `${cellType} tooltip content`;
Expand Down Expand Up @@ -417,43 +448,6 @@ describe('PivotSheet Tests', () => {
expect(afterRender).toHaveBeenCalledTimes(1);
});

test('should destroy sheet', () => {
const facetDestroySpy = jest
.spyOn(s2.facet, 'destroy')
.mockImplementation(() => {});

const hdAdapterDestroySpy = jest
.spyOn(s2.hdAdapter, 'destroy')
.mockImplementation(() => {});

s2.render(false);

s2.store.set('test', 111);
s2.tooltip.container.classList.add('destroy-test');
s2.interaction.addIntercepts([InterceptType.HOVER]);
s2.interaction.interactions.set('test-interaction', null);
s2.destroy();

// clear store
expect(s2.store.size()).toEqual(0);
// clear interaction
expect(s2.interaction.getState()).toEqual({
cells: [],
force: false,
});
expect(s2.interaction.getHoverTimer()).toBeNull();
expect(s2.interaction.interactions.size).toEqual(0);
expect(s2.interaction.intercepts.size).toEqual(0);
expect(s2.interaction.eventController.canvasEventHandlers).toHaveLength(0);
expect(s2.interaction.eventController.domEventListeners).toHaveLength(0);
// destroy tooltip
expect(s2.tooltip.container.children).toHaveLength(0);
// destroy facet
expect(facetDestroySpy).toHaveBeenCalledTimes(1);
// destroy hdAdapter
expect(hdAdapterDestroySpy).toHaveBeenCalledTimes(1);
});

test('should updatePagination', () => {
s2.updatePagination({
current: 2,
Expand Down Expand Up @@ -665,6 +659,46 @@ describe('PivotSheet Tests', () => {
expect(renderSpy).toHaveBeenCalledTimes(2);
});

test('should destroy sheet', () => {
const facetDestroySpy = jest
.spyOn(s2.facet, 'destroy')
.mockImplementation(() => {});

const hdAdapterDestroySpy = jest
.spyOn(s2.hdAdapter, 'destroy')
.mockImplementation(() => {});

s2.render(false);

s2.store.set('test', 111);
s2.tooltip.container.classList.add('destroy-test');
s2.interaction.addIntercepts([InterceptType.HOVER]);
s2.interaction.interactions.set('test-interaction', null);
s2.container.on('test-event', () => {});
s2.destroy();

// clear store
expect(s2.store.size()).toEqual(0);
// clear interaction
expect(s2.interaction.getState()).toEqual({
cells: [],
force: false,
});
expect(s2.interaction.getHoverTimer()).toBeNull();
expect(s2.interaction.interactions.size).toEqual(0);
expect(s2.interaction.intercepts.size).toEqual(0);
expect(s2.interaction.eventController.canvasEventHandlers).toHaveLength(0);
expect(s2.interaction.eventController.domEventListeners).toHaveLength(0);
// destroy tooltip
expect(s2.tooltip.container.children).toHaveLength(0);
// destroy facet
expect(facetDestroySpy).toHaveBeenCalledTimes(1);
// destroy hdAdapter
expect(hdAdapterDestroySpy).toHaveBeenCalledTimes(1);
// clear all canvas events
expect(s2.getEvents()).toEqual({});
});

describe('Test Layout by dataCfg fields', () => {
beforeEach(() => {
s2.destroy();
Expand Down
15 changes: 8 additions & 7 deletions packages/s2-core/__tests__/unit/ui/tooltip/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createFakeSpreadSheet } from 'tests/util/helpers';
import { createFakeSpreadSheet, sleep } from 'tests/util/helpers';
import type { SpreadSheet } from '@/sheet-type/spread-sheet';
import { BaseTooltip } from '@/ui/tooltip';
import { TOOLTIP_CONTAINER_CLS, TOOLTIP_POSITION_OFFSET } from '@/common';
Expand Down Expand Up @@ -127,30 +127,30 @@ describe('Tooltip Tests', () => {
expect(tooltip.container.innerHTML).toEqual('text');
});

test('should display custom dom element', () => {
test('should display custom dom element', async () => {
const element1 = document.createElement('span');
const element2 = document.createElement('span');

const position = {
x: 10,
y: 10,
};

element1.className = 'text1';
element2.className = 'text2';

tooltip.show({
position,
content: element1,
});

expect(tooltip.container.querySelector('.text1')).toBeTruthy();
expect(tooltip.container.contains(element1)).toBeTruthy();

tooltip.show({
position,
content: element2,
});

expect(tooltip.container.querySelector('.text2')).toBeTruthy();
await sleep(500);

expect(tooltip.container.contains(element2)).toBeTruthy();
expect(tooltip.container.children).toHaveLength(1);
});

Expand Down Expand Up @@ -193,6 +193,7 @@ describe('Tooltip Tests', () => {
});

expect(tooltip.container.querySelector('.text')).toBeTruthy();
expect(tooltip.container.contains(element)).toBeTruthy();
});

test('should replace tooltip content by call method', () => {
Expand Down
Loading

0 comments on commit 9e411b5

Please sign in to comment.