UNPKG

3.99 kBPlain TextView Raw
1'use strict';
2import type {
3 DependencyList,
4 RNNativeScrollEvent,
5 ReanimatedScrollEvent,
6} from './commonTypes';
7import { useHandler } from './useHandler';
8import type { EventHandlerInternal, EventHandlerProcessed } from './useEvent';
9import { useEvent } from './useEvent';
10
11export type ScrollHandler<
12 Context extends Record<string, unknown> = Record<string, unknown>
13> = (event: ReanimatedScrollEvent, context: Context) => void;
14export interface ScrollHandlers<Context extends Record<string, unknown>> {
15 onScroll?: ScrollHandler<Context>;
16 onBeginDrag?: ScrollHandler<Context>;
17 onEndDrag?: ScrollHandler<Context>;
18 onMomentumBegin?: ScrollHandler<Context>;
19 onMomentumEnd?: ScrollHandler<Context>;
20}
21
22export type ScrollHandlerProcessed<
23 Context extends Record<string, unknown> = Record<string, unknown>
24> = EventHandlerProcessed<RNNativeScrollEvent, Context>;
25
26export type ScrollHandlerInternal = EventHandlerInternal<RNNativeScrollEvent>;
27
28/**
29 * Lets you run callbacks on ScrollView events. Supports `onScroll`, `onBeginDrag`, `onEndDrag`, `onMomentumBegin`, and `onMomentumEnd` events.
30 *
31 * These callbacks are automatically workletized and ran on the UI thread.
32 *
33 * @param handlers - An object containing event handlers.
34 * @param dependencies - An optional array of dependencies. Only relevant when using Reanimated without the Babel plugin on the Web.
35 * @returns An object you need to pass to `onScroll` prop on the `Animated.ScrollView` component.
36 * @see https://docs.swmansion.com/react-native-reanimated/docs/scroll/useAnimatedScrollHandler
37 */
38// @ts-expect-error This overload is required by our API.
39export function useAnimatedScrollHandler<
40 Context extends Record<string, unknown>
41>(
42 handlers: ScrollHandler<Context> | ScrollHandlers<Context>,
43 dependencies?: DependencyList
44): ScrollHandlerProcessed<Context>;
45
46export function useAnimatedScrollHandler<
47 Context extends Record<string, unknown>
48>(
49 handlers: ScrollHandlers<Context> | ScrollHandler<Context>,
50 dependencies?: DependencyList
51) {
52 // case when handlers is a function
53 const scrollHandlers: ScrollHandlers<Context> =
54 typeof handlers === 'function' ? { onScroll: handlers } : handlers;
55 const { context, doDependenciesDiffer } = useHandler<
56 RNNativeScrollEvent,
57 Context
58 >(scrollHandlers as Record<string, ScrollHandler<Context>>, dependencies);
59
60 // build event subscription array
61 const subscribeForEvents = ['onScroll'];
62 if (scrollHandlers.onBeginDrag !== undefined) {
63 subscribeForEvents.push('onScrollBeginDrag');
64 }
65 if (scrollHandlers.onEndDrag !== undefined) {
66 subscribeForEvents.push('onScrollEndDrag');
67 }
68 if (scrollHandlers.onMomentumBegin !== undefined) {
69 subscribeForEvents.push('onMomentumScrollBegin');
70 }
71 if (scrollHandlers.onMomentumEnd !== undefined) {
72 subscribeForEvents.push('onMomentumScrollEnd');
73 }
74
75 return useEvent<RNNativeScrollEvent, Context>(
76 (event: ReanimatedScrollEvent) => {
77 'worklet';
78 const {
79 onScroll,
80 onBeginDrag,
81 onEndDrag,
82 onMomentumBegin,
83 onMomentumEnd,
84 } = scrollHandlers;
85 if (onScroll && event.eventName.endsWith('onScroll')) {
86 onScroll(event, context);
87 } else if (onBeginDrag && event.eventName.endsWith('onScrollBeginDrag')) {
88 onBeginDrag(event, context);
89 } else if (onEndDrag && event.eventName.endsWith('onScrollEndDrag')) {
90 onEndDrag(event, context);
91 } else if (
92 onMomentumBegin &&
93 event.eventName.endsWith('onMomentumScrollBegin')
94 ) {
95 onMomentumBegin(event, context);
96 } else if (
97 onMomentumEnd &&
98 event.eventName.endsWith('onMomentumScrollEnd')
99 ) {
100 onMomentumEnd(event, context);
101 }
102 },
103 subscribeForEvents,
104 doDependenciesDiffer
105 // Read https://github.com/software-mansion/react-native-reanimated/pull/5056
106 // for more information about this cast.
107 ) as unknown as ScrollHandlerInternal;
108}