From 294529679a274ac00380fe427d5f02d97f26e6f9 Mon Sep 17 00:00:00 2001 From: Hans Zeng <34590758+hanszeng-chn@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:26:34 +0800 Subject: [PATCH] fix: can't scroll the document on Firefox (#287) Co-authored-by: gzzengxianzhi@corp.netease.com --- src/List.tsx | 9 ++++-- tests/scroll-Firefox.test.js | 55 ++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/List.tsx b/src/List.tsx index f56cd47e..a7f74e96 100644 --- a/src/List.tsx +++ b/src/List.tsx @@ -438,8 +438,11 @@ export function RawList(props: ListProps, ref: React.Ref) { useLayoutEffect(() => { // Firefox only - function onMozMousePixelScroll(e: Event) { - if (useVirtual) { + function onMozMousePixelScroll(e: WheelEvent) { + // scrolling at top/bottom limit + const scrollingUpAtTop = isScrollAtTop && e.detail < 0; + const scrollingDownAtBottom = isScrollAtBottom && e.detail > 0; + if (useVirtual && !scrollingUpAtTop && !scrollingDownAtBottom) { e.preventDefault(); } } @@ -454,7 +457,7 @@ export function RawList(props: ListProps, ref: React.Ref) { componentEle.removeEventListener('DOMMouseScroll', onFireFoxScroll as any); componentEle.removeEventListener('MozMousePixelScroll', onMozMousePixelScroll as any); }; - }, [useVirtual]); + }, [useVirtual, isScrollAtTop, isScrollAtBottom]); // Sync scroll left useLayoutEffect(() => { diff --git a/tests/scroll-Firefox.test.js b/tests/scroll-Firefox.test.js index c4907867..2a9290ea 100644 --- a/tests/scroll-Firefox.test.js +++ b/tests/scroll-Firefox.test.js @@ -84,4 +84,59 @@ describe('List.Firefox-Scroll', () => { expect(wheelPreventDefault).not.toHaveBeenCalled(); expect(firefoxPreventDefault).toHaveBeenCalledTimes(1); }); + + it('should call preventDefault on MozMousePixelScroll', () => { + const preventDefault = jest.fn(); + const wrapper = genList({ itemHeight: 20, height: 100, data: genData(100) }); + const ulElement = wrapper.find('ul').instance(); + + act(() => { + const event = new Event('MozMousePixelScroll'); + event.detail = 6; + event.preventDefault = preventDefault; + ulElement.dispatchEvent(event); + + jest.runAllTimers(); + }); + + expect(preventDefault).toHaveBeenCalled(); + }); + + it('should not call preventDefault on MozMousePixelScroll when scrolling up at top boundary', () => { + const preventDefault = jest.fn(); + const wrapper = genList({ itemHeight: 20, height: 100, data: genData(100) }); + const ulElement = wrapper.find('ul').instance(); + + act(() => { + const event = new Event('MozMousePixelScroll'); + event.detail = -6; + event.preventDefault = preventDefault; + ulElement.dispatchEvent(event); + + jest.runAllTimers(); + }); + + expect(preventDefault).not.toHaveBeenCalled(); + }); + it('should not call preventDefault on MozMousePixelScroll when scrolling down at bottom boundary', () => { + const preventDefault = jest.fn(); + const listRef = React.createRef(); + const wrapper = genList({ itemHeight: 20, height: 100, data: genData(100), ref: listRef }); + const ulElement = wrapper.find('ul').instance(); + // scroll to bottom + listRef.current.scrollTo(99999); + jest.runAllTimers(); + expect(wrapper.find('ul').instance().scrollTop).toEqual(1900); + + act(() => { + const event = new Event('MozMousePixelScroll'); + event.detail = 6; + event.preventDefault = preventDefault; + ulElement.dispatchEvent(event); + + jest.runAllTimers(); + }); + + expect(preventDefault).not.toHaveBeenCalled(); + }); });