From 99b0f5eda504a2880c4fbbb9e0895c3ed37cdbed Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Wed, 29 Nov 2023 17:16:36 +0800 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=20G2=20=E5=9B=BE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/cell/base-cell.ts | 2 +- packages/s2-core/src/cell/data-cell.ts | 34 +- .../src/common/constant/events/basic.ts | 1 + .../s2-core/src/common/interface/basic.ts | 13 +- .../s2-core/src/common/interface/emitter.ts | 1 + .../src/common/interface/s2DataConfig.ts | 6 + packages/s2-core/src/facet/base-facet.ts | 38 +- packages/s2-core/src/facet/pivot-facet.ts | 4 +- packages/s2-core/src/facet/table-facet.ts | 2 +- packages/s2-core/src/utils/cell/cell.ts | 2 +- packages/s2-core/src/utils/custom-render.ts | 30 - packages/s2-core/src/utils/index.ts | 1 - .../s2-react/__tests__/data/data-g2-chart.ts | 889 ++++++++++++++++++ .../__tests__/unit/hooks/useEvents-spec.ts | 4 + packages/s2-react/package.json | 1 + .../playground/components/ChartSheet.tsx | 71 ++ .../components/{links.tsx => LinkGroup.tsx} | 2 +- packages/s2-react/playground/index.tsx | 12 +- .../sheets/chart-sheet/chart-cell.ts | 5 - .../sheets/chart-sheet/custom-cell.ts | 8 - .../chart-sheet/custom-cell/data-cell.ts | 11 + .../sheets/chart-sheet/custom-cell/index.ts | 1 + .../components/sheets/chart-sheet/index.tsx | 64 +- .../{ => custom-cell}/edit-cell/index.less | 0 .../{ => custom-cell}/edit-cell/index.tsx | 10 +- .../editable-sheet/custom-cell/index.ts | 1 + .../sheets/editable-sheet/index.tsx | 2 +- .../data-cell.ts} | 11 +- .../grid-analysis-sheet/custom-cell/index.ts | 1 + .../grid-analysis-data-cell.ts | 5 - .../sheets/grid-analysis-sheet/index.tsx | 35 +- .../{grid-analysis-theme.ts => theme.ts} | 0 .../src/components/sheets/interface.ts | 8 +- .../strategy-sheet/custom-cell/data-cell.ts | 9 +- .../sheets/strategy-sheet/index.tsx | 2 +- packages/s2-react/src/hooks/useEvents.ts | 1 + packages/s2-shared/src/interface.ts | 3 +- pnpm-lock.yaml | 389 +++++++- 38 files changed, 1512 insertions(+), 167 deletions(-) delete mode 100644 packages/s2-core/src/utils/custom-render.ts create mode 100644 packages/s2-react/__tests__/data/data-g2-chart.ts create mode 100644 packages/s2-react/playground/components/ChartSheet.tsx rename packages/s2-react/playground/components/{links.tsx => LinkGroup.tsx} (97%) delete mode 100644 packages/s2-react/src/components/sheets/chart-sheet/chart-cell.ts delete mode 100644 packages/s2-react/src/components/sheets/chart-sheet/custom-cell.ts create mode 100644 packages/s2-react/src/components/sheets/chart-sheet/custom-cell/data-cell.ts create mode 100644 packages/s2-react/src/components/sheets/chart-sheet/custom-cell/index.ts rename packages/s2-react/src/components/sheets/editable-sheet/{ => custom-cell}/edit-cell/index.less (100%) rename packages/s2-react/src/components/sheets/editable-sheet/{ => custom-cell}/edit-cell/index.tsx (94%) create mode 100644 packages/s2-react/src/components/sheets/editable-sheet/custom-cell/index.ts rename packages/s2-react/src/components/sheets/grid-analysis-sheet/{custom-cell.ts => custom-cell/data-cell.ts} (66%) create mode 100644 packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/index.ts delete mode 100644 packages/s2-react/src/components/sheets/grid-analysis-sheet/grid-analysis-data-cell.ts rename packages/s2-react/src/components/sheets/grid-analysis-sheet/{grid-analysis-theme.ts => theme.ts} (100%) diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index 01d216bfcf..be85d5327d 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -317,7 +317,7 @@ export abstract class BaseCell extends Group { return resize?.[type]; } - public getBBoxByType(type = CellClipBox.BORDER_BOX) { + public getBBoxByType(type = CellClipBox.BORDER_BOX): SimpleBBox { const bbox: SimpleBBox = { x: this.meta.x, y: this.meta.y, diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 31814695d3..55479718b7 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -1,5 +1,14 @@ import type { PointLike } from '@antv/g'; -import { find, findLast, first, get, isEmpty, isEqual, merge } from 'lodash'; +import { + find, + findLast, + first, + get, + isEmpty, + isEqual, + isObject, + merge, +} from 'lodash'; import { BaseCell } from '../cell/base-cell'; import { CellType, @@ -22,6 +31,8 @@ import type { TextTheme, ViewMeta, ViewMetaIndexType, + MultiData, + BaseChartData, } from '../common/interface'; import { getHorizontalTextIconPosition, @@ -61,6 +72,27 @@ export class DataCell extends BaseCell { return CellType.DATA_CELL; } + public isMultiData() { + return isObject(this.getMeta().fieldValue); + } + + public getRenderChartData(): BaseChartData { + const { fieldValue } = this.meta; + + return (fieldValue as MultiData)?.values as BaseChartData; + } + + public getRenderChartOptions() { + const chartData = this.getRenderChartData(); + const cellArea = this.getBBoxByType(CellClipBox.CONTENT_BOX); + + return { + ...cellArea, + ...chartData, + autoFit: true, + }; + } + protected getBorderPositions(): CellBorderPosition[] { return [CellBorderPosition.BOTTOM, CellBorderPosition.RIGHT]; } diff --git a/packages/s2-core/src/common/constant/events/basic.ts b/packages/s2-core/src/common/constant/events/basic.ts index 10ed128684..9a1335845a 100644 --- a/packages/s2-core/src/common/constant/events/basic.ts +++ b/packages/s2-core/src/common/constant/events/basic.ts @@ -37,6 +37,7 @@ export enum S2Event { DATA_CELL_MOUSE_MOVE = 'data-cell:mouse-move', DATA_CELL_BRUSH_SELECTION = 'data-cell:brush-selection', DATA_CELL_SELECT_MOVE = 'data-cell:select-move', + DATA_CELL_RENDER = 'data-cell:render', /** ================ Corner Cell ================ */ CORNER_CELL_HOVER = 'corner-cell:hover', diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index c7ad26e749..9d9736a636 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -1,5 +1,5 @@ -import type { FederatedPointerEvent as Event, Group } from '@antv/g'; -import type { MergedCell } from '../../cell'; +import type { FederatedPointerEvent as Event } from '@antv/g'; +import type { DataCell, MergedCell } from '../../cell'; import type { CustomTreeNode, Data, @@ -376,7 +376,7 @@ export type CellCallback = ( headerConfig: T, ) => S2CellType; -export type DataCellCallback = (viewMeta: ViewMeta) => S2CellType; +export type DataCellCallback = (viewMeta: ViewMeta) => DataCell; export type MergedCellCallback = ( spreadsheet: SpreadSheet, @@ -502,13 +502,6 @@ export interface GridInfo { rows: number[]; } -export type RenderHandler = ( - options: Record, - context: { - group: Group; - }, -) => void; - export interface Point { x: number; y: number; diff --git a/packages/s2-core/src/common/interface/emitter.ts b/packages/s2-core/src/common/interface/emitter.ts index fb150c90fa..d6a51ae0c8 100644 --- a/packages/s2-core/src/common/interface/emitter.ts +++ b/packages/s2-core/src/common/interface/emitter.ts @@ -78,6 +78,7 @@ export interface EmitterType { [S2Event.DATA_CELL_CONTEXT_MENU]: CanvasEventHandler; [S2Event.DATA_CELL_BRUSH_SELECTION]: (cells: (DataCell | CellMeta)[]) => void; [S2Event.DATA_CELL_SELECT_MOVE]: (metas: CellMeta[]) => void; + [S2Event.DATA_CELL_RENDER]: (cell: DataCell) => void; /** ================ Row Cell ================ */ [S2Event.ROW_CELL_MOUSE_DOWN]: CanvasEventHandler; diff --git a/packages/s2-core/src/common/interface/s2DataConfig.ts b/packages/s2-core/src/common/interface/s2DataConfig.ts index 4414f769bc..3ace8790ce 100644 --- a/packages/s2-core/src/common/interface/s2DataConfig.ts +++ b/packages/s2-core/src/common/interface/s2DataConfig.ts @@ -10,10 +10,12 @@ export interface BaseChartData { * 类型 */ type: MiniChartTypes; + /** * 数据 */ data: RawData[]; + /** * 坐标轴数据 */ @@ -21,6 +23,8 @@ export interface BaseChartData { x: keyof RawData; y: keyof RawData; }; + + [key: string]: unknown; } /* 子弹图数据结构 */ @@ -29,10 +33,12 @@ export interface BulletValue { * 类型 */ type: MiniChartTypes.Bullet; + /** * 当前值 */ measure: number | string; + /** * 目标值 */ diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 106ff35aa5..97c85a4748 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -1275,24 +1275,26 @@ export abstract class BaseFacet { this.columnHeader.onColScroll(scrollX, KEY_GROUP_COL_RESIZE_AREA); } - addCell = (cell: S2CellType) => { + addDataCell = (cell: DataCell) => { this.panelScrollGroup?.appendChild(cell); + this.spreadsheet.emit(S2Event.DATA_CELL_RENDER, cell); this.spreadsheet.emit(S2Event.LAYOUT_CELL_MOUNTED, cell); }; - realCellRender = (scrollX: number, scrollY: number) => { + realDataCellRender = (scrollX: number, scrollY: number) => { const indexes = this.calculateXYIndexes(scrollX, scrollY); DebuggerUtil.getInstance().logger( - 'realCellRender:', + 'realDataCellRender:', this.preCellIndexes, indexes, ); - const { add, remove } = diffPanelIndexes(this.preCellIndexes!, indexes); + const { add: willAddDataCells, remove: willRemoveDataCells } = + diffPanelIndexes(this.preCellIndexes!, indexes); DebuggerUtil.getInstance().debugCallback(DEBUG_VIEW_RENDER, () => { // add new cell in panelCell - each(add, ([i, j]) => { + each(willAddDataCells, ([i, j]) => { const viewMeta = this.getCellMeta(j, i); if (viewMeta) { @@ -1300,29 +1302,33 @@ export abstract class BaseFacet { // mark cell for removing cell.name = `${i}-${j}`; - this.addCell(cell); + this.addDataCell(cell); } }); - const allCells = getAllChildCells( - this.panelGroup.children, + const allDataCells = getAllChildCells( + this.panelGroup.children as DataCell[], DataCell, - ) as DataCell[]; + ); // remove cell from panelCell - each(remove, ([i, j]) => { - const findOne = find(allCells, (cell) => cell.name === `${i}-${j}`); + each(willRemoveDataCells, ([i, j]) => { + const mountedDataCell = find( + allDataCells, + (cell) => cell.name === `${i}-${j}`, + ); - findOne?.remove(); + mountedDataCell?.remove(); }); DebuggerUtil.getInstance().logger( - `Render Cell Panel: ${allCells?.length}, Add: ${add?.length}, Remove: ${remove?.length}`, + `Render Cell Panel: ${allDataCells?.length}, Add: ${willAddDataCells?.length}, Remove: ${willRemoveDataCells?.length}`, ); }); + this.preCellIndexes = indexes; this.spreadsheet.emit(S2Event.LAYOUT_AFTER_REAL_DATA_CELL_RENDER, { - add, - remove, + add: willAddDataCells, + remove: willRemoveDataCells, spreadsheet: this.spreadsheet, }); }; @@ -1549,7 +1555,7 @@ export abstract class BaseFacet { this.spreadsheet.hideTooltip(); this.spreadsheet.interaction.clearHoverTimer(); - this.realCellRender(scrollX, scrollY); + this.realDataCellRender(scrollX, scrollY); this.updatePanelScrollGroup(); this.translateRelatedGroups(scrollX, scrollY, rowHeaderScrollX); if (!skipScrollEvent) { diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index 39c128a9e6..cfe52c155a 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -27,7 +27,7 @@ import { import { EXTRA_FIELD, LayoutWidthTypes, VALUE_FIELD } from '../common/constant'; import { CellType } from '../common/constant/interaction'; import { DebuggerUtil } from '../common/debug'; -import type { LayoutResult } from '../common/interface'; +import type { LayoutResult, SimpleData } from '../common/interface'; import type { PivotDataSet } from '../data-set/pivot-data-set'; import type { SpreadSheet } from '../sheet-type'; import { safeJsonParse } from '../utils'; @@ -763,7 +763,7 @@ export class PivotFacet extends BaseFacet { for (let j = 0; j < cellDataKeys.length; j++) { const dataValue: MultiData = get(cellData, cellDataKeys[j]); - const valueSize = size(get(dataValue?.values, '0')); + const valueSize = size(get(dataValue?.values as SimpleData[][], '0')); if (valueSize > maxLength) { // greater length diff --git a/packages/s2-core/src/facet/table-facet.ts b/packages/s2-core/src/facet/table-facet.ts index 9d3ed42d4a..e71683d64c 100644 --- a/packages/s2-core/src/facet/table-facet.ts +++ b/packages/s2-core/src/facet/table-facet.ts @@ -946,7 +946,7 @@ export class TableFacet extends BaseFacet { }; }; - addCell = (cell: S2CellType) => { + addDataCell = (cell: S2CellType) => { const { rowCount: frozenRowCount = 0, colCount: frozenColCount = 0, diff --git a/packages/s2-core/src/utils/cell/cell.ts b/packages/s2-core/src/utils/cell/cell.ts index cb50d3f633..171de172bb 100644 --- a/packages/s2-core/src/utils/cell/cell.ts +++ b/packages/s2-core/src/utils/cell/cell.ts @@ -129,7 +129,7 @@ export const getCellBoxByType = ( borderPositions: CellBorderPosition[], cellStyle: CellTheme, boxType: CellClipBox, -) => { +): SimpleBBox => { if (boxType === CellClipBox.BORDER_BOX) { return bbox; } diff --git a/packages/s2-core/src/utils/custom-render.ts b/packages/s2-core/src/utils/custom-render.ts deleted file mode 100644 index edfebc2c2b..0000000000 --- a/packages/s2-core/src/utils/custom-render.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { - type S2CellType, - type RenderHandler, - CellClipBox, -} from '../common/interface'; - -/** - * @description 将外部以 g5.0 作为底层渲染引擎绘制的图形渲染进已挂载的单元格中。 - */ - -export const renderToMountedCell = ( - cell: S2CellType, - render: RenderHandler, - renderOptions?: Record, -) => { - const { fieldValue } = cell.getMeta(); - const { x, y, width, height } = cell.getBBoxByType(CellClipBox.CONTENT_BOX); - - render( - { - x, - y, - width, - height, - ...fieldValue, - ...renderOptions, - }, - { group: cell }, - ); -}; diff --git a/packages/s2-core/src/utils/index.ts b/packages/s2-core/src/utils/index.ts index 9bb50659e0..def125c3d1 100644 --- a/packages/s2-core/src/utils/index.ts +++ b/packages/s2-core/src/utils/index.ts @@ -9,7 +9,6 @@ export * from './export/index'; export * from './export/copy'; export * from './interaction'; export * from './g-renders'; -export * from './custom-render'; export * from './g-mini-charts'; export * from './merge'; export * from './is-mobile'; diff --git a/packages/s2-react/__tests__/data/data-g2-chart.ts b/packages/s2-react/__tests__/data/data-g2-chart.ts new file mode 100644 index 0000000000..0cdb61d75a --- /dev/null +++ b/packages/s2-react/__tests__/data/data-g2-chart.ts @@ -0,0 +1,889 @@ +import type { S2DataConfig } from '@antv/s2'; + +export const ChartDataConfig: S2DataConfig = { + fields: { + rows: ['province', 'city'], + columns: ['type', 'sub_type'], + values: ['number'], + valueInCols: true, + }, + meta: [ + { + field: 'number', + name: '数量', + description: '数量说明。。', + }, + { + field: 'province', + name: '省份', + description: '省份说明。。', + }, + { + field: 'city', + name: '城市', + description: '城市说明。。', + }, + { + field: 'type', + name: '类别', + description: '类别说明。。', + }, + { + field: 'sub_type', + name: '子类别', + description: '子类别说明。。', + }, + { + field: 'area', + name: '地区', + description: '地区说明。。', + }, + { + field: 'money', + name: '金额', + description: '金额说明。。', + }, + ], + data: [ + { + number: { + values: { + // 面积图 + type: 'area', + autoFit: true, + data: { + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/aapl.json', + }, + encode: { + x: (d: Record) => new Date(d['date']), + y: 'close', + }, + }, + }, + province: '浙江省', + city: '杭州市', + type: '家具', + sub_type: '桌子', + }, + { + number: { + // 玉玦图 + values: { + type: 'interval', + autoFit: true, + data: [ + { question: '问题 1', percent: 0.21 }, + { question: '问题 2', percent: 0.4 }, + { question: '问题 3', percent: 0.49 }, + { question: '问题 4', percent: 0.52 }, + { question: '问题 5', percent: 0.53 }, + { question: '问题 6', percent: 0.84 }, + { question: '问题 7', percent: 1 }, + { question: '问题 8', percent: 1.2 }, + ], + encode: { x: 'question', y: 'percent', color: 'percent' }, + scale: { color: { range: '#BAE7FF-#1890FF-#0050B3' } }, + coordinate: { + type: 'radial', + innerRadius: 0.1, + endAngle: 3.141592653589793, + }, + style: { stroke: 'white' }, + animate: { enter: { type: 'waveIn', duration: 800 } }, + // animate: false, + legend: { + color: { + length: 400, + position: 'bottom', + layout: { justifyContent: 'center' }, + }, + }, + }, + }, + province: '浙江省', + city: '绍兴市', + type: '家具', + sub_type: '桌子', + }, + { + number: { + // 柱形图 + values: { + type: 'interval', + autoFit: true, + data: [ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ], + scale: { + color: { + guide: { + position: 'right', + size: 80, + }, + }, + }, + encode: { + x: 'genre', + y: 'sold', + color: 'genre', + }, + }, + }, + province: '浙江省', + city: '宁波市', + type: '家具', + sub_type: '桌子', + }, + { + number: { + // 仪表盘 + values: { + type: 'gauge', + autoFit: true, + data: { + value: { + target: 159, + total: 400, + name: 'score', + thresholds: [100, 200, 400], + }, + }, + scale: { color: { range: ['#F4664A', '#FAAD14', 'green'] } }, + style: { + textContent: (target: number, total: number) => `得分:${target}\ + 占比:${(target / total) * 100}%`, + }, + legend: false, + }, + }, + province: '浙江省', + city: '舟山市', + type: '家具', + sub_type: '桌子', + }, + { + number: { + // 雷达图 + values: { + type: 'view', + autoFit: true, + data: [ + { item: 'Design', type: 'a', score: 70 }, + { item: 'Design', type: 'b', score: 30 }, + { item: 'Development', type: 'a', score: 60 }, + { item: 'Development', type: 'b', score: 70 }, + { item: 'Marketing', type: 'a', score: 50 }, + { item: 'Marketing', type: 'b', score: 60 }, + { item: 'Users', type: 'a', score: 40 }, + { item: 'Users', type: 'b', score: 50 }, + { item: 'Test', type: 'a', score: 60 }, + { item: 'Test', type: 'b', score: 70 }, + { item: 'Language', type: 'a', score: 70 }, + { item: 'Language', type: 'b', score: 50 }, + { item: 'Technology', type: 'a', score: 50 }, + { item: 'Technology', type: 'b', score: 40 }, + { item: 'Support', type: 'a', score: 30 }, + { item: 'Support', type: 'b', score: 40 }, + { item: 'Sales', type: 'a', score: 60 }, + { item: 'Sales', type: 'b', score: 40 }, + { item: 'UX', type: 'a', score: 50 }, + { item: 'UX', type: 'b', score: 60 }, + ], + scale: { x: { padding: 0.5, align: 0 }, y: { tickCount: 5 } }, + coordinate: { type: 'polar' }, + axis: { x: { grid: true }, y: { zIndex: 1, title: false } }, + interaction: { tooltip: { crosshairsLineDash: [4, 4] } }, + children: [ + { + type: 'area', + encode: { x: 'item', y: 'score', color: 'type', shape: 'smooth' }, + scale: { y: { domainMax: 80 } }, + style: { fillOpacity: 0.5 }, + }, + { + type: 'line', + encode: { x: 'item', y: 'score', color: 'type', shape: 'smooth' }, + style: { lineWidth: 2 }, + }, + ], + }, + }, + province: '浙江省', + city: '杭州市', + type: '家具', + sub_type: '沙发', + }, + { + number: { + // 面积图 + values: { + type: 'box', + autoFit: true, + data: [ + { x: 'Oceania', y: [1, 9, 16, 22, 24] }, + { x: 'East Europe', y: [1, 5, 8, 12, 16] }, + { x: 'Australia', y: [1, 8, 12, 19, 26] }, + { x: 'South America', y: [2, 8, 12, 21, 28] }, + { x: 'North Africa', y: [1, 8, 14, 18, 24] }, + { x: 'North America', y: [3, 10, 17, 28, 30] }, + { x: 'West Europe', y: [1, 7, 10, 17, 22] }, + { x: 'West Africa', y: [1, 6, 8, 13, 16] }, + ], + encode: { x: 'x', y: 'y', color: 'x' }, + scale: { + x: { paddingInner: 0.6, paddingOuter: 0.3 }, + y: { zero: true }, + }, + style: { stroke: 'black' }, + legend: false, + tooltip: { + items: [ + { name: 'min', channel: 'y' }, + { name: 'q1', channel: 'y1' }, + { name: 'q2', channel: 'y2' }, + { name: 'q3', channel: 'y3' }, + { name: 'max', channel: 'y4' }, + ], + }, + }, + }, + province: '浙江省', + city: '绍兴市', + type: '家具', + sub_type: '沙发', + }, + { + number: { + // 饼图 + values: { + type: 'view', + autoFit: true, + coordinate: { type: 'theta', innerRadius: 0.6 }, + children: [ + { + type: 'interval', + data: { + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/79fd9317-d2af-4bc4-90fa-9d07357398fd.csv', + }, + encode: { y: 'value', color: 'name' }, + transform: [{ type: 'stackY' }], + scale: { + color: { + palette: 'spectral', + offset: (t: number) => t * 0.8 + 0.1, + }, + }, + legend: false, + }, + { + type: 'text', + style: { + text: 'Donut', + x: '50%', + y: '50%', + fontSize: 40, + fontWeight: 'bold', + textAlign: 'center', + }, + }, + { + type: 'text', + style: { + text: 'chart', + x: 304, + y: 360, + fontSize: 20, + fontWeight: 'bold', + textAlign: 'center', + }, + }, + ], + }, + }, + province: '浙江省', + city: '宁波市', + type: '家具', + sub_type: '沙发', + }, + { + number: { + // 折线图 + values: { + type: 'line', + autoFit: true, + data: { + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/indices.json', + }, + encode: { + x: (d: Record) => new Date(d['Date']), + y: 'Close', + color: 'Symbol', + }, + transform: [{ type: 'normalizeY', basis: 'first', groupBy: 'color' }], + scale: { y: { type: 'log' } }, + axis: { y: { title: '↑ Change in price (%)' } }, + labels: [{ text: 'Symbol', selector: 'last', fontSize: 10 }], + tooltip: { items: [{ channel: 'y', valueFormatter: '.1f' }] }, + }, + }, + province: '浙江省', + city: '舟山市', + type: '家具', + sub_type: '沙发', + }, + { + number: { + // 柱形图 + values: { + type: 'interval', + autoFit: true, + data: [ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ], + scale: { + color: { + guide: { + position: 'right', + size: 80, + }, + }, + }, + encode: { + x: 'genre', + y: 'sold', + color: 'genre', + }, + }, + }, + province: '浙江省', + city: '杭州市', + type: '办公用品', + sub_type: '笔', + }, + { + number: { + // 漏斗图 + values: { + type: 'interval', + autoFit: true, + data: [ + { action: '浏览网站', pv: 50000 }, + { action: '放入购物车', pv: 35000 }, + { action: '生成订单', pv: 25000 }, + { action: '支付订单', pv: 15000 }, + { action: '完成交易', pv: 8000 }, + ], + encode: { x: 'action', y: 'pv', color: 'action', shape: 'funnel' }, + transform: [{ type: 'symmetryY' }], + scale: { x: { padding: 0 } }, + coordinate: { transform: [{ type: 'transpose' }] }, + animate: { enter: { type: 'fadeIn' } }, + axis: false, + labels: [ + { + text: (d: Record) => `${d['action']}\ + ${d['pv']}`, + position: 'inside', + transform: [{ type: 'contrastReverse' }], + }, + ], + }, + }, + province: '浙江省', + city: '绍兴市', + type: '办公用品', + sub_type: '笔', + }, + { + number: { + // 出现顺序堆叠面积图 + values: { + type: 'view', + autoFit: true, + data: { + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/f38a8ad0-6e1f-4bb3-894c-7db50781fdec.json', + }, + interaction: { + tooltip: { + filter: (d: Record) => + parseInt(d['value'], 10) > 0, + }, + }, + children: [ + { + type: 'area', + encode: { + x: (d: Record) => new Date(d['year']), + y: 'revenue', + series: 'format', + color: 'group', + shape: 'smooth', + }, + transform: [ + { type: 'stackY', orderBy: 'maxIndex', reverse: true }, + ], + axis: { y: { labelFormatter: '~s' } }, + tooltip: { items: [{ channel: 'y', valueFormatter: '.2f' }] }, + }, + { + type: 'line', + encode: { + x: (d: Record) => new Date(d['year']), + y: 'revenue', + series: 'format', + shape: 'smooth', + color: 'group', + }, + transform: [ + { type: 'stackY', orderBy: 'maxIndex', reverse: true, y: 'y1' }, + ], + style: { stroke: 'white' }, + tooltip: false, + }, + ], + }, + }, + province: '浙江省', + city: '宁波市', + type: '办公用品', + sub_type: '笔', + }, + { + number: { + // 密度热力图 + values: { + type: 'view', + autoFit: true, + padding: 0, + axis: false, + children: [ + { + type: 'image', + style: { + src: 'https://gw.alipayobjects.com/zos/rmsportal/NeUTMwKtPcPxIFNTWZOZ.png', + x: '50%', + y: '50%', + width: '100%', + height: '100%', + }, + tooltip: false, + }, + { + type: 'heatmap', + data: { + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/heatmap.json', + }, + encode: { x: 'g', y: 'l', color: 'tmp' }, + style: { opacity: 0 }, + tooltip: false, + }, + ], + }, + }, + province: '浙江省', + city: '舟山市', + type: '办公用品', + sub_type: '笔', + }, + { + number: 1343, + province: '浙江省', + city: '杭州市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 1354, + province: '浙江省', + city: '绍兴市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 1523, + province: '浙江省', + city: '宁波市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 1634, + province: '浙江省', + city: '舟山市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 1723, + province: '四川省', + city: '成都市', + type: '家具', + sub_type: '桌子', + }, + { + number: 1822, + province: '四川省', + city: '绵阳市', + type: '家具', + sub_type: '桌子', + }, + { + number: 1943, + province: '四川省', + city: '南充市', + type: '家具', + sub_type: '桌子', + }, + { + number: 2330, + province: '四川省', + city: '乐山市', + type: '家具', + sub_type: '桌子', + }, + { + number: 2451, + province: '四川省', + city: '成都市', + type: '家具', + sub_type: '沙发', + }, + { + number: 2244, + province: '四川省', + city: '绵阳市', + type: '家具', + sub_type: '沙发', + }, + { + number: 2333, + province: '四川省', + city: '南充市', + type: '家具', + sub_type: '沙发', + }, + { + number: 2445, + province: '四川省', + city: '乐山市', + type: '家具', + sub_type: '沙发', + }, + { + number: 2335, + province: '四川省', + city: '成都市', + type: '办公用品', + sub_type: '笔', + }, + { + number: 245, + province: '四川省', + city: '绵阳市', + type: '办公用品', + sub_type: '笔', + }, + { + number: 2457, + province: '四川省', + city: '南充市', + type: '办公用品', + sub_type: '笔', + }, + { + number: 2458, + province: '四川省', + city: '乐山市', + type: '办公用品', + sub_type: '笔', + }, + { + number: 4004, + province: '四川省', + city: '成都市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 3077, + province: '四川省', + city: '绵阳市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 3551, + province: '四川省', + city: '南充市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 352, + province: '四川省', + city: '乐山市', + type: '办公用品', + sub_type: '纸张', + }, + ], + totalData: [ + { + number: 26193, + type: '家具', + sub_type: '桌子', + }, + { + number: 49709, + type: '家具', + }, + { + number: 23516, + type: '家具', + sub_type: '沙发', + }, + { + number: 29159, + type: '办公用品', + }, + { + number: 12321, + type: '办公用品', + sub_type: '笔', + }, + { + number: 16838, + type: '办公用品', + sub_type: '纸张', + }, + { + number: 18375, + province: '浙江省', + type: '家具', + sub_type: '桌子', + }, + { + number: 14043, + province: '浙江省', + type: '家具', + sub_type: '沙发', + }, + { + number: 4826, + province: '浙江省', + type: '办公用品', + sub_type: '笔', + }, + { + number: 5854, + province: '浙江省', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 7818, + province: '四川省', + type: '家具', + sub_type: '桌子', + }, + { + number: 9473, + province: '四川省', + type: '家具', + sub_type: '沙发', + }, + { + number: 7495, + province: '四川省', + type: '办公用品', + sub_type: '笔', + }, + { + number: 10984, + province: '四川省', + type: '办公用品', + sub_type: '纸张', + }, + { + number: 13132, + province: '浙江省', + city: '杭州市', + type: '家具', + }, + { + number: 2288, + province: '浙江省', + city: '杭州市', + type: '办公用品', + }, + { + number: 15420, + province: '浙江省', + city: '杭州市', + }, + { + number: 2999, + province: '浙江省', + city: '绍兴市', + type: '家具', + }, + { + number: 2658, + province: '浙江省', + city: '绍兴市', + type: '办公用品', + }, + { + number: 5657, + province: '浙江省', + city: '绍兴市', + }, + { + number: 11111, + province: '浙江省', + city: '宁波市', + type: '家具', + }, + { + number: 2668, + province: '浙江省', + city: '宁波市', + type: '办公用品', + }, + { + number: 13779, + province: '浙江省', + city: '宁波市', + }, + { + number: 5176, + province: '浙江省', + city: '舟山市', + type: '家具', + }, + { + number: 3066, + province: '浙江省', + city: '舟山市', + type: '办公用品', + }, + { + number: 8242, + province: '浙江省', + city: '舟山市', + }, + { + number: 4174, + province: '四川省', + city: '成都市', + type: '家具', + }, + { + number: 6339, + province: '四川省', + city: '成都市', + type: '办公用品', + }, + { + number: 10513, + province: '四川省', + city: '成都市', + }, + { + number: 4066, + province: '四川省', + city: '绵阳市', + type: '家具', + }, + { + number: 3322, + province: '四川省', + city: '绵阳市', + type: '办公用品', + }, + { + number: 7388, + province: '四川省', + city: '绵阳市', + }, + { + number: 4276, + province: '四川省', + city: '南充市', + type: '家具', + }, + { + number: 6008, + province: '四川省', + city: '南充市', + type: '办公用品', + }, + { + number: 10284, + province: '四川省', + city: '南充市', + }, + { + number: 4775, + province: '四川省', + city: '乐山市', + type: '家具', + }, + { + number: 2810, + province: '四川省', + city: '乐山市', + type: '办公用品', + }, + { + number: 7585, + province: '四川省', + city: '乐山市', + }, + { + number: 32418, + province: '浙江省', + type: '家具', + }, + { + number: 10680, + province: '浙江省', + type: '办公用品', + }, + { + number: 43098, + province: '浙江省', + }, + { + number: 17291, + province: '四川省', + type: '家具', + }, + { + number: 18479, + province: '四川省', + type: '办公用品', + }, + { + number: 35770, + province: '四川省', + }, + { + number: 78868, + }, + ], +}; diff --git a/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts b/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts index 6f30d2aedc..cd34d114af 100644 --- a/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts +++ b/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts @@ -249,6 +249,10 @@ const cellEventCases = [ event: S2Event.DATA_CELL_SELECT_MOVE, name: 'onDataCellSelectMove', }, + { + event: S2Event.DATA_CELL_RENDER, + name: 'onDataCellRender', + }, { event: S2Event.CORNER_CELL_HOVER, name: 'onCornerCellHover', diff --git a/packages/s2-react/package.json b/packages/s2-react/package.json index c3c50e42a2..1b826c0e8e 100644 --- a/packages/s2-react/package.json +++ b/packages/s2-react/package.json @@ -75,6 +75,7 @@ "@antv/g": "^5.15.2", "@antv/g-plugin-a11y": "^0.6.19", "@antv/g-plugin-rough-canvas-renderer": "^1.9.24", + "@antv/g2": "^5.1.9", "@antv/s2": "workspace:*", "@antv/s2-shared": "workspace:*", "@testing-library/react": "^14.0.0", diff --git a/packages/s2-react/playground/components/ChartSheet.tsx b/packages/s2-react/playground/components/ChartSheet.tsx new file mode 100644 index 0000000000..a22de24439 --- /dev/null +++ b/packages/s2-react/playground/components/ChartSheet.tsx @@ -0,0 +1,71 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { SpreadSheet } from '@antv/s2'; +import { renderToMountedElement, stdlib } from '@antv/g2'; +import React from 'react'; +import { + SheetComponent, + type SheetComponentOptions, + type SheetComponentsProps, +} from '../../src/components'; +import { usePlaygroundContext } from '../context/playground.context'; +import { ChartDataConfig } from '../../__tests__/data/data-g2-chart'; + +const options: SheetComponentOptions = { + height: 1000, + interaction: { + enableCopy: true, + brushSelection: { + rowCell: true, + colCell: true, + dataCell: true, + }, + selectedCellMove: true, + selectedCellHighlight: true, + selectedCellsSpotlight: true, + hoverFocus: true, + hoverHighlight: true, + multiSelection: true, + overscrollBehavior: 'none', + }, + style: { + colCell: { + hideValue: true, + }, + rowCell: { + width: 100, + }, + dataCell: { + width: 500, + height: 400, + }, + }, +}; + +const onDataCellRender: SheetComponentsProps['onDataCellRender'] = (cell) => { + const chartOptions = cell.getRenderChartOptions(); + + // https://g2.antv.antgroup.com/manual/extra-topics/bundle#g2stdlib + renderToMountedElement(chartOptions, { + group: cell, + library: stdlib(), + }); +}; + +export const ChartSheet: React.FC< + Partial & React.RefAttributes +> = React.forwardRef((props, ref) => { + const context = usePlaygroundContext(); + + return ( + + ); +}); diff --git a/packages/s2-react/playground/components/links.tsx b/packages/s2-react/playground/components/LinkGroup.tsx similarity index 97% rename from packages/s2-react/playground/components/links.tsx rename to packages/s2-react/playground/components/LinkGroup.tsx index b7df7b250a..bd552e404c 100644 --- a/packages/s2-react/playground/components/links.tsx +++ b/packages/s2-react/playground/components/LinkGroup.tsx @@ -9,7 +9,7 @@ import { import { FloatButton } from 'antd'; import React from 'react'; -export const Links = () => { +export const LinkGroup = () => { return (
- + , }, + { + key: 'chart', + label: '绘制 G2 图表', + children: , + }, ]} - > + />
diff --git a/packages/s2-react/src/components/sheets/chart-sheet/chart-cell.ts b/packages/s2-react/src/components/sheets/chart-sheet/chart-cell.ts deleted file mode 100644 index c631f2dbd9..0000000000 --- a/packages/s2-react/src/components/sheets/chart-sheet/chart-cell.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { S2CellType, ViewMeta } from '@antv/s2'; -import { CustomCell } from './custom-cell'; - -export const ChartCell = (viewMeta: ViewMeta): S2CellType => - new CustomCell(viewMeta, viewMeta.spreadsheet); diff --git a/packages/s2-react/src/components/sheets/chart-sheet/custom-cell.ts b/packages/s2-react/src/components/sheets/chart-sheet/custom-cell.ts deleted file mode 100644 index 04ff83ccfa..0000000000 --- a/packages/s2-react/src/components/sheets/chart-sheet/custom-cell.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { DataCell } from '@antv/s2'; - -export class CustomCell extends DataCell { - public drawTextShape() { - // TODO 暂时留下个扩展位,不知道后面会有什么需求 - return null; - } -} diff --git a/packages/s2-react/src/components/sheets/chart-sheet/custom-cell/data-cell.ts b/packages/s2-react/src/components/sheets/chart-sheet/custom-cell/data-cell.ts new file mode 100644 index 0000000000..85cbe3c01a --- /dev/null +++ b/packages/s2-react/src/components/sheets/chart-sheet/custom-cell/data-cell.ts @@ -0,0 +1,11 @@ +import { DataCell, type RenderTextShapeOptions } from '@antv/s2'; + +export class ChartSheetDataCell extends DataCell { + public drawTextShape(options?: RenderTextShapeOptions) { + if (this.isMultiData()) { + return null; + } + + super.drawTextShape(options); + } +} diff --git a/packages/s2-react/src/components/sheets/chart-sheet/custom-cell/index.ts b/packages/s2-react/src/components/sheets/chart-sheet/custom-cell/index.ts new file mode 100644 index 0000000000..a7ed54c259 --- /dev/null +++ b/packages/s2-react/src/components/sheets/chart-sheet/custom-cell/index.ts @@ -0,0 +1 @@ +export { ChartSheetDataCell } from './data-cell'; 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 cf238b6562..f4af23b0b1 100644 --- a/packages/s2-react/src/components/sheets/chart-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/chart-sheet/index.tsx @@ -1,40 +1,44 @@ -import { customMerge, renderToMountedCell, type S2CellType } from '@antv/s2'; -import { isEmpty, isFunction } from 'lodash'; +import { customMerge } from '@antv/s2'; import React from 'react'; import { BaseSheet } from '../base-sheet'; import type { SheetComponentOptions, SheetComponentsProps } from '../interface'; -import { ChartCell } from './chart-cell'; +import { ChartSheetDataCell } from './custom-cell'; export const ChartSheet: React.FC = React.memo( (props) => { - const { options, renderConfig, ...restProps } = props; - const s2Options = React.useMemo( - () => - customMerge(options, { - dataCell: ChartCell, - showDefaultHeaderActionIcon: false, - }), - [options], - ); + const { options: defaultOptions, ...restProps } = props; + const s2Options = React.useMemo(() => { + const options: SheetComponentOptions = { + dataCell: (viewMeta) => + new ChartSheetDataCell(viewMeta, viewMeta.spreadsheet), + showDefaultHeaderActionIcon: false, + interaction: { + hoverFocus: false, + }, + // TODO: 刷选时获取不到正确的 tooltip 配置 + tooltip: { + // cornerCell: { + // enable: true, + // }, + // colCell: { + // enable: true, + // }, + // rowCell: { + // enable: true, + // }, + // enable: false, + enable: true, + dataCell: { + enable: false, + }, + }, + }; - const onLayoutCellMounted = (cell: S2CellType) => { - if (isEmpty(renderConfig) || !isFunction(renderConfig?.render)) { - return; - } + return customMerge(defaultOptions, options); + }, [defaultOptions]); - renderToMountedCell( - cell, - renderConfig?.render, - renderConfig?.renderOptions, - ); - }; - - return ( - - ); + return ; }, ); + +ChartSheet.displayName = 'ChartSheet'; diff --git a/packages/s2-react/src/components/sheets/editable-sheet/edit-cell/index.less b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.less similarity index 100% rename from packages/s2-react/src/components/sheets/editable-sheet/edit-cell/index.less rename to packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.less diff --git a/packages/s2-react/src/components/sheets/editable-sheet/edit-cell/index.tsx b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx similarity index 94% rename from packages/s2-react/src/components/sheets/editable-sheet/edit-cell/index.tsx rename to packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx index bd9267e2ef..9d2c87f34f 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/edit-cell/index.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx @@ -16,12 +16,12 @@ import { type S2CellType, } from '@antv/s2'; import { isNil, pick } from 'lodash'; -import { useS2Event } from '../../../../hooks'; -import { useSpreadSheetInstance } from '../../../../context/SpreadSheetContext'; +import { useS2Event } from '../../../../../hooks'; +import { useSpreadSheetInstance } from '../../../../../context/SpreadSheetContext'; import { invokeComponent, type InvokeComponentProps, -} from '../../../../utils/invokeComponent'; +} from '../../../../../utils/invokeComponent'; import './index.less'; export interface CustomProps { @@ -184,7 +184,7 @@ function EditCellComponent( ); } -const EditCell = memo(({ onChange, CustomComponent }: onChangeProps) => { +export const EditCell = memo(({ onChange, CustomComponent }: onChangeProps) => { const spreadsheet = useSpreadSheetInstance(); const onEditCell = useCallback( @@ -206,5 +206,3 @@ const EditCell = memo(({ onChange, CustomComponent }: onChangeProps) => { return null; }); - -export { EditCell }; diff --git a/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/index.ts b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/index.ts new file mode 100644 index 0000000000..d1ba03b929 --- /dev/null +++ b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/index.ts @@ -0,0 +1 @@ +export { EditCell } from './edit-cell'; diff --git a/packages/s2-react/src/components/sheets/editable-sheet/index.tsx b/packages/s2-react/src/components/sheets/editable-sheet/index.tsx index 5a49a2eaab..4f10bf7cb2 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/index.tsx @@ -2,7 +2,7 @@ import React, { useCallback } from 'react'; import { BaseSheet } from '../base-sheet'; import type { SheetComponentsProps } from '../interface'; import { DragCopyPoint } from './drag-copy'; -import { EditCell } from './edit-cell'; +import { EditCell } from './custom-cell'; export const EditableSheet: React.FC = React.memo( (props) => { diff --git a/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell.ts b/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/data-cell.ts similarity index 66% rename from packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell.ts rename to packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/data-cell.ts index b7a58db5a7..35f4fbc76a 100644 --- a/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell.ts +++ b/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/data-cell.ts @@ -1,4 +1,3 @@ -import { isObject } from 'lodash'; import { DataCell, drawObjectText, @@ -13,12 +12,12 @@ import { * | measureLabel | measure | measure | * -------------------------------------- */ -export class CustomCell extends DataCell { +export class GridAnalysisSheetDataCell extends DataCell { public drawTextShape(options?: RenderTextShapeOptions) { - if (isObject(this.getMeta().fieldValue)) { - drawObjectText(this); - } else { - super.drawTextShape(options); + if (this.isMultiData()) { + return drawObjectText(this); } + + super.drawTextShape(options); } } diff --git a/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/index.ts b/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/index.ts new file mode 100644 index 0000000000..d8d627b97d --- /dev/null +++ b/packages/s2-react/src/components/sheets/grid-analysis-sheet/custom-cell/index.ts @@ -0,0 +1 @@ +export { GridAnalysisSheetDataCell } from './data-cell'; diff --git a/packages/s2-react/src/components/sheets/grid-analysis-sheet/grid-analysis-data-cell.ts b/packages/s2-react/src/components/sheets/grid-analysis-sheet/grid-analysis-data-cell.ts deleted file mode 100644 index d42d7464bc..0000000000 --- a/packages/s2-react/src/components/sheets/grid-analysis-sheet/grid-analysis-data-cell.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { S2CellType, ViewMeta } from '@antv/s2'; -import { CustomCell } from './custom-cell'; - -export const GridAnalysisDataCell = (viewMeta: ViewMeta): S2CellType => - new CustomCell(viewMeta, viewMeta.spreadsheet); 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 02dabc9c2d..a7cc94f5f4 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 @@ -2,34 +2,35 @@ import { customMerge, type ThemeCfg } from '@antv/s2'; import React from 'react'; import { BaseSheet } from '../base-sheet'; import type { SheetComponentOptions, SheetComponentsProps } from '../interface'; -import { GridAnalysisDataCell } from './grid-analysis-data-cell'; -import { GridAnalysisTheme } from './grid-analysis-theme'; +import { GridAnalysisSheetDataCell } from './custom-cell'; +import { GridAnalysisTheme } from './theme'; export const GridAnalysisSheet: React.FC = React.memo( (props) => { - const { options, themeCfg, ...restProps } = props; + const { options: defaultOptions, themeCfg, ...restProps } = props; - const s2Options = React.useMemo( - () => - customMerge(options, { - dataCell: GridAnalysisDataCell, - showDefaultHeaderActionIcon: false, - style: { - colCell: { - hideValue: true, - }, + const s2Options = React.useMemo(() => { + const options: SheetComponentOptions = { + dataCell: (viewMeta) => + new GridAnalysisSheetDataCell(viewMeta, viewMeta.spreadsheet), + showDefaultHeaderActionIcon: false, + style: { + colCell: { + hideValue: true, }, - }), - [options], - ); + }, + }; + + return customMerge(defaultOptions, options); + }, [defaultOptions]); - const S2ThemeCfg = React.useMemo( + const s2ThemeCfg = React.useMemo( () => customMerge(themeCfg, { theme: GridAnalysisTheme }), [themeCfg], ); return ( - + ); }, ); diff --git a/packages/s2-react/src/components/sheets/grid-analysis-sheet/grid-analysis-theme.ts b/packages/s2-react/src/components/sheets/grid-analysis-sheet/theme.ts similarity index 100% rename from packages/s2-react/src/components/sheets/grid-analysis-sheet/grid-analysis-theme.ts rename to packages/s2-react/src/components/sheets/grid-analysis-sheet/theme.ts diff --git a/packages/s2-react/src/components/sheets/interface.ts b/packages/s2-react/src/components/sheets/interface.ts index 5f70b121ad..8f067c2d13 100644 --- a/packages/s2-react/src/components/sheets/interface.ts +++ b/packages/s2-react/src/components/sheets/interface.ts @@ -1,4 +1,4 @@ -import type { Pagination, RenderHandler, S2Options } from '@antv/s2'; +import type { Pagination, S2Options } from '@antv/s2'; import type { PartDrillDown as BasePartDrillDown, BaseSheetComponentProps, @@ -11,11 +11,6 @@ import type { TooltipOperatorMenuOptions } from '../tooltip/interface'; export type PartDrillDown = BasePartDrillDown; -export interface RenderProps { - render: RenderHandler; - renderOptions?: Record; -} - export type SheetComponentOptions = S2Options< ReactNode, Pagination & AntdPaginationProps, @@ -23,7 +18,6 @@ export type SheetComponentOptions = S2Options< >; export type SheetComponentsProps = BaseSheetComponentProps< - RenderProps, PartDrillDown, HeaderCfgProps, SheetComponentOptions diff --git a/packages/s2-react/src/components/sheets/strategy-sheet/custom-cell/data-cell.ts b/packages/s2-react/src/components/sheets/strategy-sheet/custom-cell/data-cell.ts index 59a426da28..1f0da673b9 100644 --- a/packages/s2-react/src/components/sheets/strategy-sheet/custom-cell/data-cell.ts +++ b/packages/s2-react/src/components/sheets/strategy-sheet/custom-cell/data-cell.ts @@ -1,4 +1,3 @@ -import { isObject } from 'lodash'; import { DataCell, drawObjectText, @@ -14,10 +13,10 @@ import { */ export class StrategySheetDataCell extends DataCell { public drawTextShape(options?: RenderTextShapeOptions) { - if (isObject(this.getMeta().fieldValue)) { - drawObjectText(this); - } else { - super.drawTextShape(options); + if (this.isMultiData()) { + return drawObjectText(this); } + + super.drawTextShape(options); } } 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 6ac31c6ba4..6c95c25b37 100644 --- a/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx @@ -81,7 +81,7 @@ export const StrategySheet: React.FC = React.memo( }, [dataCfg]); const s2Options = React.useMemo( - () => customMerge(strategySheetOptions, options), + () => customMerge(strategySheetOptions, options), [options, strategySheetOptions], ); diff --git a/packages/s2-react/src/hooks/useEvents.ts b/packages/s2-react/src/hooks/useEvents.ts index 506ef18fef..60af60c9a5 100644 --- a/packages/s2-react/src/hooks/useEvents.ts +++ b/packages/s2-react/src/hooks/useEvents.ts @@ -89,6 +89,7 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { s2, ); useS2Event(S2Event.DATA_CELL_SELECT_MOVE, props.onDataCellSelectMove, s2); + useS2Event(S2Event.DATA_CELL_RENDER, props.onDataCellRender, s2); // ============== Corner Cell ==================== useCellEvent(S2Event.CORNER_CELL_HOVER, props.onCornerCellHover, s2); diff --git a/packages/s2-shared/src/interface.ts b/packages/s2-shared/src/interface.ts index 3bdc72ff95..42c65aa1bb 100644 --- a/packages/s2-shared/src/interface.ts +++ b/packages/s2-shared/src/interface.ts @@ -54,7 +54,6 @@ export type LayoutPaginationParams = { }; export interface BaseSheetComponentProps< - RenderHandler = unknown, PartialDrillDown = PartDrillDown, Header = unknown, Options = S2Options, @@ -69,7 +68,6 @@ export interface BaseSheetComponentProps< options?: Options; loading?: boolean; partDrillDown?: PartialDrillDown; - renderConfig?: RenderHandler; adaptive?: Adaptive; showPagination?: | boolean @@ -118,6 +116,7 @@ export interface BaseSheetComponentProps< onDataCellMouseMove?: (data: TargetCellInfo) => void; onDataCellBrushSelection?: (brushRangeDataCells: DataCell[]) => void; onDataCellSelectMove?: (metaList: ViewMetaData[]) => void; + onDataCellRender?: (dataCell: DataCell) => void; // ============== Corner Cell ==================== onCornerCellHover?: (data: TargetCellInfo) => void; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a810286e3..b46d12c53f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -340,6 +340,9 @@ importers: '@antv/g-plugin-rough-canvas-renderer': specifier: ^1.9.24 version: 1.9.24 + '@antv/g2': + specifier: ^5.1.9 + version: 5.1.9 '@antv/s2': specifier: workspace:* version: link:../s2-core @@ -737,6 +740,25 @@ packages: resolution: {integrity: sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==} dev: false + /@antv/component@1.0.0-beta.2(@antv/g@5.18.21): + resolution: {integrity: sha512-WQPgnoLsvVOoHXGaQWKitD38mF1olP+IqoXYARfwCuNEMMDMtNqdUbMZrU/P3ypmz2iEbqdVEOjagL9Aebk/Rw==} + peerDependencies: + '@antv/g': ^5.14.1 + dependencies: + '@antv/g': 5.18.21 + '@antv/scale': 0.4.13 + '@antv/util': 3.3.5 + svg-path-parser: 1.1.0 + dev: true + + /@antv/coord@0.4.7: + resolution: {integrity: sha512-UTbrMLhwJUkKzqJx5KFnSRpU3BqrdLORJbwUbHK2zHSCT3q3bjcFA//ZYLVfIlwqFDXp/hzfMyRtp0c77A9ZVA==} + dependencies: + '@antv/scale': 0.4.13 + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + dev: true + /@antv/dumi-theme-antv@0.4.3(@babel/core@7.23.2)(dumi@2.2.14): resolution: {integrity: sha512-SeAf+KfmbAnvjUsKt5d0aNiFVhMzUQ8S2ZsO/cCrn9KCJCjdcgc53c2mUHOCgZT4AYbrfoIF6DyJ2j0UcEu4Ng==} peerDependencies: @@ -881,6 +903,14 @@ packages: '@antv/g-lite': 1.2.19 tslib: 2.6.2 + /@antv/g-plugin-dragndrop@1.8.19: + resolution: {integrity: sha512-dLmOXxQjnsdoEVa0FSFELuVqFHdaCVqDiTwIwrde9xSpsRHkDamyBxnihvn18aCptuX9Gwz/D340xXJNMGgjjQ==} + dependencies: + '@antv/g-lite': 1.2.19 + '@antv/util': 3.3.5 + tslib: 2.6.2 + dev: true + /@antv/g-plugin-html-renderer@1.9.22: resolution: {integrity: sha512-+vGFscjEa6yWxJzqPOmkGL5WjrfT0jDlRBzsF1UczeMNEM8zFQu5/VXL8LlCDOnOTJEo3UpkzrUT0fQe4mHaAA==} dependencies: @@ -913,6 +943,33 @@ packages: '@antv/util': 3.3.5 tslib: 2.6.2 + /@antv/g2@5.1.9: + resolution: {integrity: sha512-zvo/jd+4wKfvWsHCzqb+NdCrT5DXGytkAqS9eX2qN3UHDB7ptiY1kteh6LiCTfLtSTLko6asGYlwxcrUAOSM/w==} + dependencies: + '@antv/component': 1.0.0-beta.2(@antv/g@5.18.21) + '@antv/coord': 0.4.7 + '@antv/event-emitter': 0.1.3 + '@antv/g': 5.18.21 + '@antv/g-canvas': 1.11.24 + '@antv/g-plugin-dragndrop': 1.8.19 + '@antv/path-util': 3.0.1 + '@antv/scale': 0.4.13 + '@antv/util': 3.3.5 + d3-array: 3.2.4 + d3-dsv: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.0 + d3-hierarchy: 3.1.2 + d3-path: 3.1.0 + d3-scale-chromatic: 3.0.0 + d3-shape: 3.2.0 + d3-voronoi: 1.1.4 + flru: 1.0.2 + fmin: 0.0.2 + pdfast: 0.2.0 + dev: true + /@antv/g@5.18.21: resolution: {integrity: sha512-+RFiVeMgmPL94U4/wN3HUwxYmkOq2msrPAg38NeGG6Mwo4DOW2nEZqoQCpDFxzmTRwKM984b24epcEPv+wNy+g==} dependencies: @@ -921,6 +978,29 @@ packages: '@antv/g-lite': 1.2.19 '@antv/g-web-animations-api': 1.2.19 + /@antv/path-util@3.0.1: + resolution: {integrity: sha512-tpvAzMpF9Qm6ik2YSMqICNU5tco5POOW7S4XoxZAI/B0L26adU+Md/SmO0BBo2SpuywKvzPH3hPT3xmoyhr04Q==} + dependencies: + gl-matrix: 3.4.3 + lodash-es: 4.17.21 + tslib: 2.6.2 + dev: true + + /@antv/scale@0.4.13: + resolution: {integrity: sha512-aWOXZdvkHQjEOMWmDBJF6nja30Y38nC5WTtx3fzX4INqfqYLX9u/fcZfElsjFzryewh2qveO+7L0rq8ugutDTw==} + dependencies: + '@antv/util': 2.0.17 + color-string: 1.9.1 + fecha: 4.2.3 + dev: true + + /@antv/util@2.0.17: + resolution: {integrity: sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==} + dependencies: + csstype: 3.1.2 + tslib: 2.6.2 + dev: true + /@antv/util@3.3.5: resolution: {integrity: sha512-bVv1loamL/MgUEN9dNt7VKAsghO4Wgb+kzr8B9TgkM5tHgKk++xiTwi3pejIdgU8DDkzcyaRsO+VTOXJt8jLng==} dependencies: @@ -2842,6 +2922,13 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.15 + /@ljharb/resumer@0.0.1: + resolution: {integrity: sha512-skQiAOrCfO7vRTq53cxznMpks7wS1va95UCidALlOVWqvBAzwPVErwizDwoMqNVMEn1mDq0utxZd02eIrvF1lw==} + engines: {node: '>= 0.4'} + dependencies: + '@ljharb/through': 2.3.11 + dev: true + /@ljharb/through@2.3.11: resolution: {integrity: sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==} engines: {node: '>= 0.4'} @@ -5804,6 +5891,20 @@ packages: '@algolia/transporter': 4.14.3 dev: false + /align-text@0.1.4: + resolution: {integrity: sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + dev: true + + /amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + dev: true + /animated-scroll-to@2.3.0: resolution: {integrity: sha512-PT/5MSKCWQaK2kuOl2HT2KJMuJEvUS4/TgMhWy82c2EmF74/CIkvPBPKOvd8nMYP6Higo7xCn49/iSW9BccMoQ==} dev: false @@ -5867,6 +5968,11 @@ packages: engines: {node: '>=12'} dev: true + /ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: true + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -7122,6 +7228,11 @@ packages: quick-lru: 5.1.1 type-fest: 1.4.0 + /camelcase@1.2.1: + resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} + engines: {node: '>=0.10.0'} + dev: true + /camelcase@4.1.0: resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} engines: {node: '>=4'} @@ -7184,6 +7295,25 @@ packages: /ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + /center-align@0.1.3: + resolution: {integrity: sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + dev: true + + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: true + /chalk@2.1.0: resolution: {integrity: sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==} engines: {node: '>=4'} @@ -7399,6 +7529,14 @@ packages: - react-dom dev: false + /cliui@2.1.0: + resolution: {integrity: sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==} + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + dev: true + /cliui@5.0.0: resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} dependencies: @@ -7532,7 +7670,6 @@ packages: dependencies: color-name: 1.1.4 simple-swizzle: 0.2.2 - dev: false /color@3.2.1: resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} @@ -7688,6 +7825,10 @@ packages: resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} dev: false + /contour_plot@0.0.1: + resolution: {integrity: sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw==} + dev: true + /conventional-changelog-angular@5.0.13: resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==} engines: {node: '>=10'} @@ -8239,9 +8380,21 @@ packages: resolution: {integrity: sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==} dev: false + /d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + dependencies: + internmap: 2.0.3 + dev: true + /d3-color@1.4.1: resolution: {integrity: sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==} + /d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + dev: true + /d3-dsv@1.2.0: resolution: {integrity: sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==} hasBin: true @@ -8259,22 +8412,74 @@ packages: commander: 7.2.0 iconv-lite: 0.6.3 rw: 1.3.3 - dev: false /d3-ease@3.0.1: resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} engines: {node: '>=12'} dev: false + /d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 1.0.10 + dev: true + + /d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + dev: true + + /d3-geo@3.1.0: + resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: true + + /d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + dev: true + /d3-interpolate@1.4.0: resolution: {integrity: sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==} dependencies: d3-color: 1.4.1 - dev: false + + /d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + dev: true + + /d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + dev: true + + /d3-scale-chromatic@3.0.0: + resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==} + engines: {node: '>=12'} + dependencies: + d3-color: 1.4.1 + d3-interpolate: 1.4.0 + dev: true + + /d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: true /d3-timer@1.0.10: resolution: {integrity: sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==} - dev: false + + /d3-voronoi@1.1.4: + resolution: {integrity: sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==} + dev: true /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} @@ -8420,6 +8625,18 @@ packages: mimic-response: 2.1.0 dev: true + /deep-equal@1.1.2: + resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==} + engines: {node: '>= 0.4'} + dependencies: + is-arguments: 1.1.1 + is-date-object: 1.0.5 + is-regex: 1.1.4 + object-is: 1.1.5 + object-keys: 1.1.1 + regexp.prototype.flags: 1.5.1 + dev: true + /deep-equal@2.2.0: resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} dependencies: @@ -8542,6 +8759,10 @@ packages: is-descriptor: 1.0.2 isobject: 3.0.1 + /defined@1.0.1: + resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + dev: true + /del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} engines: {node: '>=10'} @@ -8793,6 +9014,13 @@ packages: engines: {node: '>=12'} dev: true + /dotignore@0.1.2: + resolution: {integrity: sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==} + hasBin: true + dependencies: + minimatch: 3.1.2 + dev: true + /dumi-afx-deps@1.0.0-alpha.20: resolution: {integrity: sha512-PRSJlHuJkyHDET7Hukykx/hLULkgUBX5q2CutMG5EDI3eJLzJlX634wNll10m3at1uomcDAVudL7Dgh5UOJ7IQ==} dev: false @@ -10361,6 +10589,10 @@ packages: pend: 1.2.0 dev: true + /fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + dev: true + /fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -10569,6 +10801,16 @@ packages: readable-stream: 2.3.7 dev: false + /fmin@0.0.2: + resolution: {integrity: sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==} + dependencies: + contour_plot: 0.0.1 + json2module: 0.0.3 + rollup: 0.25.8 + tape: 4.17.0 + uglify-js: 2.8.29 + dev: true + /follow-redirects@1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -11383,6 +11625,13 @@ packages: resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} dev: false + /has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -12252,6 +12501,11 @@ packages: has: 1.0.3 side-channel: 1.0.4 + /internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + dev: true + /intersection-observer@0.12.2: resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} dev: false @@ -12329,7 +12583,6 @@ packages: /is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - dev: false /is-arrow-function@2.0.3: resolution: {integrity: sha512-iDStzcT1FJMzx+TjCOK//uDugSe/Mif/8a+T0htydQ3qkJGvSweTZpVYz4hpJH0baloSPiAFQdA8WslAgJphvQ==} @@ -14078,6 +14331,13 @@ packages: /json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + /json2module@0.0.3: + resolution: {integrity: sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==} + hasBin: true + dependencies: + rw: 1.3.3 + dev: true + /json2mq@0.2.0: resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} dependencies: @@ -14225,7 +14485,6 @@ packages: /lazy-cache@1.0.4: resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==} engines: {node: '>=0.10.0'} - dev: false /leac@0.6.0: resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} @@ -14641,6 +14900,11 @@ packages: /longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + /longest@1.0.1: + resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} + engines: {node: '>=0.10.0'} + dev: true + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -15594,6 +15858,18 @@ packages: hasBin: true dev: true + /mock-property@1.0.3: + resolution: {integrity: sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.0 + hasown: 2.0.0 + isarray: 2.0.5 + dev: true + /modify-values@1.0.1: resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} engines: {node: '>=0.10.0'} @@ -16722,6 +16998,10 @@ packages: sha.js: 2.4.11 dev: false + /pdfast@0.2.0: + resolution: {integrity: sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==} + dev: true + /peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} dev: false @@ -19994,6 +20274,13 @@ packages: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} dev: true + /right-align@0.1.3: + resolution: {integrity: sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + dev: true + /rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true @@ -20123,6 +20410,15 @@ packages: estree-walker: 0.6.1 dev: true + /rollup@0.25.8: + resolution: {integrity: sha512-a2S4Bh3bgrdO4BhKr2E4nZkjTvrJ2m2bWjMTzVYtoqSCn0HnuxosXnaJUHrMEziOWr3CzL9GjilQQKcyCQpJoA==} + hasBin: true + dependencies: + chalk: 1.1.3 + minimist: 1.2.8 + source-map-support: 0.3.3 + dev: true + /rollup@0.63.5: resolution: {integrity: sha512-dFf8LpUNzIj3oE0vCvobX6rqOzHzLBoblyFp+3znPbjiSmSvOoK2kMKx+Fv9jYduG1rvcCfCveSgEaQHjWRF6g==} hasBin: true @@ -20602,7 +20898,6 @@ packages: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} dependencies: is-arrayish: 0.3.2 - dev: false /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -20755,6 +21050,12 @@ packages: decode-uri-component: 0.2.2 dev: false + /source-map-support@0.3.3: + resolution: {integrity: sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==} + dependencies: + source-map: 0.1.32 + dev: true + /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: @@ -20765,6 +21066,13 @@ packages: resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} deprecated: See https://github.com/lydell/source-map-url#deprecated + /source-map@0.1.32: + resolution: {integrity: sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==} + engines: {node: '>=0.8.0'} + dependencies: + amdefine: 1.0.1 + dev: true + /source-map@0.5.6: resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} engines: {node: '>=0.10.0'} @@ -21390,6 +21698,11 @@ packages: - supports-color dev: true + /supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: true + /supports-color@4.5.0: resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} engines: {node: '>=4'} @@ -21443,6 +21756,10 @@ packages: /svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + /svg-path-parser@1.1.0: + resolution: {integrity: sha512-jGCUqcQyXpfe38R7RFfhrMyfXcBmpMNJI/B+4CE9/Unkh98UporAc461GTthv+TVDuZXsBx7/WiwJb1Oh4tt4A==} + dev: true + /svg-pathdata@5.0.5: resolution: {integrity: sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==} engines: {node: '>=6.9.5'} @@ -21524,6 +21841,28 @@ packages: engines: {node: '>=6'} dev: false + /tape@4.17.0: + resolution: {integrity: sha512-KCuXjYxCZ3ru40dmND+oCLsXyuA8hoseu2SS404Px5ouyS0A99v8X/mdiLqsR5MTAyamMBN7PRwt2Dv3+xGIxw==} + hasBin: true + dependencies: + '@ljharb/resumer': 0.0.1 + '@ljharb/through': 2.3.11 + call-bind: 1.0.2 + deep-equal: 1.1.2 + defined: 1.0.1 + dotignore: 0.1.2 + for-each: 0.3.3 + glob: 7.2.3 + has: 1.0.3 + inherits: 2.0.4 + is-regex: 1.1.4 + minimist: 1.2.8 + mock-property: 1.0.3 + object-inspect: 1.12.3 + resolve: 1.22.8 + string.prototype.trim: 1.2.8 + dev: true + /tar-fs@1.16.3: resolution: {integrity: sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==} dependencies: @@ -22059,6 +22398,17 @@ packages: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: true + /uglify-js@2.8.29: + resolution: {integrity: sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==} + engines: {node: '>=0.8.0'} + hasBin: true + dependencies: + source-map: 0.5.7 + yargs: 3.10.0 + optionalDependencies: + uglify-to-browserify: 1.0.2 + dev: true + /uglify-js@3.17.4: resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} engines: {node: '>=0.8.0'} @@ -22066,6 +22416,12 @@ packages: requiresBuild: true dev: true + /uglify-to-browserify@1.0.2: + resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} + requiresBuild: true + dev: true + optional: true + /umi@4.0.88(@babel/core@7.23.2)(@types/node@20.8.9)(eslint@8.52.0)(jest@26.6.3)(postcss-less@6.0.0)(prettier@3.0.3)(rollup@4.1.5)(sass@1.69.5)(stylelint@15.11.0)(typescript@5.2.2): resolution: {integrity: sha512-gNgBMbLuZwj5c2uroFmtgT4tJO2JFKfIxJaad3oFa0cOzJMSx6CnaG3Z2/+pU2eAy9EMBvbtY/iAmkr3ZNEAWg==} engines: {node: '>=14'} @@ -22956,10 +23312,20 @@ packages: string-width: 2.1.1 dev: false + /window-size@0.1.0: + resolution: {integrity: sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==} + engines: {node: '>= 0.8.0'} + dev: true + /word-wrap@1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} + /wordwrap@0.0.2: + resolution: {integrity: sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==} + engines: {node: '>=0.4.0'} + dev: true + /wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} dev: true @@ -23223,6 +23589,15 @@ packages: y18n: 5.0.8 yargs-parser: 21.1.1 + /yargs@3.10.0: + resolution: {integrity: sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==} + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + dev: true + /yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} dependencies: From 832ed8053471ae23f7ed409627d8dbb36a2acb2f Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Wed, 29 Nov 2023 19:25:17 +0800 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=89=80?= =?UTF-8?q?=E6=9C=89=E5=8D=95=E5=85=83=E6=A0=BC=E7=9A=84=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/sheet-type/pivot-sheet-spec.ts | 33 +++++++++++++++-- .../src/common/constant/events/basic.ts | 10 +++++- .../s2-core/src/common/interface/basic.ts | 4 +-- .../s2-core/src/common/interface/emitter.ts | 10 +++++- .../s2-core/src/common/interface/s2Options.ts | 11 +++--- packages/s2-core/src/facet/base-facet.ts | 2 +- packages/s2-core/src/facet/header/col.ts | 8 +++-- packages/s2-core/src/facet/header/corner.ts | 5 ++- packages/s2-core/src/facet/header/row.ts | 8 +++-- .../s2-core/src/facet/header/series-number.ts | 13 +++++-- .../s2-core/src/group/panel-scroll-group.ts | 7 ++-- .../__tests__/unit/hooks/useEvents-spec.ts | 35 +++++++++++++++++-- .../playground/components/ChartSheet.tsx | 13 +------ .../components/sheets/chart-sheet/index.tsx | 15 ++++++-- packages/s2-react/src/hooks/useEvents.ts | 14 ++++++-- packages/s2-shared/src/interface.ts | 16 +++++++-- .../docs/api/components/sheet-component.en.md | 4 +-- .../docs/api/components/sheet-component.zh.md | 6 ++-- s2-site/docs/api/general/S2Event.zh.md | 32 ++++++++++++++--- 19 files changed, 192 insertions(+), 54 deletions(-) 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 1b02c7e310..7b9fde6396 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 @@ -3,7 +3,7 @@ import { Canvas, CanvasEvent } from '@antv/g'; import { cloneDeep, get, last } from 'lodash'; import dataCfg from 'tests/data/simple-data.json'; import { waitForRender } from 'tests/util'; -import { getContainer } from 'tests/util/helpers'; +import { createPivotSheet, getContainer } from 'tests/util/helpers'; import type { BaseEvent, BaseTooltipOperatorMenuOptions, @@ -498,7 +498,7 @@ describe('PivotSheet Tests', () => { expect(afterRender).toHaveBeenCalledTimes(1); }); - test('should emit after real dataCell render', async () => { + test('should emit after real dataCell render event', async () => { const afterRealDataCellRender = jest.fn(); const sheet = new PivotSheet(container, dataCfg, s2Options); @@ -511,6 +511,35 @@ describe('PivotSheet Tests', () => { expect(afterRealDataCellRender).toHaveBeenCalledTimes(1); }); + test('should emit data cell render event', async () => { + const cornerCellRender = jest.fn(); + const rowCellRender = jest.fn(); + const colCellRender = jest.fn(); + const dataCellRender = jest.fn(); + const seriesNumberCellRender = jest.fn(); + const layoutCellRender = jest.fn(); + + const sheet = createPivotSheet( + { + ...s2Options, + showSeriesNumber: true, + }, + { useSimpleData: false }, + ); + + sheet.on(S2Event.CORNER_CELL_RENDER, cornerCellRender); + sheet.on(S2Event.ROW_CELL_RENDER, rowCellRender); + sheet.on(S2Event.COL_CELL_RENDER, colCellRender); + sheet.on(S2Event.DATA_CELL_RENDER, dataCellRender); + sheet.on(S2Event.SERIES_NUMBER_CELL_RENDER, seriesNumberCellRender); + sheet.on(S2Event.LAYOUT_CELL_RENDER, layoutCellRender); + + await sheet.render(); + + expect(dataCellRender).toHaveBeenCalledTimes(8); + expect(layoutCellRender).toHaveBeenCalledTimes(20); + }); + test('should updatePagination', () => { s2.updatePagination({ current: 2, diff --git a/packages/s2-core/src/common/constant/events/basic.ts b/packages/s2-core/src/common/constant/events/basic.ts index 9a1335845a..fcda31b006 100644 --- a/packages/s2-core/src/common/constant/events/basic.ts +++ b/packages/s2-core/src/common/constant/events/basic.ts @@ -11,6 +11,8 @@ export enum S2Event { ROW_CELL_BRUSH_SELECTION = 'row-cell:brush-selection', ROW_CELL_COLLAPSED = 'row-cell:collapsed', ROW_CELL_ALL_COLLAPSED = 'row-cell:all-collapsed', + ROW_CELL_RENDER = 'row-cell:render', + // 内部用来通信的 event ROW_CELL_COLLAPSED__PRIVATE = 'row-cell:collapsed__private', ROW_CELL_ALL_COLLAPSED__PRIVATE = 'row-cell:all-collapsed__private', @@ -26,6 +28,7 @@ export enum S2Event { COL_CELL_BRUSH_SELECTION = 'col-cell:brush-selection', COL_CELL_EXPANDED = 'col-cell:expanded', COL_CELL_HIDDEN = 'col-cell:hidden', + COL_CELL_RENDER = 'col-cell:render', /** ================ Data Cell ================ */ DATA_CELL_HOVER = 'data-cell:hover', @@ -47,6 +50,7 @@ export enum S2Event { CORNER_CELL_MOUSE_DOWN = 'corner-cell:mouse-down', CORNER_CELL_MOUSE_UP = 'corner-cell:mouse-up', CORNER_CELL_MOUSE_MOVE = 'corner-cell:mouse-move', + CORNER_CELL_RENDER = 'corner-cell:render', /** ================ Merged Cells ================ */ MERGED_CELLS_HOVER = 'merged-cells:hover', @@ -56,6 +60,10 @@ export enum S2Event { MERGED_CELLS_MOUSE_DOWN = 'merged-cells:mouse-down', MERGED_CELLS_MOUSE_UP = 'merged-cells:mouse-up', MERGED_CELLS_MOUSE_MOVE = 'merged-cells:mouse-move', + MERGED_CELLS_RENDER = 'merged-cells:render', + + /** ================ SeriesNumber Cell ================ */ + SERIES_NUMBER_CELL_RENDER = 'series-number-cell:render', /** ================ Sort ================ */ RANGE_SORT = 'sort:range-sort', @@ -67,7 +75,7 @@ export enum S2Event { /** ================ Table Layout ================ */ LAYOUT_AFTER_HEADER_LAYOUT = 'layout:after-header-layout', - LAYOUT_CELL_MOUNTED = 'layout:cell-mounted', + LAYOUT_CELL_RENDER = 'layout:cell-render', LAYOUT_PAGINATION = 'layout:pagination', LAYOUT_AFTER_REAL_DATA_CELL_RENDER = 'layout:after-real-data-cell-render', LAYOUT_AFTER_RENDER = 'layout:after-render', diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index 9d9736a636..65b1d3ac64 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -370,11 +370,11 @@ export interface InternalFullyHeaderActionIcon extends HeaderActionIcon { isSortIcon?: boolean; } -export type CellCallback = ( +export type CellCallback = ( node: Node, spreadsheet: SpreadSheet, headerConfig: T, -) => S2CellType; +) => K; export type DataCellCallback = (viewMeta: ViewMeta) => DataCell; diff --git a/packages/s2-core/src/common/interface/emitter.ts b/packages/s2-core/src/common/interface/emitter.ts index d6a51ae0c8..9d22472eee 100644 --- a/packages/s2-core/src/common/interface/emitter.ts +++ b/packages/s2-core/src/common/interface/emitter.ts @@ -17,6 +17,7 @@ import type { FilterParam, SortParams, S2Style } from '../../common/interface'; import type { RawData } from '../../common/interface/s2DataConfig'; import type { CopyableList } from '../../utils/export/interface'; import type { Node } from '../../facet/layout/node'; +import type { CornerCell, MergedCell, SeriesNumberCell } from '../../cell'; import type { ResizeInfo } from './resize'; type CanvasEventHandler = (event: CanvasEvent) => void; @@ -94,6 +95,7 @@ export interface EmitterType { [S2Event.ROW_CELL_COLLAPSED__PRIVATE]: (data: RowCellCollapsedParams) => void; [S2Event.ROW_CELL_ALL_COLLAPSED]: (isCollapsed: boolean) => void; [S2Event.ROW_CELL_ALL_COLLAPSED__PRIVATE]: (isCollapsed: boolean) => void; + [S2Event.ROW_CELL_RENDER]: (cell: RowCell) => void; /** ================ Col Cell ================ */ [S2Event.COL_CELL_MOUSE_DOWN]: CanvasEventHandler; @@ -109,6 +111,7 @@ export interface EmitterType { currentHiddenColumnsInfo: HiddenColumnsInfo, hiddenColumnsDetail: HiddenColumnsInfo[], ) => void; + [S2Event.COL_CELL_RENDER]: (cell: ColCell) => void; /** ================ Corner Cell ================ */ [S2Event.CORNER_CELL_MOUSE_MOVE]: CanvasEventHandler; @@ -118,6 +121,7 @@ export interface EmitterType { [S2Event.CORNER_CELL_DOUBLE_CLICK]: CanvasEventHandler; [S2Event.CORNER_CELL_CONTEXT_MENU]: CanvasEventHandler; [S2Event.CORNER_CELL_MOUSE_UP]: CanvasEventHandler; + [S2Event.CORNER_CELL_RENDER]: (cell: CornerCell) => void; /** ================ Merged Cells ================ */ [S2Event.MERGED_CELLS_MOUSE_DOWN]: CanvasEventHandler; @@ -127,6 +131,10 @@ export interface EmitterType { [S2Event.MERGED_CELLS_CLICK]: CanvasEventHandler; [S2Event.MERGED_CELLS_CONTEXT_MENU]: CanvasEventHandler; [S2Event.MERGED_CELLS_DOUBLE_CLICK]: CanvasEventHandler; + [S2Event.MERGED_CELLS_RENDER]: (cell: MergedCell) => void; + + /** ================ SeriesNumber Cell ================ */ + [S2Event.SERIES_NUMBER_CELL_RENDER]: (cell: SeriesNumberCell) => void; /** ================ Layout ================ */ [S2Event.LAYOUT_PAGINATION]: (data: { @@ -141,7 +149,7 @@ export interface EmitterType { remove: [number, number][]; spreadsheet: SpreadSheet; }) => void; - [S2Event.LAYOUT_CELL_MOUNTED]: (cell: S2CellType) => void; + [S2Event.LAYOUT_CELL_RENDER]: (cell: T) => void; [S2Event.LAYOUT_BEFORE_RENDER]: () => void; [S2Event.LAYOUT_AFTER_RENDER]: () => void; [S2Event.LAYOUT_DESTROY]: () => void; diff --git a/packages/s2-core/src/common/interface/s2Options.ts b/packages/s2-core/src/common/interface/s2Options.ts index a238332d3c..8531a8ce5c 100644 --- a/packages/s2-core/src/common/interface/s2Options.ts +++ b/packages/s2-core/src/common/interface/s2Options.ts @@ -1,4 +1,5 @@ import type { CanvasConfig } from '@antv/g'; +import type { CornerCell, RowCell, SeriesNumberCell } from '../../cell'; import type { CellCallback, CornerHeaderCallback, @@ -27,7 +28,7 @@ import type { import type { SpreadSheet } from '../../sheet-type'; import type { CustomSVGIcon, HeaderActionIcon } from './basic'; import type { Conditions } from './condition'; -import type { InteractionOptions } from './interaction'; +import type { InteractionOptions, S2CellType } from './interaction'; import type { S2Style } from './style'; import type { BaseTooltipOperatorMenuOptions, @@ -164,25 +165,25 @@ export interface S2BasicOptions< * 自定义角头单元格 * @see https://s2.antv.antgroup.com/examples/custom/custom-cell#corner-cell */ - cornerCell?: CellCallback; + cornerCell?: CellCallback; /** * 自定义序号单元格 * @see https://s2.antv.antgroup.com/examples/custom/custom-cell#series-number-cell */ - seriesNumberCell?: CellCallback; + seriesNumberCell?: CellCallback; /** * 自定义行头单元格 * @see https://s2.antv.antgroup.com/examples/custom/custom-cell#row-cell */ - rowCell?: CellCallback; + rowCell?: CellCallback; /** * 自定义列头单元格 * @see https://s2.antv.antgroup.com/examples/custom/custom-cell#col-cell */ - colCell?: CellCallback; + colCell?: CellCallback; /** * 自定义合并单元格 diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 97c85a4748..3a7009eade 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -1278,7 +1278,7 @@ export abstract class BaseFacet { addDataCell = (cell: DataCell) => { this.panelScrollGroup?.appendChild(cell); this.spreadsheet.emit(S2Event.DATA_CELL_RENDER, cell); - this.spreadsheet.emit(S2Event.LAYOUT_CELL_MOUNTED, cell); + this.spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); }; realDataCellRender = (scrollX: number, scrollY: number) => { diff --git a/packages/s2-core/src/facet/header/col.ts b/packages/s2-core/src/facet/header/col.ts index e043204c0a..6f5f2c9ab5 100644 --- a/packages/s2-core/src/facet/header/col.ts +++ b/packages/s2-core/src/facet/header/col.ts @@ -4,8 +4,8 @@ import { ColCell } from '../../cell/col-cell'; import { FRONT_GROUND_GROUP_COL_SCROLL_Z_INDEX, KEY_GROUP_COL_SCROLL, + S2Event, } from '../../common/constant'; -import type { S2CellType } from '../../common/interface'; import type { Node } from '../layout/node'; import { translateGroupX } from '../utils'; import { BaseHeader } from './base'; @@ -25,7 +25,7 @@ export class ColHeader extends BaseHeader { this.initScrollGroup(); } - protected getCellInstance(node: Node): S2CellType { + protected getCellInstance(node: Node) { const { spreadsheet } = this.getHeaderConfig(); const { colCell } = spreadsheet.options; @@ -97,7 +97,7 @@ export class ColHeader extends BaseHeader { } protected layout() { - const { nodes } = this.getHeaderConfig(); + const { nodes, spreadsheet } = this.getHeaderConfig(); each(nodes, (node) => { if (this.isColCellInRect(node)) { @@ -108,6 +108,8 @@ export class ColHeader extends BaseHeader { const group = this.getCellGroup(node); group?.appendChild(cell); + spreadsheet.emit(S2Event.COL_CELL_RENDER, cell as ColCell); + spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); } }); } diff --git a/packages/s2-core/src/facet/header/corner.ts b/packages/s2-core/src/facet/header/corner.ts index 0309060a90..0b7cb4f848 100644 --- a/packages/s2-core/src/facet/header/corner.ts +++ b/packages/s2-core/src/facet/header/corner.ts @@ -7,6 +7,7 @@ import type { CornerBBox } from '../bbox/cornerBBox'; import type { PanelBBox } from '../bbox/panelBBox'; import { Node } from '../layout/node'; import { translateGroupX } from '../utils'; +import { S2Event } from '../../common'; import { getDefaultCornerText, getDefaultSeriesNumberText, @@ -22,7 +23,7 @@ export class CornerHeader extends BaseHeader { super(config); } - protected getCellInstance(node: Node): S2CellType { + protected getCellInstance(node: Node): CornerCell { const headerConfig = this.getHeaderConfig(); const { spreadsheet } = headerConfig; const { cornerCell } = spreadsheet.options; @@ -259,6 +260,8 @@ export class CornerHeader extends BaseHeader { const cell = this.getCellInstance(node); this.appendChild(cell); + spreadsheet.emit(S2Event.CORNER_CELL_RENDER, cell); + spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); }); } diff --git a/packages/s2-core/src/facet/header/row.ts b/packages/s2-core/src/facet/header/row.ts index 149bbda705..dafbd5eaf2 100644 --- a/packages/s2-core/src/facet/header/row.ts +++ b/packages/s2-core/src/facet/header/row.ts @@ -1,9 +1,9 @@ import { Rect } from '@antv/g'; import { each, isEmpty } from 'lodash'; import { RowCell } from '../../cell'; -import type { S2CellType } from '../../common/interface'; import type { Node } from '../layout/node'; import { translateGroup } from '../utils'; +import { S2Event } from '../../common'; import { BaseHeader } from './base'; import type { RowHeaderConfig } from './interface'; @@ -15,7 +15,7 @@ export class RowHeader extends BaseHeader { super(config); } - protected getCellInstance(node: Node): S2CellType { + protected getCellInstance(node: Node): RowCell { const headerConfig = this.getHeaderConfig(); const { spreadsheet } = headerConfig; const { rowCell } = spreadsheet.options; @@ -54,7 +54,7 @@ export class RowHeader extends BaseHeader { each(nodes, (node) => { if (rowCellInRect(node) && node.height !== 0) { - let cell: S2CellType | null = null; + let cell: RowCell | null = null; // 首先由外部控制UI展示 if (rowCell) { @@ -70,6 +70,8 @@ export class RowHeader extends BaseHeader { if (cell) { this.appendChild(cell); + spreadsheet.emit(S2Event.ROW_CELL_RENDER, cell); + spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); } } }); diff --git a/packages/s2-core/src/facet/header/series-number.ts b/packages/s2-core/src/facet/header/series-number.ts index cf09e628e6..768ee4a14e 100644 --- a/packages/s2-core/src/facet/header/series-number.ts +++ b/packages/s2-core/src/facet/header/series-number.ts @@ -1,12 +1,12 @@ import { Rect } from '@antv/g'; import { each } from 'lodash'; import { SeriesNumberCell } from '../../cell/series-number-cell'; -import type { S2CellType } from '../../common/interface'; import type { SpreadSheet } from '../../sheet-type/index'; import type { PanelBBox } from '../bbox/panelBBox'; import type { Hierarchy } from '../layout/hierarchy'; import type { Node } from '../layout/node'; import { translateGroup } from '../utils'; +import { S2Event } from '../../common'; import { BaseHeader } from './base'; import type { BaseHeaderConfig } from './interface'; import { getSeriesNumberNodes } from './util'; @@ -16,7 +16,7 @@ export class SeriesNumberHeader extends BaseHeader { super(config); } - protected getCellInstance(node: Node): S2CellType { + protected getCellInstance(node: Node) { const headerConfig = this.getHeaderConfig(); const { spreadsheet } = headerConfig; const { seriesNumberCell } = spreadsheet.options; @@ -78,7 +78,12 @@ export class SeriesNumberHeader extends BaseHeader { } public layout() { - const { nodes, scrollY = 0, viewportHeight } = this.getHeaderConfig(); + const { + nodes, + scrollY = 0, + viewportHeight, + spreadsheet, + } = this.getHeaderConfig(); each(nodes, (node) => { const { y, height: cellHeight } = node; @@ -97,6 +102,8 @@ export class SeriesNumberHeader extends BaseHeader { node.belongsCell = cell; this.appendChild(cell); + spreadsheet.emit(S2Event.SERIES_NUMBER_CELL_RENDER, cell); + spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); }); } diff --git a/packages/s2-core/src/group/panel-scroll-group.ts b/packages/s2-core/src/group/panel-scroll-group.ts index db203ead07..315355e3b7 100644 --- a/packages/s2-core/src/group/panel-scroll-group.ts +++ b/packages/s2-core/src/group/panel-scroll-group.ts @@ -2,6 +2,7 @@ import { Group } from '@antv/g'; import type { GridInfo } from '../common/interface'; import type { GridGroupConstructorParameters } from '../common/interface/group'; import { updateMergedCells } from '../utils/interaction/merge-cell'; +import { S2Event } from '../common'; import type { MergedCell } from './../cell/merged-cell'; import { KEY_GROUP_MERGED_CELLS } from './../common/constant/basic'; import { GridGroup } from './grid-group'; @@ -36,8 +37,10 @@ export class PanelScrollGroup extends GridGroup { this.mergedCellsGroup.toFront(); } - addMergeCell(mergeCell: MergedCell) { - this.mergedCellsGroup?.appendChild(mergeCell); + addMergeCell(mergedCell: MergedCell) { + this.mergedCellsGroup?.appendChild(mergedCell); + this.s2.emit(S2Event.MERGED_CELLS_RENDER, mergedCell); + this.s2.emit(S2Event.LAYOUT_CELL_RENDER, mergedCell); } update(gridInfo: GridInfo) { diff --git a/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts b/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts index cd34d114af..9ab2db6c48 100644 --- a/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts +++ b/packages/s2-react/__tests__/unit/hooks/useEvents-spec.ts @@ -48,8 +48,8 @@ const S2EventCases: Array<{ event: S2Event; name: string }> = [ name: 'onRangeFiltered', }, { - event: S2Event.LAYOUT_CELL_MOUNTED, - name: 'onLayoutCellMounted', + event: S2Event.LAYOUT_CELL_RENDER, + name: 'onLayoutCellRender', }, { event: S2Event.LAYOUT_AFTER_HEADER_LAYOUT, @@ -161,6 +161,7 @@ const S2EventCases: Array<{ event: S2Event; name: string }> = [ }); const cellEventCases = [ + // ============== Row Cell ==================== { event: S2Event.ROW_CELL_HOVER, name: 'onRowCellHover', @@ -185,6 +186,12 @@ const cellEventCases = [ event: S2Event.ROW_CELL_MOUSE_MOVE, name: 'onRowCellMouseMove', }, + { + event: S2Event.ROW_CELL_RENDER, + name: 'onRowCellRender', + }, + + // ============== Col Cell ==================== { event: S2Event.COL_CELL_HOVER, name: 'onColCellHover', @@ -217,6 +224,12 @@ const cellEventCases = [ event: S2Event.COL_CELL_HIDDEN, name: 'onColCellHidden', }, + { + event: S2Event.COL_CELL_RENDER, + name: 'onColCellRender', + }, + + // ============== Data Cell ==================== { event: S2Event.DATA_CELL_HOVER, name: 'onDataCellHover', @@ -253,6 +266,8 @@ const cellEventCases = [ event: S2Event.DATA_CELL_RENDER, name: 'onDataCellRender', }, + + // ============== Corner Cell ==================== { event: S2Event.CORNER_CELL_HOVER, name: 'onCornerCellHover', @@ -277,6 +292,12 @@ const cellEventCases = [ event: S2Event.CORNER_CELL_MOUSE_MOVE, name: 'onCornerCellMouseMove', }, + { + event: S2Event.CORNER_CELL_RENDER, + name: 'onCornerCellRender', + }, + + // ============== Merged Cells ==================== { event: S2Event.MERGED_CELLS_HOVER, name: 'onMergedCellsHover', @@ -301,6 +322,16 @@ const cellEventCases = [ event: S2Event.MERGED_CELLS_MOUSE_MOVE, name: 'onMergedCellsMouseMove', }, + { + event: S2Event.MERGED_CELLS_RENDER, + name: 'onMergedCellsRender', + }, + + // ============== SeriesNumber Cell ==================== + { + event: S2Event.SERIES_NUMBER_CELL_RENDER, + name: 'onSeriesNumberCellRender', + }, ].map((i) => { return { ...i, diff --git a/packages/s2-react/playground/components/ChartSheet.tsx b/packages/s2-react/playground/components/ChartSheet.tsx index a22de24439..8603af3228 100644 --- a/packages/s2-react/playground/components/ChartSheet.tsx +++ b/packages/s2-react/playground/components/ChartSheet.tsx @@ -27,18 +27,7 @@ const options: SheetComponentOptions = { multiSelection: true, overscrollBehavior: 'none', }, - style: { - colCell: { - hideValue: true, - }, - rowCell: { - width: 100, - }, - dataCell: { - width: 500, - height: 400, - }, - }, + style: {}, }; const onDataCellRender: SheetComponentsProps['onDataCellRender'] = (cell) => { 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 f4af23b0b1..ad7d9b1559 100644 --- a/packages/s2-react/src/components/sheets/chart-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/chart-sheet/index.tsx @@ -15,6 +15,18 @@ export const ChartSheet: React.FC = React.memo( interaction: { hoverFocus: false, }, + style: { + colCell: { + hideValue: true, + }, + rowCell: { + width: 100, + }, + dataCell: { + width: 400, + height: 400, + }, + }, // TODO: 刷选时获取不到正确的 tooltip 配置 tooltip: { // cornerCell: { @@ -28,9 +40,6 @@ export const ChartSheet: React.FC = React.memo( // }, // enable: false, enable: true, - dataCell: { - enable: false, - }, }, }; diff --git a/packages/s2-react/src/hooks/useEvents.ts b/packages/s2-react/src/hooks/useEvents.ts index 60af60c9a5..3232e3f75a 100644 --- a/packages/s2-react/src/hooks/useEvents.ts +++ b/packages/s2-react/src/hooks/useEvents.ts @@ -63,6 +63,7 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { useS2Event(S2Event.ROW_CELL_SCROLL, props.onRowCellScroll, s2); useS2Event(S2Event.ROW_CELL_COLLAPSED, props.onRowCellCollapsed, s2); useS2Event(S2Event.ROW_CELL_ALL_COLLAPSED, props.onRowCellAllCollapsed, s2); + useS2Event(S2Event.ROW_CELL_RENDER, props.onRowCellRender, s2); // ============== Col Cell ==================== useCellEvent(S2Event.COL_CELL_HOVER, props.onColCellHover, s2); @@ -74,6 +75,7 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { useCellEvent(S2Event.COL_CELL_MOUSE_MOVE, props.onColCellMouseMove, s2); useS2Event(S2Event.COL_CELL_EXPANDED, props.onColCellExpanded, s2); useS2Event(S2Event.COL_CELL_HIDDEN, props.onColCellHidden, s2); + useS2Event(S2Event.COL_CELL_RENDER, props.onColCellRender, s2); // ============== Data Cell ==================== useCellEvent(S2Event.DATA_CELL_HOVER, props.onDataCellHover, s2); @@ -107,6 +109,7 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { useCellEvent(S2Event.CORNER_CELL_MOUSE_DOWN, props.onCornerCellMouseDown, s2); useCellEvent(S2Event.CORNER_CELL_MOUSE_UP, props.onCornerCellMouseUp, s2); useCellEvent(S2Event.CORNER_CELL_MOUSE_MOVE, props.onCornerCellMouseMove, s2); + useS2Event(S2Event.CORNER_CELL_RENDER, props.onCornerCellRender, s2); // ============== Merged Cells ==================== useCellEvent(S2Event.MERGED_CELLS_HOVER, props.onMergedCellsHover, s2); @@ -121,7 +124,6 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { props.onMergedCellsContextMenu, s2, ); - useCellEvent( S2Event.MERGED_CELLS_MOUSE_DOWN, props.onMergedCellsMouseDown, @@ -133,6 +135,14 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { props.onMergedCellsMouseMove, s2, ); + useS2Event(S2Event.MERGED_CELLS_RENDER, props.onMergedCellsRender, s2); + + /** ================ SeriesNumber Cell ================ */ + useS2Event( + S2Event.SERIES_NUMBER_CELL_RENDER, + props.onSeriesNumberCellRender, + s2, + ); // ============== Sort ==================== useS2Event(S2Event.RANGE_SORT, props.onRangeSort, s2); @@ -149,7 +159,7 @@ export function useEvents(props: SheetComponentsProps, s2: SpreadSheet) { s2, ); useS2Event(S2Event.LAYOUT_PAGINATION, props.onLayoutPagination, s2); - useS2Event(S2Event.LAYOUT_CELL_MOUNTED, props.onLayoutCellMounted, s2); + useS2Event(S2Event.LAYOUT_CELL_RENDER, props.onLayoutCellRender, s2); useS2Event(S2Event.LAYOUT_BEFORE_RENDER, props.onBeforeRender, s2); useS2Event(S2Event.LAYOUT_AFTER_RENDER, props.onAfterRender, s2); useS2Event(S2Event.LAYOUT_DESTROY, props.onDestroy, s2, true); diff --git a/packages/s2-shared/src/interface.ts b/packages/s2-shared/src/interface.ts index 42c65aa1bb..a5c343847d 100644 --- a/packages/s2-shared/src/interface.ts +++ b/packages/s2-shared/src/interface.ts @@ -1,11 +1,14 @@ import type { BaseTooltipOperatorMenuOptions, CellScrollPosition, + ColCell, + CornerCell, DataCell, GEvent, HeaderActionIcon, HiddenColumnsInfo, LayoutResult, + MergedCell, Node, Pagination, RawData, @@ -17,6 +20,7 @@ import type { S2MountContainer, S2Options, S2RenderOptions, + SeriesNumberCell, SortParams, SpreadSheet, TargetCellInfo, @@ -91,6 +95,7 @@ export interface BaseSheetComponentProps< onRowCellCollapsed?: (params: RowCellCollapsedParams) => void; onRowCellAllCollapsed?: (isCollapsed: boolean) => void; onRowCellScroll?: (position: CellScrollPosition) => void; + onRowCellRender?: (cell: ColCell) => void; // ============== Col Cell ==================== onColCellHover?: (data: TargetCellInfo) => void; @@ -106,6 +111,8 @@ export interface BaseSheetComponentProps< hiddenColumnsDetail: HiddenColumnsInfo[]; }) => void; + onColCellRender?: (cell: ColCell) => void; + // ============== Data Cell ==================== onDataCellHover?: (data: TargetCellInfo) => void; onDataCellClick?: (data: TargetCellInfo) => void; @@ -116,7 +123,7 @@ export interface BaseSheetComponentProps< onDataCellMouseMove?: (data: TargetCellInfo) => void; onDataCellBrushSelection?: (brushRangeDataCells: DataCell[]) => void; onDataCellSelectMove?: (metaList: ViewMetaData[]) => void; - onDataCellRender?: (dataCell: DataCell) => void; + onDataCellRender?: (cell: DataCell) => void; // ============== Corner Cell ==================== onCornerCellHover?: (data: TargetCellInfo) => void; @@ -126,6 +133,7 @@ export interface BaseSheetComponentProps< onCornerCellMouseDown?: (data: TargetCellInfo) => void; onCornerCellMouseUp?: (data: TargetCellInfo) => void; onCornerCellMouseMove?: (data: TargetCellInfo) => void; + onCornerCellRender?: (cell: CornerCell) => void; // ============== Merged Cells ==================== onMergedCellsHover?: (data: TargetCellInfo) => void; @@ -135,6 +143,10 @@ export interface BaseSheetComponentProps< onMergedCellsMouseDown?: (data: TargetCellInfo) => void; onMergedCellsMouseUp?: (data: TargetCellInfo) => void; onMergedCellsMouseMove?: (data: TargetCellInfo) => void; + onMergedCellsRender?: (cell: MergedCell) => void; + + /** ================ SeriesNumber Cell ================ */ + onSeriesNumberCellRender?: (cell: SeriesNumberCell) => void; // ============== Sort ==================== onRangeSort?: (params: SortParams) => void; @@ -150,7 +162,7 @@ export interface BaseSheetComponentProps< // ============== Layout ==================== onLayoutAfterHeaderLayout?: (layoutResult: LayoutResult) => void; onLayoutPagination?: (data: LayoutPaginationParams) => void; - onLayoutCellMounted?: (cell: S2CellType) => void; + onLayoutCellRender?: (cell: T) => void; onBeforeRender?: () => void; onAfterRender?: () => void; onMounted?: (spreadsheet: SpreadSheet) => void; diff --git a/s2-site/docs/api/components/sheet-component.en.md b/s2-site/docs/api/components/sheet-component.en.md index 8cd7b6fe08..b3e33898e4 100644 --- a/s2-site/docs/api/components/sheet-component.en.md +++ b/s2-site/docs/api/components/sheet-component.en.md @@ -65,7 +65,7 @@ Function description: The props parameter of the React SheetComponent component | onRangeSorted | A callback event is triggered when the sorting in the group ends (for now, only pivot tables are supported) | (event: CanvasEvent ) => void; | | | | onRangeFilter | Trigger callback event when filtering | (data: { filterKey: string; filteredValues: string[] } ) => void; | | | | onRangeFiltered | Trigger callback event after filtering | (data: DataType[] ) => void; | | | -| onLayoutCellMounted | The header layout cell mount completed event | cell: S2CellType | | | +| onLayoutCellRender | The header layout cell mount completed event | cell: S2CellType | | | | onLayoutAfterHeaderLayout | Header layout structure preparation completion event | (layoutResult: [LayoutResult](/zh/docs/api/general/S2Options/#layoutresult) ) => void; | | | | onLayoutPagination | pagination event | ({ pageSize: number; pageCount: number; total: number; current: number;} ) => void; | | | | onLayoutCellScroll | Cell scroll event (**Deprecated, please use `onScroll` instead**) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | @@ -178,7 +178,7 @@ Function description: The props of the Vue SheetComponent component, such as ` void; | | | | onRangeFilter | Trigger callback event when filtering | (data: { filterKey: string; filteredValues: string[] } ) => void; | | | | onRangeFiltered | Trigger callback event after filtering | (data: DataType[] ) => void; | | | -| onLayoutCellMounted | The header layout cell mount completed event | cell: S2CellType | | | +| onLayoutCellRender | The header layout cell mount completed event | cell: S2CellType | | | | onLayoutAfterHeaderLayout | Header layout structure preparation completion event | (layoutResult: [LayoutResult](/zh/docs/api/general/S2Options/#layoutresult) ) => void; | | | | onLayoutPagination | pagination event | ({ pageSize: number; pageCount: number; total: number; current: number;} ) => void; | | | | onLayoutCellScroll | Cell scroll event (**Deprecated, please use `onScroll` instead**) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | diff --git a/s2-site/docs/api/components/sheet-component.zh.md b/s2-site/docs/api/components/sheet-component.zh.md index cd217852e9..c7e1ff872e 100644 --- a/s2-site/docs/api/components/sheet-component.zh.md +++ b/s2-site/docs/api/components/sheet-component.zh.md @@ -65,7 +65,7 @@ order: 0 | onRangeSorted | 组内排序结束触发回调事件(暂只支持透视表) | (event: CanvasEvent ) => void; | | | | onRangeFilter | 筛选时触发回调事件 | (data: { filterKey: string; filteredValues: string[] } ) => void; | | | | onRangeFiltered | 筛选结束触发回调事件 | (data: DataType[] ) => void; | | | -| onLayoutCellMounted | 表头布局单元格挂载完成事件 | cell: S2CellType | | | +| onLayoutCellRender | 单个单元格布局渲染完成事件 | cell: [S2CellType](/docs/api/basic-class/base-cell) | | | | onLayoutAfterHeaderLayout | 表头布局结构准备完成事件 | (layoutResult: [LayoutResult](/zh/docs/api/general/S2Options/#layoutresult) ) => void; | | | | onLayoutPagination | 分页事件 | ({ pageSize: number; pageCount: number; total: number; current: number;} ) => void; | | | | onLayoutCellScroll | 单元格滚动事件 (**已废弃,请使用 `onScroll` 代替**) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | @@ -94,7 +94,7 @@ order: 0 | onMouseUp | 表格鼠标松开事件 | (event: CanvasEvent) => void | | | | onSelected | 单元格选中事件 | (cells: ( [Cell](/docs/api/basic-class/base-cell)[] ) => void | | | | onReset | 交互状态重置事件 | (event: KeyboardEvent) => void | | | -| onLinkFieldJump | 链接字段跳转事件 (cellData: @antv/s2 1.37.0 新增) | (data: { key: string; cellData: [Node](/docs/api/basic-class/node); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | +| onLinkFieldJump | 链接字段跳转事件 (cellData: @antv/s2 1.37.0 新增) | (data: { key: string; cellData: [Node](/docs/api/basic-class/node); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | | onScroll | 单元格滚动事件 (含行头和数值单元格) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | | onColCellBrushSelection | 批量选中刷选范围内的列头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | (cells: [ColCell](/docs/api/basic-class/base-cell)[]) => void; | | | | onRowCellBrushSelection | 批量选中刷选范围内的行头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | (cells: [RowCell](/docs/api/basic-class/base-cell)[]) => void; | | | @@ -214,7 +214,7 @@ type SheetComponentOptions = S2Options< | mouseUp | 表格鼠标松开事件 | (event: CanvasEvent) => void | | | | selected | 单元格选中事件 | ( cells: ([Cell](/docs/api/basic-class/base-cell)[] ) => void | | | | reset | 交互状态重置事件 | (event: KeyboardEvent) => void | | | -| linkFieldJump | 链接字段跳转事件 (cellData: @antv/s2 1.37.0 新增) | (data: { key: string; cellData: [Node](/docs/api/basic-class/node); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | +| linkFieldJump | 链接字段跳转事件 (cellData: @antv/s2 1.37.0 新增) | (data: { key: string; cellData: [Node](/docs/api/basic-class/node); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | | scroll | 单元格滚动事件 (含行头和数值单元格) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | | colCellBrushSelection | 批量选中刷选范围内的列头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | (cells: ColCell[]) => void; | | | | rowCellBrushSelection | 批量选中刷选范围内的行头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | (cells: RowCell[]) => void; | | | diff --git a/s2-site/docs/api/general/S2Event.zh.md b/s2-site/docs/api/general/S2Event.zh.md index 8d3184122d..7cb09b1a4c 100644 --- a/s2-site/docs/api/general/S2Event.zh.md +++ b/s2-site/docs/api/general/S2Event.zh.md @@ -17,7 +17,7 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { }); ``` -### 行头 +### 行头单元格 (RowCell) | 名称 | 事件名 | 描述 | | ----------- | ------------------------------------ | ------------------------- | @@ -32,8 +32,9 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { | 鼠标松开 | `S2Event.ROW_CELL_MOUSE_UP` | 行头单元格鼠标松开 | | 滚动 | `S2Event.ROW_CELL_SCROLL` | 行头单元格滚动 | | 行头刷选 | `S2Event.ROW_CELL_BRUSH_SELECTION` | 批量选中刷选范围内的行头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | +| 单元格渲染 | `S2Event.ROW_CELL_RENDER` | 行头单元格布局渲染完成事件 | -### 列头 +### 列头单元格 (ColCell) | 名称 | 事件名 | 描述 | | ------- | ------------------------------ | ----------------- | @@ -45,8 +46,9 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { | 鼠标移动 | `S2Event.COL_CELL_MOUSE_MOVE` | 列头单元格鼠标移动 | | 鼠标松开 | `S2Event.COL_CELL_MOUSE_UP` | 列头单元格鼠标松开 | | 列头刷选 | `S2Event.COL_CELL_BRUSH_SELECTION` | 批量选中刷选范围内的列头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | +| 单元格渲染 | `S2Event.COL_CELL_RENDER` | 列头单元格布局渲染完成事件 | -### 数值单元格 +### 数值单元格 (DataCell) | 名称 | 事件名 | 描述 | | ------------- | ----------------------------------- | -------------------------------------- | @@ -58,8 +60,9 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { | 鼠标移动 | `S2Event.DATA_CELL_MOUSE_MOVE` | 数值单元格鼠标移动 | | 鼠标松开 | `S2Event.DATA_CELL_MOUSE_UP` | 数值单元格鼠标松开 | | 刷选 | `S2Event.DATA_CELL_BRUSH_SELECTION` | 数值单元格刷选 | +| 单元格渲染 | `S2Event.DATA_CELL_RENDER` | 数值单元格布局渲染完成事件 | -### 角头 +### 角头单元格 (CornerCell) | 名称 | 事件名 | 描述 | | ------- | --------------------------------- | ----------------- | @@ -70,6 +73,26 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { | 鼠标按下 | `S2Event.CORNER_CELL_MOUSE_DOWN` | 角头单元格鼠标按下 | | 鼠标移动 | `S2Event.CORNER_CELL_MOUSE_MOVE` | 角头单元格鼠标移动 | | 鼠标松开 | `S2Event.CORNER_CELL_MOUSE_UP` | 角头单元格鼠标松开 | +| 单元格渲染 | `S2Event.CORNER_CELL_RENDER` | 角头单元格布局渲染完成事件 | + +### 合并单元格 (MergedCells) + +| 名称 | 事件名 | 描述 | +| ------- | --------------------------------- | ----------------- | +| 点击 | `S2Event.CORNER_CELL_CLICK` | 合并单元格点击 | +| 双击 | `S2Event.CORNER_CELL_DOUBLE_CLICK` | 合并单元格双击 | +| 右键 | `S2Event.CORNER_CELL_CONTEXT_MENU` | 合并单元格右键 | +| 悬停 | `S2Event.CORNER_CELL_HOVER` | 合并单元格悬停 | +| 鼠标按下 | `S2Event.CORNER_CELL_MOUSE_DOWN` | 合并单元格鼠标按下 | +| 鼠标移动 | `S2Event.CORNER_CELL_MOUSE_MOVE` | 合并单元格鼠标移动 | +| 鼠标松开 | `S2Event.CORNER_CELL_MOUSE_UP` | 合并单元格鼠标松开 | +| 单元格渲染 | `S2Event.MERGED_CELLS_RENDER` | 合并单元格布局渲染完成事件 | + +### 序号单元格 (SeriesNumberCell) + +| 名称 | 事件名 | 描述 | +| ------- | --------------------------------- | ----------------- | +| 单元格渲染 | `S2Event.SERIES_NUMBER_CELL_RENDER` | 序号单元格布局渲染完成事件 | ### 宽高拖拽调整 @@ -98,6 +121,7 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { | 开始渲染 | `S2Event.LAYOUT_BEFORE_RENDER` | 开始 render 前的事件,即 `s2.render()` | | 渲染完成 | `S2Event.LAYOUT_AFTER_RENDER` | render 完成的事件,即 `s2.render()` | | 表格销毁 | `S2Event.LAYOUT_DESTROY` | 表格销毁后或 调用 `s2.destroy()` 触发 | +| 单元格渲染 | `S2Event.LAYOUT_CELL_RENDER` | 单个单元格布局渲染完成事件 | ### 全局 From 9c8c2d7760ce3c1ba19e00c309d0a6dae47b9d3f Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Thu, 30 Nov 2023 15:50:07 +0800 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=E5=85=BC=E5=AE=B9=E6=9A=97?= =?UTF-8?q?=E9=BB=91=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cell/__snapshots__/data-cell-spec.ts.snap | 57 ++++++++++ .../__tests__/unit/cell/data-cell-spec.ts | 53 ++++++++- packages/s2-core/src/cell/data-cell.ts | 14 ++- packages/s2-core/src/facet/base-facet.ts | 7 +- .../s2-core/src/sheet-type/spread-sheet.ts | 2 - packages/s2-core/src/utils/tooltip.ts | 8 +- .../sheets/chart-sheet/index-spec.tsx | 105 ++++++++++++++++++ .../playground/components/ChartSheet.tsx | 13 ++- .../playground/components/LinkGroup.tsx | 38 ++++++- .../playground/context/playground.context.ts | 4 +- packages/s2-react/playground/index.tsx | 1 + packages/s2-react/src/hooks/useEvents.ts | 4 +- 12 files changed, 285 insertions(+), 21 deletions(-) create mode 100644 packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap create mode 100644 packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx diff --git a/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap b/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap new file mode 100644 index 0000000000..6e7840e4aa --- /dev/null +++ b/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Data Cell Tests Data Cell Formatter & Method Tests should get empty chart data 1`] = ` +Object { + "autoFit": true, + "height": 83, + "theme": Object { + "type": "light", + }, + "width": 83, + "x": NaN, + "y": NaN, +} +`; + +exports[`Data Cell Tests Data Cell Formatter & Method Tests should get multiple chart data 1`] = ` +Object { + "autoFit": true, + "data": Array [ + Object { + "genre": "Sports", + "sold": 275, + }, + ], + "encode": Object { + "color": "genre", + "x": "genre", + "y": "sold", + }, + "type": "interval", +} +`; + +exports[`Data Cell Tests Data Cell Formatter & Method Tests should get multiple chart data 2`] = ` +Object { + "autoFit": true, + "data": Array [ + Object { + "genre": "Sports", + "sold": 275, + }, + ], + "encode": Object { + "color": "genre", + "x": "genre", + "y": "sold", + }, + "height": 83, + "theme": Object { + "type": "dark", + }, + "type": "interval", + "width": 83, + "x": 8, + "y": 208, +} +`; diff --git a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts index e3a531b48d..6629357e02 100644 --- a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts +++ b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts @@ -99,7 +99,7 @@ describe('Data Cell Tests', () => { ); }); - describe('Data Cell Formatter Tests', () => { + describe('Data Cell Formatter & Method Tests', () => { beforeEach(() => { const container = document.createElement('div'); @@ -137,6 +137,49 @@ describe('Data Cell Tests', () => { expect(dataCell.getTextShape().attr('fill')).toEqual(DEFAULT_FONT_COLOR); }); + + test('should get empty chart data and default options', () => { + const dataCell = new DataCell(meta, s2); + + expect(dataCell.isMultiData()).toBeFalsy(); + expect(dataCell.getRenderChartData()).toBeUndefined(); + expect(dataCell.getRenderChartOptions()).toMatchSnapshot(); + }); + + test('should get multiple chart data and all options', () => { + s2.setThemeCfg({ name: 'dark' }); + + const multipleMeta = { + fieldValue: { + values: { + type: 'interval', + autoFit: true, + data: [ + { + genre: 'Sports', + sold: 275, + }, + ], + encode: { + x: 'genre', + y: 'sold', + color: 'genre', + }, + }, + }, + value: 'value', + width: 100, + height: 100, + x: 0, + y: 200, + } as unknown as ViewMeta; + + const dataCell = new DataCell(multipleMeta, s2); + + expect(dataCell.isMultiData()).toBeTruthy(); + expect(dataCell.getRenderChartData()).toMatchSnapshot(); + expect(dataCell.getRenderChartOptions()).toMatchSnapshot(); + }); }); describe('Data Cell Shape Tests', () => { @@ -254,6 +297,7 @@ describe('Data Cell Tests', () => { expect(dataCell?.getTextShape().parsedStyle.fill).toBeColor('#D03050'); }); }); + describe('Condition Tests', () => { const s2 = createPivotSheet({ conditions: { @@ -530,8 +574,6 @@ describe('Data Cell Tests', () => { }); describe('Data Cell Interaction', () => { - // let s2: SpreadSheet; - beforeEach(async () => { s2 = createPivotSheet({ showSeriesNumber: true, @@ -541,6 +583,11 @@ describe('Data Cell Tests', () => { }); await s2.render(); }); + + afterEach(() => { + s2.destroy(); + }); + const emitEvent = (type: S2Event, event: Partial) => { s2.emit(type, { originalEvent: event, diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 55479718b7..089928a5fa 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -33,6 +33,7 @@ import type { ViewMetaIndexType, MultiData, BaseChartData, + ThemeName, } from '../common/interface'; import { getHorizontalTextIconPosition, @@ -85,11 +86,22 @@ export class DataCell extends BaseCell { public getRenderChartOptions() { const chartData = this.getRenderChartData(); const cellArea = this.getBBoxByType(CellClipBox.CONTENT_BOX); + const themeName = this.spreadsheet.getThemeName(); + + // 兼容 G2 主题: S2 和 G2 的主题名转换 + // https://g2.antv.antgroup.com/manual/core/theme + const g2ThemeType: Record = { + default: 'light', + colorful: 'light', + gray: 'light', + dark: 'dark', + }; return { + autoFit: true, + theme: { type: g2ThemeType[themeName] }, ...cellArea, ...chartData, - autoFit: true, }; } diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 3a7009eade..188b96605b 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -1277,8 +1277,11 @@ export abstract class BaseFacet { addDataCell = (cell: DataCell) => { this.panelScrollGroup?.appendChild(cell); - this.spreadsheet.emit(S2Event.DATA_CELL_RENDER, cell); - this.spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); + + setTimeout(() => { + this.spreadsheet.emit(S2Event.DATA_CELL_RENDER, cell); + this.spreadsheet.emit(S2Event.LAYOUT_CELL_RENDER, cell); + }, 50); }; realDataCellRender = (scrollX: number, scrollY: number) => { diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 472d06f9db..6aba27d534 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -154,8 +154,6 @@ export abstract class SpreadSheet extends EE { preventRender?: boolean, ): void; - // public abstract handleGroupSort(event: CanvasEvent, meta: Node): void; - public abstract groupSortByMethod(sortMethod: SortMethod, meta: Node): void; public constructor( diff --git a/packages/s2-core/src/utils/tooltip.ts b/packages/s2-core/src/utils/tooltip.ts index 473bbdb19d..ace09ccb27 100644 --- a/packages/s2-core/src/utils/tooltip.ts +++ b/packages/s2-core/src/utils/tooltip.ts @@ -211,12 +211,12 @@ export const getListItem = ( const formatter = getFieldFormatter(spreadsheet, field); - // 暂时对 object 类型 data 不作处理,上层通过自定义 tooltip 的方式去自行定制 - let dataValue = getFieldValueOfViewMetaData(data, field); + // 非数值类型的 data 不展示 (趋势分析表/迷你图/G2 图表),上层通过自定义 tooltip 的方式去自行定制 + const dataValue = getFieldValueOfViewMetaData(data, field); + const displayDataValue = isObject(dataValue) ? null : dataValue; - dataValue = isObject(dataValue) ? JSON.stringify(dataValue) : dataValue; const value = formatter( - valueField || dataValue, + valueField || displayDataValue, useCompleteDataForFormatter ? data : undefined, ); diff --git a/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx b/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx new file mode 100644 index 0000000000..2ab4740644 --- /dev/null +++ b/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx @@ -0,0 +1,105 @@ +/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable max-classes-per-file */ +import { renderToMountedElement, stdlib } from '@antv/g2'; +import { DataCell, SpreadSheet, customMerge } from '@antv/s2'; +import { waitFor } from '@testing-library/react'; +import React from 'react'; +import type { Root } from 'react-dom/client'; +import { ChartDataConfig } from '../../../../data/data-g2-chart'; +import { renderComponent, sleep } from '../../../../util/helpers'; +import { + SheetComponent, + type SheetComponentOptions, + type SheetComponentsProps, +} from '@/components'; + +describe(' Tests', () => { + let s2: SpreadSheet; + let unmount: Root['unmount']; + + afterEach(() => { + unmount?.(); + }); + + const renderChartSheet = ( + options: SheetComponentOptions | null, + props?: Partial, + ) => { + unmount = renderComponent( + { + s2 = instance; + }} + {...props} + />, + ); + }; + + const onDataCellRender = jest.fn((cell: DataCell) => { + const chartOptions = cell.getRenderChartOptions(); + + // https://g2.antv.antgroup.com/manual/extra-topics/bundle#g2stdlib + renderToMountedElement(chartOptions, { + group: cell, + library: stdlib(), + }); + }); + + test('should default render empty text shape', async () => { + renderChartSheet(null); + + await waitFor(() => { + s2.facet.getDataCells().forEach((cell) => { + expect(cell.getActualText()).toBeUndefined(); + expect(cell.getTextShapes()).toBeEmpty(); + }); + }); + }); + + test('should trigger date cell render event', async () => { + renderChartSheet(null, { + onDataCellRender, + }); + + await waitFor(() => { + expect(onDataCellRender).toHaveBeenCalledTimes(4); + + s2.facet.getDataCells().forEach((cell) => { + expect(cell.getActualText()).toBeUndefined(); + expect(cell.getTextShapes()).toBeEmpty(); + }); + }); + }); + + test('should not throw g2 error after render chart', async () => { + const errorSpy = jest + .spyOn(console, 'error') + .mockImplementationOnce(() => {}); + + renderChartSheet(null, { + onDataCellRender, + }); + + await waitFor(async () => { + s2.updateScrollOffset({ offsetY: { value: 800, animate: true } }); + + await sleep(1000); + + expect(errorSpy).not.toHaveBeenCalledWith( + `Uncaught (in promise) TypeError: Cannot read property 'defaultView' of null`, + ); + expect(errorSpy).not.toHaveBeenCalledWith( + `Uncaught (in promise) TypeError: Cannot read properties of null (reading 'createElement')`, + ); + }); + }); +}); diff --git a/packages/s2-react/playground/components/ChartSheet.tsx b/packages/s2-react/playground/components/ChartSheet.tsx index 8603af3228..81ad024054 100644 --- a/packages/s2-react/playground/components/ChartSheet.tsx +++ b/packages/s2-react/playground/components/ChartSheet.tsx @@ -1,17 +1,17 @@ /* eslint-disable import/no-extraneous-dependencies */ -import { SpreadSheet } from '@antv/s2'; import { renderToMountedElement, stdlib } from '@antv/g2'; +import { SpreadSheet } from '@antv/s2'; import React from 'react'; +import { ChartDataConfig } from '../../__tests__/data/data-g2-chart'; import { SheetComponent, type SheetComponentOptions, type SheetComponentsProps, } from '../../src/components'; import { usePlaygroundContext } from '../context/playground.context'; -import { ChartDataConfig } from '../../__tests__/data/data-g2-chart'; const options: SheetComponentOptions = { - height: 1000, + height: 900, interaction: { enableCopy: true, brushSelection: { @@ -53,8 +53,13 @@ export const ChartSheet: React.FC< dataCfg={ChartDataConfig} options={options} ref={ref} - adaptive + adaptive={true} onDataCellRender={onDataCellRender} + header={{ + title: 'S2 & G2', + description: '单元格内绘制 G2 图表', + exportCfg: { open: true }, + }} /> ); }); diff --git a/packages/s2-react/playground/components/LinkGroup.tsx b/packages/s2-react/playground/components/LinkGroup.tsx index bd552e404c..4bb4a023a3 100644 --- a/packages/s2-react/playground/components/LinkGroup.tsx +++ b/packages/s2-react/playground/components/LinkGroup.tsx @@ -1,20 +1,38 @@ import { CloudUploadOutlined, - CustomerServiceOutlined, FileSearchOutlined, GithubOutlined, PullRequestOutlined, YuqueOutlined, + FullscreenOutlined, + BgColorsOutlined, + MoreOutlined, + FullscreenExitOutlined, } from '@ant-design/icons'; import { FloatButton } from 'antd'; import React from 'react'; +import { usePlaygroundContext } from '../context/playground.context'; export const LinkGroup = () => { + const { themeCfg, setThemeCfg } = usePlaygroundContext(); + const [fullScreen, setFullScreen] = React.useState(false); + + const toggleFullScreen = () => { + if (!document.fullscreenElement) { + document.documentElement.requestFullscreen(); + setFullScreen(true); + } else if (document.exitFullscreen) { + document.exitFullscreen(); + setFullScreen(false); + } + }; + return ( } + icon={} > { href="https://s2.antv.antgroup.com/manual/contribution" target="_blank" /> + : } + tooltip={fullScreen ? '退出全屏' : '全屏'} + onClick={() => { + toggleFullScreen(); + }} + /> + } + tooltip={`切换主题 (${themeCfg?.name})`} + onClick={() => { + setThemeCfg?.({ + name: themeCfg?.name !== 'dark' ? 'dark' : 'default', + }); + }} + /> ); }; diff --git a/packages/s2-react/playground/context/playground.context.ts b/packages/s2-react/playground/context/playground.context.ts index 8edc02067d..71aad9e991 100644 --- a/packages/s2-react/playground/context/playground.context.ts +++ b/packages/s2-react/playground/context/playground.context.ts @@ -1,15 +1,17 @@ import { noop } from 'lodash'; import React from 'react'; -import type { SpreadSheet } from '@antv/s2'; +import type { SpreadSheet, ThemeCfg } from '@antv/s2'; import type { SheetComponentsProps } from '../../src'; export const PlaygroundContext = React.createContext< Partial & { ref?: React.MutableRefObject; + setThemeCfg: (theme: ThemeCfg) => void; } >({ onMounted: noop, themeCfg: { name: 'default' }, + setThemeCfg: () => {}, }); export function usePlaygroundContext() { diff --git a/packages/s2-react/playground/index.tsx b/packages/s2-react/playground/index.tsx index 08f94ff9b7..519e83e4f7 100644 --- a/packages/s2-react/playground/index.tsx +++ b/packages/s2-react/playground/index.tsx @@ -360,6 +360,7 @@ function MainLayout() { onMounted: onSheetMounted, onDestroy: onSheetDestroy, themeCfg, + setThemeCfg, }} >
diff --git a/packages/s2-react/src/hooks/useEvents.ts b/packages/s2-react/src/hooks/useEvents.ts index 3232e3f75a..efa5e8056a 100644 --- a/packages/s2-react/src/hooks/useEvents.ts +++ b/packages/s2-react/src/hooks/useEvents.ts @@ -15,7 +15,7 @@ export const useCellEvent = ( handler: ((data: TargetCellInfo) => void) | undefined, s2: SpreadSheet, ) => { - React.useEffect(() => { + React.useLayoutEffect(() => { const handlerFn = (event: GEvent) => { handler?.(getBaseCellData(event)); }; @@ -34,7 +34,7 @@ export const useS2Event = ( s2: SpreadSheet, emitBeforeOff = false, ) => { - React.useEffect(() => { + React.useLayoutEffect(() => { const handlerFn: EmitterType[S2Event] = (...args: any[]) => { handler?.(...args); }; From 23d15ff61f56477595229386149f5bbff0cb5bd6 Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Thu, 30 Nov 2023 17:12:22 +0800 Subject: [PATCH 04/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=B7?= =?UTF-8?q?=E9=80=89=E6=97=B6=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=9A=84=20tooltip=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cell/__snapshots__/data-cell-spec.ts.snap | 6 +-- .../__tests__/unit/cell/data-cell-spec.ts | 15 ++++++ .../__tests__/unit/utils/tooltip-spec.ts | 38 ++++++++++++- packages/s2-core/src/cell/data-cell.ts | 46 ++++++++++------ .../utils/export/copy/pivot-data-cell-copy.ts | 20 ++++--- packages/s2-core/src/utils/tooltip.ts | 9 +++- .../sheets/chart-sheet/index-spec.tsx | 25 +-------- .../playground/components/ChartSheet.tsx | 1 + packages/s2-react/playground/config.tsx | 2 + packages/s2-react/playground/index.tsx | 54 +++++++++++++++++++ .../components/sheets/chart-sheet/index.tsx | 11 ---- 11 files changed, 163 insertions(+), 64 deletions(-) diff --git a/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap b/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap index 6e7840e4aa..1c3989532b 100644 --- a/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap +++ b/packages/s2-core/__tests__/unit/cell/__snapshots__/data-cell-spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Data Cell Tests Data Cell Formatter & Method Tests should get empty chart data 1`] = ` +exports[`Data Cell Tests Data Cell Formatter & Method Tests should get empty chart data and default options 1`] = ` Object { "autoFit": true, "height": 83, @@ -13,7 +13,7 @@ Object { } `; -exports[`Data Cell Tests Data Cell Formatter & Method Tests should get multiple chart data 1`] = ` +exports[`Data Cell Tests Data Cell Formatter & Method Tests should get multiple chart data and all options 1`] = ` Object { "autoFit": true, "data": Array [ @@ -31,7 +31,7 @@ Object { } `; -exports[`Data Cell Tests Data Cell Formatter & Method Tests should get multiple chart data 2`] = ` +exports[`Data Cell Tests Data Cell Formatter & Method Tests should get multiple chart data and all options 2`] = ` Object { "autoFit": true, "data": Array [ diff --git a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts index 6629357e02..096ccf74bf 100644 --- a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts +++ b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts @@ -142,10 +142,24 @@ describe('Data Cell Tests', () => { const dataCell = new DataCell(meta, s2); expect(dataCell.isMultiData()).toBeFalsy(); + expect(dataCell.isChartData()).toBeFalsy(); expect(dataCell.getRenderChartData()).toBeUndefined(); expect(dataCell.getRenderChartOptions()).toMatchSnapshot(); }); + test('should get correctly cell data status', () => { + const multipleMeta = { + fieldValue: { + values: [1, 2, 3], + }, + } as unknown as ViewMeta; + + const dataCell = new DataCell(multipleMeta, s2); + + expect(dataCell.isMultiData()).toBeTruthy(); + expect(dataCell.isChartData()).toBeFalsy(); + }); + test('should get multiple chart data and all options', () => { s2.setThemeCfg({ name: 'dark' }); @@ -177,6 +191,7 @@ describe('Data Cell Tests', () => { const dataCell = new DataCell(multipleMeta, s2); expect(dataCell.isMultiData()).toBeTruthy(); + expect(dataCell.isChartData()).toBeTruthy(); expect(dataCell.getRenderChartData()).toMatchSnapshot(); expect(dataCell.getRenderChartOptions()).toMatchSnapshot(); }); diff --git a/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts b/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts index 93d4283a4e..d0a348b6a5 100644 --- a/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts @@ -34,6 +34,7 @@ import { PivotSheet, type S2DataConfig, type S2Options, + type TooltipOperatorMenuItems, } from '@/index'; import type { BaseFacet } from '@/facet/base-facet'; import type { BBox } from '@/engine'; @@ -256,6 +257,9 @@ describe('Tooltip Utils Tests', () => { options: { tooltip, }, + interaction: { + getInteractedCells: jest.fn(() => []), + }, } as unknown as SpreadSheet; expect(getTooltipOptions(spreadsheet, {} as Event)).toEqual({ @@ -306,6 +310,9 @@ describe('Tooltip Utils Tests', () => { options: { tooltip, }, + interaction: { + getInteractedCells: jest.fn(() => []), + }, } as unknown as SpreadSheet; const tooltipOptions = omit( @@ -330,16 +337,43 @@ describe('Tooltip Utils Tests', () => { }, ); + test('should use interacted cell type if cannot get current cell type', () => { + const mockInteractedCell = { cellType: CellType.DATA_CELL }; + + const tooltip: Tooltip = { + enable: true, + [CellType.DATA_CELL]: { + enable: false, + }, + content: '', + operation: {}, + }; + + const spreadsheet = { + getCellType: () => undefined, + options: { + tooltip, + }, + interaction: { + getInteractedCells: jest.fn(() => [mockInteractedCell]), + }, + } as unknown as SpreadSheet; + + const tooltipOptions = getTooltipOptions(spreadsheet, {} as Event); + + expect(tooltipOptions?.enable).toBeFalsy(); + }); + test('should filter not displayed tooltip operation menus', () => { const mockCell = { cellType: CellType.DATA_CELL, } as unknown as S2CellType; const onClick = jest.fn(); - const defaultMenus = [ + const defaultMenus: TooltipOperatorMenuItems = [ { key: 'default-menu', - text: 'default-menu', + label: 'default-menu', }, ]; diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 089928a5fa..35f6ea7bbc 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -7,34 +7,38 @@ import { isEmpty, isEqual, isObject, + isPlainObject, merge, } from 'lodash'; import { BaseCell } from '../cell/base-cell'; +import { EMPTY_PLACEHOLDER } from '../common/constant/basic'; import { CellType, InteractionStateName, SHAPE_STYLE_MAP, } from '../common/constant/interaction'; -import { - CellBorderPosition, - CellClipBox, - type HeaderActionNameOptions, - type IconCondition, - type InteractionStateTheme, - type RenderTextShapeOptions, -} from '../common/interface'; import type { + BaseChartData, CellMeta, Condition, - FormatResult, ConditionMappingResult, + FormatResult, + MiniChartData, + MultiData, TextTheme, + ThemeName, ViewMeta, ViewMetaIndexType, - MultiData, - BaseChartData, - ThemeName, } from '../common/interface'; +import { + CellBorderPosition, + CellClipBox, + type HeaderActionNameOptions, + type IconCondition, + type InteractionStateTheme, + type RenderTextShapeOptions, +} from '../common/interface'; +import { getFieldValueOfViewMetaData } from '../data-set/cell-data'; import { getHorizontalTextIconPosition, getVerticalIconPosition, @@ -45,12 +49,10 @@ import { shouldUpdateBySelectedCellsHighlight, updateBySelectedCellsHighlight, } from '../utils/cell/data-cell'; +import { groupIconsByPosition } from '../utils/cell/header-cell'; import { getIconPosition } from '../utils/condition/condition'; -import { updateShapeAttr } from '../utils/g-renders'; -import { EMPTY_PLACEHOLDER } from '../common/constant/basic'; import { drawInterval } from '../utils/g-mini-charts'; -import { getFieldValueOfViewMetaData } from '../data-set/cell-data'; -import { groupIconsByPosition } from '../utils/cell/header-cell'; +import { updateShapeAttr } from '../utils/g-renders'; import type { RawData } from './../common/interface/s2DataConfig'; /** @@ -74,7 +76,17 @@ export class DataCell extends BaseCell { } public isMultiData() { - return isObject(this.getMeta().fieldValue); + const fieldValue = this.getFieldValue(); + + return isObject(fieldValue); + } + + public isChartData() { + const fieldValue = this.getFieldValue(); + + return isPlainObject( + (fieldValue as unknown as MultiData)?.values, + ); } public getRenderChartData(): BaseChartData { diff --git a/packages/s2-core/src/utils/export/copy/pivot-data-cell-copy.ts b/packages/s2-core/src/utils/export/copy/pivot-data-cell-copy.ts index 8e5bcafe3c..1df16a9f85 100644 --- a/packages/s2-core/src/utils/export/copy/pivot-data-cell-copy.ts +++ b/packages/s2-core/src/utils/export/copy/pivot-data-cell-copy.ts @@ -1,16 +1,18 @@ -import { find, isEmpty, map, slice, zip } from 'lodash'; +import { find, isEmpty, isPlainObject, map, slice, zip } from 'lodash'; import { AsyncRenderThreshold, - type CellMeta, - type DataItem, EXTRA_FIELD, VALUE_FIELD, + type CellMeta, + type DataItem, + type MiniChartData, + type MultiData, } from '../../../common'; import type { Node } from '../../../facet/layout/node'; import type { SpreadSheet } from '../../../sheet-type'; import type { - CopyableList, CopyAllDataParams, + CopyableList, MeasureQuery, SheetCopyConstructorParams, } from '../interface'; @@ -22,6 +24,7 @@ import { getSelectedRows, } from '../method'; import type { BaseDataSet } from './../../../data-set/base-data-set'; +import { BaseDataCellCopy } from './base-data-cell-copy'; import { assembleMatrix, completeMatrix, @@ -30,7 +33,6 @@ import { getNodeFormatData, } from './common'; import { getHeaderNodeFromMeta } from './core'; -import { BaseDataCellCopy } from './base-data-cell-copy'; export class PivotDataCellCopy extends BaseDataCellCopy { protected leafRowNodes: Node[] = []; @@ -229,7 +231,13 @@ export class PivotDataCellCopy extends BaseDataCellCopy { dataSet, ); - return formatter(cellData?.[VALUE_FIELD] ?? ''); + const fieldValue = cellData?.[VALUE_FIELD]; + const isChartData = isPlainObject( + (fieldValue as MultiData)?.values, + ); + const value = isChartData ? '' : fieldValue; + + return formatter(value ?? ''); }; protected getCornerMatrix = (rowMatrix?: string[][]): string[][] => { diff --git a/packages/s2-core/src/utils/tooltip.ts b/packages/s2-core/src/utils/tooltip.ts index ace09ccb27..f061b29c34 100644 --- a/packages/s2-core/src/utils/tooltip.ts +++ b/packages/s2-core/src/utils/tooltip.ts @@ -704,9 +704,16 @@ export const getTooltipOptions = ( return null; } + const { options, interaction } = spreadsheet; const cellType = spreadsheet.getCellType?.(event?.target); - return getTooltipOptionsByCellType(spreadsheet.options.tooltip!, cellType!); + // 如果没有 cellType, 说明是刷选丢失 event target 的场景, 此时从产生过交互状态的单元格里取, 避免刷选读取不到争取 tooltip 配置的问题 + const sampleCell = interaction.getInteractedCells()[0]; + + return getTooltipOptionsByCellType( + options.tooltip!, + cellType || sampleCell.cellType!, + ); }; export const getTooltipVisibleOperator = ( diff --git a/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx b/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx index 2ab4740644..af8d465bb1 100644 --- a/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx +++ b/packages/s2-react/__tests__/unit/components/sheets/chart-sheet/index-spec.tsx @@ -6,7 +6,7 @@ import { waitFor } from '@testing-library/react'; import React from 'react'; import type { Root } from 'react-dom/client'; import { ChartDataConfig } from '../../../../data/data-g2-chart'; -import { renderComponent, sleep } from '../../../../util/helpers'; +import { renderComponent } from '../../../../util/helpers'; import { SheetComponent, type SheetComponentOptions, @@ -79,27 +79,4 @@ describe(' Tests', () => { }); }); }); - - test('should not throw g2 error after render chart', async () => { - const errorSpy = jest - .spyOn(console, 'error') - .mockImplementationOnce(() => {}); - - renderChartSheet(null, { - onDataCellRender, - }); - - await waitFor(async () => { - s2.updateScrollOffset({ offsetY: { value: 800, animate: true } }); - - await sleep(1000); - - expect(errorSpy).not.toHaveBeenCalledWith( - `Uncaught (in promise) TypeError: Cannot read property 'defaultView' of null`, - ); - expect(errorSpy).not.toHaveBeenCalledWith( - `Uncaught (in promise) TypeError: Cannot read properties of null (reading 'createElement')`, - ); - }); - }); }); diff --git a/packages/s2-react/playground/components/ChartSheet.tsx b/packages/s2-react/playground/components/ChartSheet.tsx index 81ad024054..7816e9b1de 100644 --- a/packages/s2-react/playground/components/ChartSheet.tsx +++ b/packages/s2-react/playground/components/ChartSheet.tsx @@ -14,6 +14,7 @@ const options: SheetComponentOptions = { height: 900, interaction: { enableCopy: true, + copyWithFormat: true, brushSelection: { rowCell: true, colCell: true, diff --git a/packages/s2-react/playground/config.tsx b/packages/s2-react/playground/config.tsx index d9eb67f4a5..54f7066879 100644 --- a/packages/s2-react/playground/config.tsx +++ b/packages/s2-react/playground/config.tsx @@ -215,6 +215,7 @@ export const TableSheetFrozenOptions: S2TableSheetFrozenOptions = { }; export const S2TooltipOptions: SheetComponentOptions['tooltip'] = { + enable: true, operation: { hiddenColumns: true, menu: { @@ -287,6 +288,7 @@ export const s2Options: SheetComponentOptions = { cornerText: '测试测试测试测试测试测试测试测试测试测试', interaction: { enableCopy: true, + copyWithFormat: true, // 防止 mac 触摸板横向滚动触发浏览器返回, 和移动端下拉刷新 overscrollBehavior: 'none', brushSelection: { diff --git a/packages/s2-react/playground/index.tsx b/packages/s2-react/playground/index.tsx index 519e83e4f7..ec83c917f4 100644 --- a/packages/s2-react/playground/index.tsx +++ b/packages/s2-react/playground/index.tsx @@ -1093,6 +1093,60 @@ function MainLayout() { + + + 复制 + + + + { + updateOptions({ + interaction: { + enableCopy: checked, + }, + }); + }} + /> + + + { + updateOptions({ + interaction: { + copyWithHeader: checked, + }, + }); + }} + /> + + + { + updateOptions({ + interaction: { + copyWithFormat: checked, + }, + }); + }} + /> + + ), }, 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 ad7d9b1559..d134fd98a6 100644 --- a/packages/s2-react/src/components/sheets/chart-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/chart-sheet/index.tsx @@ -27,18 +27,7 @@ export const ChartSheet: React.FC = React.memo( height: 400, }, }, - // TODO: 刷选时获取不到正确的 tooltip 配置 tooltip: { - // cornerCell: { - // enable: true, - // }, - // colCell: { - // enable: true, - // }, - // rowCell: { - // enable: true, - // }, - // enable: false, enable: true, }, }; From 987ff9d7f4f36936d08dc69b4bb3f3b64341c091 Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Thu, 30 Nov 2023 19:21:16 +0800 Subject: [PATCH 05/15] =?UTF-8?q?docs:=20=E5=A2=9E=E5=8A=A0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=92=8C=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 + packages/s2-core/package.json | 3 + packages/s2-react/package.json | 9 +- packages/s2-shared/package.json | 3 + packages/s2-vue/package.json | 3 + pnpm-lock.yaml | 272 ++++++------------ s2-site/.dumi/global.ts | 25 -- s2-site/.dumi/pages/playground.en.tsx | 3 - s2-site/.dumi/pages/playground.zh.tsx | 16 -- .../advanced/custom/custom-g2-chart.en.md | 4 + .../advanced/custom/custom-g2-chart.zh.md | 160 +++++++++++ .../examples/custom/custom-g2-chart/API.en.md | 4 + .../examples/custom/custom-g2-chart/API.zh.md | 4 + .../custom-g2-chart/demo/custom-g2-chart.ts | 138 +++++++++ .../custom/custom-g2-chart/demo/meta.json | 16 ++ .../custom/custom-g2-chart/index.en.md | 4 + .../custom/custom-g2-chart/index.zh.md | 4 + .../examples/custom/custom-plugins/API.en.md | 4 +- .../examples/custom/custom-plugins/API.zh.md | 3 +- .../custom/custom-plugins/demo/meta.json | 2 +- .../custom/custom-plugins/index.en.md | 4 +- .../custom/custom-plugins/index.zh.md | 4 +- s2-site/package.json | 16 +- 23 files changed, 449 insertions(+), 255 deletions(-) delete mode 100644 s2-site/.dumi/global.ts delete mode 100644 s2-site/.dumi/pages/playground.en.tsx delete mode 100644 s2-site/.dumi/pages/playground.zh.tsx create mode 100644 s2-site/docs/manual/advanced/custom/custom-g2-chart.en.md create mode 100644 s2-site/docs/manual/advanced/custom/custom-g2-chart.zh.md create mode 100644 s2-site/examples/custom/custom-g2-chart/API.en.md create mode 100644 s2-site/examples/custom/custom-g2-chart/API.zh.md create mode 100644 s2-site/examples/custom/custom-g2-chart/demo/custom-g2-chart.ts create mode 100644 s2-site/examples/custom/custom-g2-chart/demo/meta.json create mode 100644 s2-site/examples/custom/custom-g2-chart/index.en.md create mode 100644 s2-site/examples/custom/custom-g2-chart/index.zh.md diff --git a/package.json b/package.json index ae560037e2..8fcdb05722 100644 --- a/package.json +++ b/package.json @@ -170,5 +170,8 @@ "repository": { "type": "git", "url": "https://github.com/antvis/S2.git" + }, + "tnpm": { + "mode": "pnpm" } } diff --git a/packages/s2-core/package.json b/packages/s2-core/package.json index da5d919a4d..1360b8421f 100644 --- a/packages/s2-core/package.json +++ b/packages/s2-core/package.json @@ -97,5 +97,8 @@ ], "publishConfig": { "access": "public" + }, + "tnpm": { + "mode": "pnpm" } } diff --git a/packages/s2-react/package.json b/packages/s2-react/package.json index 1b826c0e8e..03e8bdea1b 100644 --- a/packages/s2-react/package.json +++ b/packages/s2-react/package.json @@ -72,10 +72,10 @@ "devDependencies": { "@ant-design/icons": "^5.2.6", "@antv/event-emitter": "^0.1.3", - "@antv/g": "^5.15.2", + "@antv/g": "^5.18.21", "@antv/g-plugin-a11y": "^0.6.19", "@antv/g-plugin-rough-canvas-renderer": "^1.9.24", - "@antv/g2": "^5.1.9", + "@antv/g2": "^5.1.10", "@antv/s2": "workspace:*", "@antv/s2-shared": "workspace:*", "@testing-library/react": "^14.0.0", @@ -85,7 +85,7 @@ "@types/react-beautiful-dnd": "^13.1.5", "@types/react-color": "^3.0.7", "@types/react-dom": "18.2.13", - "antd": "^5.11.1", + "antd": "^5.11.5", "d3-dsv": "^1.1.1", "react": "^18.2.0", "react-color": "^2.19.3", @@ -104,5 +104,8 @@ ], "publishConfig": { "access": "public" + }, + "tnpm": { + "mode": "pnpm" } } diff --git a/packages/s2-shared/package.json b/packages/s2-shared/package.json index a867516744..56fa5e607d 100644 --- a/packages/s2-shared/package.json +++ b/packages/s2-shared/package.json @@ -17,5 +17,8 @@ "devDependencies": { "@antv/s2": "workspace:*", "lodash": "^4.17.21" + }, + "tnpm": { + "mode": "pnpm" } } diff --git a/packages/s2-vue/package.json b/packages/s2-vue/package.json index cbd77f6bfb..2fe4fe06b9 100644 --- a/packages/s2-vue/package.json +++ b/packages/s2-vue/package.json @@ -87,5 +87,8 @@ ], "publishConfig": { "access": "public" + }, + "tnpm": { + "mode": "pnpm" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b46d12c53f..1135466c49 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -332,7 +332,7 @@ importers: specifier: ^0.1.3 version: 0.1.3 '@antv/g': - specifier: ^5.15.2 + specifier: ^5.18.21 version: 5.18.21 '@antv/g-plugin-a11y': specifier: ^0.6.19 @@ -341,8 +341,8 @@ importers: specifier: ^1.9.24 version: 1.9.24 '@antv/g2': - specifier: ^5.1.9 - version: 5.1.9 + specifier: ^5.1.10 + version: 5.1.10 '@antv/s2': specifier: workspace:* version: link:../s2-core @@ -371,8 +371,8 @@ importers: specifier: 18.2.13 version: 18.2.13 antd: - specifier: ^5.11.1 - version: 5.11.1(react-dom@18.2.0)(react@18.2.0) + specifier: ^5.11.5 + version: 5.11.5(react-dom@18.2.0)(react@18.2.0) d3-dsv: specifier: ^1.1.1 version: 1.2.0 @@ -441,8 +441,8 @@ importers: specifier: ^5.2.6 version: 5.2.6(react-dom@18.2.0)(react@18.2.0) '@antv/dumi-theme-antv': - specifier: ^0.4.3 - version: 0.4.3(@babel/core@7.23.2)(dumi@2.2.14) + specifier: ^0.4.4 + version: 0.4.4(@babel/core@7.23.2)(dumi@2.2.14) '@antv/g-canvas': specifier: ^1.11.24 version: 1.11.24 @@ -452,6 +452,9 @@ importers: '@antv/g-plugin-rough-canvas-renderer': specifier: ^1.9.24 version: 1.9.24 + '@antv/g2': + specifier: ^5.1.10 + version: 5.1.10 '@antv/s2': specifier: next version: link:../packages/s2-core @@ -459,8 +462,8 @@ importers: specifier: next version: link:../packages/s2-react antd: - specifier: ^5.11.2 - version: 5.11.2 + specifier: ^5.11.5 + version: 5.11.5(react-dom@18.2.0)(react@18.2.0) copy-to-clipboard: specifier: ^3.3.3 version: 3.3.3 @@ -468,8 +471,8 @@ importers: specifier: ^2.2.14 version: 2.2.14(@babel/core@7.23.2)(@types/node@20.8.9)(eslint@8.52.0)(jest@26.6.3)(postcss-less@6.0.0)(prettier@3.0.3)(rollup@4.1.5)(stylelint@15.11.0)(typescript@5.2.2) gh-pages: - specifier: ^3.1.0 - version: 3.2.3 + specifier: ^6.1.0 + version: 6.1.0 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -656,8 +659,8 @@ packages: dependencies: '@ctrl/tinycolor': 3.6.1 - /@ant-design/cssinjs@1.17.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-vu7lnfEx4Mf8MPzZxn506Zen3Nt4fRr2uutwvdCuTCN5IiU0lDdQ0tiJ24/rmB8+pefwjluYsbyzbQSbgfJy+A==} + /@ant-design/cssinjs@1.17.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Ed2rruHMxZTVYGPec6QBZkrh00Df5K1FAufmBpONai5iGYxoxIkg1sRD8YdCw0NvPRAa4r1nJP5LbwICGHzGiQ==} peerDependencies: react: '>=16.0.0' react-dom: '>=16.0.0' @@ -749,7 +752,6 @@ packages: '@antv/scale': 0.4.13 '@antv/util': 3.3.5 svg-path-parser: 1.1.0 - dev: true /@antv/coord@0.4.7: resolution: {integrity: sha512-UTbrMLhwJUkKzqJx5KFnSRpU3BqrdLORJbwUbHK2zHSCT3q3bjcFA//ZYLVfIlwqFDXp/hzfMyRtp0c77A9ZVA==} @@ -757,10 +759,9 @@ packages: '@antv/scale': 0.4.13 '@antv/util': 2.0.17 gl-matrix: 3.4.3 - dev: true - /@antv/dumi-theme-antv@0.4.3(@babel/core@7.23.2)(dumi@2.2.14): - resolution: {integrity: sha512-SeAf+KfmbAnvjUsKt5d0aNiFVhMzUQ8S2ZsO/cCrn9KCJCjdcgc53c2mUHOCgZT4AYbrfoIF6DyJ2j0UcEu4Ng==} + /@antv/dumi-theme-antv@0.4.4(@babel/core@7.23.2)(dumi@2.2.14): + resolution: {integrity: sha512-/5eB2bn9pZZmORcYFmQQ8xjgD22/W879E3XfHKvgYDNkYlxNUMmOknxiNbV5Pdf0s8oUgLEerKnSWqdkQc6Tvg==} peerDependencies: dumi: ^2.0.0 dependencies: @@ -770,7 +771,7 @@ packages: '@docsearch/css': 3.3.1 '@docsearch/react': 3.3.1(react-dom@18.2.0)(react@18.2.0) '@monaco-editor/react': 4.4.6(monaco-editor@0.25.2)(react-dom@18.2.0)(react@18.2.0) - '@stackblitz/sdk': 1.8.1 + '@stackblitz/sdk': 1.9.0 antd: 4.24.14(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 codesandbox: 2.2.3 @@ -909,7 +910,6 @@ packages: '@antv/g-lite': 1.2.19 '@antv/util': 3.3.5 tslib: 2.6.2 - dev: true /@antv/g-plugin-html-renderer@1.9.22: resolution: {integrity: sha512-+vGFscjEa6yWxJzqPOmkGL5WjrfT0jDlRBzsF1UczeMNEM8zFQu5/VXL8LlCDOnOTJEo3UpkzrUT0fQe4mHaAA==} @@ -943,8 +943,8 @@ packages: '@antv/util': 3.3.5 tslib: 2.6.2 - /@antv/g2@5.1.9: - resolution: {integrity: sha512-zvo/jd+4wKfvWsHCzqb+NdCrT5DXGytkAqS9eX2qN3UHDB7ptiY1kteh6LiCTfLtSTLko6asGYlwxcrUAOSM/w==} + /@antv/g2@5.1.10: + resolution: {integrity: sha512-Htw1Hlexpz7yFeslTH+4FnRsVayu+TrNarkZaMzQvqJ+IpVMmdflIMj+brFIFEgBe71zKjzxx6X/OcCtFww6Sg==} dependencies: '@antv/component': 1.0.0-beta.2(@antv/g@5.18.21) '@antv/coord': 0.4.7 @@ -968,7 +968,6 @@ packages: flru: 1.0.2 fmin: 0.0.2 pdfast: 0.2.0 - dev: true /@antv/g@5.18.21: resolution: {integrity: sha512-+RFiVeMgmPL94U4/wN3HUwxYmkOq2msrPAg38NeGG6Mwo4DOW2nEZqoQCpDFxzmTRwKM984b24epcEPv+wNy+g==} @@ -984,7 +983,6 @@ packages: gl-matrix: 3.4.3 lodash-es: 4.17.21 tslib: 2.6.2 - dev: true /@antv/scale@0.4.13: resolution: {integrity: sha512-aWOXZdvkHQjEOMWmDBJF6nja30Y38nC5WTtx3fzX4INqfqYLX9u/fcZfElsjFzryewh2qveO+7L0rq8ugutDTw==} @@ -992,14 +990,12 @@ packages: '@antv/util': 2.0.17 color-string: 1.9.1 fecha: 4.2.3 - dev: true /@antv/util@2.0.17: resolution: {integrity: sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==} dependencies: csstype: 3.1.2 tslib: 2.6.2 - dev: true /@antv/util@3.3.5: resolution: {integrity: sha512-bVv1loamL/MgUEN9dNt7VKAsghO4Wgb+kzr8B9TgkM5tHgKk++xiTwi3pejIdgU8DDkzcyaRsO+VTOXJt8jLng==} @@ -2927,14 +2923,12 @@ packages: engines: {node: '>= 0.4'} dependencies: '@ljharb/through': 2.3.11 - dev: true /@ljharb/through@2.3.11: resolution: {integrity: sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - dev: true /@loadable/component@5.15.2(react@18.1.0): resolution: {integrity: sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==} @@ -3750,10 +3744,6 @@ packages: resolution: {integrity: sha512-shaGl4ttFDpHjYBoMaZpciOtsi/lKvJ3VfcBYk6+PjjbFs6H5GxPAyhbiSqy3Vmx30aos284pd88QzD3rE6iag==} dev: false - /@stackblitz/sdk@1.8.1: - resolution: {integrity: sha512-hjYfjOLQBNDzqPD5AkGJOD7j+uvFwGocDTmwNqmLCWR5EY7BDtcOtDY2M+91v/twYWWNvI7N8UNIgojCPNgzMA==} - dev: false - /@stackblitz/sdk@1.9.0: resolution: {integrity: sha512-3m6C7f8pnR5KXys/Hqx2x6ylnpqOak6HtnZI6T5keEO0yT+E4Spkw37VEbdwuC+2oxmjdgq6YZEgiKX7hM1GmQ==} dev: false @@ -5898,12 +5888,10 @@ packages: kind-of: 3.2.2 longest: 1.0.1 repeat-string: 1.6.1 - dev: true /amdefine@1.0.1: resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} engines: {node: '>=0.4.2'} - dev: true /animated-scroll-to@2.3.0: resolution: {integrity: sha512-PT/5MSKCWQaK2kuOl2HT2KJMuJEvUS4/TgMhWy82c2EmF74/CIkvPBPKOvd8nMYP6Higo7xCn49/iSW9BccMoQ==} @@ -5949,7 +5937,6 @@ packages: /ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} engines: {node: '>=0.10.0'} - dev: true /ansi-regex@3.0.1: resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} @@ -5971,7 +5958,6 @@ packages: /ansi-styles@2.2.1: resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} - dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -6078,14 +6064,14 @@ packages: scroll-into-view-if-needed: 2.2.31 dev: false - /antd@5.11.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-X7Gk1TtJtM9goTrmTPVserqcP7crtV2TX/pbxgqyHpMZRrnBy0EI3h4ngrW+zsIAW8/iqpgrYsG/NVUel6xkBA==} + /antd@5.11.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-qB1YmvO4Zm4r48M0Ptxn7orpaXeMPSeTrrw6dAgtTYN+ysnWD/D/zlxFc5g73GywIzZ10XGqvNC+74A+HD0yeQ==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: '@ant-design/colors': 7.0.0 - '@ant-design/cssinjs': 1.17.2(react-dom@18.2.0)(react@18.2.0) + '@ant-design/cssinjs': 1.17.5(react-dom@18.2.0)(react@18.2.0) '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@ant-design/react-slick': 1.0.2(react@18.2.0) '@babel/runtime': 7.23.2 @@ -6105,7 +6091,7 @@ packages: rc-drawer: 6.5.2(react-dom@18.2.0)(react@18.2.0) rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) rc-field-form: 1.40.0(react-dom@18.2.0)(react@18.2.0) - rc-image: 7.3.2(react-dom@18.2.0)(react@18.2.0) + rc-image: 7.5.1(react-dom@18.2.0)(react@18.2.0) rc-input: 1.3.6(react-dom@18.2.0)(react@18.2.0) rc-input-number: 8.4.0(react-dom@18.2.0)(react@18.2.0) rc-mentions: 2.9.1(react-dom@18.2.0)(react@18.2.0) @@ -6122,7 +6108,7 @@ packages: rc-slider: 10.4.0(react-dom@18.2.0)(react@18.2.0) rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) - rc-table: 7.35.2(react-dom@18.2.0)(react@18.2.0) + rc-table: 7.36.0(react-dom@18.2.0)(react@18.2.0) rc-tabs: 12.13.1(react-dom@18.2.0)(react@18.2.0) rc-textarea: 1.5.3(react-dom@18.2.0)(react@18.2.0) rc-tooltip: 6.1.2(react-dom@18.2.0)(react@18.2.0) @@ -6138,67 +6124,6 @@ packages: - date-fns - luxon - moment - dev: true - - /antd@5.11.2: - resolution: {integrity: sha512-7/yqmfXpShHH0MJQOgv3vX9PUFwctyBm/G5L0i/S4AQy20ON6ZZ2UkjmWxgwg3vq2CEHKyVGTHozpH9WwDizgw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@ant-design/colors': 7.0.0 - '@ant-design/cssinjs': 1.17.2(react-dom@18.2.0)(react@18.2.0) - '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) - '@ant-design/react-slick': 1.0.2(react@18.2.0) - '@babel/runtime': 7.23.2 - '@ctrl/tinycolor': 3.6.1 - '@rc-component/color-picker': 1.4.1(react-dom@18.2.0)(react@18.2.0) - '@rc-component/mutate-observer': 1.1.0(react-dom@18.2.0)(react@18.2.0) - '@rc-component/tour': 1.10.0(react-dom@18.2.0)(react@18.2.0) - '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) - classnames: 2.3.2 - copy-to-clipboard: 3.3.3 - dayjs: 1.11.7 - qrcode.react: 3.1.0(react@18.2.0) - rc-cascader: 3.20.0(react-dom@18.2.0)(react@18.2.0) - rc-checkbox: 3.1.0(react-dom@18.2.0)(react@18.2.0) - rc-collapse: 3.7.1(react-dom@18.2.0)(react@18.2.0) - rc-dialog: 9.3.4(react-dom@18.2.0)(react@18.2.0) - rc-drawer: 6.5.2(react-dom@18.2.0)(react@18.2.0) - rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) - rc-field-form: 1.40.0(react-dom@18.2.0)(react@18.2.0) - rc-image: 7.3.2(react-dom@18.2.0)(react@18.2.0) - rc-input: 1.3.6(react-dom@18.2.0)(react@18.2.0) - rc-input-number: 8.4.0(react-dom@18.2.0)(react@18.2.0) - rc-mentions: 2.9.1(react-dom@18.2.0)(react@18.2.0) - rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) - rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-notification: 5.3.0(react-dom@18.2.0)(react@18.2.0) - rc-pagination: 3.7.0(react-dom@18.2.0)(react@18.2.0) - rc-picker: 3.14.6(dayjs@1.11.7)(react-dom@18.2.0)(react@18.2.0) - rc-progress: 3.5.1(react-dom@18.2.0)(react@18.2.0) - rc-rate: 2.12.0(react-dom@18.2.0)(react@18.2.0) - rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-segmented: 2.2.2(react-dom@18.2.0)(react@18.2.0) - rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) - rc-slider: 10.4.0(react-dom@18.2.0)(react@18.2.0) - rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) - rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) - rc-table: 7.36.0 - rc-tabs: 12.13.1(react-dom@18.2.0)(react@18.2.0) - rc-textarea: 1.5.3(react-dom@18.2.0)(react@18.2.0) - rc-tooltip: 6.1.2(react-dom@18.2.0)(react@18.2.0) - rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) - rc-tree-select: 5.15.0(react-dom@18.2.0)(react@18.2.0) - rc-upload: 4.3.5(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) - scroll-into-view-if-needed: 3.1.0 - throttle-debounce: 5.0.0 - transitivePeerDependencies: - - date-fns - - luxon - - moment - dev: false /anymatch@1.3.2: resolution: {integrity: sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==} @@ -6393,8 +6318,8 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.0 + define-properties: 1.2.1 + es-abstract: 1.22.2 es-array-method-boxes-properly: 1.0.0 is-string: 1.0.7 @@ -6485,6 +6410,11 @@ packages: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} dependencies: lodash: 4.17.21 + dev: true + + /async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: false /asynciterator.prototype@1.0.0: resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} @@ -7177,8 +7107,8 @@ packages: /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.1.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.1 /caller-callsite@2.0.0: resolution: {integrity: sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==} @@ -7231,7 +7161,6 @@ packages: /camelcase@1.2.1: resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} engines: {node: '>=0.10.0'} - dev: true /camelcase@4.1.0: resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} @@ -7301,7 +7230,6 @@ packages: dependencies: align-text: 0.1.4 lazy-cache: 1.0.4 - dev: true /chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} @@ -7312,7 +7240,6 @@ packages: has-ansi: 2.0.0 strip-ansi: 3.0.1 supports-color: 2.0.0 - dev: true /chalk@2.1.0: resolution: {integrity: sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==} @@ -7535,7 +7462,6 @@ packages: center-align: 0.1.3 right-align: 0.1.3 wordwrap: 0.0.2 - dev: true /cliui@5.0.0: resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} @@ -7712,7 +7638,6 @@ packages: /commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} - dev: true /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -7827,7 +7752,6 @@ packages: /contour_plot@0.0.1: resolution: {integrity: sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw==} - dev: true /conventional-changelog-angular@5.0.13: resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==} @@ -8385,7 +8309,6 @@ packages: engines: {node: '>=12'} dependencies: internmap: 2.0.3 - dev: true /d3-color@1.4.1: resolution: {integrity: sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==} @@ -8393,7 +8316,6 @@ packages: /d3-dispatch@3.0.1: resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} engines: {node: '>=12'} - dev: true /d3-dsv@1.2.0: resolution: {integrity: sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==} @@ -8425,24 +8347,20 @@ packages: d3-dispatch: 3.0.1 d3-quadtree: 3.0.1 d3-timer: 1.0.10 - dev: true /d3-format@3.1.0: resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} engines: {node: '>=12'} - dev: true /d3-geo@3.1.0: resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==} engines: {node: '>=12'} dependencies: d3-array: 3.2.4 - dev: true /d3-hierarchy@3.1.2: resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} engines: {node: '>=12'} - dev: true /d3-interpolate@1.4.0: resolution: {integrity: sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==} @@ -8452,12 +8370,10 @@ packages: /d3-path@3.1.0: resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} engines: {node: '>=12'} - dev: true /d3-quadtree@3.0.1: resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} engines: {node: '>=12'} - dev: true /d3-scale-chromatic@3.0.0: resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==} @@ -8465,21 +8381,18 @@ packages: dependencies: d3-color: 1.4.1 d3-interpolate: 1.4.0 - dev: true /d3-shape@3.2.0: resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} engines: {node: '>=12'} dependencies: d3-path: 3.1.0 - dev: true /d3-timer@1.0.10: resolution: {integrity: sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==} /d3-voronoi@1.1.4: resolution: {integrity: sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==} - dev: true /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} @@ -8635,7 +8548,6 @@ packages: object-is: 1.1.5 object-keys: 1.1.1 regexp.prototype.flags: 1.5.1 - dev: true /deep-equal@2.2.0: resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} @@ -8761,7 +8673,6 @@ packages: /defined@1.0.1: resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} - dev: true /del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} @@ -9019,7 +8930,6 @@ packages: hasBin: true dependencies: minimatch: 3.1.2 - dev: true /dumi-afx-deps@1.0.0-alpha.20: resolution: {integrity: sha512-PRSJlHuJkyHDET7Hukykx/hLULkgUBX5q2CutMG5EDI3eJLzJlX634wNll10m3at1uomcDAVudL7Dgh5UOJ7IQ==} @@ -9224,6 +9134,11 @@ packages: /email-addresses@3.1.0: resolution: {integrity: sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==} + dev: true + + /email-addresses@5.0.0: + resolution: {integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==} + dev: false /emittery@0.7.2: resolution: {integrity: sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==} @@ -9445,7 +9360,7 @@ packages: resolution: {integrity: sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 has-symbols: 1.0.3 is-arguments: 1.1.1 is-map: 2.0.2 @@ -10591,7 +10506,6 @@ packages: /fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} - dev: true /fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} @@ -10809,7 +10723,6 @@ packages: rollup: 0.25.8 tape: 4.17.0 uglify-js: 2.8.29 - dev: true /follow-redirects@1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} @@ -10994,6 +10907,7 @@ packages: graceful-fs: 4.2.10 jsonfile: 4.0.0 universalify: 0.1.2 + dev: true /fs-monkey@1.0.3: resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} @@ -11035,15 +10949,14 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true /function.prototype.name@1.1.5: resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.0 + define-properties: 1.2.1 + es-abstract: 1.22.2 functions-have-names: 1.2.3 /function.prototype.name@1.1.6: @@ -11167,7 +11080,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 /get-tsconfig@4.7.2: resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} @@ -11196,6 +11109,21 @@ packages: find-cache-dir: 3.3.2 fs-extra: 8.1.0 globby: 6.1.0 + dev: true + + /gh-pages@6.1.0: + resolution: {integrity: sha512-MdXigvqN3I66Y+tAZsQJMzpBWQOI1snD6BYuECmP+GEdryYMMOQvzn4AConk/+qNg/XIuQhB1xNGrl3Rmj1iow==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.5 + commander: 11.1.0 + email-addresses: 5.0.0 + filenamify: 4.3.0 + find-cache-dir: 3.3.2 + fs-extra: 11.1.1 + globby: 6.1.0 + dev: false /git-branch@1.0.0: resolution: {integrity: sha512-ZTzuqw5Df8fyLXQWrX6hK+4FpNCdKzMcERlxENEGO5aKcLmG7MAszhrMhluUKNKmOS/JAGijDMQDXDCDw1mE/A==} @@ -11514,7 +11442,7 @@ packages: /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 /got@6.7.1: resolution: {integrity: sha512-Y/K3EDuiQN9rTZhBvPRWMLXIKdeD1Rj0nzunfoi0Yyn5WBEbzxXKU9Ub2X41oZBagVWOBU3MuDonFMgPWQFnwg==} @@ -11630,7 +11558,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: ansi-regex: 2.1.1 - dev: true /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -11725,7 +11652,6 @@ packages: engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: true /hast-to-hyperscript@10.0.1: resolution: {integrity: sha512-dhIVGoKCQVewFi+vz3Vt567E4ejMppS1haBRL6TEmeLeJVB1i/FJIIg/e6s1Bwn0g5qtYojHEKvyGA+OZuyifw==} @@ -12504,7 +12430,6 @@ packages: /internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - dev: true /intersection-observer@0.12.2: resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} @@ -12568,7 +12493,7 @@ packages: resolution: {integrity: sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 is-typed-array: 1.1.10 /is-array-buffer@3.0.2: @@ -13083,7 +13008,7 @@ packages: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 /is-what@3.14.1: resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} @@ -13814,7 +13739,7 @@ packages: jest-pnp-resolver: 1.2.3(jest-resolve@26.6.2) jest-util: 26.6.2 read-pkg-up: 7.0.1 - resolve: 1.22.1 + resolve: 1.22.8 slash: 3.0.0 /jest-runner@24.9.0: @@ -14336,7 +14261,6 @@ packages: hasBin: true dependencies: rw: 1.3.3 - dev: true /json2mq@0.2.0: resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} @@ -14369,6 +14293,7 @@ packages: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: graceful-fs: 4.2.10 + dev: true /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -14903,7 +14828,6 @@ packages: /longest@1.0.1: resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} engines: {node: '>=0.10.0'} - dev: true /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} @@ -15868,7 +15792,6 @@ packages: has-property-descriptors: 1.0.0 hasown: 2.0.0 isarray: 2.0.5 - dev: true /modify-values@1.0.1: resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} @@ -16140,7 +16063,7 @@ packages: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.1 + resolve: 1.22.8 semver: 5.7.1 validate-npm-package-license: 3.0.4 @@ -16381,8 +16304,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 - dev: true + define-properties: 1.2.1 /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -16434,8 +16356,8 @@ packages: dependencies: array.prototype.reduce: 1.0.5 call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.0 + define-properties: 1.2.1 + es-abstract: 1.22.2 /object.getprototypeof@1.0.4: resolution: {integrity: sha512-xV/FkUNM9sHa56AB5deXrlIR+jBtDAHieyfm6XZUuehqlMX+YJPh8CAYtPrXGA/mFLFttasTc9ihhpkPrH7pLw==} @@ -17000,7 +16922,6 @@ packages: /pdfast@0.2.0: resolution: {integrity: sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==} - dev: true /peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} @@ -18139,7 +18060,7 @@ packages: estraverse: 5.3.0 glob: 8.1.0 jsdoc: 3.6.11 - minimist: 1.2.7 + minimist: 1.2.8 protobufjs: 7.1.2 semver: 7.5.4 tmp: 0.2.1 @@ -18594,8 +18515,8 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /rc-image@7.3.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ICEF6SWv9YKhDXxy1vrXcmf0TVvEcQWIww5Yg+f+mn7e4oGX7FNP4+FExwMjNO5UHBEuWrigbGhlCgI6yZZ1jg==} + /rc-image@7.5.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Z9loECh92SQp0nSipc0MBuf5+yVC05H/pzC+Nf8xw1BKDFUJzUeehYBjaWlxly8VGBZJcTHYri61Fz9ng1G3Ag==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' @@ -19073,8 +18994,8 @@ packages: shallowequal: 1.1.0 dev: false - /rc-table@7.35.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ZLIZdAEdfen21FI21xt2LDg9chQ7gc5Lpy4nkjWKPDgmQMnH0KJ8JQQzrd3zrEN16xzjiVdHHvRmi1RU8BtgYg==} + /rc-table@7.36.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3xVcdCC5OLeOOhaCg+5Lps2oPreM/GWXmUXWTSX4p6vF7F76ABM4dfPpMJ9Dnf5yGRyh+8pe7FRyhRVnWw2H/w==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' @@ -19088,22 +19009,6 @@ packages: rc-virtual-list: 3.11.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true - - /rc-table@7.36.0: - resolution: {integrity: sha512-3xVcdCC5OLeOOhaCg+5Lps2oPreM/GWXmUXWTSX4p6vF7F76ABM4dfPpMJ9Dnf5yGRyh+8pe7FRyhRVnWw2H/w==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/context': 1.4.0(react-dom@18.2.0)(react@18.2.0) - classnames: 2.3.2 - rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) - rc-virtual-list: 3.11.3(react-dom@18.2.0)(react@18.2.0) - dev: false /rc-tabs@12.13.1(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-83u3l2QkO0UznCzdBLEk9WnNcT+imtmDmMT993sUUEOGnNQAmqOdev0XjeqrcvsAMe9CDpAWDFd7L/RZw+LVJQ==} @@ -20200,6 +20105,7 @@ packages: is-core-module: 2.11.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + dev: true /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} @@ -20208,7 +20114,6 @@ packages: is-core-module: 2.13.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true /resolve@2.0.0-next.4: resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} @@ -20279,7 +20184,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: align-text: 0.1.4 - dev: true /rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} @@ -20417,7 +20321,6 @@ packages: chalk: 1.1.3 minimist: 1.2.8 source-map-support: 0.3.3 - dev: true /rollup@0.63.5: resolution: {integrity: sha512-dFf8LpUNzIj3oE0vCvobX6rqOzHzLBoblyFp+3znPbjiSmSvOoK2kMKx+Fv9jYduG1rvcCfCveSgEaQHjWRF6g==} @@ -20558,7 +20461,7 @@ packages: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 is-regex: 1.1.4 /safe-regex@1.1.0: @@ -21054,7 +20957,6 @@ packages: resolution: {integrity: sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==} dependencies: source-map: 0.1.32 - dev: true /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -21071,7 +20973,6 @@ packages: engines: {node: '>=0.8.0'} dependencies: amdefine: 1.0.1 - dev: true /source-map@0.5.6: resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} @@ -21431,8 +21332,8 @@ packages: resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.0 + define-properties: 1.2.1 + es-abstract: 1.22.2 /string.prototype.trimend@1.0.7: resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} @@ -21445,8 +21346,8 @@ packages: resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.0 + define-properties: 1.2.1 + es-abstract: 1.22.2 /string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} @@ -21476,7 +21377,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: ansi-regex: 2.1.1 - dev: true /strip-ansi@4.0.0: resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} @@ -21701,7 +21601,6 @@ packages: /supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} - dev: true /supports-color@4.5.0: resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} @@ -21758,7 +21657,6 @@ packages: /svg-path-parser@1.1.0: resolution: {integrity: sha512-jGCUqcQyXpfe38R7RFfhrMyfXcBmpMNJI/B+4CE9/Unkh98UporAc461GTthv+TVDuZXsBx7/WiwJb1Oh4tt4A==} - dev: true /svg-pathdata@5.0.5: resolution: {integrity: sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==} @@ -21861,7 +21759,6 @@ packages: object-inspect: 1.12.3 resolve: 1.22.8 string.prototype.trim: 1.2.8 - dev: true /tar-fs@1.16.3: resolution: {integrity: sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==} @@ -22407,7 +22304,6 @@ packages: yargs: 3.10.0 optionalDependencies: uglify-to-browserify: 1.0.2 - dev: true /uglify-js@3.17.4: resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} @@ -22419,7 +22315,6 @@ packages: /uglify-to-browserify@1.0.2: resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} requiresBuild: true - dev: true optional: true /umi@4.0.88(@babel/core@7.23.2)(@types/node@20.8.9)(eslint@8.52.0)(jest@26.6.3)(postcss-less@6.0.0)(prettier@3.0.3)(rollup@4.1.5)(sass@1.69.5)(stylelint@15.11.0)(typescript@5.2.2): @@ -22621,7 +22516,7 @@ packages: dependencies: '@types/unist': 2.0.6 unist-util-is: 5.1.1 - unist-util-visit-parents: 5.1.1 + unist-util-visit-parents: 5.1.3 dev: false /universal-user-agent@6.0.0: @@ -22778,7 +22673,7 @@ packages: resolution: {integrity: sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.1 for-each: 0.3.3 has-symbols: 1.0.3 object.getownpropertydescriptors: 2.1.5 @@ -23315,7 +23210,6 @@ packages: /window-size@0.1.0: resolution: {integrity: sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==} engines: {node: '>= 0.8.0'} - dev: true /word-wrap@1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} @@ -23324,7 +23218,6 @@ packages: /wordwrap@0.0.2: resolution: {integrity: sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==} engines: {node: '>=0.4.0'} - dev: true /wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} @@ -23596,7 +23489,6 @@ packages: cliui: 2.1.0 decamelize: 1.2.0 window-size: 0.1.0 - dev: true /yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} diff --git a/s2-site/.dumi/global.ts b/s2-site/.dumi/global.ts deleted file mode 100644 index e71f3a6392..0000000000 --- a/s2-site/.dumi/global.ts +++ /dev/null @@ -1,25 +0,0 @@ -if (window) { - (window as any).react = require('react'); - (window as any).reactDom = require('react-dom'); - (window as any).lodash = require('lodash'); - (window as any).reactColor = require('react-color'); - (window as any).copyToClipboard = require('copy-to-clipboard'); - - (window as any).antd = require('antd'); - (window as any).antdIcons = require('@ant-design/icons'); - - (window as any).gCanvas = require('@antv/g-canvas'); - (window as any).s2 = require('@antv/s2'); - (window as any).s2React = require('@antv/s2-react'); - - (window as any).tableCss = require('antd/es/table/style/index.css'); - (window as any).spaceCss = require('antd/es/space/style/index.css'); - (window as any).cascaderCss = require('antd/es/cascader/style/index.css'); - (window as any).checkboxCss = require('antd/es/checkbox/style/index.css'); - (window as any).paginationCss = require('antd/es/pagination/style/index.css'); - ( - window as any - ).inputNumberCss = require('antd/es/input-number/style/index.css'); - (window as any).s2Css = require('@antv/s2/dist/style.min.css'); - (window as any).s2ReactCss = require('@antv/s2-react/dist/style.min.css'); -} diff --git a/s2-site/.dumi/pages/playground.en.tsx b/s2-site/.dumi/pages/playground.en.tsx deleted file mode 100644 index 46b5455d1e..0000000000 --- a/s2-site/.dumi/pages/playground.en.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import Playground from './playground.zh'; - -export default Playground; diff --git a/s2-site/.dumi/pages/playground.zh.tsx b/s2-site/.dumi/pages/playground.zh.tsx deleted file mode 100644 index bd0cb0681d..0000000000 --- a/s2-site/.dumi/pages/playground.zh.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import Page from '../../playground/layouts'; -import { Header } from '@antv/dumi-theme-antv/dist/slots/Header'; -import { Footer } from '@antv/dumi-theme-antv/dist/slots/Footer'; - -const Playground: React.FC = () => { - return ( - <> -
- -
- - ); -}; - -export default Playground; diff --git a/s2-site/docs/manual/advanced/custom/custom-g2-chart.en.md b/s2-site/docs/manual/advanced/custom/custom-g2-chart.en.md new file mode 100644 index 0000000000..3e68e49e0a --- /dev/null +++ b/s2-site/docs/manual/advanced/custom/custom-g2-chart.en.md @@ -0,0 +1,4 @@ +--- +title: Render G2 Charts +order: 8 +--- diff --git a/s2-site/docs/manual/advanced/custom/custom-g2-chart.zh.md b/s2-site/docs/manual/advanced/custom/custom-g2-chart.zh.md new file mode 100644 index 0000000000..7ede43469d --- /dev/null +++ b/s2-site/docs/manual/advanced/custom/custom-g2-chart.zh.md @@ -0,0 +1,160 @@ +--- +title: 自定义单元格内绘制 G2 图表 +order: 8 +--- + +S2 支持 [自定义单元格](https://s2.antv.antgroup.com/examples#custom-custom-cell),也内置了 [简单的 mini 图绘制](https://s2.antv.antgroup.com/examples/custom/custom-cell/#mini-chart), 如果上诉功能都无法满足使用,那么还可以使用专业的可视化图表库 [`AntV/G2`](https://g2.antv.antgroup.com/). + +`S2` 和 `G2` 底层都使用 [AntV/G](https://g.antv.antgroup.com/) 渲染引擎绘制,也就意味着可以**共享渲染引擎**, 实现在 `S2` 表格中绘制 `G2` 图表的梦幻联动,实现真 `图·表`. + + + +
+ +## 数据准备 + +数据源类型为 [MultiData](https://s2.antv.antgroup.com/api/general/s2-data-config#multidata) 支持 `普通数值单元格` 和 `图表单元格` 共存。图表数据源为标准的 [G2 Spec](https://g2.antv.antgroup.com/examples/general/interval/#column). + +```ts +const s2DataConfig = { + data: [ + // 普通数据 + { + number: 1343, + province: '浙江省', + city: '杭州市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: { + // G2 图表数据 (Spec) https://g2.antv.antgroup.com/examples/general/interval/#column + values: { + type: 'view', + autoFit: true, + padding: 0, + axis: false, + children: [ + { + type: 'image', + style: { + src: 'https://gw.alipayobjects.com/zos/rmsportal/NeUTMwKtPcPxIFNTWZOZ.png', + x: '50%', + y: '50%', + width: '100%', + height: '100%', + }, + tooltip: false, + }, + { + type: 'heatmap', + data: { + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/heatmap.json', + }, + encode: { x: 'g', y: 'l', color: 'tmp' }, + style: { opacity: 0 }, + tooltip: false, + }, + ], + }, + }, + province: '浙江省', + city: '舟山市', + type: '办公用品', + sub_type: '笔', + }, + ], +}; +``` + +### 安装 G2 + +:::warning{title="该功能依赖 G2 的 5.x 版本,请确保使用了正确的版本 "} + +```bash +yarn add @antv/g2 --save +``` + +使用 `G2` 提供的 `renderToMountedElement` 方法 + +```ts +import { renderToMountedElement } from '@antv/g2'; +``` + +::: + +### 在 `@antv/s2` 中使用 + +#### 1. 自定义 `DataCell`, 如果是图表数据,则不渲染默认的文本 + +```ts +import { PivotSheet, DataCell } from '@antv/s2'; +import { renderToMountedElement, stdlib } from '@antv/g2'; + +class ChartSheetDataCell extends DataCell { + public drawTextShape(options) { + if (this.isMultiData()) { + return null; + } + + super.drawTextShape(options); + } +} + +const s2 = new PivotSheet(container, s2DataConfig, { + dataCell: (viewMeta) => new ChartSheetDataCell(viewMeta, viewMeta.spreadsheet) +}); + +s2.render(); + +``` + +#### 2. 监听数值单元格渲染完成后,使用 `G2` 提供的 `renderToMountedElement` 将图表挂载在 `S2` 单元格实例上 + +:::warning{title="提示"} +由于 `G2` 按需加载的特性,请根据你渲染的图表,自行选择适合的 [`library`](https://g2.antv.antgroup.com/manual/extra-topics/bundle#g2stdlib) +::: + +```ts +s2.on(S2Event.DATA_CELL_RENDER, (cell) => { + const chartOptions = cell.getRenderChartOptions(); + + renderToMountedElement(chartOptions, { + group: cell, + // https://g2.antv.antgroup.com/manual/extra-topics/bundle#g2stdlib + library: stdlib(), + }); +}); +``` + +### 在 `@antv/s2-react` 使用 + +如果希望在 `React` 中使用,除了上诉的方式外,也可以直接使用 ``, 内部封装了 `自定义 DateCell` 的步骤 + +```tsx +import { SheetComponent } from '@antv/s2-react'; +import { renderToMountedElement, stdlib } from '@antv/g2'; + +function App() { + const onDataCellRender = (cell) => { + const chartOptions = cell.getRenderChartOptions(); + + renderToMountedElement(chartOptions, { + group: cell, + // 根据实际需要渲染的图表,选择 library:https://g2.antv.antgroup.com/manual/extra-topics/bundle#g2stdlib + library: stdlib(), + }); + }; + + return ( + + ) +} +``` + +### 效果 + +[查看示例](/examples#custom-custom-g2-chart) + +preview diff --git a/s2-site/examples/custom/custom-g2-chart/API.en.md b/s2-site/examples/custom/custom-g2-chart/API.en.md new file mode 100644 index 0000000000..10cf5765b4 --- /dev/null +++ b/s2-site/examples/custom/custom-g2-chart/API.en.md @@ -0,0 +1,4 @@ +--- +title: API +order: 11 +--- diff --git a/s2-site/examples/custom/custom-g2-chart/API.zh.md b/s2-site/examples/custom/custom-g2-chart/API.zh.md new file mode 100644 index 0000000000..10cf5765b4 --- /dev/null +++ b/s2-site/examples/custom/custom-g2-chart/API.zh.md @@ -0,0 +1,4 @@ +--- +title: API +order: 11 +--- diff --git a/s2-site/examples/custom/custom-g2-chart/demo/custom-g2-chart.ts b/s2-site/examples/custom/custom-g2-chart/demo/custom-g2-chart.ts new file mode 100644 index 0000000000..69efde673b --- /dev/null +++ b/s2-site/examples/custom/custom-g2-chart/demo/custom-g2-chart.ts @@ -0,0 +1,138 @@ +import { + PivotSheet, + DataCell, + S2DataConfig, + S2Event, + S2Options, +} from '@antv/s2'; +import { renderToMountedElement, stdlib } from '@antv/g2'; + +// 自定义 `DataCell`, 如果是图表数据, 则不渲染默认的文本 + +class ChartSheetDataCell extends DataCell { + drawTextShape(options) { + if (this.isMultiData()) { + return null; + } + + super.drawTextShape(options); + } +} + +const s2Options: S2Options = { + width: 1000, + height: 900, + style: { + colCell: { + hideValue: true, + }, + rowCell: { + width: 100, + }, + // 适当增加单元格宽高, 以便于展示 G2 图表 + dataCell: { + width: 400, + height: 400, + }, + }, + dataCell: (viewMeta) => + new ChartSheetDataCell(viewMeta, viewMeta.spreadsheet), +}; + +const s2DataConfig: S2DataConfig = { + fields: { + rows: ['province', 'city'], + columns: ['type', 'sub_type'], + values: ['number'], + }, + meta: [ + { + field: 'number', + name: '数据', + }, + { + field: 'province', + name: '省份', + }, + { + field: 'city', + name: '城市', + }, + { + field: 'type', + name: '类别', + }, + { + field: 'sub_type', + name: '子类别', + }, + ], + // 数据源类型为 https://s2.antv.antgroup.com/api/general/s2-data-config#multidata 支持`普通数值单元格`和`图表单元格` 共存. + data: [ + // 普通数据 + { + number: 1343, + province: '浙江省', + city: '杭州市', + type: '办公用品', + sub_type: '纸张', + }, + { + number: { + // G2 图表数据 (Spec) https://g2.antv.antgroup.com/examples/general/interval/#column + values: { + type: 'view', + autoFit: true, + padding: 0, + axis: false, + children: [ + { + type: 'image', + style: { + src: 'https://gw.alipayobjects.com/zos/rmsportal/NeUTMwKtPcPxIFNTWZOZ.png', + x: '50%', + y: '50%', + width: '100%', + height: '100%', + }, + tooltip: false, + }, + { + type: 'heatmap', + data: { + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/heatmap.json', + }, + encode: { x: 'g', y: 'l', color: 'tmp' }, + style: { opacity: 0 }, + tooltip: false, + }, + ], + }, + }, + province: '浙江省', + city: '舟山市', + type: '办公用品', + sub_type: '笔', + }, + ], +}; + +const container = document.getElementById('container'); + +const s2 = new PivotSheet(container, s2DataConfig, s2Options); + +// 监听数值单元格渲染完成后, 使用 `G2` 提供的 `renderToMountedElement` 将图表挂载在 `S2` 单元格实例上 +s2.on(S2Event.DATA_CELL_RENDER, (cell) => { + // 获取 G2 渲染到 S2 单元格内所需配置 + const chartOptions = cell.getRenderChartOptions(); + + renderToMountedElement(chartOptions, { + // 指定渲染容器为当前单元格 + group: cell, + // 根据渲染的图表, 自行选择 G2 library: https://g2.antv.antgroup.com/manual/extra-topics/bundle#g2stdlib + library: stdlib(), + }); +}); + +s2.render(); diff --git a/s2-site/examples/custom/custom-g2-chart/demo/meta.json b/s2-site/examples/custom/custom-g2-chart/demo/meta.json new file mode 100644 index 0000000000..405e95210b --- /dev/null +++ b/s2-site/examples/custom/custom-g2-chart/demo/meta.json @@ -0,0 +1,16 @@ +{ + "title": { + "zh": "单元格内绘制 G2 图表", + "en": "Render G2 Charts" + }, + "demos": [ + { + "filename": "custom-g2-chart.ts", + "title": { + "zh": "单元格内绘制 G2 图表", + "en": "render G2 charts" + }, + "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*y9mfQqk9XwYAAAAAAAAAAAAADmJ7AQ/original" + } + ] +} diff --git a/s2-site/examples/custom/custom-g2-chart/index.en.md b/s2-site/examples/custom/custom-g2-chart/index.en.md new file mode 100644 index 0000000000..3147469cfe --- /dev/null +++ b/s2-site/examples/custom/custom-g2-chart/index.en.md @@ -0,0 +1,4 @@ +--- +title: G2 Chart +order: 11 +--- diff --git a/s2-site/examples/custom/custom-g2-chart/index.zh.md b/s2-site/examples/custom/custom-g2-chart/index.zh.md new file mode 100644 index 0000000000..75de0502c9 --- /dev/null +++ b/s2-site/examples/custom/custom-g2-chart/index.zh.md @@ -0,0 +1,4 @@ +--- +title: 单元格内绘制 G2 图表 +order: 11 +--- diff --git a/s2-site/examples/custom/custom-plugins/API.en.md b/s2-site/examples/custom/custom-plugins/API.en.md index 706a02792d..a244706871 100644 --- a/s2-site/examples/custom/custom-plugins/API.en.md +++ b/s2-site/examples/custom/custom-plugins/API.en.md @@ -1,6 +1,4 @@ --- title: API -order: 7 +order: 10 --- - - diff --git a/s2-site/examples/custom/custom-plugins/API.zh.md b/s2-site/examples/custom/custom-plugins/API.zh.md index 4b735bba97..a244706871 100644 --- a/s2-site/examples/custom/custom-plugins/API.zh.md +++ b/s2-site/examples/custom/custom-plugins/API.zh.md @@ -1,5 +1,4 @@ --- title: API -order: 7 +order: 10 --- - diff --git a/s2-site/examples/custom/custom-plugins/demo/meta.json b/s2-site/examples/custom/custom-plugins/demo/meta.json index e47dfad462..eaa3596197 100644 --- a/s2-site/examples/custom/custom-plugins/demo/meta.json +++ b/s2-site/examples/custom/custom-plugins/demo/meta.json @@ -5,7 +5,7 @@ }, "demos": [ { - "filename": "custom-g-plugins.ts", + "filename": "custom-plugins.ts", "title": { "zh": "自定义 AntV/G 5.0 插件和配置", "en": "custom AntV/G 5.0 plugins and config" diff --git a/s2-site/examples/custom/custom-plugins/index.en.md b/s2-site/examples/custom/custom-plugins/index.en.md index b2ec22e29f..6e4bdb97e2 100644 --- a/s2-site/examples/custom/custom-plugins/index.en.md +++ b/s2-site/examples/custom/custom-plugins/index.en.md @@ -1,4 +1,4 @@ --- -title: custom tree -order: 7 +title: Custom AntV/G 5.0 Plugins & Options +order: 10 --- diff --git a/s2-site/examples/custom/custom-plugins/index.zh.md b/s2-site/examples/custom/custom-plugins/index.zh.md index 421d7bde96..538fa8e2e5 100644 --- a/s2-site/examples/custom/custom-plugins/index.zh.md +++ b/s2-site/examples/custom/custom-plugins/index.zh.md @@ -1,4 +1,4 @@ --- -title: 自定义目录树 -order: 7 +title: 自定义 AntV/G 5.0 插件和配置 +order: 10 --- diff --git a/s2-site/package.json b/s2-site/package.json index c5b8f4f92e..a9ff578ec7 100644 --- a/s2-site/package.json +++ b/s2-site/package.json @@ -28,18 +28,19 @@ }, "dependencies": { "@ant-design/icons": "^5.2.6", - "@antv/dumi-theme-antv": "^0.4.3", + "@antv/dumi-theme-antv": "^0.4.4", "@antv/g-canvas": "^1.11.24", + "@antv/g-plugin-a11y": "^0.6.19", + "@antv/g-plugin-rough-canvas-renderer": "^1.9.24", + "@antv/g2": "^5.1.10", "@antv/s2": "next", "@antv/s2-react": "next", - "antd": "^5.11.2", + "antd": "^5.11.5", "copy-to-clipboard": "^3.3.3", "dumi": "^2.2.14", - "gh-pages": "^3.1.0", + "gh-pages": "^6.1.0", "lodash": "^4.17.21", - "react-color": "^2.19.3", - "@antv/g-plugin-a11y": "^0.6.19", - "@antv/g-plugin-rough-canvas-renderer": "^1.9.24" + "react-color": "^2.19.3" }, "devDependencies": { "@google-cloud/translate": "^7.0.3", @@ -59,7 +60,6 @@ "unist-util-visit": "^4.1.1" }, "tnpm": { - "mode": "yarn", - "lockfile": "enable" + "mode": "pnpm" } } From 898955136dd8270824202c245356e6d6578550fa Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Fri, 1 Dec 2023 10:13:36 +0800 Subject: [PATCH 06/15] test: fix --- .../interaction-brush-selection-scroll-spec.ts | 4 ++++ .../s2-core/__tests__/spreadsheet/spread-sheet-spec.ts | 9 +++++++++ .../__tests__/unit/sheet-type/pivot-sheet-spec.ts | 3 ++- packages/s2-core/src/utils/tooltip.ts | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts b/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts index 7ccb885f6a..a1a8739ac9 100644 --- a/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts +++ b/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts @@ -143,6 +143,8 @@ const expectScrollBrush = async ( const allCells = s2.interaction.getCells(); const lastCell = allCells[allCells.length - 1]; + await sleep(500); + expect(s2.facet.getScrollOffset().scrollY).toBeGreaterThan(0); expect(brushRange.start.colIndex).toBe(allCells[0].colIndex); expect(brushRange.start.rowIndex).toBe(allCells[0].rowIndex); @@ -238,6 +240,7 @@ describe('PivotSheet Brush Selection Scroll Tests', () => { } as any); await emitBrushEvent(s2, 200, 200); + await sleep(500); expect(s2.facet.getScrollOffset().scrollY).toBeGreaterThan(0); expect(s2.interaction.getCells()).not.toBeEmpty(); @@ -280,6 +283,7 @@ describe('PivotSheet Brush Selection Scroll Tests', () => { // 只刷选 [省份] await emitBrushEvent(s2, 100, 200); + await sleep(500); // 只选中 [浙江省, 四川省] expect(s2.facet.getScrollOffset().scrollY).toBeGreaterThan(0); diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-spec.ts index 44537bec4c..955b611046 100644 --- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-spec.ts +++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-spec.ts @@ -140,6 +140,8 @@ describe('SpreadSheet Tests', () => { s2.updateScrollOffset({ offsetX: { value: 30 }, }); + await sleep(500); + expect(s2.facet.hScrollBar.current()).toBeGreaterThan(0); expect(s2.facet.getScrollOffset()).toMatchInlineSnapshot(` Object { @@ -165,6 +167,8 @@ describe('SpreadSheet Tests', () => { s2.updateScrollOffset({ offsetY: { value: 20 }, }); + + await sleep(500); expect(s2.facet.vScrollBar.current()).toBeGreaterThan(0); expect(s2.facet.getScrollOffset()).toMatchInlineSnapshot(` Object { @@ -200,6 +204,8 @@ describe('SpreadSheet Tests', () => { s2.updateScrollOffset({ rowHeaderOffsetX: { value: 30 }, }); + + await sleep(500); expect(s2.facet.hRowScrollBar.current()).toBeGreaterThan(0); expect(s2.facet.getScrollOffset()).toMatchInlineSnapshot(` Object { @@ -230,6 +236,9 @@ describe('SpreadSheet Tests', () => { offsetX: { value: 30 }, rowHeaderOffsetX: { value: 40 }, }); + + await sleep(500); + expect(s2.facet.vScrollBar.current()).toBeGreaterThan(0); expect(s2.facet.hScrollBar.current()).toBeGreaterThan(0); expect(s2.facet.hRowScrollBar.current()).toBeGreaterThan(0); 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 7b9fde6396..35f4efca83 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 @@ -3,7 +3,7 @@ import { Canvas, CanvasEvent } from '@antv/g'; import { cloneDeep, get, last } from 'lodash'; import dataCfg from 'tests/data/simple-data.json'; import { waitForRender } from 'tests/util'; -import { createPivotSheet, getContainer } from 'tests/util/helpers'; +import { createPivotSheet, getContainer, sleep } from 'tests/util/helpers'; import type { BaseEvent, BaseTooltipOperatorMenuOptions, @@ -535,6 +535,7 @@ describe('PivotSheet Tests', () => { sheet.on(S2Event.LAYOUT_CELL_RENDER, layoutCellRender); await sheet.render(); + await sleep(500); expect(dataCellRender).toHaveBeenCalledTimes(8); expect(layoutCellRender).toHaveBeenCalledTimes(20); diff --git a/packages/s2-core/src/utils/tooltip.ts b/packages/s2-core/src/utils/tooltip.ts index f061b29c34..f457d8c998 100644 --- a/packages/s2-core/src/utils/tooltip.ts +++ b/packages/s2-core/src/utils/tooltip.ts @@ -712,7 +712,7 @@ export const getTooltipOptions = ( return getTooltipOptionsByCellType( options.tooltip!, - cellType || sampleCell.cellType!, + cellType || sampleCell?.cellType!, ); }; From 0e642cd5c8f079e084ccaba14f969ae720fab77b Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Fri, 1 Dec 2023 17:24:34 +0800 Subject: [PATCH 07/15] =?UTF-8?q?test:=20=E4=BF=AE=E5=A4=8D=E5=8D=95?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spreadsheet/spread-sheet-spec.tsx | 11 ++- .../__snapshots__/index-spec.tsx.snap | 2 +- .../__snapshots__/index-spec.tsx.snap | 10 +-- .../export/__snapshots__/index-spec.tsx.snap | 2 +- .../header/__snapshots__/index-spec.tsx.snap | 8 +-- .../__snapshots__/index-spec.tsx.snap | 4 +- .../sheets/__snapshots__/index-spec.tsx.snap | 70 +++++++++---------- .../__snapshots__/index-spec.tsx.snap | 2 +- .../__snapshots__/index-spec.tsx.snap | 2 +- .../tooltip/__snapshots__/index-spec.tsx.snap | 12 ++-- 10 files changed, 66 insertions(+), 57 deletions(-) diff --git a/packages/s2-react/__tests__/spreadsheet/spread-sheet-spec.tsx b/packages/s2-react/__tests__/spreadsheet/spread-sheet-spec.tsx index ca339c07fc..dac18da612 100644 --- a/packages/s2-react/__tests__/spreadsheet/spread-sheet-spec.tsx +++ b/packages/s2-react/__tests__/spreadsheet/spread-sheet-spec.tsx @@ -60,6 +60,11 @@ describe('Spread Sheet Tests', () => { test('should only mount container once in strict mode for React 18', async () => { // eslint-disable-next-line no-console console.table(process.env); + + const containerId = 'mounted-react-18'; + + container.id = containerId; + const onMounted = jest.fn(); renderComponent( @@ -76,7 +81,11 @@ describe('Spread Sheet Tests', () => { await waitFor(() => { expect( - Array.from(document.querySelectorAll('.antv-s2-container canvas')), + Array.from( + document + .getElementById(containerId)! + .querySelectorAll('.antv-s2-container canvas'), + ), ).toHaveLength(1); expect(onMounted).toHaveBeenCalledTimes(1); }); diff --git a/packages/s2-react/__tests__/unit/components/advanced-sort/__snapshots__/index-spec.tsx.snap b/packages/s2-react/__tests__/unit/components/advanced-sort/__snapshots__/index-spec.tsx.snap index 1a242c3932..779840c6b5 100644 --- a/packages/s2-react/__tests__/unit/components/advanced-sort/__snapshots__/index-spec.tsx.snap +++ b/packages/s2-react/__tests__/unit/components/advanced-sort/__snapshots__/index-spec.tsx.snap @@ -6,7 +6,7 @@ exports[`AdvancedSort Component Tests should render component 1`] = ` class="antv-s2-advanced-sort test" >