diff --git a/common/changes/@visactor/vtable/fix-react-component-update_2025-03-21-09-53.json b/common/changes/@visactor/vtable/fix-react-component-update_2025-03-21-09-53.json new file mode 100644 index 0000000000..1049b3b136 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-react-component-update_2025-03-21-09-53.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix react component update #3474", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/react-vtable/src/table-components/custom/custom-layout.tsx b/packages/react-vtable/src/table-components/custom/custom-layout.tsx index cac208a6ed..8401471d85 100644 --- a/packages/react-vtable/src/table-components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/table-components/custom/custom-layout.tsx @@ -31,21 +31,28 @@ export const CustomLayout: React.FC = (props: PropsWithChildr // customLayout function for vtable const createGraphic: ICustomLayoutFuc = useCallback( args => { - const key = `${args.originCol ?? args.col}-${args.originRow ?? args.row}`; + const key = `${args.originCol ?? args.col}-${args.originRow ?? args.row}${ + args.forComputation ? '-forComputation' : '' + }`; let group; if (container.current.has(key)) { const currentContainer = container.current.get(key); - // reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); reconcilorUpdateContainer(children, currentContainer, args); group = currentContainer.containerInfo; - // 这里更新group,可能会残留dx dy } else { group = new Group({}); - const currentContainer = reconcilor.createContainer(group, LegacyRoot, null, null, null, 'custom', null, null); + const currentContainer = reconcilor.createContainer( + group as any, + LegacyRoot, + null, + null, + null, + 'custom', + null, + null + ); container.current.set(key, currentContainer); reconcilorUpdateContainer(children, currentContainer, args); - // const ele = React.cloneElement(children, { ...args }); - // reconcilor.updateContainer(ele, currentContainer, null); } return { diff --git a/packages/vtable/__tests__/listTable-highlightInRange.test.ts b/packages/vtable/__tests__/listTable-highlightInRange.test.ts index 984bb5b4d3..0f25cbc68f 100644 --- a/packages/vtable/__tests__/listTable-highlightInRange.test.ts +++ b/packages/vtable/__tests__/listTable-highlightInRange.test.ts @@ -195,7 +195,7 @@ describe('listTable init test', () => { expect(listTable.stateManager?.select.ranges).toEqual([ { start: { col: 1, row: 3 }, end: { col: 4, row: 6 }, skipBodyMerge: true }, { start: { col: 0, row: 4 }, end: { col: 7, row: 4 }, skipBodyMerge: true }, - { start: { col: 4, row: 36 }, end: { col: 7, row: 36 }, skipBodyMerge: true } + { start: { col: 4, row: 20 }, end: { col: 7, row: 20 }, skipBodyMerge: true } ]); expect(listTable.getScrollTop()).toBe(scrollTop); }); diff --git a/packages/vtable/__tests__/listTable.test.ts b/packages/vtable/__tests__/listTable.test.ts index 00cfa1e789..4c81ed01c3 100644 --- a/packages/vtable/__tests__/listTable.test.ts +++ b/packages/vtable/__tests__/listTable.test.ts @@ -192,7 +192,7 @@ describe('listTable init test', () => { expect(listTable.stateManager?.select.ranges).toEqual([ { start: { col: 1, row: 3 }, end: { col: 4, row: 6 }, skipBodyMerge: true }, { start: { col: 0, row: 4 }, end: { col: 7, row: 4 }, skipBodyMerge: true }, - { start: { col: 4, row: 36 }, end: { col: 7, row: 36 }, skipBodyMerge: true } + { start: { col: 4, row: 20 }, end: { col: 7, row: 20 }, skipBodyMerge: true } ]); expect(listTable.getScrollTop()).toBe(scrollTop); }); diff --git a/packages/vtable/examples/interactive/custom-scroll.ts b/packages/vtable/examples/interactive/custom-scroll.ts index 575e1ef6ba..50f6ae0fe8 100644 --- a/packages/vtable/examples/interactive/custom-scroll.ts +++ b/packages/vtable/examples/interactive/custom-scroll.ts @@ -552,7 +552,7 @@ class VTablePaddingOperator { // right this.x2 = Math.max(this.x2Target - this.padding[1], this.x2 - (e.dx || 1)); - console.log('left', this.x2); + // console.log('left', this.x2); setTimeout(() => { this.clearCanvas(); this.updateViewBox(); @@ -562,21 +562,21 @@ class VTablePaddingOperator { // left this.x2 = Math.min(this.x2Target, this.x2 - (e.dx ?? 0)); - console.log('right', this.x2); + // console.log('right', this.x2); setTimeout(() => { this.clearCanvas(); this.updateViewBox(); this.table.scenegraph.setX(-this.table.stateManager.scroll.horizontalBarPos - 1, true); }, 0); } else { - console.log('normal', this.x2); + // console.log('normal', this.x2); } // vertical scroll if (e.scrollRatioY === 1 && (e.dy ?? 0) >= 0 && this.y2 > this.y2Target - this.padding[2]) { // bottom this.y2 = Math.max(this.y2Target - this.padding[2], this.y2 - (e.dy || 1)); - console.log('top', this.y2); + // console.log('top', this.y2); setTimeout(() => { this.clearCanvas(); this.updateViewBox(); @@ -585,14 +585,14 @@ class VTablePaddingOperator { } else if (this.y2 < this.y2Target && (e.dy ?? 0) < 0) { // top this.y2 = Math.min(this.y2Target, this.y2 - (e.dy ?? 0)); - console.log('bottom', this.y2); + // console.log('bottom', this.y2); setTimeout(() => { this.clearCanvas(); this.updateViewBox(); this.table.scenegraph.setY(-this.table.stateManager.scroll.verticalBarPos - 1, true); }, 0); } else { - console.log('normal', this.y2); + // console.log('normal', this.y2); } }); } @@ -614,6 +614,8 @@ class VTablePaddingOperator { x2: this.x2, y2: this.y2 }); + this.clearCanvas(); + this.table.render(); } reset() { diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index 47cb2a2aed..2d9324adb5 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -1885,7 +1885,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (this.internalProps._heightResizedRowMap.size === 0) { this.scenegraph.recalculateRowHeights(); } - } else if (this.isAutoRowHeight() && !this.internalProps._heightResizedRowMap.has(row)) { + } else if (this.isAutoRowHeight(row) && !this.internalProps._heightResizedRowMap.has(row)) { const oldHeight = this.getRowHeight(row); const newHeight = computeRowHeight(row, 0, this.colCount - 1, this); this.scenegraph.updateRowHeight(row, newHeight - oldHeight); @@ -2003,7 +2003,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (this.heightMode === 'adaptive' || (this.autoFillHeight && this.getAllRowsHeight() <= this.tableNoFrameHeight)) { this.scenegraph.recalculateRowHeights(); - } else if (this.isAutoRowHeight()) { + } else if (this.isAutoRowHeight(startRow)) { const rows: number[] = []; const deltaYs: number[] = []; for (let sRow = startRow; sRow <= range.end.row; sRow++) { diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 1ff2757261..8805a7e89f 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -90,6 +90,17 @@ export class ReactCustomLayout { // } // } + if (table.widthMode === 'autoWidth') { + table.scenegraph.recalculateColWidths(); + } + if ( + table.isAutoRowHeight() || + (table.internalProps.defaultRowHeight === 'auto' && !isHeaderCustomLayout) || + (table.internalProps.defaultHeaderRowHeight === 'auto' && isHeaderCustomLayout) + ) { + table.scenegraph.recalculateRowHeights(); + } + if (table.isPivotTable()) { const ranges = getUpdateCustomCellRangeInPivotTable(componentId, table, isHeaderCustomLayout); for (let i = 0; i < ranges.length; i++) { @@ -108,12 +119,7 @@ export class ReactCustomLayout { } } } - if (table.widthMode === 'autoWidth') { - table.scenegraph.recalculateColWidths(); - } - if (table.isAutoRowHeight()) { - table.scenegraph.recalculateRowHeights(); - } + // table.scenegraph.updateNextFrame(); table.scenegraph.renderSceneGraph(); // use sync render for faster update } diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index bb5271d884..fb892efe43 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -1489,7 +1489,8 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } else if (row >= 0 && row < this.columnHeaderLevelCount) { return this.getDefaultRowHeight(row) === 'auto'; } - return false; + // return false; + return this.internalProps.defaultRowHeight === 'auto'; } /** * 根据列号获取列宽定义 @@ -3126,7 +3127,19 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { customMerge.range && (isValid(customMerge.text) || customMerge.customLayout || customMerge.customRender) ) { - return customMerge.range; + // return customMerge.range; + // trim range + const range = { + start: { + col: Math.max(customMerge.range.start.col, 0), + row: Math.max(customMerge.range.start.row, 0) + }, + end: { + col: Math.min(customMerge.range.end.col, this.colCount - 1), + row: Math.min(customMerge.range.end.row, this.rowCount - 1) + } + }; + return range; } } return this.internalProps.layoutMap?.getCellRange(col, row); diff --git a/packages/vtable/src/core/TABLE_EVENT_TYPE.ts b/packages/vtable/src/core/TABLE_EVENT_TYPE.ts index d56917da1c..66a2929d1d 100644 --- a/packages/vtable/src/core/TABLE_EVENT_TYPE.ts +++ b/packages/vtable/src/core/TABLE_EVENT_TYPE.ts @@ -100,6 +100,7 @@ export interface TableEvents { * 滚动表格事件 */ SCROLL: 'scroll'; + CAN_SCROLL: 'can_scroll'; /** * 横向滚动条滚动到结束位 */ @@ -226,6 +227,7 @@ export const TABLE_EVENT_TYPE: TableEvents = { AFTER_SORT: 'after_sort', FREEZE_CLICK: 'freeze_click', SCROLL: 'scroll', + CAN_SCROLL: 'can_scroll', SCROLL_HORIZONTAL_END: 'scroll_horizontal_end', SCROLL_VERTICAL_END: 'scroll_vertical_end', DROPDOWN_MENU_CLICK: 'dropdown_menu_click', diff --git a/packages/vtable/src/core/record-helper.ts b/packages/vtable/src/core/record-helper.ts index 6c53d3e5ac..eed1083f77 100644 --- a/packages/vtable/src/core/record-helper.ts +++ b/packages/vtable/src/core/record-helper.ts @@ -85,7 +85,7 @@ export function listTableChangeCellValue( if (table.internalProps._heightResizedRowMap.size === 0) { table.scenegraph.recalculateRowHeights(); } - } else if (table.isAutoRowHeight() && !table.internalProps._heightResizedRowMap.has(row)) { + } else if (table.isAutoRowHeight(row) && !table.internalProps._heightResizedRowMap.has(row)) { const oldHeight = table.getRowHeight(row); const newHeight = computeRowHeight(row, 0, table.colCount - 1, table); table.scenegraph.updateRowHeight(row, newHeight - oldHeight); @@ -283,7 +283,7 @@ export function listTableChangeCellValues( (table.autoFillHeight && table.getAllRowsHeight() <= table.tableNoFrameHeight) ) { table.scenegraph.recalculateRowHeights(); - } else if (table.isAutoRowHeight()) { + } else if (table.isAutoRowHeight(startRow)) { const rows: number[] = []; const deltaYs: number[] = []; for (let sRow = startRow; sRow <= range.end.row; sRow++) { diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 499d3d182a..05b4bff62d 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -504,6 +504,11 @@ export function updateCell( ) { // const oldCellGroup = table.scenegraph.getCell(col, row, true); const oldCellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); + + if (oldCellGroup.role !== 'cell' && !addNew) { + return undefined; + } + const cellLocation = table.getCellLocation(col, row); let value = table.getCellValue(col, row); diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts index cb15a18f06..791d546f6a 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts @@ -151,7 +151,7 @@ function createRadio( const autoWrapText = cellStyle.autoWrapText ?? table.internalProps.autoWrapText; const { lineClamp } = cellStyle; const autoColWidth = colWidth === 'auto'; - const autoRowHeight = table.isAutoRowHeight(); + const autoRowHeight = table.isAutoRowHeight(row); const attribute = { // text: text.length === 1 ? text[0] : text, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts index e2b024fa1e..c46efc0c0a 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts @@ -226,13 +226,19 @@ export function createVideoCellGroup( const anchorY = top + (height > image.attribute.height ? image.attribute.y - top + image.attribute.height / 2 : height / 2); + // get dx dy of image graphic for merge cell + const imageGraphic = cellGroup.getChildByName('image', true); + const { dx, dy } = imageGraphic.attribute; + const playIcon: Icon = new Icon({ x: anchorX - iconSize / 2, y: anchorY - iconSize / 2, width: iconSize, height: iconSize, image: (regedIcons.play as any).svg, - cursor: (regedIcons.play as any).cursor + cursor: (regedIcons.play as any).cursor, + dx, + dy }); playIcon.name = 'play-icon'; cellGroup.appendChild(playIcon); diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts index 84b822ca3e..b305114724 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts @@ -30,7 +30,8 @@ export function createGroupForFirstScreen( let distRowForCompute; if ( table.widthMode === 'adaptive' || - (table.options.autoWrapText && (table.heightMode === 'adaptive' || table.isAutoRowHeight())) + (table.options.autoWrapText && + (table.heightMode === 'adaptive' || table.isAutoRowHeight(table.columnHeaderLevelCount))) ) { // distCol = table.colCount - 1; // proxy.colEnd = distCol; diff --git a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts index 45606a395c..c1751950b3 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts @@ -73,7 +73,7 @@ export class SceneProxy { // this.colLimit = 100; this.rowLimit = Math.max(100, Math.ceil((table.tableNoFrameHeight * 2) / table.defaultRowHeight)); this.colLimit = Math.max(100, Math.ceil((table.tableNoFrameWidth * 2) / table.defaultColWidth)); - } else if (this.table.isAutoRowHeight()) { + } else if (this.table.isAutoRowHeight(table.columnHeaderLevelCount)) { // this.rowLimit = 100; this.rowLimit = Math.max(100, Math.ceil((table.tableNoFrameHeight * 2) / table.defaultRowHeight)); } else if (this.table.widthMode === 'autoWidth') { @@ -563,13 +563,13 @@ export class SceneProxy { updateCellGroups(count: number) { const distRow = Math.min(this.bodyBottomRow, this.rowUpdatePos + count); // console.log('updateCellGroups', this.rowUpdatePos, distRow); - if (this.table.isAutoRowHeight()) { + if (this.table.isAutoRowHeight(this.rowUpdatePos)) { computeRowsHeight(this.table, this.rowUpdatePos, distRow, false); } updateRowContent(this.rowUpdatePos, distRow, this); - if (this.table.isAutoRowHeight()) { + if (this.table.isAutoRowHeight(this.rowUpdatePos)) { // body group updateAutoRow( this.bodyLeftCol, // colStart @@ -608,12 +608,12 @@ export class SceneProxy { updateBottomFrozenCellGroups() { const startRow = this.table.rowCount - this.table.bottomFrozenRowCount; const endRow = this.table.rowCount - 1; - if (this.table.isAutoRowHeight()) { + if (this.table.isAutoRowHeight(startRow)) { computeRowsHeight(this.table, startRow, endRow, false); } updateRowContent(startRow, endRow, this); - if (this.table.isAutoRowHeight()) { + if (this.table.isAutoRowHeight(startRow)) { // body group updateAutoRow( this.bodyLeftCol, // colStart @@ -653,7 +653,7 @@ export class SceneProxy { console.log('updateRightFrozenCellGroups', startCol, endCol); updateColContent(startCol, endCol, this); - if (this.table.isAutoRowHeight()) { + if (this.table.isAutoRowHeight(this.rowStart)) { // body group updateAutoColumn(startCol, endCol, this.table, this.colUpdateDirection); } diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts index 141038fd3f..4722cf1ef5 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts @@ -88,7 +88,7 @@ async function moveCell( // 更新同步范围 let syncTopRow; let syncBottomRow; - if (proxy.table.isAutoRowHeight()) { + if (proxy.table.isAutoRowHeight(startRow)) { syncTopRow = distStartRow; syncBottomRow = distEndRow; } else { @@ -115,7 +115,7 @@ async function moveCell( // 本次行更新是否同步完成,列数超过limit时为false const sync = updateRowContent(syncTopRow, syncBottomRow, proxy, true); - if (proxy.table.isAutoRowHeight()) { + if (proxy.table.isAutoRowHeight(startRow)) { // body group updateAutoRow( proxy.bodyLeftCol, // colStart @@ -177,7 +177,7 @@ async function moveCell( proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); // proxy.referenceRow = screenTopRow; // proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, distStartRow); - if (proxy.table.isAutoRowHeight() && sync) { + if (proxy.table.isAutoRowHeight(startRow) && sync) { proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, proxy.rowEnd + 1); } else { proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, distStartRow); @@ -196,7 +196,7 @@ async function moveCell( let syncTopRow; let syncBottomRow; - if (proxy.table.isAutoRowHeight()) { + if (proxy.table.isAutoRowHeight(distStartRow)) { syncTopRow = distStartRow; syncBottomRow = distEndRow; } else { @@ -214,7 +214,7 @@ async function moveCell( const sync = updateRowContent(syncTopRow, syncBottomRow, proxy, true); - if (proxy.table.isAutoRowHeight()) { + if (proxy.table.isAutoRowHeight(distStartRow)) { // body group updateAutoRow( proxy.bodyLeftCol, // colStart @@ -277,7 +277,7 @@ async function moveCell( ); proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); // proxy.referenceRow = screenTopRow; - if (proxy.table.isAutoRowHeight() && sync) { + if (proxy.table.isAutoRowHeight(distStartRow) && sync) { proxy.rowUpdatePos = proxy.rowEnd + 1; } else { proxy.rowUpdatePos = proxy.rowStart; diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts index f5cc3b3e3b..c124eb9011 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts @@ -18,7 +18,7 @@ export async function sortVertical(proxy: SceneProxy) { // 更新同步范围 let syncTopRow; let syncBottomRow; - if (proxy.table.isAutoRowHeight()) { + if (proxy.table.isAutoRowHeight(proxy.rowStart)) { syncTopRow = proxy.rowStart; syncBottomRow = proxy.rowEnd; } else { @@ -41,7 +41,7 @@ export async function sortVertical(proxy: SceneProxy) { proxy.table.scenegraph.updateContainerHeight(proxy.table.frozenRowCount, newBodyHeight - oldBodyHeight); } - for (let col = 0; col < proxy.table.frozenColCount ?? 0; col++) { + for (let col = 0; col < (proxy.table.frozenColCount ?? 0); col++) { // 将该列的chartInstance清除掉 const columnGroup = proxy.table.scenegraph.getColGroup(col); columnGroup?.setAttribute('chartInstance', undefined); @@ -74,7 +74,7 @@ export async function sortVertical(proxy: SceneProxy) { updateRowContent(syncTopRow, syncBottomRow, proxy); - if (proxy.table.isAutoRowHeight()) { + if (proxy.table.isAutoRowHeight(syncTopRow)) { updateAutoRow( proxy.bodyLeftCol, // colStart proxy.bodyRightCol, // colEnd @@ -101,7 +101,7 @@ export async function sortVertical(proxy: SceneProxy) { // } proxy.table.scenegraph.updateNextFrame(); - if (!proxy.table.isAutoRowHeight()) { + if (!proxy.table.isAutoRowHeight(proxy.rowStart)) { await proxy.progress(); } } diff --git a/packages/vtable/src/scenegraph/layout/compute-col-width.ts b/packages/vtable/src/scenegraph/layout/compute-col-width.ts index 75f13d74d6..e43ed9eb83 100644 --- a/packages/vtable/src/scenegraph/layout/compute-col-width.ts +++ b/packages/vtable/src/scenegraph/layout/compute-col-width.ts @@ -489,7 +489,8 @@ function computeCustomRenderWidth(col: number, row: number, table: BaseTableAPI) rect: getCellRect(col, row, table), table, originCol: col, - originRow: row + originRow: row, + forComputation: true }; if (customLayout === 'react-custom-layout') { // customLayout = table._reactCreateGraphic; diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index 35d1212b4b..27dc00c478 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -69,7 +69,8 @@ export function computeRowsHeight( table.defaultHeaderRowHeight === 'auto' || (isArray(table.defaultHeaderRowHeight) && table.defaultHeaderRowHeight.some(item => item === 'auto')); const isAllRowsAuto = - table.isAutoRowHeight() || (table.heightMode === 'adaptive' && table.options.autoHeightInAdaptiveMode !== false); + table.isAutoRowHeight(rowStart) || + (table.heightMode === 'adaptive' && table.options.autoHeightInAdaptiveMode !== false); const isDefaultRowHeightIsAuto = table.options.defaultRowHeight === 'auto'; if (isAllRowsAuto || isDefaultHeaderHasAuto || isDefaultRowHeightIsAuto) { @@ -133,7 +134,7 @@ export function computeRowsHeight( (table.isPivotTable() && !(table.internalProps.layoutMap as PivotHeaderLayoutMap).indicatorsAsCol) ) && !(table.options as ListTableConstructorOptions).customComputeRowHeight && - checkFixedStyleAndNoWrap(table) + checkFixedStyleAndNoWrap(table, rowStart) ) { // check fixed style and no wrap situation, fill all row width single compute // traspose table and row indicator pivot table cannot use single row height @@ -357,7 +358,7 @@ export function computeRowsHeight( export function computeRowHeight(row: number, startCol: number, endCol: number, table: BaseTableAPI): number { const isAllRowsAuto = - table.isAutoRowHeight() || (table.heightMode === 'adaptive' && table.options.autoHeightInAdaptiveMode !== false); + table.isAutoRowHeight(row) || (table.heightMode === 'adaptive' && table.options.autoHeightInAdaptiveMode !== false); if (!isAllRowsAuto && table.getDefaultRowHeight(row) !== 'auto') { return table.getDefaultRowHeight(row) as number; } @@ -449,13 +450,13 @@ export function computeRowHeight(row: number, startCol: number, endCol: number, return isNumber(defaultHeight) ? defaultHeight : table.defaultRowHeight; } -function checkFixedStyleAndNoWrap(table: BaseTableAPI): boolean { +function checkFixedStyleAndNoWrap(table: BaseTableAPI, rowStart: number): boolean { const { layoutMap } = table.internalProps; const row = table.columnHeaderLevelCount; //设置了全局自动换行的话 不能复用高度计算 if ( (table.internalProps.autoWrapText || table.internalProps.enableLineBreak || table.isPivotChart()) && - (table.isAutoRowHeight() || table.options.heightMode === 'adaptive') + (table.isAutoRowHeight(rowStart) || table.options.heightMode === 'adaptive') ) { return false; } @@ -492,7 +493,7 @@ function checkFixedStyleAndNoWrapForTranspose(table: BaseTableAPI, row: number): //设置了全局自动换行的话 不能复用高度计算 if ( (table.internalProps.autoWrapText || table.internalProps.enableLineBreak) && - (table.isAutoRowHeight() || table.options.heightMode === 'adaptive') + (table.isAutoRowHeight(row) || table.options.heightMode === 'adaptive') ) { return false; } @@ -523,7 +524,7 @@ function checkFixedStyleAndNoWrapForTranspose(table: BaseTableAPI, row: number): function checkPivotFixedStyleAndNoWrap(table: BaseTableAPI, row: number) { const { layoutMap } = table.internalProps; //设置了全局自动换行的话 不能复用高度计算 - if (table.internalProps.autoWrapText && (table.isAutoRowHeight() || table.options.heightMode === 'adaptive')) { + if (table.internalProps.autoWrapText && (table.isAutoRowHeight(row) || table.options.heightMode === 'adaptive')) { return false; } @@ -602,7 +603,8 @@ function computeCustomRenderHeight(col: number, row: number, table: BaseTableAPI rect: getCellRect(col, row, table), table, originCol: col, - originRow: row + originRow: row, + forComputation: true }; if (customLayout === 'react-custom-layout') { // customLayout = table._reactCreateGraphic; diff --git a/packages/vtable/src/scenegraph/layout/update-row.ts b/packages/vtable/src/scenegraph/layout/update-row.ts index 92ff9c7d9e..f18bd87dc0 100644 --- a/packages/vtable/src/scenegraph/layout/update-row.ts +++ b/packages/vtable/src/scenegraph/layout/update-row.ts @@ -549,11 +549,11 @@ function _getUpdateRowIndexUseCellNode(beforeRow: number, afterRow: number, scen { start: { row: beforeCell.mergeStartRow, - col: scene.table.isAutoRowHeight() ? 0 : beforeCell.mergeStartCol + col: scene.table.isAutoRowHeight(afterRow) ? 0 : beforeCell.mergeStartCol }, end: { row: beforeCell.mergeEndRow, - col: scene.table.isAutoRowHeight() ? scene.table.colCount - 1 : beforeCell.mergeEndCol + col: scene.table.isAutoRowHeight(afterRow) ? scene.table.colCount - 1 : beforeCell.mergeEndCol } }, scene @@ -567,11 +567,11 @@ function _getUpdateRowIndexUseCellNode(beforeRow: number, afterRow: number, scen { start: { row: afterCell.mergeStartRow, - col: scene.table.isAutoRowHeight() ? 0 : afterCell.mergeStartCol + col: scene.table.isAutoRowHeight(afterRow) ? 0 : afterCell.mergeStartCol }, end: { row: afterCell.mergeEndRow, - col: scene.table.isAutoRowHeight() ? scene.table.colCount - 1 : afterCell.mergeEndCol + col: scene.table.isAutoRowHeight(afterRow) ? scene.table.colCount - 1 : afterCell.mergeEndCol } }, scene diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index 5e9e467823..c598986167 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -2061,7 +2061,7 @@ export class Scenegraph { (this.table.autoFillHeight && (this.table.getAllRowsHeight() <= this.table.tableNoFrameHeight || isNotFillHeight)) ) { this.table.scenegraph.recalculateRowHeights(); - } else if (this.table.isAutoRowHeight()) { + } else if (this.table.isAutoRowHeight(this.table.columnHeaderLevelCount)) { // if (updateCells.length > 0) { // this.table.scenegraph.recalculateRowHeights(); // } diff --git a/packages/vtable/src/state/state.ts b/packages/vtable/src/state/state.ts index 13a08c51dc..a52d5c754c 100644 --- a/packages/vtable/src/state/state.ts +++ b/packages/vtable/src/state/state.ts @@ -607,6 +607,19 @@ export class StateManager { if (row !== -1 && row !== -1) { this.select.selecting = true; } + // trim select position + if (col < 0) { + col = -1; + } + if (row < 0) { + row = -1; + } + if (col > this.table.colCount - 1) { + col = this.table.colCount - 1; + } + if (row > this.table.rowCount - 1) { + row = this.table.rowCount - 1; + } updateSelectPosition(this, col, row, isShift, isCtrl, isSelectAll, makeSelectCellVisible, skipBodyMerge); } @@ -967,7 +980,7 @@ export class StateManager { // verticalBarPos -= this.table.scenegraph.proxy.deltaY; const dy = verticalBarPos - this.table.scenegraph.proxy.deltaY - oldVerticalBarPos; - const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.CAN_SCROLL, { event: undefined, scrollTop: verticalBarPos - this.table.scenegraph.proxy.deltaY, scrollLeft: this.scroll.horizontalBarPos, @@ -996,17 +1009,18 @@ export class StateManager { this.updateHoverPos(-1, -1); // this.updateSelectPos(-1, -1); - // this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { - // event: undefined, - // scrollTop: this.scroll.verticalBarPos, - // scrollLeft: this.scroll.horizontalBarPos, - // scrollHeight: this.table.theme.scrollStyle?.width, - // scrollWidth: this.table.theme.scrollStyle?.width, - // viewHeight: this.table.tableNoFrameHeight, - // viewWidth: this.table.tableNoFrameWidth, - // scrollDirection: 'vertical', - // scrollRatioY: yRatio - // }); + this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + event: undefined, + scrollTop: this.scroll.verticalBarPos, + scrollLeft: this.scroll.horizontalBarPos, + scrollHeight: this.table.theme.scrollStyle?.width, + scrollWidth: this.table.theme.scrollStyle?.width, + viewHeight: this.table.tableNoFrameHeight, + viewWidth: this.table.tableNoFrameWidth, + scrollDirection: 'vertical', + scrollRatioY: yRatio, + dy + }); if (oldVerticalBarPos !== this.scroll.verticalBarPos) { this.checkVerticalScrollBarEnd(); @@ -1022,7 +1036,8 @@ export class StateManager { } // horizontalBarPos -= this.table.scenegraph.proxy.deltaX; const dx = horizontalBarPos - this.table.scenegraph.proxy.deltaX - oldHorizontalBarPos; - const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + + const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.CAN_SCROLL, { event: undefined, scrollTop: this.scroll.verticalBarPos, scrollLeft: horizontalBarPos - this.table.scenegraph.proxy.deltaX, @@ -1059,17 +1074,18 @@ export class StateManager { // 滚动期间清空选中清空 this.updateHoverPos(-1, -1); // this.updateSelectPos(-1, -1); - // this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { - // event: undefined, - // scrollTop: this.scroll.verticalBarPos, - // scrollLeft: this.scroll.horizontalBarPos, - // scrollHeight: this.table.theme.scrollStyle?.width, - // scrollWidth: this.table.theme.scrollStyle?.width, - // viewHeight: this.table.tableNoFrameHeight, - // viewWidth: this.table.tableNoFrameWidth, - // scrollDirection: 'horizontal', - // scrollRatioX: xRatio - // }); + this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + event: undefined, + scrollTop: this.scroll.verticalBarPos, + scrollLeft: this.scroll.horizontalBarPos, + scrollHeight: this.table.theme.scrollStyle?.width, + scrollWidth: this.table.theme.scrollStyle?.width, + viewHeight: this.table.tableNoFrameHeight, + viewWidth: this.table.tableNoFrameWidth, + scrollDirection: 'horizontal', + scrollRatioX: xRatio, + dx: dx + }); if (oldHorizontalBarPos !== this.scroll.horizontalBarPos) { this.checkHorizontalScrollBarEnd(); @@ -1098,7 +1114,7 @@ export class StateManager { } const dy = verticalBarPos - oldVerticalBarPos; - const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.CAN_SCROLL, { event: (event as FederatedWheelEvent)?.nativeEvent as WheelEvent, scrollTop: verticalBarPos, scrollLeft: this.scroll.horizontalBarPos, @@ -1134,6 +1150,20 @@ export class StateManager { // 更新scrollbar位置 this.table.scenegraph.component.updateVerticalScrollBarPos(yRatio); + const dy = this.scroll.verticalBarPos - oldVerticalBarPos; + this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + event: (event as FederatedWheelEvent)?.nativeEvent as WheelEvent, + scrollTop: this.scroll.verticalBarPos, + scrollLeft: this.scroll.horizontalBarPos, + scrollHeight: this.table.theme.scrollStyle?.width, + scrollWidth: this.table.theme.scrollStyle?.width, + viewHeight: this.table.tableNoFrameHeight, + viewWidth: this.table.tableNoFrameWidth, + scrollDirection: 'vertical', + scrollRatioY: yRatio, + dy + }); + if (oldVerticalBarPos !== top && triggerEvent) { this.checkVerticalScrollBarEnd(); } @@ -1165,7 +1195,7 @@ export class StateManager { horizontalBarPos = 0; } const dx = horizontalBarPos - oldHorizontalBarPos; - const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + const canScroll = this.table.fireListeners(TABLE_EVENT_TYPE.CAN_SCROLL, { event: (event as FederatedWheelEvent)?.nativeEvent as WheelEvent, scrollTop: this.scroll.verticalBarPos, scrollLeft: horizontalBarPos, @@ -1202,6 +1232,20 @@ export class StateManager { // 更新scrollbar位置 this.table.scenegraph.component.updateHorizontalScrollBarPos(xRatio); + const dx = this.scroll.horizontalBarPos - oldHorizontalBarPos; + this.table.fireListeners(TABLE_EVENT_TYPE.SCROLL, { + event: (event as FederatedWheelEvent)?.nativeEvent as WheelEvent, + scrollTop: this.scroll.verticalBarPos, + scrollLeft: this.scroll.horizontalBarPos, + scrollHeight: this.table.theme.scrollStyle?.width, + scrollWidth: this.table.theme.scrollStyle?.width, + viewHeight: this.table.tableNoFrameHeight, + viewWidth: this.table.tableNoFrameWidth, + scrollDirection: 'horizontal', + scrollRatioX: xRatio, + dx + }); + if (oldHorizontalBarPos !== left && triggerEvent) { this.checkHorizontalScrollBarEnd(); } diff --git a/packages/vtable/src/ts-types/customElement.ts b/packages/vtable/src/ts-types/customElement.ts index 13c8fd3845..ec948e0037 100644 --- a/packages/vtable/src/ts-types/customElement.ts +++ b/packages/vtable/src/ts-types/customElement.ts @@ -13,6 +13,8 @@ export interface CustomRenderFunctionArg { rect?: RectProps; originCol?: number; originRow?: number; + + forComputation?: boolean; } interface baseElement { elementKey?: string; diff --git a/packages/vtable/src/ts-types/events.ts b/packages/vtable/src/ts-types/events.ts index 3b0f2e6878..49509d8caf 100644 --- a/packages/vtable/src/ts-types/events.ts +++ b/packages/vtable/src/ts-types/events.ts @@ -89,6 +89,20 @@ export interface TableEventHandlersEventArgumentMap { dx?: number; dy?: number; }; + can_scroll: { + event: WheelEvent; + scrollLeft: number; + scrollTop: number; + scrollWidth: number; + scrollHeight: number; + viewWidth: number; + viewHeight: number; + scrollDirection: 'horizontal' | 'vertical'; + scrollRatioX?: number; + scrollRatioY?: number; + dx?: number; + dy?: number; + }; scroll_vertical_end: { scrollLeft: number; scrollTop: number; @@ -262,7 +276,8 @@ export interface TableEventHandlersReturnMap { mouseup_cell: void; contextmenu_cell: void; keydown: void; - scroll: void | boolean; + scroll: void; + can_scroll: void | boolean; focus_table: void; blur_table: void; resize_column: void;