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 new file mode 100644 index 0000000000..0f9e0a095a --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/FlingProperties.ts @@ -0,0 +1,26 @@ +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/useFling.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFling.ts similarity index 51% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useFling.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFling.ts index fd37f4b8ad..4f06ef17ab 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useFling.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/fling/useFling.ts @@ -3,32 +3,10 @@ import { ExcludeInternalConfigProps, SingleGestureName, WithSharedValue, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig } from '../utils'; - -type FlingGestureProperties = WithSharedValue<{ - /** - * 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; -}>; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig } from '../../utils'; +import type { FlingGestureNativeProperties } from './FlingProperties'; type FlingHandlerData = { x: number; @@ -37,6 +15,8 @@ type FlingHandlerData = { absoluteY: number; }; +type FlingGestureProperties = WithSharedValue; + type FlingGestureInternalConfig = BaseGestureConfig< FlingHandlerData, FlingGestureProperties 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 new file mode 100644 index 0000000000..e8f6840eb5 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/HoverProperties.ts @@ -0,0 +1,18 @@ +import { HoverEffect } from '../../../../handlers/gestures/hoverGesture'; + +export type HoverGestureNativeProperties = { + /** + * 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` + */ + hoverEffect?: HoverEffect; +}; + +export const HoverNativeProperties = new Set< + keyof HoverGestureNativeProperties +>(['hoverEffect']); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useHover.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHover.ts similarity index 65% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useHover.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHover.ts index e057732cc2..c0a611304b 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useHover.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/hover/useHover.ts @@ -1,30 +1,15 @@ -import { StylusData } from '../../../handlers/gestureHandlerCommon'; -import { HoverEffect } from '../../../handlers/gestures/hoverGesture'; +import { StylusData } from '../../../../handlers/gestureHandlerCommon'; +import { HoverEffect } from '../../../../handlers/gestures/hoverGesture'; import { BaseGestureConfig, ExcludeInternalConfigProps, HandlerData, SingleGestureName, WithSharedValue, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig, getChangeEventCalculator } from '../utils'; - -type HoverGestureProperties = WithSharedValue< - { - /** - * 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` - */ - hoverEffect?: HoverEffect; - }, - HoverEffect ->; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig, getChangeEventCalculator } from '../../utils'; +import { HoverGestureNativeProperties } from './HoverProperties'; type HoverHandlerData = { x: number; @@ -36,6 +21,11 @@ type HoverHandlerData = { changeY: number; }; +type HoverGestureProperties = WithSharedValue< + HoverGestureNativeProperties, + HoverEffect +>; + type HoverGestureInternalConfig = BaseGestureConfig< HoverHandlerData, HoverGestureProperties 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 64e175e259..eab3ab4690 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,26 +1,26 @@ -export type { TapGestureConfig } from './useTap'; -export { useTap } from './useTap'; +export type { TapGestureConfig } from './tap/useTap'; +export { useTap } from './tap/useTap'; -export type { FlingGestureConfig } from './useFling'; -export { useFling } from './useFling'; +export type { FlingGestureConfig } from './fling/useFling'; +export { useFling } from './fling/useFling'; -export type { LongPressGestureConfig } from './useLongPress'; -export { useLongPress } from './useLongPress'; +export type { LongPressGestureConfig } from './longPress/useLongPress'; +export { useLongPress } from './longPress/useLongPress'; -export type { PinchGestureConfig } from './usePinch'; -export { usePinch } from './usePinch'; +export type { PinchGestureConfig } from './pinch/usePinch'; +export { usePinch } from './pinch/usePinch'; -export type { RotationGestureConfig } from './useRotation'; -export { useRotation } from './useRotation'; +export type { RotationGestureConfig } from './rotation/useRotation'; +export { useRotation } from './rotation/useRotation'; -export type { HoverGestureConfig } from './useHover'; -export { useHover } from './useHover'; +export type { HoverGestureConfig } from './hover/useHover'; +export { useHover } from './hover/useHover'; -export type { ManualGestureConfig } from './useManual'; -export { useManual } from './useManual'; +export type { ManualGestureConfig } from './manual/useManual'; +export { useManual } from './manual/useManual'; -export type { NativeViewGestureConfig } from './useNative'; -export { useNative } from './useNative'; +export type { NativeViewGestureConfig } from './native/useNative'; +export { useNative } from './native/useNative'; -export type { PanGestureConfig } from './usePan'; -export { usePan } from './usePan'; +export type { PanGestureConfig } from './pan/usePan'; +export { usePan } from './pan/usePan'; 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/LongPressProperties.ts new file mode 100644 index 0000000000..e5fbe0c184 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/LongPressProperties.ts @@ -0,0 +1,33 @@ +type CommonLongPressGestureProperties = { + /** + * Determine exact number of points required to handle the long press gesture. + */ + numberOfPointers?: number; +}; + +export type LongPressGestureExternalProperties = + CommonLongPressGestureProperties & { + /** + * Minimum time, expressed in milliseconds, that a finger must remain pressed on + * the corresponding view. The default value is 500. + */ + minDuration?: number; + + /** + * Maximum distance, expressed in points, that defines how far the finger is + * allowed to travel during a long press gesture. If the finger travels + * further than the defined distance and the handler hasn't yet activated, it + * will fail to recognize the gesture. The default value is 10. + */ + maxDistance?: number; + }; + +export type LongPressGestureNativeProperties = + CommonLongPressGestureProperties & { + minDurationMs?: number; + maxDist?: number; + }; + +export const LongPressNativeProperties = new Set< + keyof LongPressGestureNativeProperties +>(['minDurationMs', 'maxDist', 'numberOfPointers']); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useLongPress.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPress.ts similarity index 56% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useLongPress.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPress.ts index a054d5e8fb..932214f07b 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useLongPress.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/longPress/useLongPress.ts @@ -3,36 +3,13 @@ import { ExcludeInternalConfigProps, SingleGestureName, WithSharedValue, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig, remapProps } from '../utils'; - -type LongPressGestureProperties = WithSharedValue<{ - /** - * Minimum time, expressed in milliseconds, that a finger must remain pressed on - * the corresponding view. The default value is 500. - */ - minDuration?: number; - - /** - * Maximum distance, expressed in points, that defines how far the finger is - * allowed to travel during a long press gesture. If the finger travels - * further than the defined distance and the handler hasn't yet activated, it - * will fail to recognize the gesture. The default value is 10. - */ - maxDistance?: number; - - /** - * Determine exact number of points required to handle the long press gesture. - */ - numberOfPointers?: number; -}>; - -type LongPressGestureInternalProperties = WithSharedValue<{ - minDurationMs?: number; - maxDist?: number; - numberOfPointers?: number; -}>; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig, remapProps } from '../../utils'; +import { + LongPressGestureExternalProperties, + LongPressGestureNativeProperties, +} from './LongPressProperties'; type LongPressHandlerData = { x: number; @@ -42,6 +19,12 @@ type LongPressHandlerData = { duration: number; }; +type LongPressGestureProperties = + WithSharedValue; + +type LongPressGestureInternalProperties = + WithSharedValue; + export type LongPressGestureConfig = ExcludeInternalConfigProps< BaseGestureConfig >; 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 new file mode 100644 index 0000000000..f5676df1ca --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/ManualProperties.ts @@ -0,0 +1 @@ +export type ManualGestureNativeProperties = Record; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useManual.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManual.ts similarity index 69% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useManual.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManual.ts index 5d32f85e71..86ef77a710 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useManual.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/manual/useManual.ts @@ -2,18 +2,19 @@ import { BaseGestureConfig, ExcludeInternalConfigProps, SingleGestureName, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig } from '../utils'; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig } from '../../utils'; +import { ManualGestureNativeProperties } from './ManualProperties'; -type ManualGestureProperties = Record; type ManualHandlerData = Record; +type ManualGestureProperties = ManualGestureNativeProperties; + type ManualGestureInternalConfig = BaseGestureConfig< ManualHandlerData, ManualGestureProperties >; - export type ManualGestureConfig = ExcludeInternalConfigProps; 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 new file mode 100644 index 0000000000..e423bf401f --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/NativeProperties.ts @@ -0,0 +1,19 @@ +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/useNative.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts similarity index 54% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useNative.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts index 4a2eceb34d..c68ff92fd6 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useNative.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts @@ -3,30 +3,18 @@ import { ExcludeInternalConfigProps, SingleGestureName, WithSharedValue, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig } from '../utils'; - -type NativeViewGestureProperties = WithSharedValue<{ - /** - * 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; -}>; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig } from '../../utils'; +import { NativeGestureNativeProperties } from './NativeProperties'; type NativeViewHandlerData = { pointerInside: boolean; }; +type NativeViewGestureProperties = + WithSharedValue; + type NativeViewGestureInternalConfig = BaseGestureConfig< NativeViewHandlerData, NativeViewGestureProperties 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/PanProperties.ts new file mode 100644 index 0000000000..26679b3f6f --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/PanProperties.ts @@ -0,0 +1,118 @@ +type CommonPanGestureProperties = { + /** + * Minimum distance the finger (or multiple finger) need to travel before the + * handler activates. Expressed in points. + */ + minDistance?: number; + + /** + * Android only. + */ + avgTouches?: boolean; + + /** + * Enables two-finger gestures on supported devices, for example iPads with + * trackpads. If not enabled the gesture will require click + drag, with + * enableTrackpadTwoFingerGesture swiping with two fingers will also trigger + * the gesture. + */ + enableTrackpadTwoFingerGesture?: boolean; + + /** + * A number of fingers that is required to be placed before handler can + * activate. Should be a higher or equal to 0 integer. + */ + minPointers?: number; + + /** + * When the given number of fingers is placed on the screen and handler hasn't + * yet activated it will fail recognizing the gesture. Should be a higher or + * equal to 0 integer. + */ + maxPointers?: number; + + minVelocity?: number; + minVelocityX?: number; + minVelocityY?: number; + activateAfterLongPress?: number; +}; + +export type OffsetProps = { + /** + * Range along X axis (in points) where fingers travels without activation of + * handler. Moving outside of this range implies activation of handler. Range + * can be given as an array or a single number. If range is set as an array, + * first value must be lower or equal to 0, a the second one higher or equal + * to 0. If only one number `p` is given a range of `(-inf, p)` will be used + * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. + */ + activeOffsetY?: number | [number, number]; + + /** + * Range along X axis (in points) where fingers travels without activation of + * handler. Moving outside of this range implies activation of handler. Range + * can be given as an array or a single number. If range is set as an array, + * first value must be lower or equal to 0, a the second one higher or equal + * to 0. If only one number `p` is given a range of `(-inf, p)` will be used + * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. + */ + activeOffsetX?: number | [number, number]; + + /** + * When the finger moves outside this range (in points) along Y axis and + * handler hasn't yet activated it will fail recognizing the gesture. Range + * can be given as an array or a single number. If range is set as an array, + * first value must be lower or equal to 0, a the second one higher or equal + * to 0. If only one number `p` is given a range of `(-inf, p)` will be used + * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. + */ + failOffsetY?: number | [number, number]; + + /** + * When the finger moves outside this range (in points) along X axis and + * handler hasn't yet activated it will fail recognizing the gesture. Range + * can be given as an array or a single number. If range is set as an array, + * first value must be lower or equal to 0, a the second one higher or equal + * to 0. If only one number `p` is given a range of `(-inf, p)` will be used + * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. + */ + failOffsetX?: number | [number, number]; +}; + +export type PanGestureExternalProperties = CommonPanGestureProperties & + OffsetProps; + +export type PanGestureNativeProperties = Omit< + CommonPanGestureProperties, + 'minDistance' +> & { + minDist?: number; + activeOffsetYStart?: number; + activeOffsetYEnd?: number; + activeOffsetXStart?: number; + activeOffsetXEnd?: number; + failOffsetYStart?: number; + failOffsetYEnd?: number; + failOffsetXStart?: number; + failOffsetXEnd?: number; +}; + +export const PanNativeProperties = new Set([ + 'minDist', + 'avgTouches', + 'enableTrackpadTwoFingerGesture', + 'minPointers', + 'maxPointers', + 'minVelocity', + 'minVelocityX', + 'minVelocityY', + 'activateAfterLongPress', + 'activeOffsetYStart', + 'activeOffsetYEnd', + 'activeOffsetXStart', + 'activeOffsetXEnd', + 'failOffsetYStart', + 'failOffsetYEnd', + 'failOffsetXStart', + 'failOffsetXEnd', +]); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/usePan.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePan.ts similarity index 50% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/usePan.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePan.ts index a3bbad0987..323533ce8c 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/usePan.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pan/usePan.ts @@ -1,119 +1,25 @@ -import { StylusData } from '../../../handlers/gestureHandlerCommon'; +import { StylusData } from '../../../../handlers/gestureHandlerCommon'; import { BaseGestureConfig, ExcludeInternalConfigProps, HandlerData, SingleGestureName, WithSharedValue, -} from '../../types'; -import { useGesture } from '../useGesture'; +} from '../../../types'; +import { useGesture } from '../../useGesture'; import { getChangeEventCalculator, maybeUnpackValue, remapProps, cloneConfig, -} from '../utils'; - -type CommonPanGestureProperties = { - /** - * Minimum distance the finger (or multiple finger) need to travel before the - * handler activates. Expressed in points. - */ - minDistance?: number; - - /** - * Android only. - */ - avgTouches?: boolean; - - /** - * Enables two-finger gestures on supported devices, for example iPads with - * trackpads. If not enabled the gesture will require click + drag, with - * enableTrackpadTwoFingerGesture swiping with two fingers will also trigger - * the gesture. - */ - enableTrackpadTwoFingerGesture?: boolean; - - /** - * A number of fingers that is required to be placed before handler can - * activate. Should be a higher or equal to 0 integer. - */ - minPointers?: number; - - /** - * When the given number of fingers is placed on the screen and handler hasn't - * yet activated it will fail recognizing the gesture. Should be a higher or - * equal to 0 integer. - */ - maxPointers?: number; - - minVelocity?: number; - minVelocityX?: number; - minVelocityY?: number; - activateAfterLongPress?: number; -}; - -type OffsetProps = { - /** - * Range along X axis (in points) where fingers travels without activation of - * handler. Moving outside of this range implies activation of handler. Range - * can be given as an array or a single number. If range is set as an array, - * first value must be lower or equal to 0, a the second one higher or equal - * to 0. If only one number `p` is given a range of `(-inf, p)` will be used - * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. - */ - activeOffsetY?: number | [number, number]; - - /** - * Range along X axis (in points) where fingers travels without activation of - * handler. Moving outside of this range implies activation of handler. Range - * can be given as an array or a single number. If range is set as an array, - * first value must be lower or equal to 0, a the second one higher or equal - * to 0. If only one number `p` is given a range of `(-inf, p)` will be used - * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. - */ - activeOffsetX?: number | [number, number]; - - /** - * When the finger moves outside this range (in points) along Y axis and - * handler hasn't yet activated it will fail recognizing the gesture. Range - * can be given as an array or a single number. If range is set as an array, - * first value must be lower or equal to 0, a the second one higher or equal - * to 0. If only one number `p` is given a range of `(-inf, p)` will be used - * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. - */ - failOffsetY?: number | [number, number]; - - /** - * When the finger moves outside this range (in points) along X axis and - * handler hasn't yet activated it will fail recognizing the gesture. Range - * can be given as an array or a single number. If range is set as an array, - * first value must be lower or equal to 0, a the second one higher or equal - * to 0. If only one number `p` is given a range of `(-inf, p)` will be used - * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. - */ - failOffsetX?: number | [number, number]; -}; - -export type PanGestureProperties = WithSharedValue< - CommonPanGestureProperties & OffsetProps ->; - -type PanGestureInternalProperties = WithSharedValue< - CommonPanGestureProperties & { - minDist?: number; - activeOffsetYStart?: number; - activeOffsetYEnd?: number; - activeOffsetXStart?: number; - activeOffsetXEnd?: number; - failOffsetYStart?: number; - failOffsetYEnd?: number; - failOffsetXStart?: number; - failOffsetXEnd?: number; - } ->; +} from '../../utils'; +import { + OffsetProps, + PanGestureExternalProperties, + PanGestureNativeProperties, +} from './PanProperties'; -type PanHandlerData = { +export type PanHandlerData = { x: number; y: number; absoluteX: number; @@ -127,6 +33,12 @@ type PanHandlerData = { changeY: number; }; +export type PanGestureProperties = + WithSharedValue; + +export type PanGestureInternalProperties = + WithSharedValue; + export type PanGestureConfig = ExcludeInternalConfigProps< BaseGestureConfig >; 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 new file mode 100644 index 0000000000..1c1aa92e48 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/PinchProperties.ts @@ -0,0 +1 @@ +export type PinchGestureNativeProperties = Record; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/usePinch.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinch.ts similarity index 77% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/usePinch.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinch.ts index 1d654f7496..1bbe9a9294 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/usePinch.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/pinch/usePinch.ts @@ -3,11 +3,10 @@ import { ExcludeInternalConfigProps, HandlerData, SingleGestureName, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig, getChangeEventCalculator } from '../utils'; - -type PinchGestureProperties = Record; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig, getChangeEventCalculator } from '../../utils'; +import { PinchGestureNativeProperties } from './PinchProperties'; type PinchHandlerData = { scale: number; @@ -17,6 +16,8 @@ type PinchHandlerData = { scaleChange: number; }; +type PinchGestureProperties = PinchGestureNativeProperties; + type PinchGestureInternalConfig = BaseGestureConfig< PinchHandlerData, PinchGestureProperties 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 new file mode 100644 index 0000000000..6a74c0cf24 --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/RotationProperties.ts @@ -0,0 +1 @@ +export type RotationGestureNativeProperties = Record; diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useRotation.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotation.ts similarity index 78% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useRotation.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotation.ts index 6d43ea0f3b..1dd10b2adb 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useRotation.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/rotation/useRotation.ts @@ -3,11 +3,10 @@ import { ExcludeInternalConfigProps, HandlerData, SingleGestureName, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig, getChangeEventCalculator } from '../utils'; - -type RotationGestureProperties = Record; +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig, getChangeEventCalculator } from '../../utils'; +import { RotationGestureNativeProperties } from './RotationProperties'; type RotationHandlerData = { rotation: number; @@ -17,6 +16,8 @@ type RotationHandlerData = { rotationChange: number; }; +type RotationGestureProperties = RotationGestureNativeProperties; + type RotationGestureInternalConfig = BaseGestureConfig< RotationHandlerData, RotationGestureProperties diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useTap.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapProperties.ts similarity index 57% rename from packages/react-native-gesture-handler/src/v3/hooks/gestures/useTap.ts rename to packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapProperties.ts index 6bebbccf95..46ccdab2d5 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/useTap.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/TapProperties.ts @@ -1,13 +1,4 @@ -import { - BaseGestureConfig, - ExcludeInternalConfigProps, - SingleGestureName, - WithSharedValue, -} from '../../types'; -import { useGesture } from '../useGesture'; -import { cloneConfig, remapProps } from '../utils'; - -type TapGestureProperties = WithSharedValue<{ +type CommonTapGestureConfig = { /** * Minimum number of pointers (fingers) required to be placed before the * handler activates. Should be a positive integer. @@ -15,18 +6,6 @@ type TapGestureProperties = WithSharedValue<{ */ minPointers?: number; - /** - * Maximum time, expressed in milliseconds, that defines how fast a finger - * must be released after a touch. The default value is 500. - */ - maxDuration?: number; - - /** - * Maximum time, expressed in milliseconds, that can pass before the next tap - * if many taps are required. The default value is 500. - */ - maxDelay?: number; - /** * Number of tap gestures required to activate the handler. The default value * is 1. @@ -48,6 +27,20 @@ type TapGestureProperties = WithSharedValue<{ * hasn't yet activated, it will fail to recognize the gesture. */ maxDeltaY?: number; +}; + +export type TapGestureExternalConfig = CommonTapGestureConfig & { + /** + * Maximum time, expressed in milliseconds, that defines how fast a finger + * must be released after a touch. The default value is 500. + */ + maxDuration?: number; + + /** + * Maximum time, expressed in milliseconds, that can pass before the next tap + * if many taps are required. The default value is 500. + */ + maxDelay?: number; /** * Maximum distance, expressed in points, that defines how far the finger is @@ -56,55 +49,20 @@ type TapGestureProperties = WithSharedValue<{ * activated, it will fail to recognize the gesture. */ maxDistance?: number; -}>; +}; -type TapGestureInternalProperties = WithSharedValue<{ - minPointers?: number; - numberOfTaps?: number; - maxDeltaX?: number; - maxDeltaY?: number; +export type TapGestureNativeConfig = CommonTapGestureConfig & { maxDurationMs?: number; maxDelayMs?: number; maxDist?: number; -}>; - -type TapHandlerData = { - x: number; - y: number; - absoluteX: number; - absoluteY: number; }; -export type TapGestureConfig = ExcludeInternalConfigProps< - BaseGestureConfig ->; - -type TapGestureInternalConfig = BaseGestureConfig< - TapHandlerData, - TapGestureInternalProperties ->; - -const TapPropsMapping = new Map< - keyof TapGestureProperties, - keyof TapGestureInternalProperties ->([ - ['maxDistance', 'maxDist'], - ['maxDuration', 'maxDurationMs'], - ['maxDelay', 'maxDelayMs'], +export const TapNativeProperties = new Set([ + 'minPointers', + 'numberOfTaps', + 'maxDeltaX', + 'maxDeltaY', + 'maxDurationMs', + 'maxDelayMs', + 'maxDist', ]); - -export function useTap(config: TapGestureConfig) { - const tapConfig = cloneConfig( - config - ); - - remapProps( - tapConfig, - TapPropsMapping - ); - - return useGesture( - SingleGestureName.Tap, - tapConfig - ); -} diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTap.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTap.ts new file mode 100644 index 0000000000..04c1e0670e --- /dev/null +++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/tap/useTap.ts @@ -0,0 +1,57 @@ +import { + BaseGestureConfig, + ExcludeInternalConfigProps, + SingleGestureName, + WithSharedValue, +} from '../../../types'; +import { useGesture } from '../../useGesture'; +import { cloneConfig, remapProps } 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< + BaseGestureConfig +>; + +type TapGestureInternalConfig = BaseGestureConfig< + TapHandlerData, + TapGestureInternalProperties +>; + +const TapPropsMapping = new Map< + keyof TapGestureProperties, + keyof TapGestureInternalProperties +>([ + ['maxDistance', 'maxDist'], + ['maxDuration', 'maxDurationMs'], + ['maxDelay', 'maxDelayMs'], +]); + +export function useTap(config: TapGestureConfig) { + const tapConfig = cloneConfig( + config + ); + + remapProps( + tapConfig, + TapPropsMapping + ); + + 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 cec1f7dc18..916df6d3c0 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts @@ -94,7 +94,7 @@ export function useGesture( }, [type, tag]); useEffect(() => { - const preparedConfig = prepareConfig(config); + const preparedConfig = prepareConfig(type, config); RNGestureHandlerModule.setGestureHandlerConfig(tag, preparedConfig); RNGestureHandlerModule.flushOperations(); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils.ts index 13285c3e07..a671a0d253 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils.ts @@ -3,6 +3,7 @@ import { AnimatedEvent, BaseGestureConfig, ChangeCalculatorType, + CommonGestureConfig, DiffCalculatorType, ExcludeInternalConfigProps, UnpackedGestureHandlerEvent, @@ -10,10 +11,19 @@ import { GestureStateChangeEvent, GestureUpdateEvent, SharedValueOrT, + SingleGestureName, + InternalConfigProps, + HandlersPropsWhiteList, } from '../types'; import { GestureTouchEvent } from '../../handlers/gestureHandlerCommon'; import { tagMessage } from '../../utils'; import { Reanimated } from '../../handlers/gestures/reanimatedWrapper'; +import { PanNativeProperties } from './gestures/pan/PanProperties'; +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 { TapNativeProperties } from './gestures/tap/TapProperties'; export function isNativeEvent( event: GestureHandlerEvent @@ -79,27 +89,90 @@ export function checkMappingForChangeProperties(animatedEvent: AnimatedEvent) { } } -export function prepareConfig( +const allowedNativeProps = new Set< + keyof CommonGestureConfig | keyof InternalConfigProps +>([ + // CommonGestureConfig + 'disableReanimated', + 'enabled', + 'shouldCancelWhenOutside', + 'hitSlop', + 'userSelect', + 'activeCursor', + 'mouseButton', + 'enableContextMenu', + 'touchAction', + + // InternalConfigProps + 'shouldUseReanimated', + 'dispatchesAnimatedEvents', + 'needsPointerData', + 'changeEventCalculator', +]); + +const PropsToFilter = new Set>([ + // Callbacks + 'onBegin', + 'onStart', + 'onUpdate', + 'onEnd', + 'onFinalize', + 'onTouchesDown', + 'onTouchesMove', + 'onTouchesUp', + 'onTouchesCancelled', + + // Config props + 'changeEventCalculator', + 'disableReanimated', + + // Relations + 'simultaneousWithExternalGesture', + 'requireExternalGestureToFail', + 'blocksExternalGesture', +]); + +export const PropsWhiteLists = new Map< + SingleGestureName, + HandlersPropsWhiteList +>([ + [SingleGestureName.Pan, PanNativeProperties], + [SingleGestureName.Tap, TapNativeProperties], + [SingleGestureName.Native, NativeHandlerNativeProperties], + [SingleGestureName.Fling, FlingNativeProperties], + [SingleGestureName.Hover, HoverNativeProperties], + [SingleGestureName.LongPress, LongPressNativeProperties], +]); + +const EMPTY_WHILE_LIST = new Set(); + +export function prepareConfig( + handlerType: SingleGestureName, config: BaseGestureConfig ) { - const copy = { ...config }; - - for (const key in copy) { - // @ts-ignore It is fine to use string as index - if (Reanimated?.isSharedValue(copy[key])) { - // @ts-ignore It is fine to use string as index - copy[key] = copy[key].value; + // @ts-ignore Seems like TypeScript can't infer the type here properly because of generic + const filteredConfig: BaseGestureConfig = {}; + const handlerPropsWhiteList = + PropsWhiteLists.get(handlerType) ?? EMPTY_WHILE_LIST; + + for (const [key, value] of Object.entries(config)) { + // @ts-ignore That's the point, we want to see if key exists in the whitelists + if (allowedNativeProps.has(key) || handlerPropsWhiteList.has(key)) { + Object.assign(filteredConfig, { + [key]: Reanimated?.isSharedValue(value) ? value.value : value, + }); + } else if (PropsToFilter.has(key)) { + continue; + } else { + console.warn( + tagMessage( + `${key} is not a valid property for ${handlerType} and will be ignored.` + ) + ); } } - // TODO: Filter changes - passing functions (and possibly other types) - // causes a native crash - delete copy.onUpdate; - delete copy.simultaneousWithExternalGesture; - delete copy.requireExternalGestureToFail; - delete copy.blocksExternalGesture; - - return copy; + return filteredConfig; } export function shouldHandleTouchEvents( diff --git a/packages/react-native-gesture-handler/src/v3/types.ts b/packages/react-native-gesture-handler/src/v3/types.ts index 1883b54b9a..41210e7c0b 100644 --- a/packages/react-native-gesture-handler/src/v3/types.ts +++ b/packages/react-native-gesture-handler/src/v3/types.ts @@ -10,6 +10,12 @@ import { import { PointerType } from '../PointerType'; import { State } from '../State'; +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'; interface EventPayload { handlerTag: number; @@ -173,7 +179,7 @@ export type InternalConfigProps = { changeEventCalculator?: ChangeCalculatorType; }; -type CommonGestureConfig = WithSharedValue< +export type CommonGestureConfig = WithSharedValue< { disableReanimated?: boolean; enabled?: boolean; @@ -258,3 +264,11 @@ type Simplify = // For a generic object, retain the original structure while forcing an object type [K in keyof T]: T[K]; } & NonNullable; + +export type HandlersPropsWhiteList = + | Set + | Set + | Set + | Set + | Set + | Set;