react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
155 lines (142 loc) • 4.55 kB
text/typescript
import type {
DependencyList,
NativeEventWrapper,
ReanimatedEvent,
} from './commonTypes';
import { useEvent } from './useEvent';
import { useHandler } from './useHandler';
const EVENT_TYPE = {
UNDETERMINED: 0,
FAILED: 1,
BEGAN: 2,
CANCELLED: 3,
ACTIVE: 4,
END: 5,
} as const;
type StateType = (typeof EVENT_TYPE)[keyof typeof EVENT_TYPE];
// This type comes from React Native Gesture Handler
// import type { PanGestureHandlerGestureEvent as DefaultEvent } from 'react-native-gesture-handler';
type DefaultEvent = {
nativeEvent: {
readonly handlerTag: number;
readonly numberOfPointers: number;
readonly state: (typeof EVENT_TYPE)[keyof typeof EVENT_TYPE];
readonly x: number;
readonly y: number;
readonly absoluteX: number;
readonly absoluteY: number;
readonly translationX: number;
readonly translationY: number;
readonly velocityX: number;
readonly velocityY: number;
};
};
interface PropsUsedInUseAnimatedGestureHandler {
handlerTag?: number;
numberOfPointers?: number;
state?: StateType;
oldState?: StateType;
}
export type GestureHandlerEvent<Event extends object> =
| ReanimatedEvent<Event>
| Event;
type GestureHandler<
Event extends NativeEventWrapper<PropsUsedInUseAnimatedGestureHandler>,
Context extends Record<string, unknown>,
> = (
eventPayload: ReanimatedEvent<Event>,
context: Context,
isCanceledOrFailed?: boolean
) => void;
export interface GestureHandlers<
Event extends NativeEventWrapper<PropsUsedInUseAnimatedGestureHandler>,
Context extends Record<string, unknown>,
> {
[key: string]: GestureHandler<Event, Context> | undefined;
onStart?: GestureHandler<Event, Context>;
onActive?: GestureHandler<Event, Context>;
onEnd?: GestureHandler<Event, Context>;
onFail?: GestureHandler<Event, Context>;
onCancel?: GestureHandler<Event, Context>;
onFinish?: GestureHandler<Event, Context>;
}
/**
* @deprecated UseAnimatedGestureHandler is an old API which is no longer
* supported.
*
* Please check
* https://docs.swmansion.com/react-native-gesture-handler/docs/guides/upgrading-to-2/
* for information about how to migrate to `react-native-gesture-handler` v2
*/
export function useAnimatedGestureHandler<
Event extends
NativeEventWrapper<PropsUsedInUseAnimatedGestureHandler> = DefaultEvent,
Context extends Record<string, unknown> = Record<string, unknown>,
>(handlers: GestureHandlers<Event, Context>, dependencies?: DependencyList) {
type WebOrNativeEvent = Event | ReanimatedEvent<Event>;
const { context, doDependenciesDiffer, useWeb } = useHandler<Event, Context>(
handlers,
dependencies
);
const handler = (e: WebOrNativeEvent) => {
'worklet';
const event = useWeb
? // On Web we get events straight from React Native and they don't have
// the `eventName` field there. To simplify the types here we just
// cast it as the field was available.
((e as Event).nativeEvent as ReanimatedEvent<Event>)
: (e as ReanimatedEvent<Event>);
if (event.state === EVENT_TYPE.BEGAN && handlers.onStart) {
handlers.onStart(event, context);
}
if (event.state === EVENT_TYPE.ACTIVE && handlers.onActive) {
handlers.onActive(event, context);
}
if (
event.oldState === EVENT_TYPE.ACTIVE &&
event.state === EVENT_TYPE.END &&
handlers.onEnd
) {
handlers.onEnd(event, context);
}
if (
event.oldState === EVENT_TYPE.BEGAN &&
event.state === EVENT_TYPE.FAILED &&
handlers.onFail
) {
handlers.onFail(event, context);
}
if (
event.oldState === EVENT_TYPE.ACTIVE &&
event.state === EVENT_TYPE.CANCELLED &&
handlers.onCancel
) {
handlers.onCancel(event, context);
}
if (
(event.oldState === EVENT_TYPE.BEGAN ||
event.oldState === EVENT_TYPE.ACTIVE) &&
event.state !== EVENT_TYPE.BEGAN &&
event.state !== EVENT_TYPE.ACTIVE &&
handlers.onFinish
) {
handlers.onFinish(
event,
context,
event.state === EVENT_TYPE.CANCELLED ||
event.state === EVENT_TYPE.FAILED
);
}
};
if (useWeb) {
return handler;
}
// eslint-disable-next-line react-hooks/rules-of-hooks
return useEvent<Event>(
handler,
['onGestureHandlerStateChange', 'onGestureHandlerEvent'],
doDependenciesDiffer
// This is not correct but we want to make GH think it receives a function.
) as unknown as (e: Event) => void;
}
;