diff --git a/packages/s2-core/__tests__/bugs/issue-2340-spec.ts b/packages/s2-core/__tests__/bugs/issue-2340-spec.ts index 33f194d379..c4d095c4c9 100644 --- a/packages/s2-core/__tests__/bugs/issue-2340-spec.ts +++ b/packages/s2-core/__tests__/bugs/issue-2340-spec.ts @@ -31,6 +31,9 @@ describe('Header Brush Selection Tests', () => { await s2.render(); const isRow = cellType === CellType.ROW_CELL; + const stateName = isRow + ? InteractionStateName.ROW_CELL_BRUSH_SELECTED + : InteractionStateName.COL_CELL_BRUSH_SELECTED; const targetCells = isRow ? s2.facet.getRowCells() : s2.facet.getColCells(); @@ -45,7 +48,7 @@ describe('Header Brush Selection Tests', () => { s2.interaction.changeState({ cells: cells.map(getCellMeta), - stateName: InteractionStateName.BRUSH_SELECTED, + stateName, }); await sleep(500); @@ -65,9 +68,7 @@ describe('Header Brush Selection Tests', () => { }); expect(s2.interaction.getActiveCells()).toHaveLength(1); - expect(s2.interaction.getCurrentStateName()).toEqual( - InteractionStateName.BRUSH_SELECTED, - ); + expect(s2.interaction.getCurrentStateName()).toEqual(stateName); // 交互过的不应该有 dataCell (未触发过列头多选) s2.interaction.getInteractedCells().forEach((cell) => { 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 d89c6f5beb..86f24da64e 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 @@ -128,7 +128,7 @@ const expectScrollBrush = async ( s2.on(S2Event.GLOBAL_SELECTED, selectedFn); s2.on(S2Event.DATA_CELL_BRUSH_SELECTION, dataCellBrushSelectionFn); - // TODO: g5.0 异步渲染,第一时刻底层base-brush可能无法通过elementsFromPointSync取到元素 + // g5.0 异步渲染,第一时刻底层 base-brush 可能无法通过 elementsFromPointSync 取到元素 await sleep(50); s2.emit(mouseDownEventType, { 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 fcbc34d9ae..de72f7ae68 100644 --- a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts +++ b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts @@ -111,6 +111,7 @@ describe('Data Cell Tests', () => { getRowLeafNodes: () => [], getRowLeafNodeByIndex: jest.fn(), getCells: () => [], + destroy: jest.fn(), } as unknown as PivotFacet; await s2.render(); @@ -222,6 +223,7 @@ describe('Data Cell Tests', () => { getRowLeafNodes: () => [], getRowLeafNodeByIndex: jest.fn(), getCells: () => [], + destroy: jest.fn(), } as unknown as PivotFacet; await s2.render(); diff --git a/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts b/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts index 57ba406a56..f599bd1ef2 100644 --- a/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts @@ -177,7 +177,6 @@ describe('Interaction Event Controller Tests', () => { OriginEventType.POINTER_UP, OriginEventType.MOUSE_OUT, GEventType.RIGHT_MOUSE_UP, - OriginEventType.DOUBLE_CLICK, OriginEventType.CLICK, OriginEventType.TOUCH_START, ]; diff --git a/packages/s2-core/__tests__/unit/utils/text-spec.ts b/packages/s2-core/__tests__/unit/utils/text-spec.ts index 4829de77ab..ed290c5faa 100644 --- a/packages/s2-core/__tests__/unit/utils/text-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/text-spec.ts @@ -2,8 +2,6 @@ import { createPivotSheet } from 'tests/util/helpers'; import type { TextTheme } from '../../../src/common'; import { ELLIPSIS_SYMBOL } from '@/common'; import { - getEllipsisText, - getEllipsisTextInner, isUpDataValue, getCellWidth, getEmptyPlaceholder, @@ -31,88 +29,15 @@ describe('Text Utils Tests', () => { ).measureTextWidth; }); - test('should get correct text', () => { - const text = getEllipsisText({ - measureTextWidth, - text: '12', - maxWidth: 200, - placeholder: '--', - }); - - expect(text).toEqual('12'); - }); - test('should get ellipsis symbol', () => { expect(ELLIPSIS_SYMBOL).toEqual('...'); }); - test('should get correct text ellipsis', () => { - const text = getEllipsisText({ - measureTextWidth, - text: '12121212121212121212', - maxWidth: 20, - placeholder: '--', - }); - - expect(text).toEndWith(ELLIPSIS_SYMBOL); - expect(text.length).toBeLessThanOrEqual(5); - }); - - test('should get correct placeholder text with ""', () => { - const text = getEllipsisText({ - measureTextWidth, - text: '', - maxWidth: 20, - placeholder: '--', - }); - - expect(text).toEqual('--'); - }); - - test('should get correct placeholder text with 0', () => { - const text = getEllipsisText({ - measureTextWidth, - text: 0 as unknown as string, - maxWidth: 20, - placeholder: '--', - }); - - expect(text).toEqual('0'); - }); - - test('should get correct placeholder text with null', () => { - const text = getEllipsisText({ - measureTextWidth, - text: null, - maxWidth: 20, - placeholder: '--', - }); - - expect(text).toEqual('--'); - }); - - test('should get correct ellipsis text', () => { - const text = getEllipsisText({ - measureTextWidth, - text: '长度测试', - maxWidth: 24, - }); - - expect(text).toEndWith(ELLIPSIS_SYMBOL); - expect(text.length).toBeLessThanOrEqual(4); - }); - test('should get correct text width', () => { const width = measureTextWidth('test', font); expect(Math.floor(width)).toEqual(isHD ? 21 : 16); }); - - test('should get correct ellipsis text inner', () => { - const text = getEllipsisTextInner(measureTextWidth, 'test', 15, font); - - expect(text).toEqual('t...'); - }); }); test.each` diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 753a367ed5..d226657365 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -236,6 +236,7 @@ export class DataCell extends BaseCell { switch (stateName) { case InteractionStateName.SELECTED: + case InteractionStateName.DATA_CELL_BRUSH_SELECTED: this.handleSelect(cells); break; case InteractionStateName.HOVER_FOCUS: @@ -364,7 +365,6 @@ export class DataCell extends BaseCell { const rowMeta = this.spreadsheet.dataSet.getFieldMeta(rowId!); const fieldId = rowMeta ? rowId : valueField; const formatter = this.spreadsheet.dataSet.getFieldFormatter(fieldId!); - // TODO: 这里只用 formatter(fieldValue, this.meta) 即可, 为了保持兼容, 暂时在第三个参入传入 meta 信息 const formattedValue = displayFormattedValue ?? formatter(fieldValue, data, this.meta); diff --git a/packages/s2-core/src/cell/header-cell.ts b/packages/s2-core/src/cell/header-cell.ts index 9edae0b968..63fb383aa6 100644 --- a/packages/s2-core/src/cell/header-cell.ts +++ b/packages/s2-core/src/cell/header-cell.ts @@ -450,7 +450,8 @@ export abstract class HeaderCell< switch (stateInfo?.stateName) { case InteractionStateName.SELECTED: - case InteractionStateName.BRUSH_SELECTED: + case InteractionStateName.ROW_CELL_BRUSH_SELECTED: + case InteractionStateName.COL_CELL_BRUSH_SELECTED: this.handleSelect(cells, stateInfo?.nodes); break; case InteractionStateName.HOVER_FOCUS: diff --git a/packages/s2-core/src/common/constant/interaction.ts b/packages/s2-core/src/common/constant/interaction.ts index c8f7f8a641..150106fbd0 100644 --- a/packages/s2-core/src/common/constant/interaction.ts +++ b/packages/s2-core/src/common/constant/interaction.ts @@ -17,7 +17,9 @@ export enum InteractionName { export enum InteractionStateName { ALL_SELECTED = 'allSelected', SELECTED = 'selected', - BRUSH_SELECTED = 'brushSelected', + ROW_CELL_BRUSH_SELECTED = 'rowCellBrushSelected', + COL_CELL_BRUSH_SELECTED = 'colCellBrushSelected', + DATA_CELL_BRUSH_SELECTED = 'dataCellBrushSelected', UNSELECTED = 'unselected', HOVER = 'hover', HOVER_FOCUS = 'hoverFocus', diff --git a/packages/s2-core/src/common/constant/options.ts b/packages/s2-core/src/common/constant/options.ts index 9cc6b96ffc..f995c3d059 100644 --- a/packages/s2-core/src/common/constant/options.ts +++ b/packages/s2-core/src/common/constant/options.ts @@ -135,25 +135,3 @@ export const DEFAULT_OPTIONS: S2Options = { cornerExtraFieldText: '', placeholder: EMPTY_PLACEHOLDER, }; - -const mobileWidth = document.documentElement.clientWidth; - -export const DEFAULT_MOBILE_OPTIONS: S2Options = { - width: mobileWidth - 40, - height: 380, - style: { - layoutWidthType: LayoutWidthType.ColAdaptive, - }, - interaction: { - hoverHighlight: false, - hoverFocus: false, - brushSelection: { - dataCell: false, - rowCell: false, - colCell: false, - }, - multiSelection: false, - rangeSelection: false, - }, - device: DeviceType.MOBILE, -} as const; diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index eac6970090..e35439c15d 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -946,7 +946,6 @@ export abstract class BaseFacet { scrollBar?.thumbHorizontalMinSize!, ); - // TODO abstract this.hScrollBar = new ScrollBar({ isHorizontal: true, trackLen: finalWidth, diff --git a/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts b/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts index 5b1c6aa21d..e169f6d8e3 100644 --- a/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts @@ -15,10 +15,9 @@ const addTotals = ( ) => { const totalsConfig = spreadsheet.getTotalsConfig(currentField); - /* + /** * tree mode only has grand totals, but if there are subTotals configs, * it will display in cross-area cell - * TODO valueInCol = false and one or more values */ if (totalsConfig?.showGrandTotals) { const func = totalsConfig.reverseGrandTotalsLayout ? 'unshift' : 'push'; @@ -95,7 +94,8 @@ export const buildRowTreeHierarchy = (params: TreeHeaderParams) => { const { collapseFields, collapseAll, expandDepth } = spreadsheet.options.style?.rowCell!; - /* + + /** * 行头收起/展开配置优先级:collapseFields -> expandDepth -> collapseAll * 优先从读取 collapseFields 中的特定 node 的值 * 如果没有特定配置,再查看是否配置了层级展开配置, diff --git a/packages/s2-core/src/facet/layout/node.ts b/packages/s2-core/src/facet/layout/node.ts index fc048bb4c9..083851dbee 100644 --- a/packages/s2-core/src/facet/layout/node.ts +++ b/packages/s2-core/src/facet/layout/node.ts @@ -74,7 +74,7 @@ export class Node { // node height public height = 0; - // cell index in layout list(TODO What's use for?) + // cell index in layout list public colIndex = -1; // node's level in tree hierarchy diff --git a/packages/s2-core/src/interaction/brush-selection/base-brush-selection.ts b/packages/s2-core/src/interaction/brush-selection/base-brush-selection.ts index 6e6f550d94..5fdda45839 100644 --- a/packages/s2-core/src/interaction/brush-selection/base-brush-selection.ts +++ b/packages/s2-core/src/interaction/brush-selection/base-brush-selection.ts @@ -668,7 +668,6 @@ export class BaseBrushSelection }; protected mouseDown(event: CanvasEvent) { - event?.preventDefault?.(); if (this.spreadsheet.interaction.hasIntercepts([InterceptType.CLICK])) { return; } diff --git a/packages/s2-core/src/interaction/brush-selection/col-brush-selection.ts b/packages/s2-core/src/interaction/brush-selection/col-brush-selection.ts index 7f7cbc3233..91df1e8257 100644 --- a/packages/s2-core/src/interaction/brush-selection/col-brush-selection.ts +++ b/packages/s2-core/src/interaction/brush-selection/col-brush-selection.ts @@ -107,7 +107,7 @@ export class ColCellBrushSelection extends BaseBrushSelection { onUpdateCells: (root) => { root.updateCells(facet.getColCells()); }, - stateName: InteractionStateName.BRUSH_SELECTED, + stateName: InteractionStateName.COL_CELL_BRUSH_SELECTED, }); this.spreadsheet.emit( diff --git a/packages/s2-core/src/interaction/brush-selection/data-cell-brush-selection.ts b/packages/s2-core/src/interaction/brush-selection/data-cell-brush-selection.ts index 947d8626a1..948e24dc23 100644 --- a/packages/s2-core/src/interaction/brush-selection/data-cell-brush-selection.ts +++ b/packages/s2-core/src/interaction/brush-selection/data-cell-brush-selection.ts @@ -104,8 +104,7 @@ export class DataCellBrushSelection extends BaseBrushSelection { this.spreadsheet.interaction.changeState({ cells: selectedCellMetas, - // TODO: 怕上层有直接消费 stateName, 暂时保留, 2.0 版本改成 InteractionStateName.BRUSH_SELECTED - stateName: InteractionStateName.SELECTED, + stateName: InteractionStateName.DATA_CELL_BRUSH_SELECTED, onUpdateCells: afterSelectDataCells, }); diff --git a/packages/s2-core/src/interaction/brush-selection/row-brush-selection.ts b/packages/s2-core/src/interaction/brush-selection/row-brush-selection.ts index f30dc0c065..5298437bb3 100644 --- a/packages/s2-core/src/interaction/brush-selection/row-brush-selection.ts +++ b/packages/s2-core/src/interaction/brush-selection/row-brush-selection.ts @@ -103,7 +103,7 @@ export class RowCellBrushSelection extends BaseBrushSelection { this.spreadsheet.interaction.changeState({ cells: selectedCellMetas, - stateName: InteractionStateName.BRUSH_SELECTED, + stateName: InteractionStateName.ROW_CELL_BRUSH_SELECTED, onUpdateCells: this.onUpdateCells, }); diff --git a/packages/s2-core/src/interaction/event-controller.ts b/packages/s2-core/src/interaction/event-controller.ts index a40fbc8fd2..24633b117c 100644 --- a/packages/s2-core/src/interaction/event-controller.ts +++ b/packages/s2-core/src/interaction/event-controller.ts @@ -83,8 +83,6 @@ export class EventController { this.addCanvasEvent(OriginEventType.POINTER_MOVE, this.onCanvasMousemove); this.addCanvasEvent(OriginEventType.MOUSE_OUT, this.onCanvasMouseout); this.addCanvasEvent(OriginEventType.POINTER_UP, this.onCanvasMouseup); - // TODO: g5.0 目前没支持 dbclick 事件 - this.addCanvasEvent(OriginEventType.DOUBLE_CLICK, this.onCanvasDoubleClick); this.addCanvasEvent(GEventType.RIGHT_MOUSE_UP, this.onCanvasContextMenu); // spreadsheet events diff --git a/packages/s2-core/src/interaction/root.ts b/packages/s2-core/src/interaction/root.ts index 305a13963c..5dd1be12cc 100644 --- a/packages/s2-core/src/interaction/root.ts +++ b/packages/s2-core/src/interaction/root.ts @@ -146,10 +146,14 @@ export class RootInteraction { } public isSelectedState() { - return ( - this.isStateOf(InteractionStateName.SELECTED) || - this.isStateOf(InteractionStateName.BRUSH_SELECTED) - ); + return [ + InteractionStateName.SELECTED, + InteractionStateName.ROW_CELL_BRUSH_SELECTED, + InteractionStateName.COL_CELL_BRUSH_SELECTED, + InteractionStateName.DATA_CELL_BRUSH_SELECTED, + ].some((stateName) => { + return this.isStateOf(stateName); + }); } public isAllSelectedState() { diff --git a/packages/s2-core/src/interaction/row-column-resize.ts b/packages/s2-core/src/interaction/row-column-resize.ts index e7a6d88333..88c75a8645 100644 --- a/packages/s2-core/src/interaction/row-column-resize.ts +++ b/packages/s2-core/src/interaction/row-column-resize.ts @@ -439,8 +439,6 @@ export class RowColumnResize extends BaseEvent implements BaseEventImplement { return; } - event?.preventDefault?.(); - const resizeInfo = this.getResizeInfo(); const resizeShapes = (this.resizeReferenceGroup?.children as DisplayObject[]) || []; diff --git a/packages/s2-core/src/utils/cell/cell.ts b/packages/s2-core/src/utils/cell/cell.ts index 8b04d6a7f9..bdb8f7af7e 100644 --- a/packages/s2-core/src/utils/cell/cell.ts +++ b/packages/s2-core/src/utils/cell/cell.ts @@ -200,7 +200,7 @@ export const getBorderPositionAndStyle = ( borderDash, } = style; - // TODO: 如果是空数组 G 底层绘制会报错 + // 如果是空数组 G 底层绘制会报错 const lineDash: LineStyleProps['lineDash'] = isEmpty(borderDash) ? '' : borderDash; diff --git a/packages/s2-core/src/utils/export/copy/core.ts b/packages/s2-core/src/utils/export/copy/core.ts index 561355b51f..040a55a0b8 100644 --- a/packages/s2-core/src/utils/export/copy/core.ts +++ b/packages/s2-core/src/utils/export/copy/core.ts @@ -17,13 +17,11 @@ import { } from '../../../common/interface/export'; import { getBrushHeaderCopyable } from './pivot-header-copy'; import { - processSelectedAllPivot, - processSelectedAllPivotAsync, + asyncProcessSelectedAllPivot, processSelectedPivotByDataCell, processSelectedPivotByHeader, } from './pivot-data-cell-copy'; import { - processSelectedAllTable, asyncProcessSelectedAllTable, processSelectedTableByDataCell, processSelectedTableByHeader, @@ -206,27 +204,14 @@ export const getSelectedData = (spreadsheet: SpreadSheet): CopyableList => { return data!; }; -// 全量导出使用 -export const processAllSelected = (params: CopyAllDataParams): CopyableList => { - const { sheetInstance } = params; - - if (sheetInstance.isPivotMode()) { - const result = processSelectedAllPivot(params); - - return result; - } - - return processSelectedAllTable(params); -}; - -// 异步全量导出使用 -export const processAllSelectedAsync = ( +// 异步全量导出 +export const asyncProcessAllSelected = ( params: CopyAllDataParams, ): Promise => { const { sheetInstance } = params; if (sheetInstance.isPivotMode()) { - return processSelectedAllPivotAsync(params); + return asyncProcessSelectedAllPivot(params); } return asyncProcessSelectedAllTable(params); 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 10c39d81c2..4916d52c16 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 @@ -461,7 +461,7 @@ export const processSelectedAllPivot = ( return pivotDataCellCopy.getPivotAllCopyData(); }; -export const processSelectedAllPivotAsync = ( +export const asyncProcessSelectedAllPivot = ( params: CopyAllDataParams, ): Promise => { const { sheetInstance, split, formatOptions, customTransformer } = params; diff --git a/packages/s2-core/src/utils/export/copy/table-copy.ts b/packages/s2-core/src/utils/export/copy/table-copy.ts index f49a674cab..66b7d2abfe 100644 --- a/packages/s2-core/src/utils/export/copy/table-copy.ts +++ b/packages/s2-core/src/utils/export/copy/table-copy.ts @@ -199,8 +199,6 @@ class TableDataCellCopy extends BaseDataCellCopy { /** * allSelected: false 时,明细表点击 行头/列头 进行复制逻辑 * allSelected: true 时,明细表点击 全选 进行复制逻辑 - * @param {boolean} allSelected - * @return {CopyableList} * @deprecated 后续将废弃,使用 asyncProcessSelectedTable 替代 */ processSelectedTable(allSelected = false): CopyableList { @@ -239,47 +237,23 @@ class TableDataCellCopy extends BaseDataCellCopy { /** * 明细表点击行头进行复制逻辑 * @param {SpreadSheet} spreadsheet - * @param {CellMeta[]} selectedRowsOrCols + * @param {CellMeta[]} selectedHeaders * @return {CopyableList} */ export const processSelectedTableByHeader = ( spreadsheet: SpreadSheet, - selectedRowsOrCols: CellMeta[], + selectedHeaders: CellMeta[], ): CopyableList => { const tableDataCellCopy = new TableDataCellCopy({ spreadsheet, config: { - selectedCells: selectedRowsOrCols, + selectedCells: selectedHeaders, }, }); return tableDataCellCopy.processSelectedTable(); }; -/** - * 导出全部数据 - * @param {CopyAllDataParams} params - * @return {CopyableList} - * @deprecated 后续将废弃,使用 asyncProcessSelectedAllTable 替代 - */ -export const processSelectedAllTable = ( - params: CopyAllDataParams, -): CopyableList => { - const { sheetInstance, split, formatOptions, customTransformer } = params; - const tableDataCellCopy = new TableDataCellCopy({ - spreadsheet: sheetInstance, - config: { - selectedCells: [], - separator: split, - formatOptions, - customTransformer, - }, - isExport: true, - }); - - return tableDataCellCopy.processSelectedTable(true); -}; - // 导出全部数据 export const asyncProcessSelectedAllTable = ( params: CopyAllDataParams, diff --git a/packages/s2-core/src/utils/export/utils.ts b/packages/s2-core/src/utils/export/utils.ts index e6917642ae..4525ffb91c 100644 --- a/packages/s2-core/src/utils/export/utils.ts +++ b/packages/s2-core/src/utils/export/utils.ts @@ -5,7 +5,7 @@ import { type Copyable, type CopyableItem, } from '../../common/interface/export'; -import { processAllSelected, processAllSelectedAsync } from './copy/core'; +import { asyncProcessAllSelected } from './copy/core'; /** * 同步复制 @@ -115,18 +115,6 @@ export const download = (dataString: string, fileName: string) => { } }; -/** - * 同步获取文本数据 - * @param params CopyAllDataParams - * @deprecated 后续将废弃方法,将使用 asyncGetAllPlainData - */ - -export const getAllPlainData = (params: CopyAllDataParams) => { - const result = processAllSelected(params); - - return result[0].content; -}; - /** * 异步获取文本数据 * @example @@ -137,7 +125,7 @@ export const getAllPlainData = (params: CopyAllDataParams) => { }); */ export const asyncGetAllPlainData = async (params: CopyAllDataParams) => { - const result = await processAllSelectedAsync(params); + const result = await asyncProcessAllSelected(params); return result[0].content; }; diff --git a/packages/s2-core/src/utils/g-mini-charts.ts b/packages/s2-core/src/utils/g-mini-charts.ts index b36b94343e..5d714642ec 100644 --- a/packages/s2-core/src/utils/g-mini-charts.ts +++ b/packages/s2-core/src/utils/g-mini-charts.ts @@ -97,7 +97,6 @@ export const scale = (chartData: BaseChartData, cell: S2CellType) => { positionY = baseLinePositionY; } } else { - // TODO 之后看需不需要把基准线画出来 baseLinePositionY = minMeasure < 0 ? yStart : yEnd; measureRange = max([Math.abs(maxMeasure), Math.abs(minMeasure)])!; barHeight = @@ -178,7 +177,6 @@ export const drawBar = (chartData: BaseChartData, cell: S2CellType) => { y: points[i][1], width: box[i][0], height: box[i][1], - // TODO: 支持色板配置 fill: bar.fill, fillOpacity: bar.opacity, }); @@ -345,9 +343,8 @@ export const drawBullet = (value: BulletValue, cell: S2CellType) => { const bulletWidth = widthPercent * contentWidth; const measureWidth = contentWidth - bulletWidth; - /* - * TODO 先支持默认右对齐 - * 绘制子弹图 + /** + * 绘制子弹图 (右对齐) * 1. 背景 */ const positionX = x + width - padding.right - bulletWidth; diff --git a/packages/s2-core/src/utils/text.ts b/packages/s2-core/src/utils/text.ts index 224c6682d7..11233f8a1c 100644 --- a/packages/s2-core/src/utils/text.ts +++ b/packages/s2-core/src/utils/text.ts @@ -5,16 +5,13 @@ import { isFunction, isNil, isNumber, - isString, map, size, - toString, trim, } from 'lodash'; import type { ColCell } from '../cell'; import { CellType, - ELLIPSIS_SYMBOL, EMPTY_FIELD_VALUE, EMPTY_PLACEHOLDER, } from '../common/constant'; @@ -55,216 +52,6 @@ export const getDisplayText = ( return isEmptyText ? emptyPlaceholder : `${text}`; }; -/** - * 获取文本的 ... 文本。 - * 算法(减少每次 measureText 的长度,measureText 的性能跟字符串时间相关): - * 1. 先通过 STEP 逐步计算,找到最后一个小于 maxWidth 的字符串 - * 2. 然后对最后这个字符串二分计算 - * @param measureTextWidth 文本宽度预估函数 - * @param text 需要计算的文本, 由于历史原因 除了支持string,还支持空值,number和数组等 - * @param maxWidth - * @param font - * @deprecated - */ -export const getEllipsisTextInner = ( - measureTextWidth: (text: number | string, font: unknown) => number, - text: any, - maxWidth: number, - font: TextTheme, -) => { - // 每次 16,调参工程师 - const STEP = 16; - const DOT_WIDTH = measureTextWidth(ELLIPSIS_SYMBOL, font); - - let leftText; - - if (!isString(text)) { - leftText = toString(text); - } else { - leftText = text; - } - - let leftWidth = maxWidth; - - // 最终的分段字符串 - const r = []; - let currentText; - let currentWidth; - - if (measureTextWidth(text, font) <= maxWidth) { - return text; - } - - let runningStep1 = true; - - // 首先通过 step 计算,找出最大的未超出长度的 - while (runningStep1) { - // 更新字符串 - currentText = leftText.substr(0, STEP); - - // 计算宽度 - currentWidth = measureTextWidth(currentText, font); - - // 超出剩余宽度,则停止 - if (currentWidth + DOT_WIDTH > leftWidth) { - if (currentWidth > leftWidth) { - runningStep1 = false; - break; - } - } - - r.push(currentText); - - // 没有超出,则计算剩余宽度 - leftWidth -= currentWidth; - leftText = leftText.substr(STEP); - - // 字符串整体没有超出 - if (!leftText) { - return r.join(''); - } - } - - let runningStep2 = true; - - // 最下的最后一个 STEP,使用 1 递增(用二分效果更高) - while (runningStep2) { - // 更新字符串 - currentText = leftText.substr(0, 1); - - // 计算宽度 - currentWidth = measureTextWidth(currentText, font); - - // 超出剩余宽度,则停止 - if (currentWidth + DOT_WIDTH > leftWidth) { - runningStep2 = false; - break; - } - - r.push(currentText); - // 没有超出,则计算剩余宽度 - leftWidth -= currentWidth; - leftText = leftText.substr(1); - - if (!leftText) { - return r.join(''); - } - } - - return `${r.join('')}...`; -}; - -/** - * @desc 改良版 获取文本的 ... 文本(可传入 优先文本片段) - * @param measureTextWidth 文本长度计算函数 - * @param text 需要计算的文本 - * @param maxWidth - * @param font optional 文本字体 或 优先显示的文本 - * @param priority optional 优先显示的文本 - * @deprecated - */ -export const getEllipsisText = ({ - measureTextWidth, - text, - maxWidth, - fontParam, - priorityParam, - placeholder, -}: { - measureTextWidth: (text: number | string, font: unknown) => number; - text: string | number | null | undefined; - maxWidth: number; - fontParam?: TextTheme; - priorityParam?: string[]; - placeholder?: string; -}) => { - let font: TextTheme = {} as TextTheme; - let priority = priorityParam; - - const finalText = getDisplayText(text, placeholder); - - if (fontParam && isArray(fontParam)) { - priority = fontParam as string[]; - } else { - font = fontParam || ({} as TextTheme); - } - - if (!priority || !priority.length) { - return getEllipsisTextInner(measureTextWidth, finalText, maxWidth, font); - } - - const leftSubTexts: string[] = []; - let subTexts = [finalText]; - - priority.forEach((priorityItem) => { - subTexts.forEach((tempSubText, index) => { - // 处理 leftText - let startIdx = -1; - const matched = tempSubText.match(new RegExp(priorityItem)); - - if (matched?.index) { - const matchedText = matched[0]; - - startIdx = matched.index; - leftSubTexts.push(matchedText); - const endIdx = startIdx + matchedText.length; - const left = tempSubText.slice(0, startIdx); - const right = tempSubText.slice(endIdx); - const tmp = [left, right].filter((v) => !!v); - - subTexts.splice(index, 1, ...tmp); - } - }); - }); - - // original text is split into serval texts by priority - subTexts = leftSubTexts.concat(subTexts); - - let result = finalText; - const DOT_WIDTH = measureTextWidth(ELLIPSIS_SYMBOL, font); - let remainWidth = maxWidth; - - subTexts.forEach((subText) => { - if (remainWidth <= 0) { - const originIdx = result.indexOf(subText); - const prev = result.slice(originIdx - 3, originIdx); - - if (prev && prev !== ELLIPSIS_SYMBOL) { - const subWidth = measureTextWidth(subText, font); - - // fix-边界处理: when subWidth <= DOT_WIDTH 不做 ... 处理 - result = result.replace( - subText, - subWidth > DOT_WIDTH ? ELLIPSIS_SYMBOL : subText, - ); - } else { - result = result.replace(subText, ''); - } - - remainWidth -= DOT_WIDTH; - } else { - const subWidth = measureTextWidth(subText, font); - - // fix-边界处理: when subWidth <= DOT_WIDTH 不做 ... 处理 - if (remainWidth < subWidth && subWidth > DOT_WIDTH) { - const ellipsis = getEllipsisTextInner( - measureTextWidth, - subText, - remainWidth, - font, - ); - - result = result.replace(subText, ellipsis); - remainWidth = 0; - } else { - remainWidth -= subWidth; - } - } - }); - - return result; -}; - /** * To decide whether the data is positive or negative. * Two cases needed to be considered since the derived value could be number or string. 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 e8d4b6beff..ca93b3ca2b 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 @@ -80,8 +80,7 @@ describe(' Tests', () => { }); }); - // TODO: G2 发布新版后修复 - test.skip('should find canvas container for g2 library', async () => { + test('should find canvas container for g2 library', async () => { const errorSpy = jest .spyOn(console, 'error') .mockImplementationOnce(() => {}); diff --git a/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/__snapshots__/index-spec.tsx.snap b/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/__snapshots__/index-spec.tsx.snap deleted file mode 100644 index 8c0ca8acab..0000000000 --- a/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/__snapshots__/index-spec.tsx.snap +++ /dev/null @@ -1,28 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MobileSheet Tests get mobile default fragment 1`] = ` - -
-
-
-
- -
-
-
-
-
-`; diff --git a/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/index-spec.tsx b/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/index-spec.tsx deleted file mode 100644 index 970c47e39b..0000000000 --- a/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/index-spec.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { render, waitFor } from '@testing-library/react'; -import React from 'react'; -import { DEFAULT_MOBILE_OPTIONS, DeviceType, SpreadSheet } from '@antv/s2'; -import { pick } from 'lodash'; -import * as mockDataConfig from '../../../../data/simple-data.json'; -import { MobileSheet } from '../../../../../src/components/sheets/mobile-sheet'; - -describe('MobileSheet Tests', () => { - test('get mobile default option', async () => { - let s2: SpreadSheet; - - render( - { - s2 = s; - }} - />, - ); - - await waitFor(() => { - const interactionOptions = pick( - s2!.options.interaction, - Object.keys(DEFAULT_MOBILE_OPTIONS.interaction!), - ); - const { height, device } = s2!.options; - - expect(interactionOptions).toEqual(DEFAULT_MOBILE_OPTIONS.interaction); - expect(height).toEqual(300); - expect(device).toEqual(DeviceType.MOBILE); - }); - }); - - test('get mobile default fragment', () => { - const { asFragment } = render( - , - ); - - expect(asFragment()).toMatchSnapshot(); - }); -}); diff --git a/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/mobile-tooltip-spec.tsx b/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/mobile-tooltip-spec.tsx deleted file mode 100644 index 96c14b39d0..0000000000 --- a/packages/s2-react/__tests__/unit/components/sheets/mobile-sheet/mobile-tooltip-spec.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import type { SpreadSheet } from '@antv/s2'; -import { render, waitFor } from '@testing-library/react'; -import React from 'react'; -import { CustomTooltip } from '../../../../../src'; -import { SheetComponent } from '../../../../../src/components/sheets'; -import { MobileSheet } from '../../../../../src/components/sheets/mobile-sheet'; -import * as mockDataConfig from '../../../../data/simple-data.json'; - -describe('Mobile Tooltip Different Tests', () => { - test('SheetComponent hide tooltip do not trigger renderContent', async () => { - let s2: SpreadSheet; - let customTooltipInstance: CustomTooltip; - - render( - { - customTooltipInstance = new CustomTooltip(spreadsheet); - customTooltipInstance.renderContent = jest.fn(); - - return customTooltipInstance; - }, - }, - }} - onMounted={(s) => { - s2 = s; - }} - />, - ); - - await waitFor(() => { - s2!.showTooltip({ position: { x: 0, y: 0 }, content: '111' }); - expect(s2!.tooltip).toBeInstanceOf(CustomTooltip); - expect(s2!.tooltip.renderContent).toHaveBeenCalledTimes(1); - - s2!.hideTooltip(); - expect(s2!.tooltip.renderContent).toHaveBeenCalledTimes(1); - }); - }); - - test('hide tooltip trigger renderContent', async () => { - let s2: SpreadSheet; - let customTooltipInstance; - - render( - { - customTooltipInstance = new CustomTooltip(spreadsheet); - customTooltipInstance.renderContent = jest.fn(); - - return customTooltipInstance; - }, - }, - }} - onMounted={(s) => { - s2 = s; - }} - />, - ); - - await waitFor(() => { - s2!.showTooltip({ position: { x: 0, y: 0 }, content: '111' }); - expect(s2!.tooltip).toBeInstanceOf(CustomTooltip); - expect(s2!.tooltip.renderContent).toHaveBeenCalledTimes(1); - - s2!.hideTooltip(); - expect(s2!.tooltip.renderContent).toHaveBeenCalledTimes(2); - }); - }); - - test('show tooltip when visible is true', async () => { - let s2: SpreadSheet; - let customTooltipInstance; - - render( - { - customTooltipInstance = new CustomTooltip(spreadsheet); - customTooltipInstance.renderContent = jest.fn(); - - return customTooltipInstance; - }, - }, - }} - onMounted={(s) => { - s2 = s; - }} - />, - ); - - await waitFor(() => { - s2!.showTooltip({ position: { x: 0, y: 0 }, content: '111' }); - expect(s2!.tooltip.visible).toEqual(true); - }); - }); -}); diff --git a/packages/s2-react/__tests__/unit/components/tooltip/index-spec.tsx b/packages/s2-react/__tests__/unit/components/tooltip/index-spec.tsx index 480ad69e72..67d6d92505 100644 --- a/packages/s2-react/__tests__/unit/components/tooltip/index-spec.tsx +++ b/packages/s2-react/__tests__/unit/components/tooltip/index-spec.tsx @@ -1,18 +1,14 @@ import { DownCircleOutlined } from '@ant-design/icons'; import { - BaseTooltip, - SpreadSheet, getTooltipOperatorSortMenus, type S2CellType, - type TooltipOperatorMenuItem, type TooltipDetailListItem, + type TooltipOperatorMenuItem, type TooltipSummaryOptions, } from '@antv/s2'; -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React from 'react'; -import * as mockDataConfig from 'tests/data/simple-data.json'; -import { CustomTooltip, TooltipComponent } from '../../../../src'; -import { MobileSheet } from '../../../../src/components/sheets/mobile-sheet'; +import { TooltipComponent } from '../../../../src'; import { TooltipDetail } from '../../../../src/components/tooltip/components/detail'; import { TooltipHead } from '../../../../src/components/tooltip/components/head-info'; import { TooltipOperator } from '../../../../src/components/tooltip/components/operator'; @@ -58,26 +54,6 @@ describe('Tooltip Component Tests', () => { }); describe('Tooltip Common Components Tests', () => { - test('custom tooltip instance of CustomTooltip', async () => { - let s2: SpreadSheet; - - render( - { - s2 = s; - }} - />, - ); - - await waitFor(() => { - s2!.showTooltip({ position: { x: 0, y: 0 }, content: '111' }); - expect(s2!.tooltip).toBeInstanceOf(CustomTooltip); - expect(s2!.tooltip).toBeInstanceOf(BaseTooltip); - }); - }); - test('render sort tooltip: TooltipOperator', () => { const mockCell = jest.fn(); const mockMenuClick = jest.fn(); diff --git a/packages/s2-react/playground/components/Mobile.tsx b/packages/s2-react/playground/components/Mobile.tsx deleted file mode 100644 index 27af788644..0000000000 --- a/packages/s2-react/playground/components/Mobile.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import { customMerge, SpreadSheet, type S2DataConfig } from '@antv/s2'; -import { MobileSheet } from '../../src/components/sheets/mobile-sheet'; -import { defaultOptions, pivotSheetDataCfg } from '../config'; -import type { SheetComponentOptions, SheetComponentsProps } from '../../src'; -import { usePlaygroundContext } from '../context/playground.context'; - -const MobileDataCfg: S2DataConfig = { - ...pivotSheetDataCfg, -}; - -export const MobileSheetComponent: React.FC< - Partial & React.RefAttributes -> = React.forwardRef((props, ref) => { - const context = usePlaygroundContext(); - const mobileOptions: SheetComponentOptions = { - width: 400, - style: { - rowCell: { - width: 60, - }, - colCell: { - width: 140, - height: 30, - }, - dataCell: { - width: 60, - }, - }, - }; - const options = customMerge( - defaultOptions, - mobileOptions, - ); - - return ( - - ); -}); diff --git a/packages/s2-react/playground/index.tsx b/packages/s2-react/playground/index.tsx index 5518610296..a221cff2bf 100644 --- a/packages/s2-react/playground/index.tsx +++ b/packages/s2-react/playground/index.tsx @@ -54,7 +54,6 @@ import { CustomTree } from './components/CustomTree'; import { EditableSheet } from './components/EditableSheet'; import { GridAnalysisSheet } from './components/GridAnalysisSheet'; import { LinkGroup } from './components/LinkGroup'; -import { MobileSheetComponent } from './components/Mobile'; import { PluginsSheet } from './components/Plugins'; import { ResizeConfig } from './components/ResizeConfig'; import { StrategySheet } from './components/StrategySheet'; @@ -1616,11 +1615,6 @@ function MainLayout() { /> ), }, - { - key: 'mobile', - label: '移动端表格', - children: , - }, { key: 'plugins', label: 'G 5.0 插件系统', diff --git a/packages/s2-react/src/components/index.ts b/packages/s2-react/src/components/index.ts index 87c45b4f4d..ed1178995a 100644 --- a/packages/s2-react/src/components/index.ts +++ b/packages/s2-react/src/components/index.ts @@ -4,7 +4,6 @@ export { EditableSheet } from './sheets/editable-sheet'; export { EditCell } from './sheets/editable-sheet/custom-cell'; export { GridAnalysisSheet } from './sheets/grid-analysis-sheet'; export { StrategySheet } from './sheets/strategy-sheet'; -export { MobileSheet } from './sheets/mobile-sheet'; export { ChartSheet } from './sheets/chart-sheet'; export { StrategySheetDataSet } from './sheets/strategy-sheet/custom-data-set'; export * from './sheets/strategy-sheet/custom-tooltip'; diff --git a/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx index 48678efa5f..93b108baaa 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx @@ -4,7 +4,6 @@ import { TableDataCell, customMerge, type DataItem, - type RawData, type ViewMeta, GEvent, } from '@antv/s2'; @@ -19,7 +18,7 @@ import { } from '../../../../../utils/invokeComponent'; import './index.less'; -export interface CustomProps { +export interface CustomEditComponentProps { style: React.CSSProperties; onChange: (value: string) => void; onSave: () => void; @@ -31,14 +30,10 @@ export interface CustomProps { type DateCellEdit = (meta: ViewMeta, cell: TableDataCell) => void; type EditCellProps = { - /** - * @deprecated use `onDataCellEditEnd` instead. - */ - onChange?: (data: RawData[]) => void; onDataCellEditStart?: DateCellEdit; onDataCellEditEnd?: DateCellEdit; trigger?: number; - CustomComponent?: React.FunctionComponent; + CustomComponent?: React.FunctionComponent; }; function EditCellComponent( @@ -46,13 +41,8 @@ function EditCellComponent( ) { const { params, resolver } = props; const s2 = useSpreadSheetInstance(); - const { - cell, - onChange, - onDataCellEditStart, - onDataCellEditEnd, - CustomComponent, - } = params; + const { cell, onDataCellEditStart, onDataCellEditEnd, CustomComponent } = + params; const { left, top, width, height } = React.useMemo>(() => { const rect = s2.getCanvasElement()?.getBoundingClientRect(); @@ -114,7 +104,6 @@ function EditCellComponent( }); onDataCellEditEnd?.(editedMeta, cell!); - onChange?.(displayData); resolver(true); }; @@ -141,9 +130,18 @@ function EditCellComponent( }; }, []); - const onChangeValue = (val: string) => { + const onChangeValue = React.useCallback((val: string) => { setInputVal(val); - }; + }, []); + + const onChange = React.useCallback< + React.ChangeEventHandler + >( + (e) => { + onChangeValue(e.target.value); + }, + [onChangeValue], + ); React.useEffect(() => { onDataCellEditStart?.(cell!.getMeta() as ViewMeta, cell!); @@ -184,9 +182,7 @@ function EditCellComponent( className={'s2-edit-cell'} value={inputVal as string} ref={inputRef} - onChange={(e) => { - setInputVal(e.target.value); - }} + onChange={onChange} onBlur={onSave} onKeyDown={onKeyDown} onFocus={onFocus} @@ -197,7 +193,7 @@ function EditCellComponent( } export const EditCell: React.FC = React.memo((props) => { - const { onChange, CustomComponent } = props; + const { CustomComponent } = props; const s2 = useSpreadSheetInstance(); const onEditCell = React.useCallback( @@ -206,13 +202,12 @@ export const EditCell: React.FC = React.memo((props) => { component: EditCellComponent, params: { cell: s2.getCell(event.target) as TableDataCell, - onChange, CustomComponent, }, s2, }); }, - [CustomComponent, onChange, s2], + [CustomComponent, s2], ); useS2Event(S2Event.DATA_CELL_DOUBLE_CLICK, onEditCell, s2); diff --git a/packages/s2-react/src/components/sheets/mobile-sheet/index.tsx b/packages/s2-react/src/components/sheets/mobile-sheet/index.tsx deleted file mode 100644 index af67a75d8b..0000000000 --- a/packages/s2-react/src/components/sheets/mobile-sheet/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { getMobileSheetComponentOptions } from '@antv/s2-shared'; -import { SheetComponent } from '../index'; -import type { SheetComponentsProps } from '../interface'; - -export const MobileSheet: React.FC = React.memo( - (props) => ( - - ), -); - -MobileSheet.displayName = 'MobileSheet'; diff --git a/packages/s2-shared/__tests__/utils/options-spec.ts b/packages/s2-shared/__tests__/utils/options-spec.ts index c2b6520bb7..514b28839f 100644 --- a/packages/s2-shared/__tests__/utils/options-spec.ts +++ b/packages/s2-shared/__tests__/utils/options-spec.ts @@ -1,14 +1,5 @@ -import { - DEFAULT_MOBILE_OPTIONS, - DeviceType, - LayoutWidthType, - type S2Options, -} from '@antv/s2'; -import { pick } from 'lodash'; -import { - getBaseSheetComponentOptions, - getMobileSheetComponentOptions, -} from '../../src'; +import { type S2Options } from '@antv/s2'; +import { getBaseSheetComponentOptions } from '../../src'; describe('Options Tests', () => { test('should get safety options', () => { @@ -55,35 +46,4 @@ describe('Options Tests', () => { } `); }); - - test('should get mobile options', () => { - const options = getMobileSheetComponentOptions(); - const firstLevelOptions = pick(getMobileSheetComponentOptions(), [ - 'height', - 'device', - ]); - const interactionOptions = pick( - options.interaction, - Object.keys(DEFAULT_MOBILE_OPTIONS.interaction!), - ); - - expect(interactionOptions).toMatchInlineSnapshot(` - Object { - "brushSelection": Object { - "colCell": false, - "dataCell": false, - "rowCell": false, - }, - "hoverFocus": false, - "hoverHighlight": false, - "multiSelection": false, - "rangeSelection": false, - } - `); - expect(options.style?.layoutWidthType).toEqual(LayoutWidthType.ColAdaptive); - expect(firstLevelOptions).toEqual({ - height: 380, - device: DeviceType.MOBILE, - }); - }); }); diff --git a/packages/s2-shared/src/utils/options.ts b/packages/s2-shared/src/utils/options.ts index e1c09e1510..52be6f8424 100644 --- a/packages/s2-shared/src/utils/options.ts +++ b/packages/s2-shared/src/utils/options.ts @@ -1,9 +1,4 @@ -import { - customMerge, - DEFAULT_MOBILE_OPTIONS, - DEFAULT_OPTIONS, - type S2Options, -} from '@antv/s2'; +import { customMerge, DEFAULT_OPTIONS, type S2Options } from '@antv/s2'; import { SHEET_COMPONENT_DEFAULT_OPTIONS } from '../constant/option'; export const getBaseSheetComponentOptions = ( @@ -14,13 +9,3 @@ export const getBaseSheetComponentOptions = ( SHEET_COMPONENT_DEFAULT_OPTIONS, ...options, ); - -export const getMobileSheetComponentOptions = ( - ...options: Partial[] -): Options => - customMerge( - DEFAULT_OPTIONS, - DEFAULT_MOBILE_OPTIONS, - SHEET_COMPONENT_DEFAULT_OPTIONS, - ...options, - ); diff --git a/packages/s2-vue/src/hooks/useSpreadSheet.ts b/packages/s2-vue/src/hooks/useSpreadSheet.ts index e8549bcdcf..3ea661dcb2 100644 --- a/packages/s2-vue/src/hooks/useSpreadSheet.ts +++ b/packages/s2-vue/src/hooks/useSpreadSheet.ts @@ -24,7 +24,7 @@ export function useSpreadSheet( themeCfg, loading: loadingProps, sheetType, - onSpreadsheet, + spreadsheet: customSpreadSheet, onMounted: onS2Mounted, } = props; const wrapperRef = ref(); @@ -35,15 +35,14 @@ export function useSpreadSheet( const { loading, setLoading } = useLoading(s2Ref, loadingProps); const pagination = usePagination(s2Ref, props); - // TODO: 如果 onSpreadsheet 属性变更了怎么办??? const renderSpreadSheet = (container: HTMLDivElement) => { const rawDataCfg = toRaw(dataCfg!); const rawOptions = toRaw(options); const s2Options = getSheetComponentOptions(rawOptions as S2Options); - if (onSpreadsheet) { - return onSpreadsheet(container, rawDataCfg, s2Options); + if (customSpreadSheet) { + return customSpreadSheet(container, rawDataCfg, s2Options); } if (sheetType === 'table') { diff --git a/packages/s2-vue/src/utils/initPropAndEmits.ts b/packages/s2-vue/src/utils/initPropAndEmits.ts index 44d681b193..5571ec1380 100644 --- a/packages/s2-vue/src/utils/initPropAndEmits.ts +++ b/packages/s2-vue/src/utils/initPropAndEmits.ts @@ -22,10 +22,8 @@ export const initBaseSheetProps = () => { default: false as SheetComponentProps['showPagination'], }, loading: Boolean, - // TODO: 待后续完善 partDrillDown: Object, header: Object, - options: { type: Object as PropType, default: {} as SheetComponentProps['options'], @@ -34,7 +32,7 @@ export const initBaseSheetProps = () => { type: [Object, Boolean] as PropType, default: false as Adaptive, }, - onSpreadsheet: Function as PropType, + spreadsheet: Function as PropType, onMounted: Function as PropType, }; }; diff --git a/s2-site/docs/api/basic-class/interaction.zh.md b/s2-site/docs/api/basic-class/interaction.zh.md index a30eef44bf..cbd7bfa652 100644 --- a/s2-site/docs/api/basic-class/interaction.zh.md +++ b/s2-site/docs/api/basic-class/interaction.zh.md @@ -98,8 +98,11 @@ type S2CellType = | ColCell | CornerCell | RowCell - | MergedCell | SeriesNumberCell + | MergedCell + | TableDataCell + | TableCornerCell + | TableSeriesNumberCell | BaseCell; ``` @@ -154,7 +157,9 @@ interface CellMeta { enum InteractionStateName { ALL_SELECTED = 'allSelected', SELECTED = 'selected', - BRUSH_SELECTED = 'brushSelected', + ROW_CELL_BRUSH_SELECTED = 'rowCellBrushSelected', + COL_CELL_BRUSH_SELECTED = 'colCellBrushSelected', + DATA_CELL_BRUSH_SELECTED = 'dataCellBrushSelected', UNSELECTED = 'unselected', HOVER = 'hover', HOVER_FOCUS = 'hoverFocus', diff --git a/s2-site/docs/api/general/S2Options.zh.md b/s2-site/docs/api/general/S2Options.zh.md index 4e74f3aaec..d1c8e67cb5 100644 --- a/s2-site/docs/api/general/S2Options.zh.md +++ b/s2-site/docs/api/general/S2Options.zh.md @@ -221,7 +221,7 @@ export type Data = RawData & ExtraData; ## DataSet -功能描述:自定义数据集。[查看示例](#TODO) +功能描述:自定义数据集。[查看示例](/examples/custom/custom-dataset/#custom-strategy-sheet-dataset) ```js DataSet = (spreadsheet: SpreadSheet) => BaseDataSet; diff --git a/s2-site/docs/manual/advanced/analysis/mobile-component.en.md b/s2-site/docs/manual/advanced/analysis/mobile-component.en.md deleted file mode 100644 index bf815975ab..0000000000 --- a/s2-site/docs/manual/advanced/analysis/mobile-component.en.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Mobile Component -order: 10 -tag: New ---- - -In order to meet the usage scenarios of the mobile terminal, the analysis component in `s2-react` has been adapted for mobile. Help users view data more conveniently and efficiently on the mobile terminal. - -## premise - -The mobile table component uses various capabilities provided by S2 for integration, so it is recommended that you have read the following chapters before reading this chapter: - -* [basic concept](/zh/docs/manual/basic/base-concept) -* [form form](/zh/docs/manual/basic/sheet-type/pivot-mode) -* [tooltip](/zh/docs/manual/basic/tooltip) - -## mobile form - -```ts -import React from 'react'; -import ReactDOM from 'react-dom'; -import { MobileSheet } from '@antv/s2-react'; -import '@antv/s2-react/dist/style.min.css'; - -const container = document.getElementById('container'); - -ReactDOM.render( - , - document.getElementById('container'), -); -``` - -| PC | Mobile | -| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| PC | PC | - -The mobile component `MobileSheet` will have built-in mobile-specific `options` to make the form more compact and disable interactive operations that cannot be used on mobile. Of course, you can also override the original configuration through external `options` settings. - -```ts -const mobileWidth = document.documentElement.clientWidth; -export const DEFAULT_MOBILE_OPTIONS: Readonly = { - width: mobileWidth - 40, - height: 380, - style: { - layoutWidthType: LayoutWidthTypes.ColAdaptive, - }, - interaction: { - hoverHighlight: false, - hoverFocus: false, - brushSelection: { - dataCell: false, - rowCell: false, - colCell: false, - }, - multiSelection: false, - rangeSelection: false, - }, - device: DeviceType.MOBILE, -}; -``` - -> The configuration may change in real time, you can view the `options` configuration of the current version by getting `DEFAULT_MOBILE_OPTIONS` . - -## Mobile Tooltips - -We modified the interactive operation of `tooltips` on mobile components. However, the original [Tooltip API](/zh/docs/api/basic-class/base-tooltip) is retained, you only need to use the `MobileSheet` component to use the customized `tooltips` on the mobile side. - -​📊 View [Tooltip usage](/zh/docs/manual/basic/tooltip) - -| | PC | Mobile | -| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| sort function | PC | PC | -| Cell information display | PC | PC | -| Indicator information display | PC | PC | -| Summary information display | PC | PC | diff --git a/s2-site/docs/manual/advanced/analysis/mobile-component.zh.md b/s2-site/docs/manual/advanced/analysis/mobile-component.zh.md deleted file mode 100644 index c52a60add0..0000000000 --- a/s2-site/docs/manual/advanced/analysis/mobile-component.zh.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: 移动端表格组件 -order: 10 -tag: New ---- - -@antv/s2-react - -为了满足移动端的使用场景,`@antv/s2-react` 中的分析组件进行了移动端的适配。帮助用户在移动端更加便利、高效的看数。 - -:::warning{title="注意"} - -**移动端表组件**使用了 S2 提供的各种能力进行融合,所以建议在阅读本章前,请确保你已经阅读过以下章节: - -- [基本概念](/zh/docs/manual/basic/base-concept) -- [表格形态](/zh/docs/manual/basic/sheet-type/pivot-mode) -- [tooltip](/zh/docs/manual/basic/tooltip) - -::: - -## 快速上手 - -```tsx -import React from 'react'; -import { MobileSheet } from '@antv/s2-react'; -import '@antv/s2-react/dist/style.min.css'; - -const App = () => { - return ( - - ) -} -``` - -| PC 端 | Mobile 端 | -|--------------------------------------| --------------------------------- | -| PC | PC | - -移动端组件 `MobileSheet`, 将会被内置移动专用的 `options`,使表格更加紧凑,同时禁用了移动无法使用的交互操作。当然,您也可以通过外部 `options` 设置来覆盖原有的配置。 - -```ts -const DEFAULT_MOBILE_OPTIONS = { - width: document.documentElement.clientWidth - 40, - height: 380, - style: { - layoutWidthType: 'colAdaptive', - }, - interaction: { - hoverHighlight: false, - hoverFocus: false, - brushSelection: { - dataCell: false, - rowCell: false, - colCell: false, - }, - multiSelection: false, - rangeSelection: false, - }, - device: 'mobile', -}; -``` - -## 移动端 Tooltip - -我们修改了 `tooltip` 在移动端组件的交互操作。 -但保留了原本 [Tooltip API](/zh/docs/api/basic-class/base-tooltip) 的使用方式,您只需要使用 `MobileSheet` 组件即可使用到移动端定制的 `tooltips`。 - -​📊 查看 [Tooltip 使用](/zh/docs/manual/basic/tooltip) - -| 功能 | PC 端 | Mobile 端 | -| ------------- |---------------|----------------------------------------------| -| 排序功能 | PC | PC | -| 单元格信息展示 | PC | PC | -| 指标信息展示 | PC | PC | -| 汇总信息展示 | PC | PC | diff --git a/s2-site/docs/manual/basic/tooltip.zh.md b/s2-site/docs/manual/basic/tooltip.zh.md index 0d7c47c9d3..05d77207b7 100644 --- a/s2-site/docs/manual/basic/tooltip.zh.md +++ b/s2-site/docs/manual/basic/tooltip.zh.md @@ -144,11 +144,33 @@ const s2Options = {
我是自定义内容

我也是是自定义内容

- `, + ` }, }; ``` +或者是手动调用: + +```ts +const content = document.createElement('div') +content.innerHTML = '我是自定义内容' + +s2.showTooltip({ + position: {}, + content +}) + +s2.showTooltip({ + position: {}, + content: ` +
+
我是自定义内容
+

我也是是自定义内容

+
+ ` +}) +``` + ##### 在 React 中使用 @antv/s2-react 对于 `@antv/s2-react` 组件的使用方式:tooltip 内容 可以是任意的 `jsx` 元素 @@ -391,7 +413,7 @@ const s2Options = { { key: 'custom-a', label:
操作 1
, - icon: , + icon: , } ] } @@ -506,7 +528,7 @@ const s2Options = { . [示例](/examples/interaction/custom#row-col-hover-tooltip) ```ts -import { PivotSheet, BaseEvent, S2Event } from '@antv/s2'; +import { BaseEvent, S2Event } from '@antv/s2'; class RowHoverInteraction extends BaseEvent { bindEvents() { diff --git a/s2-site/docs/manual/getting-started.en.md b/s2-site/docs/manual/getting-started.en.md index 0294702f36..7a4827f501 100644 --- a/s2-site/docs/manual/getting-started.en.md +++ b/s2-site/docs/manual/getting-started.en.md @@ -215,30 +215,6 @@ yarn add antd @ant-design/icons ​📊 Check out the [React version pivot table demo](/examples/react-component/sheet#pivot) . -#### Table mobile component usage - -```ts -import React from 'react'; -import ReactDOM from 'react-dom'; -import { MobileSheet } from '@antv/s2-react'; -import '@antv/s2-react/dist/style.min.css'; - -const container = document.getElementById('container'); - -ReactDOM.render( - , - document.getElementById('container'), -); -``` - -#### Precautions - -The mobile-side component `MobileSheet` will have built-in mobile-specific `options` , and there are special components on the mobile side, which are different from those on the PC side. - -​📊 Check out the [React version pivot table mobile demo](/zh/examples/react-component/sheet#mobile-pivot) . - ### `Vue3` version `S2` also provides an out-of-the-box `Vue3` version of the table component to help developers quickly meet business analysis needs. diff --git a/s2-site/docs/manual/getting-started.zh.md b/s2-site/docs/manual/getting-started.zh.md index c1a0cb6ca7..f618c51604 100644 --- a/s2-site/docs/manual/getting-started.zh.md +++ b/s2-site/docs/manual/getting-started.zh.md @@ -223,28 +223,6 @@ pnpm add antd @ant-design/icons ​📊 查看 [React 版本透视表 demo](/examples/react-component/sheet#pivot)。 -#### 表格移动端组件使用 - -```ts -import React from 'react'; -import { MobileSheet } from '@antv/s2-react'; -import '@antv/s2-react/dist/style.min.css'; - -const App = () => { - return ( - - ) -} -``` - -#### 注意事项 - -移动端组件 `MobileSheet`, 将会被内置移动专用的 `options`, 并且移动端存在专门的组件,与 PC 端的组件有所不同。 - -​📊 查看 [React 版本透视表移动端 demo](/zh/examples/react-component/sheet#mobile-pivot)。 - ### `Vue3` 版本 `S2` 同时也提供了开箱即用的 `Vue3` 版本表格组件,帮助开发者快速满足业务看数分析需求。 diff --git a/s2-site/docs/manual/migration-v2.zh.md b/s2-site/docs/manual/migration-v2.zh.md index 10c5415b0b..706026b9ff 100644 --- a/s2-site/docs/manual/migration-v2.zh.md +++ b/s2-site/docs/manual/migration-v2.zh.md @@ -598,6 +598,26 @@ const s2Options = { 具体请查看 [获取单元格数据](/manual/advanced/get-cell-data) 相关文档。 +#### 单元格刷选选中状态变更 + +`1.x` 中,行列头刷选选中状态为 `brushSelected`, 数值单元格的刷选选中状态为 `selected`, `2.x` 中做了进一步统一和区分: + +```diff +s2.interaction.getState() + +// 行头 +- stateName: "brushSelected" ++ stateName: "rowCellBrushSelected" + +// 列头 +- stateName: "brushSelected" ++ stateName: "colCellBrushSelected" + +// 数值 +- stateName: "selected" ++ stateName: "dataCellBrushSelected" +``` + ### 组件层 @antv/s2-react #### 支持 React 18 和 Ant Design 5.0 diff --git a/s2-site/examples/custom/custom-icon/demo/custom-header-action-icon.tsx b/s2-site/examples/custom/custom-icon/demo/custom-header-action-icon.ts similarity index 78% rename from s2-site/examples/custom/custom-icon/demo/custom-header-action-icon.tsx rename to s2-site/examples/custom/custom-icon/demo/custom-header-action-icon.ts index 569ea75edf..3ed10dcfbd 100644 --- a/s2-site/examples/custom/custom-icon/demo/custom-header-action-icon.tsx +++ b/s2-site/examples/custom/custom-icon/demo/custom-header-action-icon.ts @@ -1,19 +1,14 @@ -import React from 'react'; -import { SheetComponent, SheetComponentOptions } from '@antv/s2-react'; -import '@antv/s2-react/dist/style.min.css'; - -const CornerTooltip = () =>
CornerTooltip
; - -const RowTooltip = () =>
RowTooltip
; - -const ColTooltip = () =>
ColTooltip
; +import { PivotSheet, S2Options } from '@antv/s2'; +import '@antv/s2/dist/style.min.css'; fetch( 'https://gw.alipayobjects.com/os/bmw-prod/2a5dbbc8-d0a7-4d02-b7c9-34f6ca63cff6.json', ) .then((res) => res.json()) - .then((dataCfg) => { - const s2Options: SheetComponentOptions = { + .then(async (dataCfg) => { + const container = document.getElementById('container'); + + const s2Options: S2Options = { width: 600, height: 480, customSVGIcons: [ @@ -45,7 +40,7 @@ fetch( meta.spreadsheet.tooltip.show({ position: { x: event.clientX, y: event.clientY }, - content: , + content: `
ColTooltip
`, }); }, }, @@ -58,7 +53,7 @@ fetch( meta.spreadsheet.tooltip.show({ position: { x: event.clientX, y: event.clientY }, - content: , + content: `
CornerTooltip
`, }); }, }, @@ -73,7 +68,7 @@ fetch( meta.spreadsheet.tooltip.show({ position: { x: event.clientX, y: event.clientY }, - content: , + content: `
RowTooltip
`, }); }, }, @@ -84,10 +79,13 @@ fetch( displayCondition: (meta) => meta.rowIndex > 2, onHover: (options) => { const { meta, event } = options; + const content = document.createElement('div'); + + content.innerHTML = '我是 RowTooltip 自定义内容'; meta.spreadsheet.tooltip.show({ position: { x: event.clientX, y: event.clientY }, - content: , + content, }); }, }, @@ -102,7 +100,7 @@ fetch( }, }; - reactDOMClient - .createRoot(document.getElementById('container')) - .render(); + const s2 = new PivotSheet(container, dataCfg, s2Options); + + await s2.render(); }); diff --git a/s2-site/examples/custom/custom-icon/demo/meta.json b/s2-site/examples/custom/custom-icon/demo/meta.json index 63a4b6f230..cedecee50f 100644 --- a/s2-site/examples/custom/custom-icon/demo/meta.json +++ b/s2-site/examples/custom/custom-icon/demo/meta.json @@ -13,7 +13,7 @@ "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/%24KQ3JqKkrA/67f074b6-739b-4a61-a5c5-b18488a65797.png" }, { - "filename": "custom-header-action-icon.tsx", + "filename": "custom-header-action-icon.ts", "title": { "zh": "自定义行列头操作图标", "en": "Custom header action icons" diff --git a/s2-site/examples/custom/custom-layout/demo/custom-facet.ts b/s2-site/examples/custom/custom-layout/demo/custom-facet.ts index 9860947209..ed92149fad 100644 --- a/s2-site/examples/custom/custom-layout/demo/custom-facet.ts +++ b/s2-site/examples/custom/custom-layout/demo/custom-facet.ts @@ -8,7 +8,6 @@ import { PivotFacet, } from '@antv/s2'; -// TODO: 目前没有导出 PivotFacet /** * 自定义 Facet, 修改单元格布局逻辑和宽高坐标 * 查看更多 https://github.com/antvis/S2/blob/next/packages/s2-core/src/facet/pivot-facet.ts diff --git a/s2-site/examples/react-component/sheet/demo/mobile-pivot.tsx b/s2-site/examples/react-component/sheet/demo/mobile-pivot.tsx deleted file mode 100644 index 916d8376d2..0000000000 --- a/s2-site/examples/react-component/sheet/demo/mobile-pivot.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; - -import { MobileSheet } from '@antv/s2-react'; -import '@antv/s2-react/dist/style.min.css'; - -fetch( - 'https://gw.alipayobjects.com/os/bmw-prod/2a5dbbc8-d0a7-4d02-b7c9-34f6ca63cff6.json', -) - .then((res) => res.json()) - .then((dataCfg) => { - reactDOMClient - .createRoot(document.getElementById('container')) - .render(); - }); diff --git a/s2-site/examples/react-component/tooltip/demo/custom-content-base.ts b/s2-site/examples/react-component/tooltip/demo/custom-content-base.ts index c85de8199c..f57b2de93a 100644 --- a/s2-site/examples/react-component/tooltip/demo/custom-content-base.ts +++ b/s2-site/examples/react-component/tooltip/demo/custom-content-base.ts @@ -11,6 +11,23 @@ fetch( const s2Options: S2Options = { width: 600, height: 480, + // 自定义 Icon 点击后显示 Tooltip + headerActionIcons: [ + { + icons: ['Trend'], + belongsCell: 'rowCell', + defaultHide: false, + onClick({ event, meta }) { + meta.spreadsheet.showTooltip({ + position: { + x: event?.clientX || 0, + y: event?.clientX || 0, + }, + content: `

我是 Trend Icon 自定义内容

`, + }); + }, + }, + ], tooltip: { enable: true, // 1. 支持字符串 diff --git a/s2-site/examples/theme/custom/demo/custom-scrollbar.ts b/s2-site/examples/theme/custom/demo/custom-scrollbar.ts index 5f9985378c..5c7d30664c 100644 --- a/s2-site/examples/theme/custom/demo/custom-scrollbar.ts +++ b/s2-site/examples/theme/custom/demo/custom-scrollbar.ts @@ -1,4 +1,4 @@ -import { PivotSheet, S2DataConfig, S2Options, ThemeCfg } from '@antv/s2'; +import { PivotSheet, S2DataConfig, S2Options } from '@antv/s2'; fetch('https://render.alipay.com/p/yuyan/180020010001215413/s2/basic.json') .then((res) => res.json())