diff --git a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts index dee0a070f5..998e7acf04 100644 --- a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts +++ b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts @@ -8,13 +8,17 @@ import { totalData as drillDownTotalData, } from 'tests/data/mock-drill-down-dataset.json'; import { data } from 'tests/data/mock-dataset.json'; - import type { ViewMeta, SortMethod, CustomHeaderField, } from '@/common/interface'; -import { EXTRA_FIELD, ORIGIN_FIELD, TOTAL_VALUE } from '@/common/constant'; +import { + EXTRA_FIELD, + ORIGIN_FIELD, + TOTAL_VALUE, + SERIES_NUMBER_FIELD, +} from '@/common/constant'; import type { S2DataConfig } from '@/common/interface'; import { PivotSheet } from '@/sheet-type'; import { PivotDataSet } from '@/data-set/pivot-data-set'; @@ -45,6 +49,7 @@ describe('Pivot Dataset Test', () => { mockSheet.store = new Store(); mockSheet.interaction = new MockRootInteraction(mockSheet); + mockSheet.getSeriesNumberText = () => '序号'; dataSet = new PivotDataSet(mockSheet); dataSet.setDataCfg(dataCfg); }); @@ -483,6 +488,7 @@ describe('Pivot Dataset Test', () => { expect(dataSet.getFieldName('not-found-field')).toEqual( 'not-found-field', ); + expect(dataSet.getFieldName(SERIES_NUMBER_FIELD)).toStrictEqual('序号'); // 异常情况 // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore diff --git a/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts b/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts index a96e5d399c..e76bc821db 100644 --- a/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts +++ b/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts @@ -1,13 +1,11 @@ -/** - * table mode data-set test. - */ import { assembleDataCfg } from 'tests/util'; -import type { S2DataConfig } from '@/common/interface'; +import { type S2DataConfig, SERIES_NUMBER_FIELD } from '@/common'; import { SpreadSheet, TableSheet } from '@/sheet-type'; import { TableDataSet } from '@/data-set/table-data-set'; jest.mock('@/sheet-type'); jest.mock('@/facet/layout/node'); + const MockTableSheet = TableSheet as any as jest.Mock; describe('Table Mode Dataset Test', () => { @@ -63,6 +61,7 @@ describe('Table Mode Dataset Test', () => { MockTableSheet.mockClear(); s2 = new MockTableSheet(); + s2.getSeriesNumberText = () => '序号'; dataSet = new TableDataSet(s2); dataSet.setDataCfg(dataCfg); @@ -77,7 +76,7 @@ describe('Table Mode Dataset Test', () => { ${'city'} | ${'城市'} | ${'城市描述'} | ${mockCityFormatter} ${'type'} | ${'类型'} | ${'类型描述'} | ${mockTypeFormatter} ${'sub_type'} | ${'子类型'} | ${'子类型描述'} | ${mockSubTypeFormatter} - ${'number'} | ${'数量'} | ${'数量描述'} | ${mockProvinceFormatter} + ${'number'} | ${'数量'} | ${'数量描述'} | ${mockNumberFormatter} `( 'should return correct filed meta when field=$field', ({ field, name, description }) => { @@ -86,6 +85,10 @@ describe('Table Mode Dataset Test', () => { expect(dataSet.getFieldFormatter(field)(null)).toStrictEqual(field); }, ); + + test('should get series number field name', () => { + expect(dataSet.getFieldName(SERIES_NUMBER_FIELD)).toStrictEqual('序号'); + }); }); describe('test base dataset structure', () => { diff --git a/packages/s2-core/__tests__/unit/facet/header/corner-spec.ts b/packages/s2-core/__tests__/unit/facet/header/corner-spec.ts index eefcd31769..be1d15aeb1 100644 --- a/packages/s2-core/__tests__/unit/facet/header/corner-spec.ts +++ b/packages/s2-core/__tests__/unit/facet/header/corner-spec.ts @@ -40,7 +40,7 @@ describe('Corner Tests', () => { }); test('should get custom series number text', () => { - s2.options.seriesNumber!.text = 'test'; + s2.getSeriesNumberText = () => 'test'; const cornerNode = createCornerNode(); expect(cornerNode.value).toEqual('test'); diff --git a/packages/s2-core/__tests__/unit/facet/layout/layout-hooks-spec.ts b/packages/s2-core/__tests__/unit/facet/layout/layout-hooks-spec.ts new file mode 100644 index 0000000000..d973f34ab5 --- /dev/null +++ b/packages/s2-core/__tests__/unit/facet/layout/layout-hooks-spec.ts @@ -0,0 +1,117 @@ +import { createFakeSpreadSheet } from 'tests/util/helpers'; +import { + layoutArrange, + layoutCoordinate, + layoutHierarchy, +} from '@/facet/layout/layout-hooks'; +import { Hierarchy, Node } from '@/index'; + +describe('layout-hooks test', () => { + const s2 = createFakeSpreadSheet({ + width: 600, + height: 480, + }); + + const node = new Node({ + id: '', + key: '', + value: '', + }); + + const hierarchy = new Hierarchy(); + + test('#layoutArrange()', () => { + const layoutArrangeFn = jest.fn(() => ['b']); + + expect(layoutArrange(s2, ['a'], node, '')).toEqual(['a']); + + expect( + layoutArrange( + { options: { layoutArrange: layoutArrangeFn } }, + ['a'], + node, + '', + ), + ).toEqual(['b']); + expect(layoutArrangeFn).toHaveBeenCalledTimes(1); + }); + + test('#layoutHierarchy()', () => { + const colNode = new Node({ + id: 'test', + key: 'test', + value: 'test', + }); + + const layoutHierarchyFn = jest.fn(() => { + return { + push: [node], + unshift: [colNode], + }; + }); + + expect( + layoutHierarchy( + { + options: { + layoutHierarchy: layoutHierarchyFn, + }, + facet: { + getHiddenColumnsInfo: () => colNode, + }, + columns: [colNode.id], + }, + node, + colNode, + hierarchy, + ), + ).toEqual(true); + + expect( + layoutHierarchy( + { + options: { + layoutHierarchy: layoutHierarchyFn, + }, + facet: { + getHiddenColumnsInfo: () => {}, + }, + columns: [], + }, + node, + colNode, + hierarchy, + ), + ).toEqual(true); + }); + + test('#layoutCoordinate()', () => { + const layoutCoordinateFn = jest.fn(); + const rowNode = new Node({ + id: 'rowNode', + key: 'rowNode', + value: 'rowNode', + }); + const colNode = new Node({ + id: 'colNode', + key: 'colNode', + value: 'colNode', + }); + + layoutCoordinate( + { options: { layoutCoordinate: layoutCoordinateFn } }, + rowNode, + colNode, + ); + + expect(layoutCoordinateFn).toHaveBeenCalledTimes(0); + + layoutCoordinate( + { options: { layoutCoordinate: layoutCoordinateFn } }, + { ...rowNode, isLeaf: true }, + { ...colNode, isLeaf: true }, + ); + + expect(layoutCoordinateFn).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/s2-core/__tests__/unit/facet/layout/node-spec.ts b/packages/s2-core/__tests__/unit/facet/layout/node-spec.ts index 07457681dd..788ce9c846 100644 --- a/packages/s2-core/__tests__/unit/facet/layout/node-spec.ts +++ b/packages/s2-core/__tests__/unit/facet/layout/node-spec.ts @@ -1,19 +1,62 @@ -/** - * Node test. - */ - +import { SERIES_NUMBER_FIELD } from '../../../../src'; import { Node } from '@/facet/layout/node'; describe('Node Test', () => { - const root = new Node({ id: `root`, field: '', value: '', children: [] }); + const root = new Node({ + id: 'root', + key: 'root', + value: 'root', + children: [], + }); + const child = new Node({ + id: 'child', + key: 'child', + value: 'child', + isLeaf: true, + children: [], + }); const node = new Node({ - id: `root[&]country`, + id: 'root[&]country', + key: '', value: '', field: 'country', parent: root, }); + node.children = [child]; + test('should get correct field path', () => { expect(Node.getFieldPath(node)).toEqual(['country']); }); + + test('#getAllLeaveNodes()', () => { + expect(Node.getAllLeaveNodes(node)).toHaveLength(1); + }); + + test('#getAllChildrenNodes()', () => { + expect(Node.getAllChildrenNodes(node)).toHaveLength(1); + }); + + test('#getAllBranch()', () => { + expect(Node.getBranchNodes(node)).toHaveLength(1); + }); + + test('#rootNode()', () => { + expect(Node.rootNode().id).toEqual('root'); + }); + + test('#getHeadLeafChild()', () => { + expect(node.getHeadLeafChild().id).toEqual('child'); + }); + + test('#getTotalHeightForTreeHierarchy()', () => { + expect(node.getTotalHeightForTreeHierarchy()).toEqual(0); + }); + + test('#isSeriesNumberNode()', () => { + expect(node.isSeriesNumberNode()).toBeFalsy(); + + node.field = SERIES_NUMBER_FIELD; + expect(node.isSeriesNumberNode()).toBeTruthy(); + }); }); diff --git a/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts b/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts index 51f72d7f2b..2f4106c086 100644 --- a/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts +++ b/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts @@ -5,6 +5,7 @@ import { Canvas, Group, Rect, type CanvasConfig } from '@antv/g'; import { Renderer } from '@antv/g-canvas'; import { find, size } from 'lodash'; import { assembleDataCfg, assembleOptions } from 'tests/util'; +import { getDefaultSeriesNumberText } from '../../../src'; import { createFakeSpreadSheet } from '../../util/helpers'; import { getMockPivotMeta } from './util'; import { CornerCell, DataCell } from '@/cell'; @@ -54,7 +55,8 @@ jest.mock('@/sheet-type', () => { return { dataCfg: assembleDataCfg(), options: assembleOptions({ - dataCell: (viewMeta) => new DataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new DataCell(viewMeta, spreadsheet), }), container, theme: getTheme({}), @@ -96,6 +98,7 @@ jest.mock('@/sheet-type', () => { }, measureTextWidth: jest.fn() as unknown as SpreadSheet['measureTextWidth'], + getSeriesNumberText: jest.fn(() => getDefaultSeriesNumberText()), }; }), }; diff --git a/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts b/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts index 3f58a422f1..7d3c0afc2d 100644 --- a/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts +++ b/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts @@ -7,6 +7,7 @@ import { assembleDataCfg, assembleOptions } from 'tests/util'; import { pick } from 'lodash'; import { data } from '../../data/mock-dataset.json'; import { createFakeSpreadSheet } from '../../util/helpers'; +import { getDefaultSeriesNumberText } from '../../../src'; import { LayoutWidthType, ROOT_NODE_ID } from '@/common/constant'; import { Store } from '@/common/store'; import { TableDataSet } from '@/data-set/table-data-set'; @@ -82,6 +83,7 @@ jest.mock('@/sheet-type', () => { isCustomColumnFields: jest.fn(), measureTextWidthRoughly: jest.fn(), measureTextWidth: jest.fn(), + getSeriesNumberText: jest.fn(() => getDefaultSeriesNumberText()), }; }), }; @@ -152,28 +154,6 @@ describe('Table Mode Facet Test', () => { expect(rowsHierarchy.getIndexNodes()).toHaveLength(0); }); - test('should get default seriesNumberText', () => { - const { facet } = createMockTableFacet({ - seriesNumber: { - enable: true, - }, - }); - - expect(facet.getColLeafNodes()[0].value).toEqual('序号'); - }); - - test('should get custom seriesNumberText', () => { - const seriesNumberText = 'test'; - const { facet } = createMockTableFacet({ - seriesNumber: { - enable: true, - text: seriesNumberText, - }, - }); - - expect(facet.getColLeafNodes()[0].value).toEqual(seriesNumberText); - }); - describe('should get none layer when dataCfg.fields is empty', () => { const spreadsheet = createFakeSpreadSheet({ s2DataConfig: { diff --git a/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts b/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts index 70d2ca24dd..bd4b7c11fd 100644 --- a/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts +++ b/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts @@ -479,6 +479,27 @@ describe('PivotSheet Tests', () => { expect(s2.options.seriesNumber?.enable).toBeTruthy(); }); + test.each([ + { + enable: true, + text: '测试', + result: '测试', + }, + { + enable: false, + text: '测试', + result: '', + }, + ])( + 'should get correctly series number text by %o', + ({ result, ...options }) => { + s2.setOptions({ + seriesNumber: options, + }); + expect(s2.getSeriesNumberText()).toEqual(result); + }, + ); + test('should init new tooltip', () => { const tooltipDestroySpy = jest .spyOn(s2.tooltip, 'destroy') diff --git a/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts b/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts index e522848722..0f660c8f46 100644 --- a/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts +++ b/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts @@ -213,6 +213,27 @@ describe('TableSheet Tests', () => { ); }); + test.each([ + { + enable: true, + text: '测试', + result: '测试', + }, + { + enable: false, + text: '测试', + result: '', + }, + ])( + 'should get correctly series number text by %o', + ({ result, ...options }) => { + s2.setOptions({ + seriesNumber: options, + }); + expect(s2.getSeriesNumberText()).toEqual(result); + }, + ); + test('should get normal header fields status', () => { expect(s2.isCustomHeaderFields()).toBeFalsy(); expect(s2.isCustomRowFields()).toBeFalsy(); diff --git a/packages/s2-core/__tests__/unit/utils/color-spec.ts b/packages/s2-core/__tests__/unit/utils/color-spec.ts index 2fccd75c6c..b9142c193c 100644 --- a/packages/s2-core/__tests__/unit/utils/color-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/color-spec.ts @@ -1,4 +1,4 @@ -import { getPalette, shouldReverseFontColor } from '@/utils'; +import { getPalette, shouldReverseFontColor, isReadableText } from '@/utils'; import { generatePalette, generateStandardColors } from '@/utils/color'; const expectThemeColor = '#F1535F'; @@ -115,4 +115,24 @@ describe('Theme Color Tests', () => { expect(shouldReverseFontColor(color)).toBeFalsy(); }); }); + + test('should use reverse font color when the background color dark and the contrast between the background color and the font color is too low', () => { + const backgroundColor = '#000000'; + + const fontColors = ['#000000', '#1D2129']; + + fontColors.forEach((fontColor) => { + expect(isReadableText(backgroundColor, fontColor)).toBeFalsy(); + }); + }); + + test('should use default font color when the background color light and the contrast between the background color and the font color is too high', () => { + const backgroundColor = '#ffffff'; + + const fontColors = ['#000000', '#1D2129']; + + fontColors.forEach((fontColor) => { + expect(isReadableText(backgroundColor, fontColor)).toBeTruthy(); + }); + }); }); diff --git a/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-table-spec.ts.snap b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-table-spec.ts.snap index a8ac12216d..df9081a2f2 100644 --- a/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-table-spec.ts.snap +++ b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-table-spec.ts.snap @@ -278,6 +278,168 @@ exports[`TableSheet Export Test should export correct data with totals 1`] = ` 浙江省-province 家具-type 沙发 5343" `; +exports[`TableSheet Export Test should export correctly data for custom series number text by { formatHeader: true } 1`] = ` +"测试 省份 城市 类别 子类别 数量 +1 浙江省 杭州市 家具 桌子 7789 +2 浙江省 绍兴市 家具 桌子 2367 +3 浙江省 宁波市 家具 桌子 3877 +4 浙江省 舟山市 家具 桌子 4342 +5 浙江省 杭州市 家具 沙发 5343 +6 浙江省 绍兴市 家具 沙发 632 +7 浙江省 宁波市 家具 沙发 7234 +8 浙江省 舟山市 家具 沙发 834 +9 浙江省 杭州市 办公用品 笔 945 +10 浙江省 绍兴市 办公用品 笔 1304 +11 浙江省 宁波市 办公用品 笔 1145 +12 浙江省 舟山市 办公用品 笔 1432 +13 浙江省 杭州市 办公用品 纸张 1343 +14 浙江省 绍兴市 办公用品 纸张 1354 +15 浙江省 宁波市 办公用品 纸张 1523 +16 浙江省 舟山市 办公用品 纸张 1634 +17 四川省 成都市 家具 桌子 1723 +18 四川省 绵阳市 家具 桌子 1822 +19 四川省 南充市 家具 桌子 1943 +20 四川省 乐山市 家具 桌子 2330 +21 四川省 成都市 家具 沙发 2451 +22 四川省 绵阳市 家具 沙发 2244 +23 四川省 南充市 家具 沙发 2333 +24 四川省 乐山市 家具 沙发 2445 +25 四川省 成都市 办公用品 笔 2335 +26 四川省 绵阳市 办公用品 笔 245 +27 四川省 南充市 办公用品 笔 2457 +28 四川省 乐山市 办公用品 笔 2458 +29 四川省 成都市 办公用品 纸张 4004 +30 四川省 绵阳市 办公用品 纸张 3077 +31 四川省 南充市 办公用品 纸张 3551 +32 四川省 乐山市 办公用品 纸张 352 +33 家具 桌子 26193 +34 家具 49709 +35 家具 沙发 23516 +36 办公用品 29159 +37 办公用品 笔 12321 +38 办公用品 纸张 16838 +39 浙江省 家具 桌子 18375 +40 浙江省 家具 沙发 14043 +41 浙江省 办公用品 笔 4826 +42 浙江省 办公用品 纸张 5854 +43 四川省 家具 桌子 7818 +44 四川省 家具 沙发 9473 +45 四川省 办公用品 笔 7495 +46 四川省 办公用品 纸张 10984 +47 浙江省 杭州市 家具 13132 +48 浙江省 杭州市 办公用品 2288 +49 浙江省 杭州市 15420 +50 浙江省 绍兴市 家具 2999 +51 浙江省 绍兴市 办公用品 2658 +52 浙江省 绍兴市 5657 +53 浙江省 宁波市 家具 11111 +54 浙江省 宁波市 办公用品 2668 +55 浙江省 宁波市 13779 +56 浙江省 舟山市 家具 5176 +57 浙江省 舟山市 办公用品 3066 +58 浙江省 舟山市 8242 +59 四川省 成都市 家具 4174 +60 四川省 成都市 办公用品 6339 +61 四川省 成都市 10513 +62 四川省 绵阳市 家具 4066 +63 四川省 绵阳市 办公用品 3322 +64 四川省 绵阳市 7388 +65 四川省 南充市 家具 4276 +66 四川省 南充市 办公用品 6008 +67 四川省 南充市 10284 +68 四川省 乐山市 家具 4775 +69 四川省 乐山市 办公用品 2810 +70 四川省 乐山市 7585 +71 浙江省 家具 32418 +72 浙江省 办公用品 10680 +73 浙江省 43098 +74 四川省 家具 17291 +75 四川省 办公用品 18479 +76 四川省 35770 +77 78868" +`; + +exports[`TableSheet Export Test should export correctly data for default series number text by { formatHeader: false } 1`] = ` +"序号 province city type sub_type number +1 浙江省 杭州市 家具 桌子 7789 +2 浙江省 绍兴市 家具 桌子 2367 +3 浙江省 宁波市 家具 桌子 3877 +4 浙江省 舟山市 家具 桌子 4342 +5 浙江省 杭州市 家具 沙发 5343 +6 浙江省 绍兴市 家具 沙发 632 +7 浙江省 宁波市 家具 沙发 7234 +8 浙江省 舟山市 家具 沙发 834 +9 浙江省 杭州市 办公用品 笔 945 +10 浙江省 绍兴市 办公用品 笔 1304 +11 浙江省 宁波市 办公用品 笔 1145 +12 浙江省 舟山市 办公用品 笔 1432 +13 浙江省 杭州市 办公用品 纸张 1343 +14 浙江省 绍兴市 办公用品 纸张 1354 +15 浙江省 宁波市 办公用品 纸张 1523 +16 浙江省 舟山市 办公用品 纸张 1634 +17 四川省 成都市 家具 桌子 1723 +18 四川省 绵阳市 家具 桌子 1822 +19 四川省 南充市 家具 桌子 1943 +20 四川省 乐山市 家具 桌子 2330 +21 四川省 成都市 家具 沙发 2451 +22 四川省 绵阳市 家具 沙发 2244 +23 四川省 南充市 家具 沙发 2333 +24 四川省 乐山市 家具 沙发 2445 +25 四川省 成都市 办公用品 笔 2335 +26 四川省 绵阳市 办公用品 笔 245 +27 四川省 南充市 办公用品 笔 2457 +28 四川省 乐山市 办公用品 笔 2458 +29 四川省 成都市 办公用品 纸张 4004 +30 四川省 绵阳市 办公用品 纸张 3077 +31 四川省 南充市 办公用品 纸张 3551 +32 四川省 乐山市 办公用品 纸张 352 +33 家具 桌子 26193 +34 家具 49709 +35 家具 沙发 23516 +36 办公用品 29159 +37 办公用品 笔 12321 +38 办公用品 纸张 16838 +39 浙江省 家具 桌子 18375 +40 浙江省 家具 沙发 14043 +41 浙江省 办公用品 笔 4826 +42 浙江省 办公用品 纸张 5854 +43 四川省 家具 桌子 7818 +44 四川省 家具 沙发 9473 +45 四川省 办公用品 笔 7495 +46 四川省 办公用品 纸张 10984 +47 浙江省 杭州市 家具 13132 +48 浙江省 杭州市 办公用品 2288 +49 浙江省 杭州市 15420 +50 浙江省 绍兴市 家具 2999 +51 浙江省 绍兴市 办公用品 2658 +52 浙江省 绍兴市 5657 +53 浙江省 宁波市 家具 11111 +54 浙江省 宁波市 办公用品 2668 +55 浙江省 宁波市 13779 +56 浙江省 舟山市 家具 5176 +57 浙江省 舟山市 办公用品 3066 +58 浙江省 舟山市 8242 +59 四川省 成都市 家具 4174 +60 四川省 成都市 办公用品 6339 +61 四川省 成都市 10513 +62 四川省 绵阳市 家具 4066 +63 四川省 绵阳市 办公用品 3322 +64 四川省 绵阳市 7388 +65 四川省 南充市 家具 4276 +66 四川省 南充市 办公用品 6008 +67 四川省 南充市 10284 +68 四川省 乐山市 家具 4775 +69 四川省 乐山市 办公用品 2810 +70 四川省 乐山市 7585 +71 浙江省 家具 32418 +72 浙江省 办公用品 10680 +73 浙江省 43098 +74 四川省 家具 17291 +75 四川省 办公用品 18479 +76 四川省 35770 +77 78868" +`; + exports[`TableSheet Export Test should export correctly data for single row data by { async: false } 1`] = ` Array [ "province city type price cost", diff --git a/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts b/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts index 26589e092a..590ef81507 100644 --- a/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts @@ -466,4 +466,55 @@ describe('TableSheet Export Test', () => { // The first line is the header, so the number of lines should be the same as the number of data plus one expect(data.split(LINE_SEPARATOR)).toHaveLength(bigData.length + 1); }); + + it('should export correctly data for default series number text by { formatHeader: false }', async () => { + const tableSheet = new TableSheet( + getContainer(), + assembleDataCfg({ + fields: { + columns: ['province', 'city', 'type', 'sub_type', 'number'], + }, + }), + assembleOptions({ + seriesNumber: { enable: true }, + }), + ); + + await tableSheet.render(); + const data = await asyncGetAllPlainData({ + sheetInstance: tableSheet, + split: TAB_SEPARATOR, + formatOptions: { + formatHeader: false, + }, + }); + + expect(data).toMatchSnapshot(); + }); + + // https://github.com/antvis/S2/issues/2755 + it('should export correctly data for custom series number text by { formatHeader: true }', async () => { + const tableSheet = new TableSheet( + getContainer(), + assembleDataCfg({ + fields: { + columns: ['province', 'city', 'type', 'sub_type', 'number'], + }, + }), + assembleOptions({ + seriesNumber: { enable: true, text: '测试' }, + }), + ); + + await tableSheet.render(); + const data = await asyncGetAllPlainData({ + sheetInstance: tableSheet, + split: TAB_SEPARATOR, + formatOptions: { + formatHeader: true, + }, + }); + + expect(data).toMatchSnapshot(); + }); }); diff --git a/packages/s2-core/__tests__/unit/utils/interaction/select-event-spec.ts b/packages/s2-core/__tests__/unit/utils/interaction/select-event-spec.ts index a49bf97778..c288e25e0c 100644 --- a/packages/s2-core/__tests__/unit/utils/interaction/select-event-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/interaction/select-event-spec.ts @@ -1,11 +1,20 @@ +import { createFakeSpreadSheet, createMockCellInfo } from 'tests/util/helpers'; import { TableSeriesNumberCell } from '../../../../src/cell'; +import type { ViewMeta } from '@/common'; +import { InteractionKeyboardKey, S2Event } from '@/common/constant'; +import type { SpreadSheet } from '@/sheet-type/spread-sheet'; import { - isMultiSelectionKey, + getCellMeta, + getColHeaderByCellId, + getInteractionCells, + getInteractionCellsBySelectedCells, + getRangeIndex, getRowCellForSelectedCell, + getRowHeaderByCellId, + isMouseEventWithMeta, + isMultiSelectionKey, + selectCells, } from '@/utils/interaction/select-event'; -import { InteractionKeyboardKey } from '@/common/constant'; -import type { SpreadSheet } from '@/sheet-type/spread-sheet'; -import type { ViewMeta } from '@/common'; jest.mock('@/cell', () => { return { @@ -28,13 +37,29 @@ describe('Select Event Utils Tests', () => { isMultiSelectionKey({ key: InteractionKeyboardKey.META, } as KeyboardEvent), - ).toBe(true); + ).toBeTruthy(); expect( isMultiSelectionKey({ key: InteractionKeyboardKey.CONTROL, } as KeyboardEvent), - ).toBe(true); + ).toBeTruthy(); + }); + }); + + describe('#isMouseEventWithMeta()', () => { + test('should return true for ctrl and meta key', () => { + expect( + isMouseEventWithMeta({ + ctrlKey: InteractionKeyboardKey.CONTROL, + } as KeyboardEvent), + ).toBeTruthy(); + + expect( + isMouseEventWithMeta({ + metaKey: InteractionKeyboardKey.META, + } as KeyboardEvent), + ).toBeTruthy(); }); }); @@ -71,4 +96,65 @@ describe('Select Event Utils Tests', () => { ).toStrictEqual(['5-序号']); }); }); + + test('#getCellMeta()', () => { + const cell = createMockCellInfo('test-a').mockCell; + + expect(getCellMeta(cell)).toEqual({ + colIndex: 0, + id: 'test-a', + rowIndex: 0, + rowQuery: undefined, + type: undefined, + }); + }); + + test('#selectCells()', () => { + const s2 = createFakeSpreadSheet({ width: 100, height: 100 }); + const selected = jest.fn(); + + s2.on(S2Event.GLOBAL_SELECTED, selected); + const cell = createMockCellInfo('test-a').mockCell; + + selectCells(s2, [cell]); + + expect(selected).toHaveBeenCalled(); + }); + + test('#getRangeIndex()', () => { + expect( + getRangeIndex({ rowIndex: 0, colIndex: 0 }, { rowIndex: 2, colIndex: 2 }), + ).toEqual({ + end: { colIndex: 2, rowIndex: 2 }, + start: { colIndex: 0, rowIndex: 0 }, + }); + }); + + test('#getRowHeaderByCellId()', () => { + const s2 = createFakeSpreadSheet({ width: 100, height: 100 }); + + expect(getRowHeaderByCellId('a', s2)).toEqual([]); + }); + + test('#getColHeaderByCellId()', () => { + const s2 = createFakeSpreadSheet({ width: 100, height: 100 }); + + expect(getColHeaderByCellId('a', s2)).toEqual([]); + }); + + test('#getInteractionCells()', () => { + const cell = createMockCellInfo('test-a').mockCell; + const s2 = createFakeSpreadSheet({ width: 100, height: 100 }); + const meta = getCellMeta(cell); + + expect(getInteractionCells(meta, s2)).toEqual([meta]); + }); + + test('#getInteractionCellsBySelectedCells()', () => { + const cell = createMockCellInfo('test-a').mockCell; + const s2 = createFakeSpreadSheet({ width: 100, height: 100 }); + const meta = getCellMeta(cell); + + expect(getInteractionCellsBySelectedCells([meta], s2)).toEqual([meta]); + }); }); diff --git a/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts b/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts index c5c70a4069..739dccc01a 100644 --- a/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts @@ -1,30 +1,33 @@ import type { Group } from '@antv/g'; +import type { DataCell, MergedCell } from '@/cell'; +import type { + MergedCellInfo, + TempMergedCell, + ViewMeta, +} from '@/common/interface'; import type { DataCellCallback } from '@/common/interface/basic'; -import { SpreadSheet } from '@/sheet-type'; import { Store } from '@/common/store'; +import type { BaseFacet } from '@/facet'; +import type { RootInteraction } from '@/interaction/root'; +import { SpreadSheet } from '@/sheet-type'; import { + differenceTempMergedCells, getActiveCellsInfo, - getRectangleEdges, - unique, + getInvisibleInfo, + getMergedCellInstance, getNextEdge, getPolygonPoints, - getInvisibleInfo, - getVisibleInfo, + getRectangleEdges, getTempMergedCell, + getVisibleInfo, + mergeCell, + mergeTempMergedCell, + mergedCellConvertTempMergedCells, removeUnmergedCellsInfo, + unique, + unmergeCell, updateMergedCells, - mergeTempMergedCell, - MergedCellConvertTempMergedCells, - differenceTempMergedCells, } from '@/utils'; -import type { RootInteraction } from '@/interaction/root'; -import type { - MergedCellInfo, - TempMergedCell, - ViewMeta, -} from '@/common/interface'; -import type { BaseFacet } from '@/facet'; -import type { DataCell, MergedCell } from '@/cell'; jest.mock('@/sheet-type'); @@ -39,6 +42,9 @@ describe('Merge Cells Test', () => { beforeEach(() => { mockInstance = new MockSpreadSheet(); mockInstance.store = new Store(); + mockInstance.options = { + conditions: [], + }; mockInstance.interaction = { getPanelGroupAllDataCells() { return mockAllVisibleCells; @@ -279,6 +285,63 @@ describe('Merge Cells Test', () => { expect(result).toEqual([[mockMergeCellInfo[0], mockMergeCellInfo[1]]]); }); + test('#getMergedCellInstance()', () => { + const mergedCell = jest.fn(() => true); + + mockInstance = { + options: { + mergedCell, + }, + }; + + expect(getMergedCellInstance(mockInstance, [], null)).toEqual(true); + }); + + test('#mergeCell()', () => { + const addMergeCell = jest.fn(); + + mockInstance.interaction.getActiveCells = () => []; + mockInstance.facet.panelScrollGroup = { + addMergeCell, + }; + mockInstance.facet.getCellMeta = jest + .fn() + .mockImplementation((scalar) => mockMergeCellInfo[scalar]); + Object.defineProperty(mockInstance.facet.cfg, 'dataCell', { + value: jest.fn().mockImplementation((scalar) => { + return { + getMeta: jest.fn().mockReturnValue(scalar), + }; + }), + }); + + const errorSpy = jest + .spyOn(console, 'error') + .mockImplementationOnce(() => {}); + + mergeCell(mockInstance); + + expect(errorSpy).toHaveBeenCalledWith( + '[mergeCell]: The merged cells must be more than one!', + ); + + mergeCell(mockInstance, mockMergeCellInfo); + + expect(addMergeCell).toHaveBeenCalledTimes(1); + }); + + test('#unmergeCell()', () => { + const errorSpy = jest + .spyOn(console, 'error') + .mockImplementationOnce(() => {}); + + unmergeCell(mockInstance); + + expect(errorSpy).toHaveBeenCalledWith( + '[unmergeCell]: The undefined is not a MergedCell', + ); + }); + describe('Update mergedCells', () => { test('should not update mergedCells when mergedCellsInfo is empty', () => { mockInstance.options = { @@ -342,13 +405,13 @@ describe('Merge Cells Test', () => { ]); }); - test('should convert TempMergedCell to MergedCell. (MergedCellConvertTempMergedCells)', () => { + test('should convert TempMergedCell to MergedCell. (mergedCellConvertTempMergedCells)', () => { const mockMergedCell = { cells: mockAllVisibleCells, getMeta: jest.fn().mockReturnValue(mockMergeCellInfo[2]), isPartiallyVisible: true, } as unknown as MergedCell; - const result = MergedCellConvertTempMergedCells([mockMergedCell]); + const result = mergedCellConvertTempMergedCells([mockMergedCell]); expect(result).toEqual([ { diff --git a/packages/s2-core/__tests__/unit/utils/text-spec.ts b/packages/s2-core/__tests__/unit/utils/text-spec.ts index d77df9bbd0..ff463bd036 100644 --- a/packages/s2-core/__tests__/unit/utils/text-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/text-spec.ts @@ -1,15 +1,22 @@ -import { createPivotSheet } from 'tests/util/helpers'; +import { + createFakeSpreadSheet, + createMockCellInfo, + createPivotSheet, +} from 'tests/util/helpers'; import type { TextTheme } from '../../../src/common'; import { safeJsonParse } from '../../../src/utils/common'; -import { ELLIPSIS_SYMBOL } from '@/common'; import { - isUpDataValue, + drawCustomContent, getCellWidth, - getEmptyPlaceholder, getContentAreaForMultiData, - isZeroOrEmptyValue, + getEmptyPlaceholder, isUnchangedValue, + isUpDataValue, + isZeroOrEmptyValue, } from '@/utils/text'; +import { ELLIPSIS_SYMBOL } from '@/common'; + +jest.mock('@/utils/g-mini-charts'); describe('Text Utils Tests', () => { const font: TextTheme = { @@ -288,4 +295,62 @@ describe('isUnchangedValue', () => { test('should return false for negative values', () => { expect(isUnchangedValue(-123, 123)).toBeFalsy(); }); + + test('should draw custom content', () => { + const renderTextShape = jest.fn(); + const s2 = createFakeSpreadSheet({ + style: { + cellCfg: {}, + }, + }); + const cell = createMockCellInfo('test').mockCell; + + cell.updateTextPosition = () => {}; + cell.getActualTextWidth = () => 0; + cell.getBBoxByType = () => ({ + width: 200, + height: 200, + }); + cell.getMeta = () => ({ + spreadsheet: s2, + }); + cell.getStyle = () => ({}); + cell.renderTextShape = renderTextShape; + + const errorSpy = jest + .spyOn(console, 'error') + .mockImplementationOnce(() => {}); + + function render() { + drawCustomContent(cell, { values: ['test'] }); + } + + expect(render).not.toThrow(); + expect(errorSpy).not.toHaveBeenCalled(); + expect(renderTextShape).toHaveBeenCalledTimes(4); + }); + + test('should draw custom mini chart', () => { + const s2 = createFakeSpreadSheet({ + style: { + cellCfg: {}, + }, + }); + const cell = createMockCellInfo('test').mockCell; + + cell.getBBoxByType = () => ({ + width: 200, + height: 200, + }); + cell.getMeta = () => ({ + spreadsheet: s2, + }); + cell.getStyle = () => ({}); + + function render() { + drawCustomContent(cell, { values: { data: 'test' } }); + } + + expect(render).not.toThrow(); + }); }); diff --git a/packages/s2-core/__tests__/util/helpers.ts b/packages/s2-core/__tests__/util/helpers.ts index c69fedccba..b49abfb876 100644 --- a/packages/s2-core/__tests__/util/helpers.ts +++ b/packages/s2-core/__tests__/util/helpers.ts @@ -23,6 +23,7 @@ import { asyncGetAllPlainData, TAB_SEPARATOR, EventController, + getDefaultSeriesNumberText, } from '../../src'; import { assembleOptions, assembleDataCfg } from '.'; @@ -218,8 +219,6 @@ export const createFakeSpreadSheet = (config?: { s2.isPivotMode = jest.fn(); s2.getCell = jest.fn(); s2.isHierarchyTreeType = jest.fn(); - s2.facet.getRowNodes = jest.fn().mockReturnValue([]); - s2.facet.getCells = jest.fn().mockReturnValue([]); s2.getCanvasElement = () => s2.container.getContextService().getDomElement() as any; s2.getCanvasConfig = () => s2.container.getConfig(); @@ -234,6 +233,7 @@ export const createFakeSpreadSheet = (config?: { s2.getLayoutWidthType = jest.fn(); s2.measureTextWidth = jest.fn(); s2.isFrozenRowHeader = jest.fn(); + s2.getSeriesNumberText = jest.fn(() => getDefaultSeriesNumberText()); s2.theme = getTheme({ name: 'default', spreadsheet: s2, diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index ab18fdbf11..aa5cfc1ac7 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -65,7 +65,7 @@ import { getIconTotalWidth, type GroupedIcons, } from '../utils/cell/header-cell'; -import { shouldReverseFontColor } from '../utils/color'; +import { isReadableText, shouldReverseFontColor } from '../utils/color'; import { getIconPosition } from '../utils/condition/condition'; import { renderIcon, @@ -727,7 +727,8 @@ export abstract class BaseCell extends Group { // text 默认为黑色,当背景颜色亮度过低时,修改 text 为白色 if ( shouldReverseFontColor(backgroundColor as string) && - textFill === DEFAULT_FONT_COLOR && + (textFill === DEFAULT_FONT_COLOR || + !isReadableText(backgroundColor!, textFill)) && intelligentReverseTextColor ) { textFill = REVERSE_FONT_COLOR; @@ -746,6 +747,7 @@ export abstract class BaseCell extends Group { if (attrs) { return { backgroundColor: attrs.fill, + backgroundColorOpacity: 1, intelligentReverseTextColor: attrs.intelligentReverseTextColor || false, }; diff --git a/packages/s2-core/src/common/constant/basic.ts b/packages/s2-core/src/common/constant/basic.ts index ca03221696..39ba5bbadc 100644 --- a/packages/s2-core/src/common/constant/basic.ts +++ b/packages/s2-core/src/common/constant/basic.ts @@ -84,8 +84,7 @@ export enum MiniChartType { Bullet = 'bullet', } -export const getDefaultSeriesNumberText = (defaultText?: string) => - defaultText ?? i18n('序号'); +export const getDefaultSeriesNumberText = () => i18n('序号'); export const getDefaultCornerText = () => i18n('指标'); diff --git a/packages/s2-core/src/common/constant/interaction.ts b/packages/s2-core/src/common/constant/interaction.ts index 150106fbd0..08a9be3d5e 100644 --- a/packages/s2-core/src/common/constant/interaction.ts +++ b/packages/s2-core/src/common/constant/interaction.ts @@ -113,6 +113,8 @@ export enum ScrollbarPositionType { export enum ScrollDirection { SCROLL_UP = 'scrollUp', SCROLL_DOWN = 'scrollDown', + SCROLL_LEFT = 'scrollLeft', + SCROLL_RIGHT = 'scrollRight', } export enum ScrollDirectionRowIndexDiff { diff --git a/packages/s2-core/src/data-set/base-data-set.ts b/packages/s2-core/src/data-set/base-data-set.ts index a5c211e625..8afd4d4850 100644 --- a/packages/s2-core/src/data-set/base-data-set.ts +++ b/packages/s2-core/src/data-set/base-data-set.ts @@ -12,7 +12,7 @@ import { min, } from 'lodash'; import type { CellMeta, CustomHeaderField, ViewMeta } from '../common'; -import { CellType } from '../common'; +import { CellType, SERIES_NUMBER_FIELD } from '../common'; import type { Fields, FilterParam, @@ -112,6 +112,10 @@ export abstract class BaseDataSet { * @param field */ public getFieldName(field: CustomHeaderField, defaultValue?: string): string { + if (field === SERIES_NUMBER_FIELD) { + return this.spreadsheet?.getSeriesNumberText(); + } + const realField = this.getField(field); // 兼容自定义行列头场景 const headerNode = this.spreadsheet?.facet diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 924ba7fbfc..5cf9efe3e9 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -1327,6 +1327,9 @@ export abstract class BaseFacet { onWheel = (event: WheelEvent) => { const { interaction } = this.spreadsheet.options; let { deltaX, deltaY, offsetX, offsetY } = event; + const { scrollX: currentScrollX, rowHeaderScrollX } = + this.getScrollOffset(); + const { shiftKey } = event; // Windows 环境,按住 shift 时,固定为水平方向滚动,macOS 环境默认有该行为 @@ -1368,6 +1371,34 @@ export abstract class BaseFacet { return; } + if ( + this.scrollDirection !== undefined && + this.scrollDirection !== + (optimizedDeltaX > 0 + ? ScrollDirection.SCROLL_LEFT + : ScrollDirection.SCROLL_RIGHT) + ) { + this.scrollDirection = + optimizedDeltaX > 0 + ? ScrollDirection.SCROLL_LEFT + : ScrollDirection.SCROLL_RIGHT; + + this.updateHorizontalRowScrollOffset({ + offsetX, + offsetY, + offset: rowHeaderScrollX, + }); + this.updateHorizontalScrollOffset({ + offsetX, + offsetY, + offset: currentScrollX, + }); + + return; + } + + this.scrollDirection = + deltaX > 0 ? ScrollDirection.SCROLL_LEFT : ScrollDirection.SCROLL_RIGHT; this.scrollFrameId = requestAnimationFrame(() => { const { scrollX: currentScrollX, diff --git a/packages/s2-core/src/facet/header/corner.ts b/packages/s2-core/src/facet/header/corner.ts index f8e2ebdcae..9f0be4b9a3 100644 --- a/packages/s2-core/src/facet/header/corner.ts +++ b/packages/s2-core/src/facet/header/corner.ts @@ -11,7 +11,6 @@ import { FRONT_GROUND_GROUP_SCROLL_Z_INDEX, KEY_GROUP_CORNER_SCROLL, getDefaultCornerText, - getDefaultSeriesNumberText, } from './../../common/constant/basic'; import { BaseHeader } from './base'; import type { BaseCornerOptions, CornerHeaderConfig } from './interface'; @@ -138,9 +137,7 @@ export class CornerHeader extends BaseHeader { const sNode: Node = new Node({ id: '', field: '', - value: getDefaultSeriesNumberText( - spreadsheet.options.seriesNumber?.text, - ), + value: spreadsheet.getSeriesNumberText(), }); sNode.x = position?.x; diff --git a/packages/s2-core/src/facet/layout/build-header-hierarchy.ts b/packages/s2-core/src/facet/layout/build-header-hierarchy.ts index 3fb0d901a2..1048f3e3ae 100644 --- a/packages/s2-core/src/facet/layout/build-header-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-header-hierarchy.ts @@ -1,7 +1,6 @@ import { filter } from 'lodash'; import { EXTRA_FIELD, - getDefaultSeriesNumberText, SERIES_NUMBER_FIELD, type CustomTreeNode, } from '../../common'; @@ -109,12 +108,12 @@ const handleRowHeaderHierarchy = (params: HeaderParams) => { const handleTableHierarchy = (params: HeaderParams) => { const { isCustomTreeFields, spreadsheet } = params; - const { enable, text } = spreadsheet.options.seriesNumber ?? {}; + const { enable } = spreadsheet.options.seriesNumber ?? {}; if (isCustomTreeFields) { const seriesNumberField: CustomTreeNode = { field: SERIES_NUMBER_FIELD, - title: getDefaultSeriesNumberText(text), + title: spreadsheet.getSeriesNumberText(), }; const fields = enable diff --git a/packages/s2-core/src/facet/layout/build-table-hierarchy.ts b/packages/s2-core/src/facet/layout/build-table-hierarchy.ts index e49da166f9..7f2abfcacd 100644 --- a/packages/s2-core/src/facet/layout/build-table-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-table-hierarchy.ts @@ -1,4 +1,3 @@ -import { getDefaultSeriesNumberText } from '../../common'; import { SERIES_NUMBER_FIELD } from '../../common/constant'; import { generateHeaderNodes } from '../../utils/layout/generate-header-nodes'; import type { HeaderParams } from './interface'; @@ -6,9 +5,9 @@ import type { HeaderParams } from './interface'; export const buildTableHierarchy = (params: HeaderParams) => { const { spreadsheet, rootNode, fields, hierarchy } = params; const { columns = [] } = spreadsheet.dataSet.fields; - const { enable, text } = spreadsheet.options.seriesNumber ?? {}; + const { enable } = spreadsheet.options.seriesNumber ?? {}; - const seriesNumberNodeValue = getDefaultSeriesNumberText(text); + const seriesNumberNodeValue = spreadsheet.getSeriesNumberText(); const fieldValues = columns.map((field) => { return field === SERIES_NUMBER_FIELD ? seriesNumberNodeValue diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 11520da9cf..8e0ec242db 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -24,6 +24,7 @@ import { InterceptType, LayoutWidthType, S2Event, + getDefaultSeriesNumberText, getTooltipOperatorSortMenus, getTooltipOperatorTableSortMenus, } from '../common/constant'; @@ -913,4 +914,14 @@ export abstract class SpreadSheet extends EE { onlyShowOperator: true, }); } + + public getSeriesNumberText() { + const { text, enable } = this.options.seriesNumber ?? {}; + + if (!enable) { + return ''; + } + + return text ?? getDefaultSeriesNumberText(); + } } diff --git a/packages/s2-core/src/utils/color.ts b/packages/s2-core/src/utils/color.ts index cea14c109e..a4268b584b 100644 --- a/packages/s2-core/src/utils/color.ts +++ b/packages/s2-core/src/utils/color.ts @@ -25,6 +25,17 @@ const BASIC_COLOR_COUNT = 15; export const shouldReverseFontColor = (color: string) => tinycolor(color).getLuminance() <= 0.5; +/** + * @param backgroundColor + * @param fontColor + */ +export const isReadableText = (backgroundColor: string, fontColor: string) => { + return tinycolor.isReadable(backgroundColor, fontColor, { + level: 'AA', + size: 'small', + }); +}; + const FONT_COLOR_RELATIONS: Array<{ fontColorIndex: number; bgColorIndex: number; diff --git a/packages/s2-core/src/utils/export/copy/table-copy.ts b/packages/s2-core/src/utils/export/copy/table-copy.ts index 807402755d..d83c929899 100644 --- a/packages/s2-core/src/utils/export/copy/table-copy.ts +++ b/packages/s2-core/src/utils/export/copy/table-copy.ts @@ -1,7 +1,6 @@ import { map, zip } from 'lodash'; import { SERIES_NUMBER_FIELD, - getDefaultSeriesNumberText, type CellMeta, type RawData, } from '../../../common'; @@ -164,13 +163,7 @@ class TableDataCellCopy extends BaseDataCellCopy { private getColMatrix(): string[][] { return zip( - ...this.columnNodes.map((node) => { - const matrix = this.getHeaderNodeMatrix(node); - - return this.isSeriesNumberField(node.field) - ? [getDefaultSeriesNumberText()] - : matrix; - }), + ...this.columnNodes.map((node) => this.getHeaderNodeMatrix(node)), ) as string[][]; } diff --git a/packages/s2-core/src/utils/export/method.ts b/packages/s2-core/src/utils/export/method.ts index 17d2667aa5..565d441c8e 100644 --- a/packages/s2-core/src/utils/export/method.ts +++ b/packages/s2-core/src/utils/export/method.ts @@ -4,7 +4,12 @@ import { forEach, map } from 'lodash'; import type { ColCell, RowCell } from '../../cell'; import type { DataItem } from '../../common'; -import { type CellMeta, CellType, NODE_ID_SEPARATOR } from '../../common'; +import { + CellType, + NODE_ID_SEPARATOR, + SERIES_NUMBER_FIELD, + type CellMeta, +} from '../../common'; import type { Node } from '../../facet/layout/node'; import type { SpreadSheet } from '../../sheet-type'; @@ -51,6 +56,11 @@ export const getHeaderMeasureFieldNames = ( formatHeader: boolean = true, ): string[] => { return map(fields, (field) => { + // https://github.com/antvis/S2/issues/2755 + if (field === SERIES_NUMBER_FIELD) { + return spreadsheet.getSeriesNumberText(); + } + // https://github.com/antvis/S2/issues/2688 if (!formatHeader) { return field; diff --git a/packages/s2-core/src/utils/interaction/merge-cell.ts b/packages/s2-core/src/utils/interaction/merge-cell.ts index 42dca5194e..6d0b2565bc 100644 --- a/packages/s2-core/src/utils/interaction/merge-cell.ts +++ b/packages/s2-core/src/utils/interaction/merge-cell.ts @@ -305,7 +305,7 @@ export const getMergedCellInstance: MergedCellCallback = ( cells, meta, ) => { - if (spreadsheet.options.mergedCell) { + if (spreadsheet.options?.mergedCell) { return spreadsheet.options.mergedCell(spreadsheet, cells, meta); } @@ -327,7 +327,7 @@ export const mergeCell = ( if (mergeCellInfo?.length <= 1) { // eslint-disable-next-line no-console - console.error('then merged cells must be more than one'); + console.error('[mergeCell]: The merged cells must be more than one!'); return; } @@ -388,19 +388,19 @@ export const removeUnmergedCellsInfo = ( /** * unmerge MergedCell - * @param removedCells + * @param removedCell * @param sheet */ -export const unmergeCell = (sheet: SpreadSheet, removedCells: MergedCell) => { - if (!removedCells || removedCells.cellType !== CellType.MERGED_CELL) { +export const unmergeCell = (sheet: SpreadSheet, removedCell: MergedCell) => { + if (!removedCell || removedCell.cellType !== CellType.MERGED_CELL) { // eslint-disable-next-line no-console - console.error(`unmergeCell: the ${removedCells} is not a MergedCell`); + console.error(`[unmergeCell]: The ${removedCell} is not a MergedCell`); return; } const newMergedCellsInfo = removeUnmergedCellsInfo( - removedCells, + removedCell, sheet.options?.mergedCellsInfo || [], ); @@ -408,7 +408,7 @@ export const unmergeCell = (sheet: SpreadSheet, removedCells: MergedCell) => { sheet.setOptions({ mergedCellsInfo: newMergedCellsInfo, }); - removedCells.remove(); + removedCell.remove(); } }; @@ -435,7 +435,7 @@ export const mergeTempMergedCell = ( * @param oldMergedCells * @constructor */ -export const MergedCellConvertTempMergedCells = ( +export const mergedCellConvertTempMergedCells = ( oldMergedCells: MergedCell[], ) => map(oldMergedCells, (mergedCell) => { @@ -493,7 +493,7 @@ export const updateMergedCells = ( const oldMergedCells = mergedCellsGroup.children as MergedCell[]; const oldTempMergedCells: TempMergedCell[] = - MergedCellConvertTempMergedCells(oldMergedCells); + mergedCellConvertTempMergedCells(oldMergedCells); // compare oldTempMergedCells and allTempMergedCells, find remove MergedCells and add MergedCells const removeTempMergedCells = differenceTempMergedCells( diff --git a/packages/s2-core/src/utils/text.ts b/packages/s2-core/src/utils/text.ts index 6bdbeee3c0..1289701269 100644 --- a/packages/s2-core/src/utils/text.ts +++ b/packages/s2-core/src/utils/text.ts @@ -338,10 +338,10 @@ export const drawCustomContent = ( const maxTextWidth = contentBoxes[i][j].width - - iconStyle.size - + iconStyle?.size - (iconCfg?.position === 'left' - ? iconStyle.margin.right - : iconStyle.margin.left); + ? iconStyle?.margin?.right + : iconStyle?.margin?.left); const groupedIcons: GroupedIcons = { left: [], diff --git a/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx b/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx index c1c939ceea..a27945cd5e 100644 --- a/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx +++ b/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx @@ -575,8 +575,8 @@ describe(' Tests', () => { } const s2Options: SheetComponentOptions = { - dataCell: (viewMeta) => - new CustomDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new CustomDataCell(viewMeta, spreadsheet), }; renderStrategySheet(s2Options, StrategySheetDataConfig); diff --git a/packages/s2-react/playground/components/BigDataSheet.tsx b/packages/s2-react/playground/components/BigDataSheet.tsx new file mode 100644 index 0000000000..5e3177684d --- /dev/null +++ b/packages/s2-react/playground/components/BigDataSheet.tsx @@ -0,0 +1,79 @@ +import { SpreadSheet, type S2DataConfig } from '@antv/s2'; +import React from 'react'; + +import { + SheetComponent, + type SheetComponentOptions, + type SheetComponentsProps, +} from '../../src'; +import { usePlaygroundContext } from '../context/playground.context'; + +const s2Options: SheetComponentOptions = { + width: 1600, + height: 480, + interaction: { + scrollSpeedRatio: { + vertical: 10, + horizontal: 10, + }, + }, +}; + +export function generateRawData( + row: Record, + col: Record, +) { + const res: Record[] = []; + const rowKeys = Object.keys(row); + const colKeys = Object.keys(col); + + for (let i = 0; i < row[rowKeys[0]]; i++) { + for (let j = 0; j < row[rowKeys[1]]; j++) { + for (let m = 0; m < col[colKeys[0]]; m++) { + for (let n = 0; n < col[colKeys[1]]; n++) { + res.push({ + province: `p${i}`, + city: `c${j}`, + type: `type${m}`, + subType: `subType${n}`, + number: i * n, + }); + } + } + } + } + + return res; +} + +const s2DataConfig: S2DataConfig = { + fields: { + rows: ['type', 'subType'], + columns: ['province', 'city'], + values: ['number'], + }, + data: generateRawData( + { province: 10, city: 100 }, + { type: 10, subType: 100 }, + ), +}; + +type CustomGridProps = Partial; +const sheetType = 'pivot'; + +export const BigDataSheet = React.forwardRef( + (props, ref) => { + const context = usePlaygroundContext(); + + return ( + + ); + }, +); diff --git a/packages/s2-react/playground/index.tsx b/packages/s2-react/playground/index.tsx index ec9479c3ff..3bea2ca93d 100644 --- a/packages/s2-react/playground/index.tsx +++ b/packages/s2-react/playground/index.tsx @@ -59,6 +59,8 @@ import { LinkGroup } from './components/LinkGroup'; import { PluginsSheet } from './components/Plugins'; import { ResizeConfig } from './components/ResizeConfig'; import { StrategySheet } from './components/StrategySheet'; +import { BigDataSheet } from './components/BigDataSheet'; + import { PivotSheetFrozenOptions, TableSheetFrozenOptions, @@ -1640,6 +1642,11 @@ function MainLayout() { label: '绘制 G2 图表', children: , }, + { + key: 'bigData', + label: '100w 数据', + children: , + }, ]} /> diff --git a/packages/s2-react/src/components/sheets/chart-sheet/index.tsx b/packages/s2-react/src/components/sheets/chart-sheet/index.tsx index 6b186f4099..2e6975d5d4 100644 --- a/packages/s2-react/src/components/sheets/chart-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/chart-sheet/index.tsx @@ -14,8 +14,8 @@ export const ChartSheet: React.FC = React.memo( const s2Options = React.useMemo(() => { const options: SheetComponentOptions = { - dataCell: (viewMeta) => - new ChartSheetDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new ChartSheetDataCell(viewMeta, spreadsheet), showDefaultHeaderActionIcon: false, interaction: { hoverFocus: false, diff --git a/packages/s2-react/src/components/sheets/grid-analysis-sheet/index.tsx b/packages/s2-react/src/components/sheets/grid-analysis-sheet/index.tsx index a7cc94f5f4..46d207632e 100644 --- a/packages/s2-react/src/components/sheets/grid-analysis-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/grid-analysis-sheet/index.tsx @@ -11,8 +11,8 @@ export const GridAnalysisSheet: React.FC = React.memo( const s2Options = React.useMemo(() => { const options: SheetComponentOptions = { - dataCell: (viewMeta) => - new GridAnalysisSheetDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new GridAnalysisSheetDataCell(viewMeta, spreadsheet), showDefaultHeaderActionIcon: false, style: { colCell: { diff --git a/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx b/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx index 20ac123d7d..3548735197 100644 --- a/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx @@ -1,4 +1,3 @@ -import { type ViewMeta } from '@antv/s2'; import { isEmpty, size } from 'lodash'; import React from 'react'; import { customMerge, Node, SpreadSheet, type ColHeaderConfig } from '@antv/s2'; @@ -37,8 +36,8 @@ export const StrategySheet: React.FC = React.memo( return { hierarchyType: 'tree', - dataCell: (viewMeta: ViewMeta) => - new StrategySheetDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new StrategySheetDataCell(viewMeta, spreadsheet), colCell: ( node: Node, spreadsheet: SpreadSheet, diff --git a/s2-site/docs/api/basic-class/spreadsheet.zh.md b/s2-site/docs/api/basic-class/spreadsheet.zh.md index d8d44a41f6..fc43019118 100644 --- a/s2-site/docs/api/basic-class/spreadsheet.zh.md +++ b/s2-site/docs/api/basic-class/spreadsheet.zh.md @@ -66,6 +66,7 @@ s2.isPivotMode() | measureTextWidth | 获取文本在画布中的测量宽度 | (text: `string`, font: [TextTheme](/docs/api/general/S2Theme#texttheme)) => `number` \| `null` | | | measureTextHeight | 获取文本在画布中的测量高度 | (text:`string`, font: [TextTheme](/docs/api/general/S2Theme#texttheme)) => `number` \| `null` | | | groupSortByMethod | 组内排序(透视表有效) | (sortMethod: `'asc' \| 'desc'`, meta: [Node](/docs/api/basic-class/node)) => void | | +| getSeriesNumberText | 获取序号文本(根据 `s2Options.series.text` 配置,默认 "序号") | () => string | | ### S2MountContainer diff --git a/s2-site/docs/api/general/S2Options.zh.md b/s2-site/docs/api/general/S2Options.zh.md index d1c8e67cb5..c4048cab0d 100644 --- a/s2-site/docs/api/general/S2Options.zh.md +++ b/s2-site/docs/api/general/S2Options.zh.md @@ -71,7 +71,7 @@ const s2Options = { ## DataCellCallback ```js -DataCellCallback = (viewMeta: ViewMeta, s2: Spreadsheet) => G.Group; +DataCellCallback = (viewMeta: ViewMeta, spreadsheet: SpreadSheet) => G.Group; ``` 功能描述:自定义数值单元格。[查看示例](/examples/custom/custom-cell#data-cell) diff --git a/s2-site/docs/common/custom/dataCellCallback.zh.md b/s2-site/docs/common/custom/dataCellCallback.zh.md index 0aa298371b..ef9ab2af8f 100644 --- a/s2-site/docs/common/custom/dataCellCallback.zh.md +++ b/s2-site/docs/common/custom/dataCellCallback.zh.md @@ -6,7 +6,7 @@ order: 2 ## DataCellCallback ```js -DataCellCallback = (viewMeta: ViewMeta) => DataCell; +DataCellCallback = (viewMeta: ViewMeta, spreadsheet: SpreadSheet) => DataCell | TableDataCell; ``` 功能描述:自定义数值单元格,[ViewMeta](#viewmeta) diff --git a/s2-site/docs/manual/advanced/chart-in-cell.zh.md b/s2-site/docs/manual/advanced/chart-in-cell.zh.md index 306e2f9dab..5ef2bde2d9 100644 --- a/s2-site/docs/manual/advanced/chart-in-cell.zh.md +++ b/s2-site/docs/manual/advanced/chart-in-cell.zh.md @@ -192,8 +192,8 @@ class CustomDataCell extends DataCell { } const s2Options = { - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, }; ``` @@ -348,7 +348,7 @@ class ChartSheetDataCell extends DataCell { } const s2 = new PivotSheet(container, s2DataConfig, { - dataCell: (viewMeta) => new ChartSheetDataCell(viewMeta, viewMeta.spreadsheet) + dataCell: (viewMeta, spreadsheet) => new ChartSheetDataCell(viewMeta, spreadsheet) }); await s2.render(); diff --git a/s2-site/docs/manual/basic/conditions.en.md b/s2-site/docs/manual/basic/conditions.en.md index ef9cb0da83..4d5e1eed21 100644 --- a/s2-site/docs/manual/basic/conditions.en.md +++ b/s2-site/docs/manual/basic/conditions.en.md @@ -148,7 +148,10 @@ The `price` field uses a gradient color: diff --git a/s2-site/docs/manual/basic/conditions.zh.md b/s2-site/docs/manual/basic/conditions.zh.md index c4a1648dab..343fb0e8e6 100644 --- a/s2-site/docs/manual/basic/conditions.zh.md +++ b/s2-site/docs/manual/basic/conditions.zh.md @@ -159,7 +159,7 @@ export type ConditionMapping = ( ### 开启文字智能反色 通过显示指定 `background` 字段标记中的 `mapping` 函数返回值 `intelligentReverseTextColor` 属性值为 `true`。 -当标记背景颜色较暗时,文本颜色将变为白色。当标记背景颜色明亮时,文本颜色默认为黑色。 +当标记背景颜色较暗且文本颜色与背景颜色组合不符合 WCAG2.0 指南的 [AA](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html) 级标准时,文本颜色将变为白色。当标记背景颜色明亮时,文本颜色默认为黑色。 优先级: `background condition` 的 `intelligentReverseTextColor` < `text condition` 的 `fill` diff --git a/s2-site/docs/manual/migration-v2.zh.md b/s2-site/docs/manual/migration-v2.zh.md index 7d4acd46b8..40bbb98a69 100644 --- a/s2-site/docs/manual/migration-v2.zh.md +++ b/s2-site/docs/manual/migration-v2.zh.md @@ -698,7 +698,7 @@ const s2Options = { 具体请查看 [自定义空数据占位符](/examples/custom/custom-cell/#empty-placeholder) 和 [自定义单元格空数据占位符](/examples/custom/custom-cell/#data-cell-placeholder) 示例。 -### 内部常量重命名 +#### 内部常量重命名 ```diff - import { ROOT_ID, ID_SEPARATOR } from '@antv/s2' @@ -707,11 +707,68 @@ const s2Options = { 如有消费请注意修改,具体请查看 [源代码定义](https://github.com/antvis/S2/tree/next/packages/s2-core/src/common/constant). +#### 自定义数值单元格参数变更 + +增加第二个参数 `spreadsheet`, 和其他单元格保持一致。 + +```diff +const s2Options = { + width: 600, +- dataCell: (viewMeta) => { +- return new CustomDataCell(viewMeta, viewMeta.spreadsheet); +- } ++ dataCell: (viewMeta, spreadsheet) => { ++ return new CustomDataCell(viewMeta, spreadsheet); ++ } +} +``` + ### 组件层 @antv/s2-react #### 支持 React 18 和 Ant Design 5.0 -`@antv/s2-react` 的 `2.x` 版本适配了 `React 18`, 并兼容 `React 16 和 17`, 分析组件升级到了 `antd@v5`. +`@antv/s2-react` 的 `2.x` 版本适配了 `React 18`, 并兼容 `React 16 和 17`, 分析组件升级到了 `antd@5.x`. + +#### Ant Design 多版本共存 + +对于项目使用的是 `antd@4.x`, 或者所依赖的其他库依赖 `antd@4.x`, 由于种种历史原因无法升级到 `antd@5.x` 的情况,可以通过 [多版本共存](https://ant-design.antgroup.com/docs/react/migration-v5-cn#%E5%A4%9A%E7%89%88%E6%9C%AC%E5%85%B1%E5%AD%98) 的方式来临时过渡。 + +```json +// $ npm install --save antd-v5@npm:antd@5 +{ + "antd": "4.x", + "antd-v5": "npm:antd@5" +} +``` + +通过 webpack 内置插件 [`NormalModuleReplacementPlugin`](https://webpack.js.org/plugins/normal-module-replacement-plugin/) 或者 `自定义 webpack 插件` 的方式指定 `@antv/s2-react` 使用 `antd-v5`, 无需做任何修改,项目中其他依赖将继续使用 `antd@4.x`. + +:::warning{title="注意"} +其他打包工具 (如 `Vite`) 或者基于 `webpack` 封装的库或框架(如 `father`, `umi`) 同理,请自行搜索,这里不再赘述。 +需要注意的是:这种方式为临时过渡解决方案,从长远来看,**[Ant Design v4 版本已于 2023 年年底停止维护](https://ant-design.antgroup.com/docs/blog/v4-ood-cn),建议尽快升级至 `antd@5.x`.** +::: + +自定义 webpack 插件参考: + +```ts +class AntdV5AliasPlugin { + apply(compiler) { + compiler.hooks.normalModuleFactory.tap("AntdV5AliasPlugin", (nmf) => { + nmf.hooks.beforeResolve.tapAsync("AntdV5AliasPlugin", (resolveData, callback) => { + if (resolveData.contextInfo?.issuer?.includes('node_modules/@antv/s2-react')) { + // 匹配:"antd" 和 "antd/es/locale/xxx" + if (/antd(\/*)?/.test(resolveData.request)) { + // 替换为:"antd-v5" 和 "antd-v5/es/locale/xxx" + resolveData.request = resolveData.request.replace(/antd(\/*)?/,'antd-v5$1') + } + } + + callback(); + }); + }); + } +} +``` #### 表头组件配置调整 diff --git a/s2-site/examples/case/art/demo/time-spend-abstract.tsx b/s2-site/examples/case/art/demo/time-spend-abstract.tsx index f987b28375..a2dbe29433 100644 --- a/s2-site/examples/case/art/demo/time-spend-abstract.tsx +++ b/s2-site/examples/case/art/demo/time-spend-abstract.tsx @@ -174,8 +174,8 @@ fetch('https://assets.antv.antgroup.com/s2/time-spend.json') width: 1150, height: 720, showDefaultHeaderActionIcon: false, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, interaction: { hoverHighlight: false, diff --git a/s2-site/examples/case/comparison/demo/measure-comparison.tsx b/s2-site/examples/case/comparison/demo/measure-comparison.tsx index 104b5e4cb7..63958d0d64 100644 --- a/s2-site/examples/case/comparison/demo/measure-comparison.tsx +++ b/s2-site/examples/case/comparison/demo/measure-comparison.tsx @@ -199,11 +199,10 @@ class CustomDataCell extends DataCell { // 自定义icon显示 getIconStyle() { - const tagName = Object.keys(this.customConditions).find( - (item) => - this.meta.colId?.includes( - `root${NODE_ID_SEPARATOR}${item}${NODE_ID_SEPARATOR}`, - ), + const tagName = Object.keys(this.customConditions).find((item) => + this.meta.colId?.includes( + `root${NODE_ID_SEPARATOR}${item}${NODE_ID_SEPARATOR}`, + ), ); if (tagName) { @@ -218,11 +217,10 @@ class CustomDataCell extends DataCell { drawTextShape() { const { fieldValue } = this.meta; - const tagName = Object.keys(this.textConfig).find( - (item) => - this.meta.colId?.includes( - `root${NODE_ID_SEPARATOR}${item}${NODE_ID_SEPARATOR}`, - ), + const tagName = Object.keys(this.textConfig).find((item) => + this.meta.colId?.includes( + `root${NODE_ID_SEPARATOR}${item}${NODE_ID_SEPARATOR}`, + ), ); if (!tagName) { @@ -511,8 +509,8 @@ fetch( return parseFloat(fieldValue) > 0 ? 'CellUp' : fieldValue < 0 - ? 'CellDown' - : ''; + ? 'CellDown' + : ''; }; const conditionsIcon = [ @@ -548,8 +546,8 @@ fetch( parseFloat(value) > 0 ? UP_COLOR : parseFloat(value) < 0 - ? DOWN_COLOR - : textStyle?.fill, + ? DOWN_COLOR + : textStyle?.fill, }; }; @@ -585,8 +583,8 @@ fetch( lineConfigStyle, ); }, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta.spreadsheet, { + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet, { lineConfig, lineConfigStyle, conditions: { diff --git a/s2-site/examples/case/comparison/demo/time-spend.tsx b/s2-site/examples/case/comparison/demo/time-spend.tsx index 3d814109cb..8ba7c83e31 100644 --- a/s2-site/examples/case/comparison/demo/time-spend.tsx +++ b/s2-site/examples/case/comparison/demo/time-spend.tsx @@ -258,8 +258,8 @@ fetch('https://assets.antv.antgroup.com/s2/time-spend.json') width: 1150, height: 420, showDefaultHeaderActionIcon: false, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, frame: (cfg) => { return new CustomFrame(cfg); diff --git a/s2-site/examples/case/kpi-strategy/demo/basic.tsx b/s2-site/examples/case/kpi-strategy/demo/basic.tsx index 8614a15e16..09ed3d13b6 100644 --- a/s2-site/examples/case/kpi-strategy/demo/basic.tsx +++ b/s2-site/examples/case/kpi-strategy/demo/basic.tsx @@ -252,8 +252,8 @@ fetch('https://assets.antv.antgroup.com/s2/kpi-strategy.json') // 自定义角头文本 cornerText: '指标', // 覆盖默认数值单元格, 额外绘制衍生指标和子弹图 - dataCell: (viewMeta) => - new KpiStrategyDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new KpiStrategyDataCell(viewMeta, spreadsheet), }; // 覆盖默认主题, 让单元格文字靠左显示 diff --git a/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts b/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts index 1741c431eb..46b7a14ae3 100644 --- a/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts +++ b/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts @@ -325,8 +325,8 @@ fetch( rowCell: (node, spreadsheet, headerConfig) => { return new CustomRowCell(node, spreadsheet, headerConfig); }, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, }; diff --git a/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts b/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts index b7cc4d24c0..6be956c681 100644 --- a/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts +++ b/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts @@ -1,5 +1,11 @@ /* eslint-disable max-classes-per-file */ -import { TableColCell, TableDataCell, TableSheet } from '@antv/s2'; +import { + TableColCell, + TableDataCell, + TableSheet, + type S2DataConfig, + type S2Options, +} from '@antv/s2'; /** * 自定义 TableDataCell,通过复写基类方法, 给特定单元格设置背景色, 文字大小, 颜色等... @@ -115,14 +121,15 @@ fetch( .then((res) => res.json()) .then((res) => { const container = document.getElementById('container'); - const s2DataConfig = { + const s2DataConfig: S2DataConfig = { fields: { columns: ['province', 'city', 'type', 'sub_type', 'number'], }, meta: res.meta, data: res.data, }; - const s2Options = { + + const s2Options: S2Options = { width: 600, height: 480, seriesNumber: { @@ -131,8 +138,8 @@ fetch( colCell: (node, spreadsheet, headerConfig) => { return new CustomColCell(node, spreadsheet, headerConfig); }, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, }; diff --git a/s2-site/examples/custom/custom-cell/demo/data-cell.ts b/s2-site/examples/custom/custom-cell/demo/data-cell.ts index d06c55a20f..b8b7c33b17 100644 --- a/s2-site/examples/custom/custom-cell/demo/data-cell.ts +++ b/s2-site/examples/custom/custom-cell/demo/data-cell.ts @@ -46,8 +46,8 @@ fetch( // 关闭 hover 十字高亮, 为了视觉效果,可不设置 hoverHighlight: false, }, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, }; diff --git a/s2-site/examples/custom/custom-cell/demo/mini-chart.ts b/s2-site/examples/custom/custom-cell/demo/mini-chart.ts index 5ba23e29d2..4473f3ff5d 100644 --- a/s2-site/examples/custom/custom-cell/demo/mini-chart.ts +++ b/s2-site/examples/custom/custom-cell/demo/mini-chart.ts @@ -173,8 +173,8 @@ fetch( }, ], }, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, }; diff --git a/s2-site/examples/custom/custom-dataset/demo/custom-strategy-sheet-dataset.ts b/s2-site/examples/custom/custom-dataset/demo/custom-strategy-sheet-dataset.ts index 52a02aec44..bb3db61674 100644 --- a/s2-site/examples/custom/custom-dataset/demo/custom-strategy-sheet-dataset.ts +++ b/s2-site/examples/custom/custom-dataset/demo/custom-strategy-sheet-dataset.ts @@ -125,8 +125,8 @@ fetch( height: 480, hierarchyType: 'tree', dataSet: (spreadsheet) => new CustomDataSet(spreadsheet), - dataCell: (viewMeta) => - new CustomDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new CustomDataCell(viewMeta, spreadsheet), }; const s2 = new PivotSheet(container, s2DataConfig, s2Options); diff --git a/s2-site/examples/custom/custom-order/demo/custom-order.tsx b/s2-site/examples/custom/custom-order/demo/custom-order.tsx index 10b81b990d..e2a1318605 100644 --- a/s2-site/examples/custom/custom-order/demo/custom-order.tsx +++ b/s2-site/examples/custom/custom-order/demo/custom-order.tsx @@ -1,12 +1,12 @@ -import React from 'react'; -import { SheetComponent, SheetComponentOptions } from '@antv/s2-react'; import { Node, S2DataConfig, TooltipOptions, - type SortParams, type SortMethod, + type SortParams, } from '@antv/s2'; +import { SheetComponent, SheetComponentOptions } from '@antv/s2-react'; +import React from 'react'; const SortMethodType = { asc: 'asc', @@ -51,7 +51,7 @@ const s2Options: SheetComponentOptions = { }; const useDataCfg = () => { - const [res, setRes] = await ReactuseState({ meta: [], data: [] }); + const [res, setRes] = React.useState({ meta: [], data: [] }); const [dataCfg, setDataCfg] = React.useState(s2DataConfig); React.useEffect(() => { diff --git a/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g-shape.ts b/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g-shape.ts index 0de5b5f105..74714eadc5 100644 --- a/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g-shape.ts +++ b/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g-shape.ts @@ -167,8 +167,8 @@ fetch( colCell: (node, spreadsheet, headerConfig) => { return new CustomColCell(node, spreadsheet, headerConfig); }, - dataCell: (viewMeta) => { - return new CustomDataCell(viewMeta, viewMeta?.spreadsheet); + dataCell: (viewMeta, spreadsheet) => { + return new CustomDataCell(viewMeta, spreadsheet); }, }; diff --git a/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g2-chart.ts b/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g2-chart.ts index f68a21ef19..7bc1e74285 100644 --- a/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g2-chart.ts +++ b/s2-site/examples/custom/custom-shape-and-chart/demo/custom-g2-chart.ts @@ -35,8 +35,8 @@ const s2Options: S2Options = { height: 400, }, }, - dataCell: (viewMeta) => - new ChartSheetDataCell(viewMeta, viewMeta.spreadsheet), + dataCell: (viewMeta, spreadsheet) => + new ChartSheetDataCell(viewMeta, spreadsheet), }; const s2DataConfig: S2DataConfig = {