From 2c1b552f9df3de4c6e5d8c3cc7f1adc2ce2376f3 Mon Sep 17 00:00:00 2001 From: "gzzengxianzhi@corp.netease.com" Date: Fri, 20 Sep 2024 10:17:57 +0800 Subject: [PATCH] fix: can't scroll the document on Firefox --- 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 ad8ff805..bcb4e106 100644 --- a/src/List.tsx +++ b/src/List.tsx @@ -425,8 +425,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(); } } @@ -441,7 +444,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(); + }); });