From c88e6ce8e1156195b71875dbfcbf45409da28bc7 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Mon, 17 Aug 2026 19:27:23 -0400 Subject: [PATCH] fix(slickgrid): prevent native wheel drift with frozen columns --- packages/common/src/core/__tests__/slickGrid.spec.ts | 2 ++ packages/common/src/core/slickGrid.ts | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/packages/common/src/core/__tests__/slickGrid.spec.ts b/packages/common/src/core/__tests__/slickGrid.spec.ts index a7ed24948..13497051f 100644 --- a/packages/common/src/core/__tests__/slickGrid.spec.ts +++ b/packages/common/src/core/__tests__/slickGrid.spec.ts @@ -6116,6 +6116,7 @@ describe('SlickGrid core file', () => { const mouseEvent = new Event('mousewheel'); const mousePreventSpy = vi.spyOn(mouseEvent, 'stopPropagation'); + const nativeScrollPreventSpy = vi.spyOn(mouseEvent, 'preventDefault'); const onViewportChangedSpy = vi.spyOn(grid.onViewportChanged, 'notify'); const viewportBottomRightElm = container.querySelector('.slick-viewport-bottom.slick-viewport-right') as HTMLDivElement; Object.defineProperty(viewportBottomRightElm, 'scrollHeight', { writable: true, value: DEFAULT_GRID_HEIGHT }); @@ -6136,6 +6137,7 @@ describe('SlickGrid core file', () => { expect(viewportBottomRightElm.scrollTop).toBe(0); expect(onViewportChangedSpy).toHaveBeenCalled(); expect(mousePreventSpy).toHaveBeenCalled(); + expect(nativeScrollPreventSpy).toHaveBeenCalled(); }); it('should scroll all elements shown when triggered by mousewheel and preHeader/footer/frozenColumn are enabled', () => { diff --git a/packages/common/src/core/slickGrid.ts b/packages/common/src/core/slickGrid.ts index f8c37413b..ed158a1bd 100755 --- a/packages/common/src/core/slickGrid.ts +++ b/packages/common/src/core/slickGrid.ts @@ -6318,6 +6318,13 @@ export class SlickGrid = Column, O e const handled = this._handleScroll('mousewheel'); if (handled) { e.stopPropagation(); + // Frozen columns use a second viewport whose vertical position is mirrored + // from the scrolling pane. Letting the browser also process this wheel event + // advances the source pane a second time, briefly putting it ahead of the + // frozen viewport until its subsequent scroll event is handled. + if (this.hasFrozenColumns()) { + e.preventDefault(); + } } }