From ebdd4a3e3ddabfaf159c4dfe8c50a56867943840 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 20 May 2026 09:34:39 +0800 Subject: [PATCH 1/3] fix: preserve sticky group position after toggle --- packages/vtable/src/event/event.ts | 3 ++ .../src/plugins/list-tree-stick-cell.ts | 43 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/event/event.ts b/packages/vtable/src/event/event.ts index 198f5325ae..bae7c2fd28 100644 --- a/packages/vtable/src/event/event.ts +++ b/packages/vtable/src/event/event.ts @@ -551,6 +551,9 @@ export class EventManager { cellIsHeaderCheck(eventArgsSet: SceneEvent, update?: boolean): boolean { const { eventArgs } = eventArgsSet; + if (!eventArgs) { + return false; + } const { col, row, target } = eventArgs; if (!this.table.isHeader(col, row)) { return false; diff --git a/packages/vtable/src/plugins/list-tree-stick-cell.ts b/packages/vtable/src/plugins/list-tree-stick-cell.ts index af05f37134..93c82918b1 100644 --- a/packages/vtable/src/plugins/list-tree-stick-cell.ts +++ b/packages/vtable/src/plugins/list-tree-stick-cell.ts @@ -6,6 +6,8 @@ import type { Graphic } from '@src/vrender'; import { createRect } from '@src/vrender'; import { Factory } from '../core/factory'; import { getTargetCell } from '../event/util'; +import { getIconAndPositionFromTarget } from '../scenegraph/utils/icon'; +import { IconFuncTypeEnum } from '../ts-types'; export interface IListTreeStickCellPlugin { new (table: ListTable): ListTreeStickCellPlugin; @@ -247,7 +249,18 @@ function prepareShadowRoot(table: ListTable) { const titleRows = table.listTreeStickCellPlugin.titleRows; const { shadowTarget } = e.pickParams; const cellGroup = getTargetCell(shadowTarget); - const { col, row } = cellGroup; + if (!cellGroup) { + return; + } + const iconInfo = getIconAndPositionFromTarget(shadowTarget); + const funcType = iconInfo?.icon?.attribute?.funcType; + if (funcType === IconFuncTypeEnum.collapse || funcType === IconFuncTypeEnum.expand) { + const stickCellTop = getStickCellTop(cellGroup, table); + table.toggleHierarchyState(cellGroup.col, cellGroup.row); + keepRowAtVisiblePosition(cellGroup.col, cellGroup.row, stickCellTop, table); + return; + } + const { row } = cellGroup; const rowIndex = titleRows.indexOf(row); // table.scrollToCell({ col, row: row - rowIndex }); scrollToRow(row - rowIndex, table); @@ -271,7 +284,18 @@ function prepareShadowRoot(table: ListTable) { const titleRows = table.listTreeStickCellPlugin.titleRows; const { shadowTarget } = e.pickParams; const cellGroup = getTargetCell(shadowTarget); - const { col, row } = cellGroup; + if (!cellGroup) { + return; + } + const iconInfo = getIconAndPositionFromTarget(shadowTarget); + const funcType = iconInfo?.icon?.attribute?.funcType; + if (funcType === IconFuncTypeEnum.collapse || funcType === IconFuncTypeEnum.expand) { + const stickCellTop = getStickCellTop(cellGroup, table); + table.toggleHierarchyState(cellGroup.col, cellGroup.row); + keepRowAtVisiblePosition(cellGroup.col, cellGroup.row, stickCellTop, table); + return; + } + const { row } = cellGroup; const rowIndex = titleRows.indexOf(row); // table.scrollToCell({ col, row: row - rowIndex }); scrollToRow(row - rowIndex, table); @@ -297,6 +321,21 @@ function scrollToRow(row: number, table: ListTable) { table.scenegraph.updateNextFrame(); } +function getStickCellTop(cellGroup: Group, table: ListTable) { + return table.getFrozenRowsHeight() + (cellGroup.attribute?.y ?? 0); +} + +function keepRowAtVisiblePosition(col: number, row: number, visibleTop: number, table: ListTable) { + const drawRange = table.getDrawRange(); + // Keep the clicked sticky group row in roughly the same viewport position after collapse/expand. + const targetScrollTop = Math.max( + 0, + Math.min(table.getCellRect(col, row).top - visibleTop, table.getAllRowsHeight() - drawRange.height) + ); + table.scrollTop = targetScrollTop; + table.scenegraph.updateNextFrame(); +} + export const registerListTreeStickCellPlugin = () => { Factory.registerComponent('listTreeStickCellPlugin', ListTreeStickCellPlugin); }; From 362fee1e120c7f2cc6646f0ecda8dc8f725cd60f Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 20 May 2026 10:00:55 +0800 Subject: [PATCH 2/3] docs: update changlog of rush --- .rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc | 23 ++++++++++++++ .../pnpm-10.7.0/last-install.flag | 3 ++ .../pnpm-10.7.0/package-lock.json | 31 +++++++++++++++++++ .../node-v24.11.0/pnpm-10.7.0/package.json | 9 ++++++ ...roup-sticky-collapse_2026-05-20-02-00.json | 11 +++++++ 5 files changed, 77 insertions(+) create mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc create mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag create mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json create mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/package.json create mode 100644 common/changes/@visactor/vtable/fix-issue-4984-group-sticky-collapse_2026-05-20-02-00.json diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc b/.rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc new file mode 100644 index 0000000000..7db0e7b3d6 --- /dev/null +++ b/.rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc @@ -0,0 +1,23 @@ +# Rush uses this file to configure the NPM package registry during installation. It is applicable +# to PNPM, NPM, and Yarn package managers. It is used by operations such as "rush install", +# "rush update", and the "install-run.js" scripts. +# +# NOTE: The "rush publish" command uses .npmrc-publish instead. +# +# Before invoking the package manager, Rush will copy this file to the folder where installation +# is performed. The copied file will omit any config lines that reference environment variables +# that are undefined in that session; this avoids problems that would otherwise result due to +# a missing variable being replaced by an empty string. +# +# * * * SECURITY WARNING * * * +# +# It is NOT recommended to store authentication tokens in a text file on a lab machine, because +# other unrelated processes may be able to read the file. Also, the file may persist indefinitely, +# for example if the machine loses power. A safer practice is to pass the token via an +# environment variable, which can be referenced from .npmrc using ${} expansion. For example: +# +# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} +# + +registry=https://registry.npmjs.org/ +always-auth=false diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag b/.rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag new file mode 100644 index 0000000000..0aae51e4a3 --- /dev/null +++ b/.rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag @@ -0,0 +1,3 @@ +{ + "node": "24.11.0" +} diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json b/.rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json new file mode 100644 index 0000000000..c810d8aeaf --- /dev/null +++ b/.rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json @@ -0,0 +1,31 @@ +{ + "name": "pnpm-local-install", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pnpm-local-install", + "version": "0.0.0", + "dependencies": { + "pnpm": "10.7.0" + } + }, + "node_modules/pnpm": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/pnpm/-/pnpm-10.7.0.tgz", + "integrity": "sha512-a4Za1LYqHZhCth1nSjk5A7hx2SRJVPZSuIQsK1U8chdrJ49kxGPlLUD/+KujhcI1yMns9cx95P14uLttSWM6tg==", + "license": "MIT", + "bin": { + "pnpm": "bin/pnpm.cjs", + "pnpx": "bin/pnpx.cjs" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + } + } +} diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/package.json b/.rush-global/node-v24.11.0/pnpm-10.7.0/package.json new file mode 100644 index 0000000000..fe8ad16943 --- /dev/null +++ b/.rush-global/node-v24.11.0/pnpm-10.7.0/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "pnpm": "10.7.0" + }, + "description": "Temporary file generated by the Rush tool", + "name": "pnpm-local-install", + "private": true, + "version": "0.0.0" +} diff --git a/common/changes/@visactor/vtable/fix-issue-4984-group-sticky-collapse_2026-05-20-02-00.json b/common/changes/@visactor/vtable/fix-issue-4984-group-sticky-collapse_2026-05-20-02-00.json new file mode 100644 index 0000000000..422bad3dcb --- /dev/null +++ b/common/changes/@visactor/vtable/fix-issue-4984-group-sticky-collapse_2026-05-20-02-00.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: preserve sticky group position after toggle\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 826774780561aa62f9fbc4249733c282e29628b3 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 20 May 2026 10:02:21 +0800 Subject: [PATCH 3/3] chore: remove local rush artifacts --- .rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc | 23 -------------- .../pnpm-10.7.0/last-install.flag | 3 -- .../pnpm-10.7.0/package-lock.json | 31 ------------------- .../node-v24.11.0/pnpm-10.7.0/package.json | 9 ------ 4 files changed, 66 deletions(-) delete mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc delete mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag delete mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json delete mode 100644 .rush-global/node-v24.11.0/pnpm-10.7.0/package.json diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc b/.rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc deleted file mode 100644 index 7db0e7b3d6..0000000000 --- a/.rush-global/node-v24.11.0/pnpm-10.7.0/.npmrc +++ /dev/null @@ -1,23 +0,0 @@ -# Rush uses this file to configure the NPM package registry during installation. It is applicable -# to PNPM, NPM, and Yarn package managers. It is used by operations such as "rush install", -# "rush update", and the "install-run.js" scripts. -# -# NOTE: The "rush publish" command uses .npmrc-publish instead. -# -# Before invoking the package manager, Rush will copy this file to the folder where installation -# is performed. The copied file will omit any config lines that reference environment variables -# that are undefined in that session; this avoids problems that would otherwise result due to -# a missing variable being replaced by an empty string. -# -# * * * SECURITY WARNING * * * -# -# It is NOT recommended to store authentication tokens in a text file on a lab machine, because -# other unrelated processes may be able to read the file. Also, the file may persist indefinitely, -# for example if the machine loses power. A safer practice is to pass the token via an -# environment variable, which can be referenced from .npmrc using ${} expansion. For example: -# -# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} -# - -registry=https://registry.npmjs.org/ -always-auth=false diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag b/.rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag deleted file mode 100644 index 0aae51e4a3..0000000000 --- a/.rush-global/node-v24.11.0/pnpm-10.7.0/last-install.flag +++ /dev/null @@ -1,3 +0,0 @@ -{ - "node": "24.11.0" -} diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json b/.rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json deleted file mode 100644 index c810d8aeaf..0000000000 --- a/.rush-global/node-v24.11.0/pnpm-10.7.0/package-lock.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "pnpm-local-install", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "pnpm-local-install", - "version": "0.0.0", - "dependencies": { - "pnpm": "10.7.0" - } - }, - "node_modules/pnpm": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/pnpm/-/pnpm-10.7.0.tgz", - "integrity": "sha512-a4Za1LYqHZhCth1nSjk5A7hx2SRJVPZSuIQsK1U8chdrJ49kxGPlLUD/+KujhcI1yMns9cx95P14uLttSWM6tg==", - "license": "MIT", - "bin": { - "pnpm": "bin/pnpm.cjs", - "pnpx": "bin/pnpx.cjs" - }, - "engines": { - "node": ">=18.12" - }, - "funding": { - "url": "https://opencollective.com/pnpm" - } - } - } -} diff --git a/.rush-global/node-v24.11.0/pnpm-10.7.0/package.json b/.rush-global/node-v24.11.0/pnpm-10.7.0/package.json deleted file mode 100644 index fe8ad16943..0000000000 --- a/.rush-global/node-v24.11.0/pnpm-10.7.0/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "dependencies": { - "pnpm": "10.7.0" - }, - "description": "Temporary file generated by the Rush tool", - "name": "pnpm-local-install", - "private": true, - "version": "0.0.0" -}