From a53d57015958d2879107aacfb44eeef2b75f0742 Mon Sep 17 00:00:00 2001 From: Daniil Suvorov Date: Thu, 9 Mar 2023 13:54:25 +0300 Subject: [PATCH] feat(HorizontalScroll): add scrollOnAnyWheel (#4390) - closed #4367 --- .../HorizontalScroll.test.tsx | 22 ++++++++++++++ .../HorizontalScroll/HorizontalScroll.tsx | 30 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.test.tsx b/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.test.tsx index fc093191b2..6a26fab6e6 100644 --- a/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.test.tsx +++ b/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.test.tsx @@ -1,6 +1,28 @@ +import * as React from 'react'; +import { fireEvent, render } from '@testing-library/react'; import { baselineComponent } from '../../testing/utils'; import { HorizontalScroll } from './HorizontalScroll'; describe('HorizontalScroll', () => { baselineComponent(HorizontalScroll); + + it('scrollOnAnyWheel', () => { + const ref = React.createRef(); + render( + +
+
+ , + ); + + const scrollBy: Element['scrollBy'] = jest.fn(); + ref.current!.scrollBy = scrollBy; + + fireEvent.wheel(ref.current!, { + deltaX: 10, + deltaY: 10, + }); + + expect(scrollBy).toBeCalledTimes(1); + }); }); diff --git a/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx b/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx index c8e1dd026a..034ab28591 100644 --- a/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx +++ b/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { classNames } from '@vkontakte/vkjs'; +import { classNames, noop } from '@vkontakte/vkjs'; import { useAdaptivityHasPointer } from '../../hooks/useAdaptivityHasPointer'; import { useEventListener } from '../../hooks/useEventListener'; import { useExternRef } from '../../hooks/useExternRef'; @@ -39,6 +39,11 @@ export interface HorizontalScrollProps arrowSize?: 'm' | 'l'; showArrows?: boolean | 'always'; scrollAnimationDuration?: number; + /** + * Добавляет возможность прокручивать контент на любое колесо мыши. + * По умолчанию прокручивается как любой горизонтальный контент через shift. + */ + scrollOnAnyWheel?: boolean; } /** @@ -131,6 +136,7 @@ export const HorizontalScroll = ({ scrollAnimationDuration = SCROLL_ONE_FRAME_TIME, getRef, className, + scrollOnAnyWheel = false, ...restProps }: HorizontalScrollProps) => { const [canScrollLeft, setCanScrollLeft] = React.useState(false); @@ -199,6 +205,28 @@ export const HorizontalScroll = ({ }, [scrollEvent, scrollerRef]); React.useEffect(onscroll, [scrollerRef, children, onscroll]); + /** + * Прокрутка с помощью любого колеса мыши + */ + const onwheel = React.useCallback( + (e: WheelEvent) => { + scrollerRef.current!.scrollBy({ left: e.deltaX + e.deltaY, behavior: 'auto' }); + e.preventDefault(); + }, + [scrollerRef], + ); + + const wheelEvent = useEventListener('wheel', onwheel); + React.useEffect(() => { + if (!scrollerRef.current || !scrollOnAnyWheel) { + return noop; + } + + wheelEvent.add(scrollerRef.current); + + return wheelEvent.remove; + }, [wheelEvent, scrollerRef, scrollOnAnyWheel]); + return (