react-native-gesture-handler
Version:
Declarative API exposing native platform touch and gesture system to React Native
283 lines (252 loc) • 9.11 kB
text/typescript
import type { PanGestureHandlerEventPayload } from './GestureHandlerEventPayload';
import createHandler from './createHandler';
import {
BaseGestureHandlerProps,
baseGestureHandlerProps,
} from './gestureHandlerCommon';
export const panGestureHandlerProps = [
'activeOffsetY',
'activeOffsetX',
'failOffsetY',
'failOffsetX',
'minDist',
'minVelocity',
'minVelocityX',
'minVelocityY',
'minPointers',
'maxPointers',
'avgTouches',
'enableTrackpadTwoFingerGesture',
'activateAfterLongPress',
] as const;
export const panGestureHandlerCustomNativeProps = [
'activeOffsetYStart',
'activeOffsetYEnd',
'activeOffsetXStart',
'activeOffsetXEnd',
'failOffsetYStart',
'failOffsetYEnd',
'failOffsetXStart',
'failOffsetXEnd',
] as const;
interface CommonPanProperties {
/**
* Minimum distance the finger (or multiple finger) need to travel before the
* handler activates. Expressed in points.
*/
minDist?: 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 interface PanGestureConfig extends CommonPanProperties {
activeOffsetYStart?: number;
activeOffsetYEnd?: number;
activeOffsetXStart?: number;
activeOffsetXEnd?: number;
failOffsetYStart?: number;
failOffsetYEnd?: number;
failOffsetXStart?: number;
failOffsetXEnd?: number;
}
/**
* @deprecated PanGestureHandler will be removed in the future version of Gesture Handler. Use `Gesture.Pan()` instead.
*/
export interface PanGestureHandlerProps
extends BaseGestureHandlerProps<PanGestureHandlerEventPayload>,
CommonPanProperties {
/**
* 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
| [activeOffsetYStart: number, activeOffsetYEnd: 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
| [activeOffsetXStart: number, activeOffsetXEnd: 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 | [failOffsetYStart: number, failOffsetYEnd: 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 | [failOffsetXStart: number, failOffsetXEnd: number];
}
export const panHandlerName = 'PanGestureHandler';
/**
* @deprecated PanGestureHandler will be removed in the future version of Gesture Handler. Use `Gesture.Pan()` instead.
*/
export type PanGestureHandler = typeof PanGestureHandler;
/**
* @deprecated PanGestureHandler will be removed in the future version of Gesture Handler. Use `Gesture.Pan()` instead.
*/
// eslint-disable-next-line @typescript-eslint/no-redeclare -- backward compatibility; see description on the top of gestureHandlerCommon.ts file
export const PanGestureHandler = createHandler<
PanGestureHandlerProps,
PanGestureHandlerEventPayload
>({
name: panHandlerName,
allowedProps: [
...baseGestureHandlerProps,
...panGestureHandlerProps,
] as const,
config: {},
transformProps: managePanProps,
customNativeProps: panGestureHandlerCustomNativeProps,
});
function validatePanGestureHandlerProps(props: PanGestureHandlerProps) {
if (
Array.isArray(props.activeOffsetX) &&
(props.activeOffsetX[0] > 0 || props.activeOffsetX[1] < 0)
) {
throw new Error(
`First element of activeOffsetX should be negative, a the second one should be positive`
);
}
if (
Array.isArray(props.activeOffsetY) &&
(props.activeOffsetY[0] > 0 || props.activeOffsetY[1] < 0)
) {
throw new Error(
`First element of activeOffsetY should be negative, a the second one should be positive`
);
}
if (
Array.isArray(props.failOffsetX) &&
(props.failOffsetX[0] > 0 || props.failOffsetX[1] < 0)
) {
throw new Error(
`First element of failOffsetX should be negative, a the second one should be positive`
);
}
if (
Array.isArray(props.failOffsetY) &&
(props.failOffsetY[0] > 0 || props.failOffsetY[1] < 0)
) {
throw new Error(
`First element of failOffsetY should be negative, a the second one should be positive`
);
}
if (props.minDist && (props.failOffsetX || props.failOffsetY)) {
throw new Error(
`It is not supported to use minDist with failOffsetX or failOffsetY, use activeOffsetX and activeOffsetY instead`
);
}
if (props.minDist && (props.activeOffsetX || props.activeOffsetY)) {
throw new Error(
`It is not supported to use minDist with activeOffsetX or activeOffsetY`
);
}
}
function transformPanGestureHandlerProps(props: PanGestureHandlerProps) {
type InternalPanGHKeys =
| 'activeOffsetXStart'
| 'activeOffsetXEnd'
| 'failOffsetXStart'
| 'failOffsetXEnd'
| 'activeOffsetYStart'
| 'activeOffsetYEnd'
| 'failOffsetYStart'
| 'failOffsetYEnd';
type PanGestureHandlerInternalProps = PanGestureHandlerProps &
Partial<Record<InternalPanGHKeys, number>>;
const res: PanGestureHandlerInternalProps = { ...props };
if (props.activeOffsetX !== undefined) {
delete res.activeOffsetX;
if (Array.isArray(props.activeOffsetX)) {
res.activeOffsetXStart = props.activeOffsetX[0];
res.activeOffsetXEnd = props.activeOffsetX[1];
} else if (props.activeOffsetX < 0) {
res.activeOffsetXStart = props.activeOffsetX;
} else {
res.activeOffsetXEnd = props.activeOffsetX;
}
}
if (props.activeOffsetY !== undefined) {
delete res.activeOffsetY;
if (Array.isArray(props.activeOffsetY)) {
res.activeOffsetYStart = props.activeOffsetY[0];
res.activeOffsetYEnd = props.activeOffsetY[1];
} else if (props.activeOffsetY < 0) {
res.activeOffsetYStart = props.activeOffsetY;
} else {
res.activeOffsetYEnd = props.activeOffsetY;
}
}
if (props.failOffsetX !== undefined) {
delete res.failOffsetX;
if (Array.isArray(props.failOffsetX)) {
res.failOffsetXStart = props.failOffsetX[0];
res.failOffsetXEnd = props.failOffsetX[1];
} else if (props.failOffsetX < 0) {
res.failOffsetXStart = props.failOffsetX;
} else {
res.failOffsetXEnd = props.failOffsetX;
}
}
if (props.failOffsetY !== undefined) {
delete res.failOffsetY;
if (Array.isArray(props.failOffsetY)) {
res.failOffsetYStart = props.failOffsetY[0];
res.failOffsetYEnd = props.failOffsetY[1];
} else if (props.failOffsetY < 0) {
res.failOffsetYStart = props.failOffsetY;
} else {
res.failOffsetYEnd = props.failOffsetY;
}
}
return res;
}
export function managePanProps(props: PanGestureHandlerProps) {
if (__DEV__) {
validatePanGestureHandlerProps(props);
}
return transformPanGestureHandlerProps(props);
}