From 4a3b89818fe92b965bed57ff76d0c63d2020cea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 18 Sep 2023 15:59:04 +0800 Subject: [PATCH 1/2] fix: resize should trigger scrollLeft --- src/List.tsx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/List.tsx b/src/List.tsx index b76e9a40..ad4d1520 100644 --- a/src/List.tsx +++ b/src/List.tsx @@ -255,7 +255,21 @@ export function RawList(props: ListProps, ref: React.Ref) { // ================================= Size ================================= const [size, setSize] = React.useState({ width: 0, height }); + + const keepInHorizontalRange = (nextOffsetLeft: number) => { + let tmpOffsetLeft = nextOffsetLeft; + const max = scrollWidth - size.width; + tmpOffsetLeft = Math.max(tmpOffsetLeft, 0); + tmpOffsetLeft = Math.min(tmpOffsetLeft, max); + + return tmpOffsetLeft; + }; + const onHolderResize: ResizeObserverProps['onResize'] = (sizeInfo) => { + setOffsetLeft((left) => { + return keepInHorizontalRange(left); + }); + setSize(sizeInfo); }; @@ -340,15 +354,6 @@ export function RawList(props: ListProps, ref: React.Ref) { triggerScroll(); } - const keepInHorizontalRange = (nextOffsetLeft: number) => { - let tmpOffsetLeft = nextOffsetLeft; - const max = scrollWidth - size.width; - tmpOffsetLeft = Math.max(tmpOffsetLeft, 0); - tmpOffsetLeft = Math.min(tmpOffsetLeft, max); - - return tmpOffsetLeft; - }; - const onWheelDelta: Parameters[4] = useEvent((offsetXY, fromHorizontal) => { if (fromHorizontal) { // Horizontal scroll no need sync virtual position From f1210cf1ef5b24b59d921c5cc1895194e908190a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 18 Sep 2023 16:16:18 +0800 Subject: [PATCH 2/2] fix: resize not handle scroll --- src/List.tsx | 31 ++++++++++++++++++------------- tests/scrollWidth.test.tsx | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/List.tsx b/src/List.tsx index ad4d1520..d71db85c 100644 --- a/src/List.tsx +++ b/src/List.tsx @@ -256,20 +256,7 @@ export function RawList(props: ListProps, ref: React.Ref) { // ================================= Size ================================= const [size, setSize] = React.useState({ width: 0, height }); - const keepInHorizontalRange = (nextOffsetLeft: number) => { - let tmpOffsetLeft = nextOffsetLeft; - const max = scrollWidth - size.width; - tmpOffsetLeft = Math.max(tmpOffsetLeft, 0); - tmpOffsetLeft = Math.min(tmpOffsetLeft, max); - - return tmpOffsetLeft; - }; - const onHolderResize: ResizeObserverProps['onResize'] = (sizeInfo) => { - setOffsetLeft((left) => { - return keepInHorizontalRange(left); - }); - setSize(sizeInfo); }; @@ -354,6 +341,15 @@ export function RawList(props: ListProps, ref: React.Ref) { triggerScroll(); } + const keepInHorizontalRange = (nextOffsetLeft: number) => { + let tmpOffsetLeft = nextOffsetLeft; + const max = scrollWidth - size.width; + tmpOffsetLeft = Math.max(tmpOffsetLeft, 0); + tmpOffsetLeft = Math.min(tmpOffsetLeft, max); + + return tmpOffsetLeft; + }; + const onWheelDelta: Parameters[4] = useEvent((offsetXY, fromHorizontal) => { if (fromHorizontal) { // Horizontal scroll no need sync virtual position @@ -414,6 +410,15 @@ export function RawList(props: ListProps, ref: React.Ref) { }; }, [useVirtual]); + // Sync scroll left + useLayoutEffect(() => { + if (scrollWidth) { + setOffsetLeft((left) => { + return keepInHorizontalRange(left); + }); + } + }, [size.width, scrollWidth]); + // ================================= Ref ================================== const delayHideScrollBar = () => { verticalScrollBarRef.current?.delayHidden(); diff --git a/tests/scrollWidth.test.tsx b/tests/scrollWidth.test.tsx index b64f9ac4..7a5db3b1 100644 --- a/tests/scrollWidth.test.tsx +++ b/tests/scrollWidth.test.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { act, fireEvent, render } from '@testing-library/react'; import { spyElementPrototypes } from 'rc-util/lib/test/domHook'; -import {} from 'rc-resize-observer'; import type { ListRef } from '../src'; import List, { type ListProps } from '../src'; import { _rs as onLibResize } from 'rc-resize-observer/lib/utils/observerUtil'; @@ -18,16 +17,18 @@ describe('List.scrollWidth', () => { let mockMouseEvent; let pageX: number; + let holderWidth = 100; + beforeAll(() => { mockElement = spyElementPrototypes(HTMLElement, { offsetHeight: { get: () => ITEM_HEIGHT, }, clientHeight: { - get: () => 100, + get: () => holderWidth, }, getBoundingClientRect: () => ({ - width: 100, + width: holderWidth, height: 100, }), }); @@ -45,6 +46,7 @@ describe('List.scrollWidth', () => { }); beforeEach(() => { + holderWidth = 100; jest.useFakeTimers(); }); @@ -229,4 +231,34 @@ describe('List.scrollWidth', () => { `${ITEM_HEIGHT}/${4 * ITEM_HEIGHT}`, ); }); + + it('resize should back of scrollLeft', async () => { + const { container } = await genList({ + itemHeight: ITEM_HEIGHT, + height: 100, + data: genData(100), + scrollWidth: 1000, + }); + + // Wheel + fireEvent.wheel(container.querySelector('.rc-virtual-list-holder')!, { + deltaX: 9999999, + }); + + holderWidth = 200; + + await act(async () => { + onLibResize([ + { + target: container.querySelector('.rc-virtual-list-holder')!, + } as ResizeObserverEntry, + ]); + + await Promise.resolve(); + }); + + expect(container.querySelector('.rc-virtual-list-holder-inner')).toHaveStyle({ + marginLeft: '-800px', + }); + }); });