UNPKG

react-native-reanimated

Version:

More powerful alternative to Animated library for React Native.

87 lines (77 loc) 3.38 kB
'use strict'; import type { WorkletFunction } from '../commonTypes'; import { WorkletEventHandler } from '../WorkletEventHandler'; import type { ReanimatedEvent } from './commonTypes'; import type { EventHandlerInternal, EventHandlerProcessed } from './useEvent'; import { useEvent } from './useEvent'; import { useHandler } from './useHandler'; type ComposedHandlerProcessed< Event extends object, Context extends Record<string, unknown> = Record<string, unknown>, > = EventHandlerProcessed<Event, Context>; type ComposedHandlerInternal<Event extends object> = EventHandlerInternal<Event>; /** * Lets you compose multiple event handlers based on * [useEvent](https://docs.swmansion.com/react-native-reanimated/docs/advanced/useEvent) * hook. * * @param handlers - An array of event handlers created using * [useEvent](https://docs.swmansion.com/react-native-reanimated/docs/advanced/useEvent) * hook. * @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). * @see https://docs.swmansion.com/react-native-reanimated/docs/advanced/useComposedEventHandler */ // @ts-expect-error This overload is required by our API. export function useComposedEventHandler< Event extends object, Context extends Record<string, unknown>, >( handlers: (EventHandlerProcessed<Event, Context> | null)[] ): ComposedHandlerProcessed<Event, Context>; export function useComposedEventHandler< Event extends object, Context extends Record<string, unknown>, >(handlers: (EventHandlerProcessed<Event, Context> | null)[]) { // Record of handlers' worklets to calculate deps diffs. We use the record type to match the useHandler API requirements const workletsRecord: Record<string, WorkletFunction> = {}; // Summed event names for registration const composedEventNames = new Set<string>(); // Map that holds worklets for specific handled events const workletsMap: { [key: string]: ((event: ReanimatedEvent<Event>) => void)[]; } = {}; handlers .filter((h) => h !== null) .forEach((handler) => { // EventHandlerProcessed is the return type of useEvent and has to be force casted to EventHandlerInternal, because we need WorkletEventHandler object const { workletEventHandler } = handler as unknown as EventHandlerInternal<Context>; if (workletEventHandler instanceof WorkletEventHandler) { workletEventHandler.eventNames.forEach((eventName) => { composedEventNames.add(eventName); if (workletsMap[eventName]) { workletsMap[eventName].push(workletEventHandler.worklet); } else { workletsMap[eventName] = [workletEventHandler.worklet]; } const handlerName = eventName + `${workletsMap[eventName].length}`; workletsRecord[handlerName] = workletEventHandler.worklet as WorkletFunction; }); } }); const { doDependenciesDiffer } = useHandler(workletsRecord); return useEvent<Event, Context>( (event) => { 'worklet'; if (workletsMap[event.eventName]) { workletsMap[event.eventName].forEach((worklet) => worklet(event)); } }, Array.from(composedEventNames), doDependenciesDiffer ) as unknown as ComposedHandlerInternal<Event>; }