UNPKG

3.35 kBPlain TextView Raw
1'use strict';
2import { useEvent } from './useEvent';
3import { useHandler } from './useHandler';
4import { WorkletEventHandler } from '../WorkletEventHandler';
5import type { ReanimatedEvent } from './commonTypes';
6import type { WorkletFunction } from '../commonTypes';
7import type { EventHandlerProcessed, EventHandlerInternal } from './useEvent';
8
9type ComposedHandlerProcessed<
10 Event extends object,
11 Context extends Record<string, unknown> = Record<string, unknown>
12> = EventHandlerProcessed<Event, Context>;
13
14type ComposedHandlerInternal<Event extends object> =
15 EventHandlerInternal<Event>;
16
17/**
18 * Lets you compose multiple event handlers based on [useEvent](https://docs.swmansion.com/react-native-reanimated/docs/advanced/useEvent) hook.
19 *
20 * @param handlers - An array of event handlers created using [useEvent](https://docs.swmansion.com/react-native-reanimated/docs/advanced/useEvent) hook.
21 * @returns An object you need to pass to a coresponding "onEvent" prop on an `Animated` component (for example handlers responsible for `onScroll` event go to `onScroll` prop).
22 * @see https://docs.swmansion.com/react-native-reanimated/docs/advanced/useComposedEventHandler
23 */
24// @ts-expect-error This overload is required by our API.
25export function useComposedEventHandler<
26 Event extends object,
27 Context extends Record<string, unknown>
28>(
29 handlers: (EventHandlerProcessed<Event, Context> | null)[]
30): ComposedHandlerProcessed<Event, Context>;
31
32export function useComposedEventHandler<
33 Event extends object,
34 Context extends Record<string, unknown>
35>(handlers: (EventHandlerProcessed<Event, Context> | null)[]) {
36 // Record of handlers' worklets to calculate deps diffs. We use the record type to match the useHandler API requirements
37 const workletsRecord: Record<string, WorkletFunction> = {};
38 // Summed event names for registration
39 const composedEventNames = new Set<string>();
40 // Map that holds worklets for specific handled events
41 const workletsMap: {
42 [key: string]: ((event: ReanimatedEvent<Event>) => void)[];
43 } = {};
44
45 handlers
46 .filter((h) => h !== null)
47 .forEach((handler) => {
48 // EventHandlerProcessed is the return type of useEvent and has to be force casted to EventHandlerInternal, because we need WorkletEventHandler object
49 const { workletEventHandler } =
50 handler as unknown as EventHandlerInternal<Context>;
51 if (workletEventHandler instanceof WorkletEventHandler) {
52 workletEventHandler.eventNames.forEach((eventName) => {
53 composedEventNames.add(eventName);
54
55 if (workletsMap[eventName]) {
56 workletsMap[eventName].push(workletEventHandler.worklet);
57 } else {
58 workletsMap[eventName] = [workletEventHandler.worklet];
59 }
60
61 const handlerName = eventName + `${workletsMap[eventName].length}`;
62 workletsRecord[handlerName] =
63 workletEventHandler.worklet as WorkletFunction;
64 });
65 }
66 });
67
68 const { doDependenciesDiffer } = useHandler(workletsRecord);
69
70 return useEvent<Event, Context>(
71 (event) => {
72 'worklet';
73 if (workletsMap[event.eventName]) {
74 workletsMap[event.eventName].forEach((worklet) => worklet(event));
75 }
76 },
77 Array.from(composedEventNames),
78 doDependenciesDiffer
79 ) as unknown as ComposedHandlerInternal<Event>;
80}
81
\No newline at end of file