diff --git a/apps/common-app/src/new_api/complicated/velocity_test/index.tsx b/apps/common-app/src/new_api/complicated/velocity_test/index.tsx index b1071b1f13..28c9f930d6 100644 --- a/apps/common-app/src/new_api/complicated/velocity_test/index.tsx +++ b/apps/common-app/src/new_api/complicated/velocity_test/index.tsx @@ -33,11 +33,7 @@ export default function App() { offsetX.value += event.changeX; offsetY.value += event.changeY; }, - onFinalize: (event) => { - isPressed.value = false; - colorProgress.value = withTiming(0, { - duration: 100, - }); + onDeactivate: (event) => { // If we can't get view size, just ignore it. Half of the view will be // able to go outside the screen const size = measure(aref) ?? { width: 0, height: 0 }; @@ -59,6 +55,13 @@ export default function App() { rubberBandFactor: 0.75, }); }, + onFinalize: () => { + isPressed.value = false; + + colorProgress.value = withTiming(0, { + duration: 100, + }); + }, }); const animatedStyles = useAnimatedStyle(() => { diff --git a/apps/common-app/src/new_api/showcase/bottom_sheet/index.tsx b/apps/common-app/src/new_api/showcase/bottom_sheet/index.tsx index 83a02847b1..1cde9bbc10 100644 --- a/apps/common-app/src/new_api/showcase/bottom_sheet/index.tsx +++ b/apps/common-app/src/new_api/showcase/bottom_sheet/index.tsx @@ -8,7 +8,7 @@ import { } from 'react-native'; import { GestureDetector, - PanGestureEvent, + PanGestureActiveEvent, useSimultaneousGestures, usePanGesture, useTapGesture, @@ -35,7 +35,7 @@ function Example() { const scrollOffset = useSharedValue(0); const bottomSheetTranslateY = useSharedValue(CLOSED_SNAP_POINT); - const onHandlerDeactivate = (e: PanGestureEvent) => { + const onHandlerDeactivate = (e: PanGestureActiveEvent) => { const dragToss = 0.01; const endOffsetY = bottomSheetTranslateY.value + translationY.value + e.velocityY * dragToss; diff --git a/packages/react-native-gesture-handler/src/__tests__/RelationsTraversal.test.tsx b/packages/react-native-gesture-handler/src/__tests__/RelationsTraversal.test.tsx index 89baee3457..2dc9e3245d 100644 --- a/packages/react-native-gesture-handler/src/__tests__/RelationsTraversal.test.tsx +++ b/packages/react-native-gesture-handler/src/__tests__/RelationsTraversal.test.tsx @@ -9,10 +9,10 @@ import { configureRelations } from '../v3/detectors/utils'; import { SingleGesture, SingleGestureName } from '../v3/types'; import { renderHook } from '@testing-library/react-native'; +type AnySingleGesture = SingleGesture; + describe('Ensure only one leaf node', () => { - let pan1: SingleGesture, - pan2: SingleGesture, - pan3: SingleGesture; + let pan1: AnySingleGesture, pan2: AnySingleGesture, pan3: AnySingleGesture; beforeEach(() => { pan1 = renderHook(() => @@ -55,8 +55,8 @@ describe('Ensure only one leaf node', () => { }); describe('Simple relations', () => { - let pan1: SingleGesture, - pan2: SingleGesture; + let pan1: SingleGesture, + pan2: SingleGesture; beforeEach(() => { pan1 = renderHook(() => @@ -203,12 +203,8 @@ describe('External relations', () => { }); describe('Complex relations', () => { - let pan1: SingleGesture, - pan2: SingleGesture, - pan3: SingleGesture; - let tap1: SingleGesture, - tap2: SingleGesture, - tap3: SingleGesture; + let pan1: AnySingleGesture, pan2: AnySingleGesture, pan3: AnySingleGesture; + let tap1: AnySingleGesture, tap2: AnySingleGesture, tap3: AnySingleGesture; beforeEach(() => { tap1 = renderHook(() => diff --git a/packages/react-native-gesture-handler/src/components/Pressable/utils.ts b/packages/react-native-gesture-handler/src/components/Pressable/utils.ts index 058a4c25ce..04650ce576 100644 --- a/packages/react-native-gesture-handler/src/components/Pressable/utils.ts +++ b/packages/react-native-gesture-handler/src/components/Pressable/utils.ts @@ -1,19 +1,20 @@ import { Insets } from 'react-native'; -import { +import type { HoverGestureHandlerEventPayload, LongPressGestureHandlerEventPayload, } from '../../handlers/GestureHandlerEventPayload'; -import { +import type { TouchData, GestureStateChangeEvent, GestureTouchEvent, } from '../../handlers/gestureHandlerCommon'; -import { +import type { PressableDimensions, InnerPressableEvent, PressableEvent, } from './PressableProps'; -import { HoverGestureEvent, LongPressGestureEvent } from '../../v3'; +import type { HoverGestureEvent, LongPressGestureEvent } from '../../v3'; +import type { HoverGestureActiveEvent } from '../../v3/hooks'; const numberAsInset = (value: number): Insets => ({ left: value, @@ -51,6 +52,7 @@ const gestureToPressEvent = ( HoverGestureHandlerEventPayload | LongPressGestureHandlerEventPayload > | HoverGestureEvent + | HoverGestureActiveEvent | LongPressGestureEvent, timestamp: number, targetId: number @@ -82,6 +84,7 @@ const gestureToPressableEvent = ( HoverGestureHandlerEventPayload | LongPressGestureHandlerEventPayload > | HoverGestureEvent + | HoverGestureActiveEvent | LongPressGestureEvent ): PressableEvent => { const timestamp = Date.now(); diff --git a/packages/react-native-gesture-handler/src/components/ReanimatedDrawerLayout.tsx b/packages/react-native-gesture-handler/src/components/ReanimatedDrawerLayout.tsx index ad9b1570c9..d1f6620036 100644 --- a/packages/react-native-gesture-handler/src/components/ReanimatedDrawerLayout.tsx +++ b/packages/react-native-gesture-handler/src/components/ReanimatedDrawerLayout.tsx @@ -43,7 +43,7 @@ import { HitSlop, } from '../handlers/gestureHandlerCommon'; import { - PanGestureEvent, + PanGestureActiveEvent, usePanGesture, useTapGesture, } from '../v3/hooks/gestures'; @@ -434,7 +434,7 @@ const DrawerLayout = forwardRef( ); const handleRelease = useCallback( - (event: PanGestureEvent) => { + (event: PanGestureActiveEvent) => { 'worklet'; let { translationX: dragX, velocityX, x: touchX } = event; diff --git a/packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx b/packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx index a4aac45ed5..5199741e8d 100644 --- a/packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx +++ b/packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx @@ -17,7 +17,7 @@ import { SwipeDirection, } from './ReanimatedSwipeableProps'; import { - PanGestureEvent, + PanGestureActiveEvent, usePanGesture, useTapGesture, } from '../../v3/hooks/gestures'; @@ -402,7 +402,7 @@ const Swipeable = (props: SwipeableProps) => { ); const handleRelease = useCallback( - (event: PanGestureEvent) => { + (event: PanGestureActiveEvent) => { 'worklet'; const { velocityX } = event; userDrag.value = event.translationX; @@ -476,7 +476,7 @@ const Swipeable = (props: SwipeableProps) => { block, hitSlop: hitSlop, onActivate: updateElementWidths, - onUpdate: (event: PanGestureEvent) => { + onUpdate: (event: PanGestureActiveEvent) => { 'worklet'; userDrag.value = event.translationX; @@ -500,7 +500,7 @@ const Swipeable = (props: SwipeableProps) => { updateAnimatedEvent(); }, - onDeactivate: (event: PanGestureEvent) => { + onDeactivate: (event: PanGestureActiveEvent) => { 'worklet'; handleRelease(event); }, diff --git a/packages/react-native-gesture-handler/src/handlers/gestures/reanimatedWrapper.ts b/packages/react-native-gesture-handler/src/handlers/gestures/reanimatedWrapper.ts index afef43867e..e4ec22a69e 100644 --- a/packages/react-native-gesture-handler/src/handlers/gestures/reanimatedWrapper.ts +++ b/packages/react-native-gesture-handler/src/handlers/gestures/reanimatedWrapper.ts @@ -53,9 +53,9 @@ let Reanimated: ): ComponentClass

; }; NativeEventsManager: NativeEventsManager; - useHandler: ( - handlers: GestureCallbacks - ) => ReanimatedHandler; + useHandler: ( + handlers: GestureCallbacks + ) => ReanimatedHandler; useEvent: ( callback: (event: T) => void, events: string[], diff --git a/packages/react-native-gesture-handler/src/handlers/handlersRegistry.ts b/packages/react-native-gesture-handler/src/handlers/handlersRegistry.ts index 0996d75075..f0a1943260 100644 --- a/packages/react-native-gesture-handler/src/handlers/handlersRegistry.ts +++ b/packages/react-native-gesture-handler/src/handlers/handlersRegistry.ts @@ -8,14 +8,18 @@ export const handlerIDToTag: Record = {}; // There were attempts to create types that merge possible HandlerData and Config, // but ts was not able to infer them properly in many cases, so we use any here. // eslint-disable-next-line @typescript-eslint/no-explicit-any -const hookGestures = new Map>(); +const hookGestures = new Map>(); const gestures = new Map(); const oldHandlers = new Map(); const testIDs = new Map(); -export function registerGesture( +export function registerGesture< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - gesture: SingleGesture + gesture: SingleGesture ) { if (isTestEnv() && gesture.config.testID) { hookGestures.set(handlerTag, gesture); diff --git a/packages/react-native-gesture-handler/src/jestUtils/jestUtils.ts b/packages/react-native-gesture-handler/src/jestUtils/jestUtils.ts index eab23ef3b1..ece62c3537 100644 --- a/packages/react-native-gesture-handler/src/jestUtils/jestUtils.ts +++ b/packages/react-native-gesture-handler/src/jestUtils/jestUtils.ts @@ -166,14 +166,17 @@ const handlersDefaultEvents: DefaultEventsMapping = { }; function isGesture( - componentOrGesture: ReactTestInstance | GestureType | SingleGesture + componentOrGesture: + | ReactTestInstance + | GestureType + | SingleGesture ): componentOrGesture is GestureType { return componentOrGesture instanceof BaseGesture; } function isHookGesture( - componentOrGesture: ReactTestInstance | SingleGesture -): componentOrGesture is SingleGesture { + componentOrGesture: ReactTestInstance | SingleGesture +): componentOrGesture is SingleGesture { return 'detectorCallbacks' in componentOrGesture; } @@ -416,7 +419,10 @@ interface HandlerData { enabled: boolean | undefined; } function getHandlerData( - componentOrGesture: ReactTestInstance | GestureType | SingleGesture + componentOrGesture: + | ReactTestInstance + | GestureType + | SingleGesture ): HandlerData { if (isGesture(componentOrGesture)) { const gesture = componentOrGesture; @@ -500,7 +506,10 @@ type ExtractConfig = : Record; export function fireGestureHandler( - componentOrGesture: ReactTestInstance | GestureType | SingleGesture, + componentOrGesture: + | ReactTestInstance + | GestureType + | SingleGesture, eventList: Partial>>[] = [] ): void { const { emitEvent, handlerType, handlerTag, enabled } = diff --git a/packages/react-native-gesture-handler/src/v3/NativeProxy.ts b/packages/react-native-gesture-handler/src/v3/NativeProxy.ts index c115060b28..1260273272 100644 --- a/packages/react-native-gesture-handler/src/v3/NativeProxy.ts +++ b/packages/react-native-gesture-handler/src/v3/NativeProxy.ts @@ -22,9 +22,13 @@ export const NativeProxy = { config || {} ); }, - setGestureHandlerConfig: ( + setGestureHandlerConfig: < + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, + >( handlerTag: number, - newConfig: BaseGestureConfig + newConfig: BaseGestureConfig ) => { scheduleOperationToBeFlushed(() => { RNGestureHandlerModule.setGestureHandlerConfig(handlerTag, newConfig); @@ -33,9 +37,13 @@ export const NativeProxy = { // updateGestureHandlerConfig can be called on the UI thread when using // SharedValue binding. Therefore, it needs to be a worklet and we flush // immediately since we're likely already on the UI thread. - updateGestureHandlerConfig: ( + updateGestureHandlerConfig: < + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, + >( handlerTag: number, - newConfig: BaseGestureConfig + newConfig: BaseGestureConfig ) => { 'worklet'; updateGestureHandlerConfig(handlerTag, newConfig); diff --git a/packages/react-native-gesture-handler/src/v3/NativeProxy.web.ts b/packages/react-native-gesture-handler/src/v3/NativeProxy.web.ts index ef81140e62..4a11307097 100644 --- a/packages/react-native-gesture-handler/src/v3/NativeProxy.web.ts +++ b/packages/react-native-gesture-handler/src/v3/NativeProxy.web.ts @@ -17,15 +17,23 @@ export const NativeProxy = { config || {} ); }, - setGestureHandlerConfig: ( + setGestureHandlerConfig: < + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, + >( handlerTag: number, - newConfig: BaseGestureConfig + newConfig: BaseGestureConfig ) => { RNGestureHandlerModule.setGestureHandlerConfig(handlerTag, newConfig); }, - updateGestureHandlerConfig: ( + updateGestureHandlerConfig: < + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, + >( handlerTag: number, - newConfig: BaseGestureConfig + newConfig: BaseGestureConfig ) => { RNGestureHandlerModule.updateGestureHandlerConfig(handlerTag, newConfig); }, diff --git a/packages/react-native-gesture-handler/src/v3/components/GestureButtons.tsx b/packages/react-native-gesture-handler/src/v3/components/GestureButtons.tsx index 4da169ac42..fc6eee6ebc 100644 --- a/packages/react-native-gesture-handler/src/v3/components/GestureButtons.tsx +++ b/packages/react-native-gesture-handler/src/v3/components/GestureButtons.tsx @@ -9,9 +9,9 @@ import type { } from './GestureButtonsProps'; import type { GestureEvent } from '../types'; -import type { NativeViewHandlerData } from '../hooks/gestures/native/useNativeGesture'; +import type { NativeHandlerData } from '../hooks/gestures/native/NativeTypes'; -type CallbackEventType = GestureEvent; +type CallbackEventType = GestureEvent; export const RawButton = createNativeWrapper(GestureHandlerButton, { shouldCancelWhenOutside: false, diff --git a/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx b/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx index 076a8020a8..688bac8f8a 100644 --- a/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx +++ b/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx @@ -14,10 +14,10 @@ import { import createNativeWrapper from '../createNativeWrapper'; -import { NativeWrapperProperties } from '../types/NativeWrapperType'; -import { NativeWrapperProps } from '../hooks/utils'; +import type { NativeWrapperProperties } from '../types/NativeWrapperType'; +import type { NativeWrapperProps } from '../hooks/utils'; import { GestureDetectorType } from '../detectors'; -import { NativeGesture } from '../hooks/gestures/native/useNativeGesture'; +import type { NativeGesture } from '../hooks/gestures/native/NativeTypes'; import { ghQueueMicrotask } from '../../ghQueueMicrotask'; export const RefreshControl = createNativeWrapper< diff --git a/packages/react-native-gesture-handler/src/v3/detectors/GestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/GestureDetector.tsx index 73b5bc0e9f..1e97156e5a 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/GestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/GestureDetector.tsx @@ -8,8 +8,14 @@ import { } from '../../handlers/gestures/GestureDetector'; import { useEnsureGestureHandlerRootView } from './useEnsureGestureHandlerRootView'; -export function GestureDetector( - props: NativeDetectorProps | LegacyGestureDetectorProps +export function GestureDetector< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + props: + | NativeDetectorProps + | LegacyGestureDetectorProps ) { useEnsureGestureHandlerRootView(); @@ -22,7 +28,11 @@ export function GestureDetector( return ( )} + {...(props as NativeDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData + >)} /> ); } diff --git a/packages/react-native-gesture-handler/src/v3/detectors/NativeDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/NativeDetector.tsx index 396a2cb7f3..37614db708 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/NativeDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/NativeDetector.tsx @@ -10,13 +10,17 @@ import { import { ReanimatedNativeDetector } from './ReanimatedNativeDetector'; import { Platform } from 'react-native'; -export function NativeDetector({ +export function NativeDetector< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>({ gesture, children, touchAction, userSelect, enableContextMenu, -}: NativeDetectorProps) { +}: NativeDetectorProps) { const NativeDetectorComponent = gesture.config.dispatchesAnimatedEvents ? AnimatedNativeDetector : gesture.config.shouldUseReanimatedDetector diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx index 54de97d439..5056a2bbe6 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx @@ -36,13 +36,21 @@ interface StrippedVirtualChildren { enableContextMenu?: boolean; } -export function InterceptingGestureDetector({ +export function InterceptingGestureDetector< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>({ gesture, children, touchAction, userSelect, enableContextMenu, -}: InterceptingGestureDetectorProps) { +}: InterceptingGestureDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData +>) { useEnsureGestureHandlerRootView(); const [virtualChildren, setVirtualChildren] = useState>( @@ -146,8 +154,13 @@ export function InterceptingGestureDetector({ } const createGestureEventHandler = useCallback( - (key: keyof DetectorCallbacks) => { - return (e: GestureHandlerEventWithHandlerData) => { + (key: keyof DetectorCallbacks) => { + return ( + e: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > + ) => { if (typeof gesture?.detectorCallbacks[key] === 'function') { // @ts-expect-error passing event to a union of functions where only one is typed as such gesture.detectorCallbacks[key](e); @@ -166,15 +179,18 @@ export function InterceptingGestureDetector({ ); const getHandlers = useCallback( - (key: keyof DetectorCallbacks) => { + (key: keyof DetectorCallbacks) => { const handlers: (( - e: GestureHandlerEventWithHandlerData + e: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > ) => void)[] = []; if (gesture?.detectorCallbacks[key]) { handlers.push( gesture.detectorCallbacks[key] as ( - e: GestureHandlerEventWithHandlerData + e: GestureHandlerEventWithHandlerData ) => void ); } @@ -184,7 +200,10 @@ export function InterceptingGestureDetector({ if (handler) { handlers.push( handler as ( - e: GestureHandlerEventWithHandlerData + e: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > ) => void ); } diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx index 42379a6e9d..fae30d2c0e 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx @@ -23,9 +23,11 @@ function useRequiredInterceptingDetectorContext() { return context; } -export function VirtualDetector( - props: VirtualDetectorProps -) { +export function VirtualDetector< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>(props: VirtualDetectorProps) { // Don't memoize virtual detectors to be able to listen to changes in children // TODO: replace with MutationObserver when it rolls out in React Native 'use no memo'; @@ -73,7 +75,10 @@ export function VirtualDetector( const virtualChild: VirtualChild = { viewTag, handlerTags, - methods: props.gesture.detectorCallbacks as DetectorCallbacks, + methods: props.gesture.detectorCallbacks as DetectorCallbacks< + unknown, + unknown + >, // used by HostGestureDetector on web viewRef: Platform.OS === 'web' ? viewRef : undefined, userSelect: props.userSelect, diff --git a/packages/react-native-gesture-handler/src/v3/detectors/common.ts b/packages/react-native-gesture-handler/src/v3/detectors/common.ts index cf2c6ccf7d..02065589b8 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/common.ts +++ b/packages/react-native-gesture-handler/src/v3/detectors/common.ts @@ -18,24 +18,41 @@ interface CommonGestureDetectorProps { enableContextMenu?: boolean; } -export interface NativeDetectorProps - extends CommonGestureDetectorProps { - gesture: Gesture; +export interface NativeDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +> extends CommonGestureDetectorProps { + gesture: Gesture; } -export interface InterceptingGestureDetectorProps - extends CommonGestureDetectorProps { - gesture?: Gesture; +export interface InterceptingGestureDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +> extends CommonGestureDetectorProps { + gesture?: Gesture; } -export interface VirtualDetectorProps - extends CommonGestureDetectorProps { - gesture: Gesture; +export interface VirtualDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +> extends CommonGestureDetectorProps { + gesture: Gesture; } -export type GestureDetectorProps = - | NativeDetectorProps - | InterceptingGestureDetectorProps +export type GestureDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +> = + | NativeDetectorProps + | InterceptingGestureDetectorProps< + TConfig, + THandlerData, + TExtendedHandlerData + > | LegacyDetectorProps; export const AnimatedNativeDetector = diff --git a/packages/react-native-gesture-handler/src/v3/detectors/utils.ts b/packages/react-native-gesture-handler/src/v3/detectors/utils.ts index c627f56e4c..4ffecd7c46 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/utils.ts +++ b/packages/react-native-gesture-handler/src/v3/detectors/utils.ts @@ -135,8 +135,8 @@ export const traverseAndConfigureRelations = ( }); }; -export function configureRelations( - gesture: Gesture +export function configureRelations( + gesture: Gesture ) { if (isComposedGesture(gesture)) { const simultaneousHandlers = new Set( diff --git a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/eventHandler.ts b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/eventHandler.ts index b01b90fd84..7e273e8e68 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/eventHandler.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/eventHandler.ts @@ -10,6 +10,7 @@ import { ReanimatedContext } from '../../../handlers/gestures/reanimatedWrapper' import { ChangeCalculatorType, GestureCallbacks, + GestureEvent, GestureHandlerEventWithHandlerData, GestureStateChangeEventWithHandlerData, GestureUpdateEventWithHandlerData, @@ -18,11 +19,18 @@ import { CALLBACK_TYPE } from '../../../handlers/gestures/gesture'; import { State } from '../../../State'; import { TouchEventType } from '../../../TouchEventType'; import { GestureTouchEvent } from '../../../handlers/gestureHandlerCommon'; +import { isStateChangeEvent, isTouchEvent } from '../utils/eventUtils'; -function handleStateChangeEvent( - eventWithData: GestureStateChangeEventWithHandlerData, - callbacks: GestureCallbacks, - context: ReanimatedContext +function handleStateChangeEvent< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + eventWithData: GestureStateChangeEventWithHandlerData< + THandlerData | TExtendedHandlerData + >, + callbacks: GestureCallbacks, + context: ReanimatedContext, + fillInDefaultValues?: (event: GestureEvent) => void ) { 'worklet'; const { oldState, state } = eventWithData; @@ -34,9 +42,11 @@ function handleStateChangeEvent( (oldState === State.BEGAN || oldState === State.UNDETERMINED) && state === State.ACTIVE ) { + fillInDefaultValues?.(event as GestureEvent); runCallback(CALLBACK_TYPE.START, callbacks, event); } else if (oldState !== state && state === State.END) { if (oldState === State.ACTIVE) { + fillInDefaultValues?.(event as GestureEvent); runCallback(CALLBACK_TYPE.END, callbacks, event, true); } runCallback(CALLBACK_TYPE.FINALIZE, callbacks, event, true); @@ -49,6 +59,7 @@ function handleStateChangeEvent( state !== oldState ) { if (oldState === State.ACTIVE) { + fillInDefaultValues?.(event as GestureEvent); runCallback(CALLBACK_TYPE.END, callbacks, event, false); } runCallback(CALLBACK_TYPE.FINALIZE, callbacks, event, false); @@ -59,11 +70,14 @@ function handleStateChangeEvent( } } -export function handleUpdateEvent( - eventWithData: GestureUpdateEventWithHandlerData, - handlers: GestureCallbacks, - changeEventCalculator: ChangeCalculatorType | undefined, - context: ReanimatedContext +export function handleUpdateEvent< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + eventWithData: GestureUpdateEventWithHandlerData, + handlers: GestureCallbacks, + changeEventCalculator: ChangeCalculatorType | undefined, + context: ReanimatedContext ) { 'worklet'; const eventWithChanges = changeEventCalculator @@ -86,9 +100,12 @@ export function handleUpdateEvent( context.lastUpdateEvent = eventWithData; } -export function handleTouchEvent( +export function handleTouchEvent< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( event: GestureTouchEvent, - handlers: GestureCallbacks + handlers: GestureCallbacks ) { 'worklet'; @@ -97,13 +114,20 @@ export function handleTouchEvent( } } -export function eventHandler( +export function eventHandler< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - sourceEvent: GestureHandlerEventWithHandlerData, - handlers: GestureCallbacks, - changeEventCalculator: ChangeCalculatorType | undefined, - jsContext: ReanimatedContext, - dispatchesAnimatedEvents: boolean + sourceEvent: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + >, + handlers: GestureCallbacks, + changeEventCalculator: ChangeCalculatorType | undefined, + jsContext: ReanimatedContext, + dispatchesAnimatedEvents: boolean, + fillInDefaultValues?: (event: GestureEvent) => void ) { 'worklet'; const eventWithData = maybeExtractNativeEvent(sourceEvent); @@ -112,11 +136,22 @@ export function eventHandler( return; } - if ('oldState' in eventWithData && eventWithData.oldState !== undefined) { - handleStateChangeEvent(eventWithData, handlers, jsContext); - } else if ('allTouches' in eventWithData) { + if (isStateChangeEvent(eventWithData)) { + handleStateChangeEvent( + eventWithData, + handlers, + jsContext, + fillInDefaultValues + ); + return; + } + + if (isTouchEvent(eventWithData)) { handleTouchEvent(eventWithData, handlers); - } else if (!dispatchesAnimatedEvents) { + return; + } + + if (!dispatchesAnimatedEvents) { handleUpdateEvent( eventWithData, handlers, diff --git a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/stateChangeHandler.ts b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/stateChangeHandler.ts index 0b671dfd53..10b34d90f5 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/stateChangeHandler.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/stateChangeHandler.ts @@ -13,10 +13,13 @@ import { runCallback, } from '../utils'; -export function getStateChangeHandler( +export function getStateChangeHandler< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - callbacks: GestureCallbacks, - context?: ReanimatedContext + callbacks: GestureCallbacks, + context?: ReanimatedContext ) { return (sourceEvent: StateChangeEventWithHandlerData) => { 'worklet'; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/touchEventHandler.ts b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/touchEventHandler.ts index ef65483218..f063111cc5 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/touchEventHandler.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/touchEventHandler.ts @@ -8,9 +8,12 @@ import { import { TouchEventType } from '../../../TouchEventType'; import { GestureTouchEvent } from '../../../handlers/gestureHandlerCommon'; -export function getTouchEventHandler( +export function getTouchEventHandler< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - callbacks: GestureCallbacks + callbacks: GestureCallbacks ) { return (sourceEvent: TouchEvent) => { 'worklet'; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/updateHandler.ts b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/updateHandler.ts index a59c9e3621..ae022d968b 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/updateHandler.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/updateHandler.ts @@ -14,18 +14,21 @@ import { runCallback, } from '../utils'; -export function getUpdateHandler( +export function getUpdateHandler< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - callbacks: GestureCallbacks, - context: ReanimatedContext | undefined, - changeEventCalculator?: ChangeCalculatorType + callbacks: GestureCallbacks, + context: ReanimatedContext | undefined, + changeEventCalculator?: ChangeCalculatorType ) { - return (sourceEvent: UpdateEventWithHandlerData) => { + return (sourceEvent: UpdateEventWithHandlerData) => { 'worklet'; const eventWithData = maybeExtractNativeEvent( sourceEvent - ) as GestureUpdateEventWithHandlerData; + ) as GestureUpdateEventWithHandlerData; const eventWithChanges = changeEventCalculator ? changeEventCalculator( diff --git a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useGestureEventHandler.ts b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useGestureEventHandler.ts index 442b0207cf..27b2108a85 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useGestureEventHandler.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useGestureEventHandler.ts @@ -7,26 +7,36 @@ import { import { useMemo } from 'react'; import { eventHandler } from './eventHandler'; -export function useGestureEventHandler( +export function useGestureEventHandler< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - handlers: GestureCallbacks, - config: BaseGestureConfig + handlers: GestureCallbacks, + config: BaseGestureConfig ) { - const jsContext: ReanimatedContext = useMemo(() => { + const jsContext: ReanimatedContext = useMemo(() => { return { lastUpdateEvent: undefined, }; }, []); return useMemo(() => { - return (event: GestureHandlerEventWithHandlerData) => { + return ( + event: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > + ) => { eventHandler( handlerTag, event, handlers, config.changeEventCalculator, jsContext, - !!config.dispatchesAnimatedEvents + !!config.dispatchesAnimatedEvents, + config.fillInDefaultValues ); }; }, [ @@ -34,6 +44,7 @@ export function useGestureEventHandler( handlers, config.changeEventCalculator, config.dispatchesAnimatedEvents, + config.fillInDefaultValues, jsContext, ]); } diff --git a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useReanimatedEventHandler.ts b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useReanimatedEventHandler.ts index 012d18d3dc..dceec0ae2e 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useReanimatedEventHandler.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/callbacks/useReanimatedEventHandler.ts @@ -6,6 +6,7 @@ import { import { ChangeCalculatorType, GestureCallbacks, + GestureEvent, UnpackedGestureHandlerEventWithHandlerData, } from '../../types'; import { eventHandler } from './eventHandler'; @@ -15,11 +16,15 @@ const workletNOOP = () => { // no-op }; -export function useReanimatedEventHandler( +export function useReanimatedEventHandler< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - handlers: GestureCallbacks, - reanimatedHandler: ReanimatedHandler | undefined, - changeEventCalculator: ChangeCalculatorType | undefined + handlers: GestureCallbacks, + reanimatedHandler: ReanimatedHandler | undefined, + changeEventCalculator: ChangeCalculatorType | undefined, + fillInDefaultValues?: (event: GestureEvent) => void ) { const workletizedHandlers = useMemo(() => { // We don't want to call hooks conditionally, `useEvent` will be always called. @@ -37,7 +42,10 @@ export function useReanimatedEventHandler( }, [handlers]); const callback = ( - event: UnpackedGestureHandlerEventWithHandlerData + event: UnpackedGestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > ) => { 'worklet'; eventHandler( @@ -47,7 +55,8 @@ export function useReanimatedEventHandler( changeEventCalculator, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain reanimatedHandler?.context!, - false + false, + fillInDefaultValues ); }; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/composition/useComposedGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/composition/useComposedGesture.ts index 294ff4948f..fa699dca4b 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/composition/useComposedGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/composition/useComposedGesture.ts @@ -44,7 +44,7 @@ export function useComposedGesture( } const jsEventHandler = ( - event: GestureHandlerEventWithHandlerData + event: GestureHandlerEventWithHandlerData ) => { for (const gesture of gestures) { if (gesture.detectorCallbacks.jsEventHandler) { diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingProperties.ts deleted file mode 100644 index 0f9e0a095a..0000000000 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingProperties.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type FlingGestureNativeProperties = { - /** - * Expressed allowed direction of movement. It's possible to pass one or many - * directions in one parameter: - * - * ```js - * direction={Directions.RIGHT | Directions.LEFT} - * ``` - * - * or - * - * ```js - * direction={Directions.DOWN} - * ``` - */ - direction?: number; - - /** - * Determine exact number of points required to handle the fling gesture. - */ - numberOfPointers?: number; -}; - -export const FlingNativeProperties = new Set< - keyof FlingGestureNativeProperties ->(['direction', 'numberOfPointers']); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingTypes.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingTypes.ts new file mode 100644 index 0000000000..617b6b75ca --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingTypes.ts @@ -0,0 +1,60 @@ +import { + BaseDiscreteGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, + WithSharedValue, +} from '../../../types'; + +export type FlingGestureNativeProperties = { + /** + * Expressed allowed direction of movement. It's possible to pass one or many + * directions in one parameter: + * + * ```js + * direction={Directions.RIGHT | Directions.LEFT} + * ``` + * + * or + * + * ```js + * direction={Directions.DOWN} + * ``` + */ + direction?: number; + + /** + * Determine exact number of points required to handle the fling gesture. + */ + numberOfPointers?: number; +}; + +export const FlingNativeProperties = new Set< + keyof FlingGestureNativeProperties +>(['direction', 'numberOfPointers']); + +export type FlingHandlerData = { + x: number; + y: number; + absoluteX: number; + absoluteY: number; +}; + +export type FlingGestureProperties = + WithSharedValue; + +export type FlingGestureInternalConfig = BaseDiscreteGestureConfig< + FlingGestureProperties, + FlingHandlerData +>; + +export type FlingGestureConfig = + ExcludeInternalConfigProps; + +export type FlingGestureEvent = GestureEvent; +export type FlingGestureActiveEvent = FlingGestureEvent; + +export type FlingGesture = SingleGesture< + FlingGestureProperties, + FlingHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFlingGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFlingGesture.ts index 3f59712238..8cfbb7c7d3 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFlingGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFlingGesture.ts @@ -1,44 +1,17 @@ -import { - BaseDiscreteGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - SingleGestureName, - WithSharedValue, - GestureEvent, -} from '../../../types'; +import { SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig } from '../../utils'; -import type { FlingGestureNativeProperties } from './FlingProperties'; - -type FlingHandlerData = { - x: number; - y: number; - absoluteX: number; - absoluteY: number; -}; - -type FlingGestureProperties = WithSharedValue; - -type FlingGestureInternalConfig = BaseDiscreteGestureConfig< - FlingHandlerData, - FlingGestureProperties ->; - -export type FlingGestureConfig = - ExcludeInternalConfigProps; - -export type FlingGestureEvent = GestureEvent; - -export type FlingGesture = SingleGesture< +import { + FlingGesture, + FlingGestureConfig, + FlingGestureProperties, FlingHandlerData, - FlingGestureProperties ->; +} from './FlingTypes'; export function useFlingGesture(config: FlingGestureConfig): FlingGesture { const flingConfig = useClonedAndRemappedConfig< - FlingHandlerData, FlingGestureProperties, - FlingGestureProperties + FlingHandlerData >(config); return useGesture(SingleGestureName.Fling, flingConfig); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverProperties.ts deleted file mode 100644 index dd442a36ee..0000000000 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverProperties.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { HoverEffect } from '../../../../handlers/gestures/hoverGesture'; - -export type HoverGestureExternalProperties = { - /** - * Visual effect applied to the view while the view is hovered. The possible values are: - * - * - `HoverEffect.None` - * - `HoverEffect.Lift` - * - `HoverEffect.Highlight` - * - * Defaults to `HoverEffect.None` - */ - effect?: HoverEffect; -}; - -export type HoverGestureNativeProperties = { - hoverEffect: HoverEffect; -}; - -export const HoverNativeProperties = new Set< - keyof HoverGestureNativeProperties ->(['hoverEffect']); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverTypes.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverTypes.ts new file mode 100644 index 0000000000..31d86e6906 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverTypes.ts @@ -0,0 +1,76 @@ +import { StylusData } from '../../../../handlers/gestureHandlerCommon'; +import { HoverEffect } from '../../../../handlers/gestures/hoverGesture'; +import { + BaseGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, + WithSharedValue, +} from '../../../types'; + +export type HoverGestureExternalProperties = { + /** + * Visual effect applied to the view while the view is hovered. The possible values are: + * + * - `HoverEffect.None` + * - `HoverEffect.Lift` + * - `HoverEffect.Highlight` + * + * Defaults to `HoverEffect.None` + */ + effect?: HoverEffect; +}; + +export type HoverGestureNativeProperties = { + hoverEffect: HoverEffect; +}; + +export const HoverNativeProperties = new Set< + keyof HoverGestureNativeProperties +>(['hoverEffect']); + +export type HoverHandlerData = { + x: number; + y: number; + absoluteX: number; + absoluteY: number; + stylusData: StylusData; +}; + +export type HoverExtendedHandlerData = HoverHandlerData & { + changeX: number; + changeY: number; +}; + +export type HoverGestureProperties = WithSharedValue< + HoverGestureExternalProperties, + HoverEffect +>; + +export type HoverGestureInternalProperties = WithSharedValue< + HoverGestureNativeProperties, + HoverEffect +>; + +export type HoverGestureConfig = ExcludeInternalConfigProps< + BaseGestureConfig< + HoverGestureProperties, + HoverHandlerData, + HoverExtendedHandlerData + > +>; + +export type HoverGestureInternalConfig = BaseGestureConfig< + HoverGestureInternalProperties, + HoverHandlerData, + HoverExtendedHandlerData +>; + +export type HoverGestureEvent = GestureEvent; +export type HoverGestureActiveEvent = GestureEvent; + +export type HoverGesture = SingleGesture< + HoverGestureInternalProperties, + HoverHandlerData, + HoverExtendedHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHoverGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHoverGesture.ts index 6f1c600f49..94c7cb97ce 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHoverGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHoverGesture.ts @@ -1,63 +1,22 @@ -import { StylusData } from '../../../../handlers/gestureHandlerCommon'; -import { HoverEffect } from '../../../../handlers/gestures/hoverGesture'; -import { - BaseGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - HandlerData, - SingleGestureName, - WithSharedValue, - GestureEvent, -} from '../../../types'; +import { GestureEvent, HandlerData, SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig, getChangeEventCalculator, } from '../../utils'; import { - HoverGestureExternalProperties, - HoverGestureNativeProperties, -} from './HoverProperties'; - -type HoverHandlerData = { - x: number; - y: number; - absoluteX: number; - absoluteY: number; - stylusData: StylusData; - changeX: number; - changeY: number; -}; - -type HoverGestureProperties = WithSharedValue< - HoverGestureExternalProperties, - HoverEffect ->; - -type HoverGestureInternalProperties = WithSharedValue< - HoverGestureNativeProperties, - HoverEffect ->; - -export type HoverGestureConfig = ExcludeInternalConfigProps< - BaseGestureConfig ->; - -type HoverGestureInternalConfig = BaseGestureConfig< + HoverExtendedHandlerData, + HoverGesture, + HoverGestureConfig, + HoverGestureInternalConfig, + HoverGestureInternalProperties, + HoverGestureProperties, HoverHandlerData, - HoverGestureInternalProperties ->; - -export type HoverGestureEvent = GestureEvent; - -export type HoverGesture = SingleGesture< - HoverHandlerData, - HoverGestureInternalProperties ->; +} from './HoverTypes'; function diffCalculator( - current: HandlerData, - previous: HandlerData | null + current: HandlerData, + previous: HandlerData | null ) { 'worklet'; return { @@ -66,10 +25,18 @@ function diffCalculator( }; } +function fillInDefaultValues(event: GestureEvent) { + 'worklet'; + + event.changeX = 0; + event.changeY = 0; +} + function transformHoverProps( config: HoverGestureConfig & HoverGestureInternalConfig ) { config.changeEventCalculator = getChangeEventCalculator(diffCalculator); + config.fillInDefaultValues = fillInDefaultValues; return config; } @@ -78,9 +45,10 @@ const HoverPropsMapping = new Map([['effect', 'hoverEffect']]); export function useHoverGesture(config: HoverGestureConfig): HoverGesture { const hoverConfig = useClonedAndRemappedConfig< - HoverHandlerData, HoverGestureProperties, - HoverGestureInternalProperties + HoverHandlerData, + HoverGestureInternalProperties, + HoverExtendedHandlerData >(config, HoverPropsMapping, transformHoverProps); return useGesture(SingleGestureName.Hover, hoverConfig); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/index.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/index.ts index 98b41c2ea0..b8d86c237d 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/index.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/index.ts @@ -1,59 +1,128 @@ -import type { FlingGestureEvent, FlingGesture } from './fling/useFlingGesture'; -import type { HoverGestureEvent, HoverGesture } from './hover/useHoverGesture'; +import type { + FlingGestureEvent, + FlingGestureActiveEvent, + FlingGesture, + FlingGestureConfig, +} from './fling/FlingTypes'; +import type { + HoverGestureEvent, + HoverGesture, + HoverGestureActiveEvent, + HoverGestureConfig, +} from './hover/HoverTypes'; import type { LongPressGestureEvent, + LongPressGestureActiveEvent, LongPressGesture, -} from './longPress/useLongPressGesture'; + LongPressGestureConfig, +} from './longPress/LongPressTypes'; import type { ManualGestureEvent, + ManualGestureActiveEvent, ManualGesture, -} from './manual/useManualGesture'; + ManualGestureConfig, +} from './manual/ManualTypes'; import type { NativeGestureEvent, + NativeGestureActiveEvent, NativeGesture, -} from './native/useNativeGesture'; -import type { PanGestureEvent, PanGesture } from './pan/usePanGesture'; -import type { PinchGestureEvent, PinchGesture } from './pinch/usePinchGesture'; + NativeGestureConfig, +} from './native/NativeTypes'; +import type { + PanGestureEvent, + PanGesture, + PanGestureActiveEvent, + PanGestureConfig, +} from './pan/PanTypes'; +import type { + PinchGestureEvent, + PinchGesture, + PinchGestureActiveEvent, + PinchGestureConfig, +} from './pinch/PinchTypes'; import type { RotationGestureEvent, + RotationGestureActiveEvent, RotationGesture, -} from './rotation/useRotationGesture'; -import type { TapGestureEvent, TapGesture } from './tap/useTapGesture'; + RotationGestureConfig, +} from './rotation/RotationTypes'; +import type { + TapGestureEvent, + TapGesture, + TapGestureActiveEvent, + TapGestureConfig, +} from './tap/TapTypes'; -export type { TapGestureConfig } from './tap/useTapGesture'; -export type { TapGesture, TapGestureEvent }; +export type { + TapGesture, + TapGestureEvent, + TapGestureActiveEvent, + TapGestureConfig, +}; export { useTapGesture } from './tap/useTapGesture'; -export type { FlingGestureConfig } from './fling/useFlingGesture'; -export type { FlingGesture, FlingGestureEvent }; +export type { + FlingGesture, + FlingGestureConfig, + FlingGestureEvent, + FlingGestureActiveEvent, +}; export { useFlingGesture } from './fling/useFlingGesture'; -export type { LongPressGestureConfig } from './longPress/useLongPressGesture'; -export type { LongPressGesture, LongPressGestureEvent }; +export type { + LongPressGesture, + LongPressGestureEvent, + LongPressGestureConfig, + LongPressGestureActiveEvent, +}; export { useLongPressGesture } from './longPress/useLongPressGesture'; -export type { PinchGestureConfig } from './pinch/usePinchGesture'; -export type { PinchGesture, PinchGestureEvent }; +export type { + PinchGesture, + PinchGestureEvent, + PinchGestureActiveEvent, + PinchGestureConfig, +}; export { usePinchGesture } from './pinch/usePinchGesture'; -export type { RotationGestureConfig } from './rotation/useRotationGesture'; -export type { RotationGesture, RotationGestureEvent }; +export type { + RotationGesture, + RotationGestureEvent, + RotationGestureActiveEvent, + RotationGestureConfig, +}; export { useRotationGesture } from './rotation/useRotationGesture'; -export type { HoverGestureConfig } from './hover/useHoverGesture'; -export type { HoverGesture, HoverGestureEvent }; +export type { + HoverGesture, + HoverGestureEvent, + HoverGestureConfig, + HoverGestureActiveEvent, +}; export { useHoverGesture } from './hover/useHoverGesture'; -export type { ManualGestureConfig } from './manual/useManualGesture'; -export type { ManualGesture, ManualGestureEvent }; +export type { + ManualGesture, + ManualGestureEvent, + ManualGestureConfig, + ManualGestureActiveEvent, +}; export { useManualGesture } from './manual/useManualGesture'; -export type { NativeViewGestureConfig } from './native/useNativeGesture'; -export type { NativeGesture, NativeGestureEvent }; +export type { + NativeGesture, + NativeGestureEvent, + NativeGestureActiveEvent, + NativeGestureConfig, +}; export { useNativeGesture } from './native/useNativeGesture'; -export type { PanGestureConfig } from './pan/usePanGesture'; -export type { PanGesture, PanGestureEvent }; +export type { + PanGesture, + PanGestureEvent, + PanGestureConfig, + PanGestureActiveEvent, +}; export { usePanGesture } from './pan/usePanGesture'; export type SingleGesture = @@ -67,12 +136,22 @@ export type SingleGesture = | NativeGesture | PanGesture; +/* eslint-disable @typescript-eslint/no-duplicate-type-constituents */ export type SingleGestureEvent = | TapGestureEvent + | TapGestureActiveEvent | FlingGestureEvent + | FlingGestureActiveEvent | LongPressGestureEvent + | LongPressGestureActiveEvent | RotationGestureEvent + | RotationGestureActiveEvent | HoverGestureEvent + | HoverGestureActiveEvent | ManualGestureEvent + | ManualGestureActiveEvent | NativeGestureEvent - | PanGestureEvent; + | NativeGestureActiveEvent + | PanGestureEvent + | PanGestureActiveEvent; +/* eslint-enable @typescript-eslint/no-duplicate-type-constituents */ diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressTypes.ts similarity index 51% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressProperties.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressTypes.ts index e5fbe0c184..db920d2774 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressProperties.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressTypes.ts @@ -1,3 +1,11 @@ +import { + BaseDiscreteGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, + WithSharedValue, +} from '../../../types'; + type CommonLongPressGestureProperties = { /** * Determine exact number of points required to handle the long press gesture. @@ -31,3 +39,34 @@ export type LongPressGestureNativeProperties = export const LongPressNativeProperties = new Set< keyof LongPressGestureNativeProperties >(['minDurationMs', 'maxDist', 'numberOfPointers']); + +export type LongPressHandlerData = { + x: number; + y: number; + absoluteX: number; + absoluteY: number; + duration: number; +}; + +export type LongPressGestureProperties = + WithSharedValue; + +export type LongPressGestureInternalProperties = + WithSharedValue; + +export type LongPressGestureConfig = ExcludeInternalConfigProps< + BaseDiscreteGestureConfig +>; + +export type LongPressGestureInternalConfig = BaseDiscreteGestureConfig< + LongPressGestureInternalProperties, + LongPressHandlerData +>; + +export type LongPressGestureEvent = GestureEvent; +export type LongPressGestureActiveEvent = LongPressGestureEvent; + +export type LongPressGesture = SingleGesture< + LongPressGestureProperties, + LongPressHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPressGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPressGesture.ts index 9f480cf9c1..cb6be26d36 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPressGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPressGesture.ts @@ -1,47 +1,14 @@ -import { - BaseDiscreteGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - SingleGestureName, - WithSharedValue, - GestureEvent, -} from '../../../types'; +import { SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig } from '../../utils'; import { - LongPressGestureExternalProperties, - LongPressGestureNativeProperties, -} from './LongPressProperties'; - -type LongPressHandlerData = { - x: number; - y: number; - absoluteX: number; - absoluteY: number; - duration: number; -}; - -type LongPressGestureProperties = - WithSharedValue; - -type LongPressGestureInternalProperties = - WithSharedValue; - -export type LongPressGestureConfig = ExcludeInternalConfigProps< - BaseDiscreteGestureConfig ->; - -type LongPressGestureInternalConfig = BaseDiscreteGestureConfig< + LongPressGesture, + LongPressGestureConfig, + LongPressGestureInternalConfig, + LongPressGestureInternalProperties, + LongPressGestureProperties, LongPressHandlerData, - LongPressGestureInternalProperties ->; - -export type LongPressGestureEvent = GestureEvent; - -export type LongPressGesture = SingleGesture< - LongPressHandlerData, - LongPressGestureProperties ->; +} from './LongPressTypes'; const LongPressPropsMapping = new Map< keyof LongPressGestureProperties, @@ -65,12 +32,12 @@ export function useLongPressGesture( config: LongPressGestureConfig ): LongPressGesture { const longPressConfig = useClonedAndRemappedConfig< - LongPressHandlerData, LongPressGestureProperties, + LongPressHandlerData, LongPressGestureInternalProperties >(config, LongPressPropsMapping, transformLongPressProps); - return useGesture( + return useGesture( SingleGestureName.LongPress, longPressConfig ); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualProperties.ts deleted file mode 100644 index f5676df1ca..0000000000 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualProperties.ts +++ /dev/null @@ -1 +0,0 @@ -export type ManualGestureNativeProperties = Record; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualTypes.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualTypes.ts new file mode 100644 index 0000000000..2059679a7b --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualTypes.ts @@ -0,0 +1,28 @@ +import { + BaseGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, +} from '../../../types'; + +export type ManualGestureNativeProperties = Record; + +export type ManualHandlerData = Record; + +export type ManualGestureProperties = ManualGestureNativeProperties; + +export type ManualGestureInternalConfig = BaseGestureConfig< + ManualGestureProperties, + ManualHandlerData +>; + +export type ManualGestureConfig = + ExcludeInternalConfigProps; + +export type ManualGestureEvent = GestureEvent; +export type ManualGestureActiveEvent = ManualGestureEvent; + +export type ManualGesture = SingleGesture< + ManualGestureProperties, + ManualHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManualGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManualGesture.ts index c4ffef7d54..c2e520a344 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManualGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManualGesture.ts @@ -1,38 +1,17 @@ -import { - BaseGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - SingleGestureName, - GestureEvent, -} from '../../../types'; +import { SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig } from '../../utils'; -import { ManualGestureNativeProperties } from './ManualProperties'; - -type ManualHandlerData = Record; - -type ManualGestureProperties = ManualGestureNativeProperties; - -type ManualGestureInternalConfig = BaseGestureConfig< - ManualHandlerData, - ManualGestureProperties ->; - -export type ManualGestureConfig = - ExcludeInternalConfigProps; - -export type ManualGestureEvent = GestureEvent; - -export type ManualGesture = SingleGesture< +import { + ManualGestureProperties, ManualHandlerData, - ManualGestureProperties ->; + ManualGesture, + ManualGestureConfig, +} from './ManualTypes'; export function useManualGesture(config: ManualGestureConfig): ManualGesture { const manualConfig = useClonedAndRemappedConfig< - ManualHandlerData, ManualGestureProperties, - ManualGestureProperties + ManualHandlerData >(config); return useGesture(SingleGestureName.Manual, manualConfig); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeProperties.ts deleted file mode 100644 index e423bf401f..0000000000 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeProperties.ts +++ /dev/null @@ -1,19 +0,0 @@ -export type NativeGestureNativeProperties = { - /** - * Android only. - * - * Determines whether the handler should check for an existing touch event on - * instantiation. - */ - shouldActivateOnStart?: boolean; - - /** - * When `true`, cancels all other gesture handlers when this - * `NativeViewGestureHandler` receives an `ACTIVE` state event. - */ - disallowInterruption?: boolean; -}; - -export const NativeHandlerNativeProperties = new Set< - keyof NativeGestureNativeProperties ->(['shouldActivateOnStart', 'disallowInterruption']); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeTypes.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeTypes.ts new file mode 100644 index 0000000000..f786dc0954 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeTypes.ts @@ -0,0 +1,50 @@ +import { + BaseDiscreteGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, + WithSharedValue, +} from '../../../types'; + +export type NativeGestureNativeProperties = { + /** + * Android only. + * + * Determines whether the handler should check for an existing touch event on + * instantiation. + */ + shouldActivateOnStart?: boolean; + + /** + * When `true`, cancels all other gesture handlers when this + * `NativeViewGestureHandler` receives an `ACTIVE` state event. + */ + disallowInterruption?: boolean; +}; + +export const NativeHandlerNativeProperties = new Set< + keyof NativeGestureNativeProperties +>(['shouldActivateOnStart', 'disallowInterruption']); + +export type NativeHandlerData = { + pointerInside: boolean; +}; + +export type NativeGestureProperties = + WithSharedValue; + +export type NativeGestureInternalConfig = BaseDiscreteGestureConfig< + NativeGestureProperties, + NativeHandlerData +>; + +export type NativeGestureConfig = + ExcludeInternalConfigProps; + +export type NativeGestureEvent = GestureEvent; +export type NativeGestureActiveEvent = NativeGestureEvent; + +export type NativeGesture = SingleGesture< + NativeGestureProperties, + NativeHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNativeGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNativeGesture.ts index e5d6fc6320..708e03c5a0 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNativeGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNativeGesture.ts @@ -1,44 +1,17 @@ -import { - BaseDiscreteGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - SingleGestureName, - WithSharedValue, - GestureEvent, -} from '../../../types'; +import { SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig } from '../../utils'; -import { NativeGestureNativeProperties } from './NativeProperties'; - -export type NativeViewHandlerData = { - pointerInside: boolean; -}; - -type NativeViewGestureProperties = - WithSharedValue; - -type NativeViewGestureInternalConfig = BaseDiscreteGestureConfig< - NativeViewHandlerData, - NativeViewGestureProperties ->; - -export type NativeViewGestureConfig = - ExcludeInternalConfigProps; - -export type NativeGestureEvent = GestureEvent; - -export type NativeGesture = SingleGesture< - NativeViewHandlerData, - NativeViewGestureProperties ->; +import { + NativeGesture, + NativeGestureConfig, + NativeGestureProperties, + NativeHandlerData, +} from './NativeTypes'; -export function useNativeGesture( - config: NativeViewGestureConfig -): NativeGesture { +export function useNativeGesture(config: NativeGestureConfig): NativeGesture { const nativeConfig = useClonedAndRemappedConfig< - NativeViewHandlerData, - NativeViewGestureProperties, - NativeViewGestureProperties + NativeGestureProperties, + NativeHandlerData >(config); return useGesture(SingleGestureName.Native, nativeConfig); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanTypes.ts similarity index 76% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanProperties.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanTypes.ts index acf434ae6d..b1c7d42b17 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanProperties.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanTypes.ts @@ -1,3 +1,12 @@ +import { StylusData } from '../../../../handlers/gestureHandlerCommon'; +import { + BaseGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, + WithSharedValue, +} from '../../../types'; + type CommonPanGestureProperties = { /** * Minimum distance the finger (or multiple finger) need to travel before the @@ -117,3 +126,49 @@ export const PanNativeProperties = new Set([ 'failOffsetXStart', 'failOffsetXEnd', ]); + +export type PanHandlerData = { + x: number; + y: number; + absoluteX: number; + absoluteY: number; + stylusData: StylusData; +}; + +export type PanExtendedHandlerData = PanHandlerData & { + changeX: number; + changeY: number; + translationX: number; + translationY: number; + velocityX: number; + velocityY: number; +}; + +export type PanGestureProperties = + WithSharedValue; + +export type PanGestureInternalProperties = + WithSharedValue; + +export type PanGestureConfig = ExcludeInternalConfigProps< + BaseGestureConfig< + PanGestureProperties, + PanHandlerData, + PanExtendedHandlerData + > +>; + +export type PanGestureInternalConfig = BaseGestureConfig< + PanGestureInternalProperties, + PanHandlerData, + PanExtendedHandlerData +>; + +export type PanGestureEvent = GestureEvent; +export type PanGestureActiveEvent = GestureEvent; + +export type PanGesture = SingleGesture< + PanGestureInternalProperties, + PanHandlerData, + PanExtendedHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePanGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePanGesture.ts index 93afc7d0d6..fd62e4b316 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePanGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePanGesture.ts @@ -1,12 +1,8 @@ -import { StylusData } from '../../../../handlers/gestureHandlerCommon'; import { - BaseGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, + GestureEvent, HandlerData, SingleGestureName, WithSharedValue, - GestureEvent, } from '../../../types'; import { useGesture } from '../../useGesture'; import { @@ -16,45 +12,14 @@ import { } from '../../utils'; import { OffsetProps, - PanGestureExternalProperties, - PanGestureNativeProperties, -} from './PanProperties'; - -export type PanHandlerData = { - x: number; - y: number; - absoluteX: number; - absoluteY: number; - translationX: number; - translationY: number; - velocityX: number; - velocityY: number; - stylusData: StylusData; - changeX: number; - changeY: number; -}; - -export type PanGestureProperties = - WithSharedValue; - -export type PanGestureInternalProperties = - WithSharedValue; - -export type PanGestureConfig = ExcludeInternalConfigProps< - BaseGestureConfig ->; - -type PanGestureInternalConfig = BaseGestureConfig< - PanHandlerData, - PanGestureInternalProperties ->; - -export type PanGestureEvent = GestureEvent; - -export type PanGesture = SingleGesture< + PanExtendedHandlerData, + PanGesture, + PanGestureConfig, + PanGestureInternalConfig, + PanGestureInternalProperties, + PanGestureProperties, PanHandlerData, - PanGestureInternalProperties ->; +} from './PanTypes'; const PanPropsMapping = new Map< keyof PanGestureProperties, @@ -139,8 +104,8 @@ function transformOffsetProp( } function diffCalculator( - current: HandlerData, - previous: HandlerData | null + current: HandlerData, + previous: HandlerData | null ) { 'worklet'; return { @@ -153,6 +118,13 @@ function diffCalculator( }; } +function fillInDefaultValues(event: GestureEvent) { + 'worklet'; + + event.changeX = 0; + event.changeY = 0; +} + function transformPanProps( config: PanGestureConfig & PanGestureInternalConfig ) { @@ -162,6 +134,7 @@ function transformPanProps( transformOffsetProp(config, 'activeOffsetX'); config.changeEventCalculator = getChangeEventCalculator(diffCalculator); + config.fillInDefaultValues = fillInDefaultValues; return config; } @@ -172,13 +145,15 @@ export function usePanGesture(config: PanGestureConfig): PanGesture { } const panConfig = useClonedAndRemappedConfig< - PanHandlerData, PanGestureProperties, - PanGestureInternalProperties + PanHandlerData, + PanGestureInternalProperties, + PanExtendedHandlerData >(config, PanPropsMapping, transformPanProps); - return useGesture( - SingleGestureName.Pan, - panConfig - ); + return useGesture< + PanGestureInternalProperties, + PanHandlerData, + PanExtendedHandlerData + >(SingleGestureName.Pan, panConfig); } diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchProperties.ts deleted file mode 100644 index 1c1aa92e48..0000000000 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchProperties.ts +++ /dev/null @@ -1 +0,0 @@ -export type PinchGestureNativeProperties = Record; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchTypes.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchTypes.ts new file mode 100644 index 0000000000..325eda0b4c --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchTypes.ts @@ -0,0 +1,40 @@ +import { + BaseGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, +} from '../../../types'; + +export type PinchGestureNativeProperties = Record; + +// We want to keep `{}` because it does not break ts-server suggestions +// eslint-disable-next-line @typescript-eslint/ban-types +export type PinchHandlerData = {}; + +export type PinchExtendedHandlerData = { + scale: number; + velocity: number; + focalX: number; + focalY: number; + scaleChange: number; +}; + +export type PinchGestureProperties = PinchGestureNativeProperties; + +export type PinchGestureInternalConfig = BaseGestureConfig< + PinchGestureProperties, + PinchHandlerData, + PinchExtendedHandlerData +>; + +export type PinchGestureConfig = + ExcludeInternalConfigProps; + +export type PinchGestureEvent = GestureEvent; +export type PinchGestureActiveEvent = GestureEvent; + +export type PinchGesture = SingleGesture< + PinchGestureProperties, + PinchHandlerData, + PinchExtendedHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinchGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinchGesture.ts index e42a9e89ff..375990460c 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinchGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinchGesture.ts @@ -1,46 +1,21 @@ -import { - BaseGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - HandlerData, - SingleGestureName, - GestureEvent, -} from '../../../types'; +import { GestureEvent, HandlerData, SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig, getChangeEventCalculator, } from '../../utils'; -import { PinchGestureNativeProperties } from './PinchProperties'; - -type PinchHandlerData = { - scale: number; - focalX: number; - focalY: number; - velocity: number; - scaleChange: number; -}; - -type PinchGestureProperties = PinchGestureNativeProperties; - -type PinchGestureInternalConfig = BaseGestureConfig< - PinchHandlerData, - PinchGestureProperties ->; - -export type PinchGestureConfig = - ExcludeInternalConfigProps; - -export type PinchGestureEvent = GestureEvent; - -export type PinchGesture = SingleGesture< +import { + PinchExtendedHandlerData, + PinchGesture, + PinchGestureConfig, + PinchGestureInternalConfig, + PinchGestureProperties, PinchHandlerData, - PinchGestureProperties ->; +} from './PinchTypes'; function diffCalculator( - current: HandlerData, - previous: HandlerData | null + current: HandlerData, + previous: HandlerData | null ) { 'worklet'; return { @@ -48,10 +23,16 @@ function diffCalculator( }; } +function fillInDefaultValues(event: GestureEvent) { + 'worklet'; + event.scaleChange = 1; +} + function transformPinchProps( config: PinchGestureConfig & PinchGestureInternalConfig ) { config.changeEventCalculator = getChangeEventCalculator(diffCalculator); + config.fillInDefaultValues = fillInDefaultValues; return config; } @@ -60,13 +41,12 @@ const PinchPropsMapping = new Map(); export function usePinchGesture(config: PinchGestureConfig): PinchGesture { const pinchConfig = useClonedAndRemappedConfig< - PinchHandlerData, PinchGestureProperties, + PinchHandlerData, // no internal props, pass record as PinchGestureProperties maps everything to never - Record + Record, + PinchExtendedHandlerData >(config, PinchPropsMapping, transformPinchProps); - pinchConfig.changeEventCalculator = getChangeEventCalculator(diffCalculator); - return useGesture(SingleGestureName.Pinch, pinchConfig); } diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationProperties.ts deleted file mode 100644 index 6a74c0cf24..0000000000 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationProperties.ts +++ /dev/null @@ -1 +0,0 @@ -export type RotationGestureNativeProperties = Record; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationTypes.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationTypes.ts new file mode 100644 index 0000000000..97741be913 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationTypes.ts @@ -0,0 +1,41 @@ +import { + BaseGestureConfig, + ExcludeInternalConfigProps, + GestureEvent, + SingleGesture, +} from '../../../types'; + +export type RotationGestureNativeProperties = Record; + +// We want to keep `{}` because it does not break ts-server suggestions +// eslint-disable-next-line @typescript-eslint/ban-types +export type RotationHandlerData = {}; + +export type RotationExtendedHandlerData = { + rotation: number; + velocity: number; + anchorX: number; + anchorY: number; + rotationChange: number; +}; + +export type RotationGestureProperties = RotationGestureNativeProperties; + +export type RotationGestureInternalConfig = BaseGestureConfig< + RotationGestureProperties, + RotationHandlerData, + RotationExtendedHandlerData +>; + +export type RotationGestureConfig = + ExcludeInternalConfigProps; + +export type RotationGestureEvent = GestureEvent; +export type RotationGestureActiveEvent = + GestureEvent; + +export type RotationGesture = SingleGesture< + RotationGestureProperties, + RotationHandlerData, + RotationExtendedHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotationGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotationGesture.ts index 96124a0d06..9dfbfddc3b 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotationGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotationGesture.ts @@ -1,46 +1,21 @@ -import { - BaseGestureConfig, - ExcludeInternalConfigProps, - SingleGesture, - HandlerData, - SingleGestureName, - GestureEvent, -} from '../../../types'; +import { GestureEvent, HandlerData, SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig, getChangeEventCalculator, } from '../../utils'; -import { RotationGestureNativeProperties } from './RotationProperties'; - -type RotationHandlerData = { - rotation: number; - anchorX: number; - anchorY: number; - velocity: number; - rotationChange: number; -}; - -type RotationGestureProperties = RotationGestureNativeProperties; - -type RotationGestureInternalConfig = BaseGestureConfig< - RotationHandlerData, - RotationGestureProperties ->; - -export type RotationGestureConfig = - ExcludeInternalConfigProps; - -export type RotationGestureEvent = GestureEvent; - -export type RotationGesture = SingleGesture< +import { + RotationExtendedHandlerData, + RotationGesture, + RotationGestureConfig, + RotationGestureInternalConfig, + RotationGestureProperties, RotationHandlerData, - RotationGestureProperties ->; +} from './RotationTypes'; function diffCalculator( - current: HandlerData, - previous: HandlerData | null + current: HandlerData, + previous: HandlerData | null ) { 'worklet'; return { @@ -50,10 +25,16 @@ function diffCalculator( }; } +function fillInDefaultValues(event: GestureEvent) { + 'worklet'; + event.rotationChange = 0; +} + function transformRotationProps( config: RotationGestureConfig & RotationGestureInternalConfig ) { config.changeEventCalculator = getChangeEventCalculator(diffCalculator); + config.fillInDefaultValues = fillInDefaultValues; return config; } @@ -64,10 +45,11 @@ export function useRotationGesture( config: RotationGestureConfig ): RotationGesture { const rotationConfig = useClonedAndRemappedConfig< - RotationHandlerData, RotationGestureProperties, + RotationHandlerData, // no internal props, pass record as RotationGestureProperties maps everything to never - Record + Record, + RotationExtendedHandlerData >(config, RotationPropsMapping, transformRotationProps); return useGesture(SingleGestureName.Rotation, rotationConfig); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapProperties.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapTypes.ts similarity index 73% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapProperties.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapTypes.ts index 46ccdab2d5..18f085aae0 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapProperties.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapTypes.ts @@ -1,3 +1,11 @@ +import { + BaseDiscreteGestureConfig, + DiscreteSingleGesture, + ExcludeInternalConfigProps, + GestureEvent, + WithSharedValue, +} from '../../../types'; + type CommonTapGestureConfig = { /** * Minimum number of pointers (fingers) required to be placed before the @@ -66,3 +74,27 @@ export const TapNativeProperties = new Set([ 'maxDelayMs', 'maxDist', ]); + +export type TapHandlerData = { + x: number; + y: number; + absoluteX: number; + absoluteY: number; +}; + +export type TapGestureProperties = WithSharedValue; + +export type TapGestureInternalProperties = + WithSharedValue; + +export type TapGestureConfig = ExcludeInternalConfigProps< + BaseDiscreteGestureConfig +>; + +export type TapGestureEvent = GestureEvent; +export type TapGestureActiveEvent = TapGestureEvent; + +export type TapGesture = DiscreteSingleGesture< + TapGestureInternalProperties, + TapHandlerData +>; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTapGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTapGesture.ts index dbd243de41..8330c0b6de 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTapGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTapGesture.ts @@ -1,39 +1,13 @@ -import { - BaseDiscreteGestureConfig, - ExcludeInternalConfigProps, - GestureEvent, - DiscreteSingleGesture, - SingleGestureName, - WithSharedValue, -} from '../../../types'; +import { SingleGestureName } from '../../../types'; import { useGesture } from '../../useGesture'; import { useClonedAndRemappedConfig } from '../../utils'; import { - TapGestureExternalConfig, - TapGestureNativeConfig, -} from './TapProperties'; - -type TapHandlerData = { - x: number; - y: number; - absoluteX: number; - absoluteY: number; -}; - -type TapGestureProperties = WithSharedValue; - -type TapGestureInternalProperties = WithSharedValue; - -export type TapGestureConfig = ExcludeInternalConfigProps< - BaseDiscreteGestureConfig ->; - -export type TapGestureEvent = GestureEvent; - -export type TapGesture = DiscreteSingleGesture< + TapGestureProperties, + TapGestureInternalProperties, TapHandlerData, - TapGestureInternalProperties ->; + TapGestureConfig, + TapGesture, +} from './TapTypes'; const TapPropsMapping = new Map< keyof TapGestureProperties, @@ -46,12 +20,12 @@ const TapPropsMapping = new Map< export function useTapGesture(config: TapGestureConfig): TapGesture { const tapConfig = useClonedAndRemappedConfig< - TapHandlerData, TapGestureProperties, + TapHandlerData, TapGestureInternalProperties >(config, TapPropsMapping); - return useGesture( + return useGesture( SingleGestureName.Tap, tapConfig ); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts b/packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts index 139dbb7d0e..45d95363ee 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts @@ -17,10 +17,14 @@ import { } from '../../handlers/handlersRegistry'; import { NativeProxy } from '../NativeProxy'; -export function useGesture( +export function useGesture< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +>( type: SingleGestureName, - config: BaseGestureConfig -): SingleGesture { + config: BaseGestureConfig +): SingleGesture { const handlerTag = useMemo(() => getNextHandlerTag(), []); const disableReanimated = useMemo(() => config.disableReanimated, []); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/useGestureCallbacks.ts b/packages/react-native-gesture-handler/src/v3/hooks/useGestureCallbacks.ts index 1f1bb70804..a0c02fc63a 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/useGestureCallbacks.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/useGestureCallbacks.ts @@ -36,9 +36,13 @@ function guardJSAnimatedEvent(handler: (...args: unknown[]) => void) { }; } -export function useGestureCallbacks( +export function useGestureCallbacks< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - config: BaseGestureConfig + config: BaseGestureConfig ) { const callbacks = useMemoizedGestureCallbacks(config); @@ -54,12 +58,13 @@ export function useGestureCallbacks( handlerTag, callbacks, reanimatedHandler, - config.changeEventCalculator + config.changeEventCalculator, + config.fillInDefaultValues ); } let animatedEventHandler: - | ((event: GestureUpdateEventWithHandlerData) => void) + | ((event: GestureUpdateEventWithHandlerData) => void) | AnimatedEvent | undefined; if (config.dispatchesAnimatedEvents) { diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/configUtils.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/configUtils.ts index f85c351a5d..9db466a05f 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/configUtils.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/configUtils.ts @@ -15,9 +15,11 @@ import { } from './propsWhiteList'; import { useMemo } from 'react'; -export function prepareConfig( - config: BaseGestureConfig -) { +export function prepareConfig< + TConfig extends object, + THandlerData, + TExtendedHandlerData extends THandlerData, +>(config: BaseGestureConfig) { const runOnJS = maybeUnpackValue(config.runOnJS); if ( @@ -64,12 +66,20 @@ export function prepareConfig( config.shouldUseReanimatedDetector && !runOnJS; } -export function prepareConfigForNativeSide( +export function prepareConfigForNativeSide< + TConfig extends object, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerType: SingleGestureName, - config: BaseGestureConfig + config: BaseGestureConfig ) { // @ts-ignore Seems like TypeScript can't infer the type here properly because of generic - const filteredConfig: BaseGestureConfig = {}; + const filteredConfig: BaseGestureConfig< + TConfig, + THandlerData, + TExtendedHandlerData + > = {}; const handlerPropsWhiteList = PropsWhiteLists.get(handlerType) ?? EMPTY_WHITE_LIST; @@ -93,10 +103,20 @@ export function prepareConfigForNativeSide( return filteredConfig; } -function cloneConfig( - config: ExcludeInternalConfigProps> -): BaseGestureConfig { - return { ...config } as BaseGestureConfig; +function cloneConfig< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + config: ExcludeInternalConfigProps< + BaseGestureConfig + > +): BaseGestureConfig { + return { ...config } as BaseGestureConfig< + TConfig, + THandlerData, + TExtendedHandlerData + >; } function remapProps< @@ -122,16 +142,23 @@ function remapProps< } export function useClonedAndRemappedConfig< + TConfig extends Record, THandlerData, - TConfig extends object, - TInternalConfig extends Record, + TInternalConfig extends Record = TConfig, + TExtendedHandlerData extends THandlerData = THandlerData, >( - config: ExcludeInternalConfigProps>, + config: ExcludeInternalConfigProps< + BaseGestureConfig + >, propsMapping: Map = new Map(), propsTransformer: (config: TInternalConfig) => TInternalConfig = (cfg) => cfg -): BaseGestureConfig { +): BaseGestureConfig { return useMemo(() => { - const clonedConfig = cloneConfig(config); + const clonedConfig = cloneConfig< + TConfig, + THandlerData, + TExtendedHandlerData + >(config); return propsTransformer( remapProps( diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/eventHandlersUtils.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/eventHandlersUtils.ts index 3c7da5c433..58f14bebb1 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/eventHandlersUtils.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/eventHandlersUtils.ts @@ -9,9 +9,12 @@ import { UnpackedGestureHandlerEvent, } from '../../types'; -export function useMemoizedGestureCallbacks( - callbacks: GestureCallbacks -): GestureCallbacks { +export function useMemoizedGestureCallbacks< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + callbacks: GestureCallbacks +): GestureCallbacks { return useMemo( () => ({ ...(callbacks.onBegin ? { onBegin: callbacks.onBegin } : {}), @@ -46,12 +49,14 @@ export function useMemoizedGestureCallbacks( ); } -function getHandler( +function getHandler( type: CALLBACK_TYPE, - callbacks: GestureCallbacks + callbacks: GestureCallbacks ): | GestureEventCallback + | GestureEventCallback | GestureEventCallbackWithDidSucceed + | GestureEventCallbackWithDidSucceed | GestureTouchEventCallback | undefined { 'worklet'; @@ -61,7 +66,7 @@ function getHandler( case CALLBACK_TYPE.START: return callbacks.onActivate; case CALLBACK_TYPE.UPDATE: - return callbacks.onUpdate as GestureEventCallback; // Animated event is handled in different place. + return callbacks.onUpdate as GestureEventCallback; // Animated event is handled in different place. case CALLBACK_TYPE.END: return callbacks.onDeactivate; case CALLBACK_TYPE.FINALIZE: @@ -97,9 +102,12 @@ export function touchEventTypeToCallbackType( type SingleParameterCallback = (event: T) => void; type DoubleParameterCallback = (event: T, didSucceed: boolean) => void; -export function runCallback( +export function runCallback< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( type: CALLBACK_TYPE, - callbacks: GestureCallbacks, + callbacks: GestureCallbacks, event: UnpackedGestureHandlerEvent, didSucceed?: boolean ) { diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/eventUtils.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/eventUtils.ts index f5d41462f3..1c47b7ea94 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/eventUtils.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/eventUtils.ts @@ -12,10 +12,12 @@ import { import { GestureTouchEvent } from '../../../handlers/gestureHandlerCommon'; import { tagMessage } from '../../../utils'; -function isNativeEvent( - event: GestureHandlerEventWithHandlerData +function isNativeEvent( + event: GestureHandlerEventWithHandlerData ): event is - | NativeSyntheticEvent> + | NativeSyntheticEvent< + GestureUpdateEventWithHandlerData + > | NativeSyntheticEvent> | NativeSyntheticEvent { 'worklet'; @@ -23,11 +25,14 @@ function isNativeEvent( return 'nativeEvent' in event; } -export function maybeExtractNativeEvent( - event: GestureHandlerEventWithHandlerData +export function maybeExtractNativeEvent< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + event: GestureHandlerEventWithHandlerData ): | GestureTouchEvent - | GestureUpdateEventWithHandlerData + | GestureUpdateEventWithHandlerData | GestureStateChangeEventWithHandlerData { 'worklet'; @@ -44,9 +49,15 @@ export function flattenAndFilterEvent( return { handlerTag: event.handlerTag, ...event.handlerData }; } -export function isEventForHandlerWithTag( +export function isEventForHandlerWithTag< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( handlerTag: number, - event: GestureUpdateEventWithHandlerData | GestureTouchEvent + event: + | GestureStateChangeEventWithHandlerData + | GestureUpdateEventWithHandlerData + | GestureTouchEvent ) { 'worklet'; @@ -83,9 +94,11 @@ export function checkMappingForChangeProperties(animatedEvent: AnimatedEvent) { } } -export function shouldHandleTouchEvents( - config: BaseGestureConfig -) { +export function shouldHandleTouchEvents< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>(config: BaseGestureConfig) { return ( !!config.onTouchesDown || !!config.onTouchesMove || @@ -94,13 +107,13 @@ export function shouldHandleTouchEvents( ); } -export function getChangeEventCalculator( - diffCalculator: DiffCalculatorType -): ChangeCalculatorType { +export function getChangeEventCalculator( + diffCalculator: DiffCalculatorType +): ChangeCalculatorType { 'worklet'; return ( - current: GestureUpdateEventWithHandlerData, - previous?: GestureUpdateEventWithHandlerData + current: GestureUpdateEventWithHandlerData, + previous?: GestureUpdateEventWithHandlerData ) => { 'worklet'; const currentEventData = current.handlerData; @@ -113,3 +126,31 @@ export function getChangeEventCalculator( return current; }; } + +export function isTouchEvent< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + event: + | GestureStateChangeEventWithHandlerData + | GestureUpdateEventWithHandlerData + | GestureTouchEvent +): event is GestureTouchEvent { + 'worklet'; + + return 'allTouches' in event; +} + +export function isStateChangeEvent< + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + event: + | GestureStateChangeEventWithHandlerData + | GestureUpdateEventWithHandlerData + | GestureTouchEvent +): event is GestureStateChangeEventWithHandlerData { + 'worklet'; + + return 'oldState' in event && event.oldState !== undefined; +} diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts index 1698bf9456..df832c78a8 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts @@ -8,12 +8,12 @@ import { SingleGestureName, } from '../../types'; import { NativeWrapperProperties } from '../../types/NativeWrapperType'; -import { FlingNativeProperties } from '../gestures/fling/FlingProperties'; -import { HoverNativeProperties } from '../gestures/hover/HoverProperties'; -import { LongPressNativeProperties } from '../gestures/longPress/LongPressProperties'; -import { NativeHandlerNativeProperties } from '../gestures/native/NativeProperties'; -import { PanNativeProperties } from '../gestures/pan/PanProperties'; -import { TapNativeProperties } from '../gestures/tap/TapProperties'; +import { FlingNativeProperties } from '../gestures/fling/FlingTypes'; +import { HoverNativeProperties } from '../gestures/hover/HoverTypes'; +import { LongPressNativeProperties } from '../gestures/longPress/LongPressTypes'; +import { NativeHandlerNativeProperties } from '../gestures/native/NativeTypes'; +import { PanNativeProperties } from '../gestures/pan/PanTypes'; +import { TapNativeProperties } from '../gestures/tap/TapTypes'; const CommonConfig = new Set([ 'enabled', @@ -52,7 +52,7 @@ if (!__DEV__) { } export const HandlerCallbacks = new Set< - keyof Required> + keyof Required> >([ 'onBegin', 'onActivate', @@ -65,7 +65,9 @@ export const HandlerCallbacks = new Set< 'onTouchesCancel', ]); -export const PropsToFilter = new Set>([ +export const PropsToFilter = new Set< + BaseGestureConfig +>([ ...HandlerCallbacks, ...ExternalRelationsConfig, diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/reanimatedUtils.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/reanimatedUtils.ts index 72426d6500..cd20d11d3f 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/reanimatedUtils.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/reanimatedUtils.ts @@ -26,8 +26,12 @@ const SHARED_VALUE_OFFSET = 1.618; // Don't transfer entire NativeProxy to the UI thread const { updateGestureHandlerConfig } = NativeProxy; -export function bindSharedValues( - config: BaseGestureConfig, +export function bindSharedValues< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + config: BaseGestureConfig, handlerTag: number ) { if (Reanimated === undefined) { @@ -64,8 +68,12 @@ export function bindSharedValues( } } -export function unbindSharedValues( - config: BaseGestureConfig, +export function unbindSharedValues< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>( + config: BaseGestureConfig, handlerTag: number ) { if (Reanimated === undefined) { @@ -88,12 +96,16 @@ export function unbindSharedValues( } } -export function hasWorkletEventHandlers( - config: BaseGestureConfig -) { +export function hasWorkletEventHandlers< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData, +>(config: BaseGestureConfig) { return Object.entries(config).some( ([key, value]) => - HandlerCallbacks.has(key as keyof GestureCallbacks) && + HandlerCallbacks.has( + key as keyof GestureCallbacks + ) && typeof value === 'function' && '__workletHash' in value ); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/relationUtils.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/relationUtils.ts index c893eb20d9..19dbf7fb0d 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/relationUtils.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/relationUtils.ts @@ -5,8 +5,8 @@ import { GestureRelations, } from '../../types'; -export function isComposedGesture( - gesture: Gesture | ComposedGesture +export function isComposedGesture( + gesture: Gesture | ComposedGesture ): gesture is ComposedGesture { return 'handlerTags' in gesture; } diff --git a/packages/react-native-gesture-handler/src/v3/index.ts b/packages/react-native-gesture-handler/src/v3/index.ts index 66a960164a..350755ff4b 100644 --- a/packages/react-native-gesture-handler/src/v3/index.ts +++ b/packages/react-native-gesture-handler/src/v3/index.ts @@ -10,30 +10,39 @@ export type { TapGesture, TapGestureConfig, TapGestureEvent, + TapGestureActiveEvent, FlingGesture, FlingGestureConfig, FlingGestureEvent, + FlingGestureActiveEvent, LongPressGesture, LongPressGestureConfig, LongPressGestureEvent, + LongPressGestureActiveEvent, PinchGesture, PinchGestureConfig, PinchGestureEvent, + PinchGestureActiveEvent, RotationGesture, RotationGestureConfig, RotationGestureEvent, + RotationGestureActiveEvent, HoverGesture, HoverGestureConfig, HoverGestureEvent, + HoverGestureActiveEvent, ManualGesture, ManualGestureConfig, ManualGestureEvent, + ManualGestureActiveEvent, NativeGesture, - NativeViewGestureConfig, + NativeGestureConfig, NativeGestureEvent, + NativeGestureActiveEvent, PanGesture, PanGestureConfig, PanGestureEvent, + PanGestureActiveEvent, SingleGesture, SingleGestureEvent, } from './hooks'; diff --git a/packages/react-native-gesture-handler/src/v3/types/ConfigTypes.ts b/packages/react-native-gesture-handler/src/v3/types/ConfigTypes.ts index ddb2363c8d..9d0fee2581 100644 --- a/packages/react-native-gesture-handler/src/v3/types/ConfigTypes.ts +++ b/packages/react-native-gesture-handler/src/v3/types/ConfigTypes.ts @@ -24,12 +24,15 @@ export type GestureEventCallbackWithDidSucceed = ( export type GestureTouchEventCallback = (event: GestureTouchEvent) => void; -export type GestureCallbacks = { +export type GestureCallbacks< + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = { onBegin?: GestureEventCallback; - onActivate?: GestureEventCallback; - onDeactivate?: GestureEventCallbackWithDidSucceed; + onActivate?: GestureEventCallback; + onUpdate?: GestureEventCallback | AnimatedEvent; + onDeactivate?: GestureEventCallbackWithDidSucceed; onFinalize?: GestureEventCallbackWithDidSucceed; - onUpdate?: GestureEventCallback | AnimatedEvent; onTouchesDown?: GestureTouchEventCallback; onTouchesMove?: GestureTouchEventCallback; onTouchesUp?: GestureTouchEventCallback; @@ -42,7 +45,7 @@ export type GestureRelations = { blocksHandlers: number[]; }; -export type InternalConfigProps = { +export type InternalConfigProps = { shouldUseReanimatedDetector?: boolean; dispatchesReanimatedEvents?: boolean; dispatchesAnimatedEvents?: boolean; @@ -50,7 +53,8 @@ export type InternalConfigProps = { userSelect?: UserSelect; touchAction?: TouchAction; enableContextMenu?: boolean; - changeEventCalculator?: ChangeCalculatorType; + changeEventCalculator?: ChangeCalculatorType; + fillInDefaultValues?: (event: GestureEvent) => void; }; export type CommonGestureConfig = { diff --git a/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts b/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts index e0b59b62ae..1903748104 100644 --- a/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts +++ b/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts @@ -5,23 +5,38 @@ import { } from './EventTypes'; import { TouchAction, UserSelect } from '../../handlers/gestureHandlerCommon'; -export type DetectorCallbacks = { +export type DetectorCallbacks< + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = { jsEventHandler: | undefined - | ((event: GestureHandlerEventWithHandlerData) => void); + | (( + event: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > + ) => void); reanimatedEventHandler: | undefined - | ((event: GestureHandlerEventWithHandlerData) => void); + | (( + event: GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData + > + ) => void); animatedEventHandler: | undefined | AnimatedEvent - | ((event: GestureUpdateEventWithHandlerData) => void); + | (( + event: GestureUpdateEventWithHandlerData + ) => void); }; export type VirtualChild = { viewTag: number; handlerTags: number[]; - methods: DetectorCallbacks; + methods: DetectorCallbacks; // only set on web viewRef: unknown; diff --git a/packages/react-native-gesture-handler/src/v3/types/EventTypes.ts b/packages/react-native-gesture-handler/src/v3/types/EventTypes.ts index 79d2643cd1..388c7ea02c 100644 --- a/packages/react-native-gesture-handler/src/v3/types/EventTypes.ts +++ b/packages/react-native-gesture-handler/src/v3/types/EventTypes.ts @@ -27,13 +27,19 @@ export type GestureStateChangeEventWithHandlerData = handlerData: HandlerData; }; -export type GestureHandlerEventWithHandlerData = - | UpdateEventWithHandlerData +export type GestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = + | UpdateEventWithHandlerData | StateChangeEventWithHandlerData | TouchEvent; -export type UnpackedGestureHandlerEventWithHandlerData = - | GestureUpdateEventWithHandlerData +export type UnpackedGestureHandlerEventWithHandlerData< + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = + | GestureUpdateEventWithHandlerData | GestureStateChangeEventWithHandlerData | GestureTouchEvent; @@ -64,12 +70,12 @@ export type AnimatedEvent = { _argMapping: (Animated.Mapping | null)[]; }; -export type ChangeCalculatorType = ( - current: GestureUpdateEventWithHandlerData, - previous?: GestureUpdateEventWithHandlerData -) => GestureUpdateEventWithHandlerData; +export type ChangeCalculatorType = ( + current: GestureUpdateEventWithHandlerData, + previous?: GestureUpdateEventWithHandlerData +) => GestureUpdateEventWithHandlerData; -export type DiffCalculatorType = ( - current: HandlerData, - previous: HandlerData | null -) => Partial>; +export type DiffCalculatorType = ( + current: HandlerData, + previous: HandlerData | null +) => Partial>; diff --git a/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts b/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts index ba83883530..9f2a48d111 100644 --- a/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts +++ b/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts @@ -16,46 +16,73 @@ export type ExternalRelations = { }; // Similarly, this type cannot be moved into ConfigTypes.ts because it depends on `ExternalRelations` -export type BaseGestureConfig = ExternalRelations & - GestureCallbacks & +export type BaseGestureConfig< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = ExternalRelations & + GestureCallbacks & FilterNeverProperties & - InternalConfigProps & + InternalConfigProps & CommonGestureConfig; -export type BaseDiscreteGestureConfig = Omit< - BaseGestureConfig, +export type BaseDiscreteGestureConfig< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = Omit< + BaseGestureConfig, 'onUpdate' >; -export type SingleGesture = { +export type SingleGesture< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = { handlerTag: number; type: SingleGestureName; - config: BaseGestureConfig; - detectorCallbacks: DetectorCallbacks; + config: BaseGestureConfig; + detectorCallbacks: DetectorCallbacks; gestureRelations: GestureRelations; }; -export type DiscreteSingleGesture = { - [K in keyof SingleGesture]: K extends 'config' - ? Omit[K], 'onUpdate'> - : SingleGesture[K]; +export type DiscreteSingleGesture< + TConfig, + THandlerData, + TExtendedHandlerData extends THandlerData = THandlerData, +> = { + [K in keyof SingleGesture< + TConfig, + THandlerData, + TExtendedHandlerData + >]: K extends 'config' + ? Omit< + SingleGesture[K], + 'onUpdate' + > + : SingleGesture[K]; }; export type ComposedGesture = { handlerTags: number[]; type: ComposedGestureName; config: ComposedGestureConfig; - detectorCallbacks: DetectorCallbacks; + detectorCallbacks: DetectorCallbacks; externalSimultaneousHandlers: number[]; gestures: Gesture[]; }; -export type Gesture = - | SingleGesture +export type Gesture< + TConfig = unknown, + THandlerData = unknown, + TExtendedHandlerData extends THandlerData = THandlerData, +> = + | SingleGesture | ComposedGesture; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export type AnyGesture = Gesture; +export type AnyGesture = Gesture; export enum SingleGestureName { Tap = 'TapGestureHandler', diff --git a/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts b/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts index 4b0543a3f2..66c6589f88 100644 --- a/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts +++ b/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts @@ -1,9 +1,10 @@ import { CommonGestureConfig, ExternalRelations, GestureCallbacks } from '.'; -import { NativeGestureNativeProperties } from '../hooks/gestures/native/NativeProperties'; + import { + NativeGestureNativeProperties, + NativeHandlerData, NativeGesture, - NativeViewHandlerData, -} from '../hooks/gestures/native/useNativeGesture'; +} from '../hooks/gestures/native/NativeTypes'; export type WrapperSpecificProperties = { ref?: React.RefObject; @@ -13,7 +14,7 @@ export type WrapperSpecificProperties = { }; export type NativeWrapperProperties = CommonGestureConfig & - GestureCallbacks & + GestureCallbacks & NativeGestureNativeProperties & ExternalRelations & WrapperSpecificProperties; diff --git a/packages/react-native-gesture-handler/src/v3/types/UtilityTypes.ts b/packages/react-native-gesture-handler/src/v3/types/UtilityTypes.ts index 56c6fedaa7..8f95353786 100644 --- a/packages/react-native-gesture-handler/src/v3/types/UtilityTypes.ts +++ b/packages/react-native-gesture-handler/src/v3/types/UtilityTypes.ts @@ -1,9 +1,9 @@ -import { PanGestureNativeProperties } from '../hooks/gestures/pan/PanProperties'; -import { FlingGestureNativeProperties } from '../hooks/gestures/fling/FlingProperties'; -import { HoverGestureNativeProperties } from '../hooks/gestures/hover/HoverProperties'; -import { LongPressGestureNativeProperties } from '../hooks/gestures/longPress/LongPressProperties'; -import { NativeGestureNativeProperties } from '../hooks/gestures/native/NativeProperties'; -import { TapGestureNativeConfig } from '../hooks/gestures/tap/TapProperties'; +import { PanGestureNativeProperties } from '../hooks/gestures/pan/PanTypes'; +import { FlingGestureNativeProperties } from '../hooks/gestures/fling/FlingTypes'; +import { HoverGestureNativeProperties } from '../hooks/gestures/hover/HoverTypes'; +import { LongPressGestureNativeProperties } from '../hooks/gestures/longPress/LongPressTypes'; +import { NativeGestureNativeProperties } from '../hooks/gestures/native/NativeTypes'; +import { TapGestureNativeConfig } from '../hooks/gestures/tap/TapTypes'; import { InternalConfigProps } from './ConfigTypes'; export type HandlersPropsWhiteList =