Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,42 +35,44 @@ Low-level `TouchEvent` callbacks are tied to raw pointer activity. Drag out of t

## Callbacks

The signatures below use the [`Pan`](/docs/gestures/use-pan-gesture) gesture as an example. Other gestures export analogous types, for example `TapGestureBeginEvent` for the [`onBegin`](#onbegin) callback of the [`Tap`](/docs/gestures/use-tap-gesture) gesture. See [Gesture events](#gesture-events).

### onBegin

```ts
onBegin: (event: GestureEvent<HandlerData>) => void
onBegin: (event: PanGestureBeginEvent) => void
```

Called when a handler begins to recognize gestures. If `onBegin` was called, it is guaranteed that `onFinalize` will be called later.

### onActivate

```ts
onActivate: (event: GestureEvent<HandlerData>) => void
onActivate: (event: PanGestureActiveEvent) => void
```

Called when activation criteria for the handler are met. If `onActivate` was called, it is guaranteed that `onDeactivate` will be called later.

### onUpdate

```ts
onUpdate: (event: GestureEvent<HandlerData>) => void
onUpdate: (event: PanGestureActiveEvent) => void
```

Called each time a pointer tracked by the gesture changes state, typically due to movement, after the gesture has been activated.

### onDeactivate

```ts
onDeactivate: (event: GestureEndEvent<HandlerData>) => void
onDeactivate: (event: PanGestureDeactivateEvent) => void
```

Called when handler stops recognizing gestures, but only if the handler activated. It is called before `onFinalize`. The event object contains a `canceled` property — if the gesture was interrupted, `canceled` is set to `true`. Otherwise it is set to `false`.

### onFinalize

```ts
onFinalize: (event: GestureEndEvent<HandlerData>) => void
onFinalize: (event: PanGestureFinalizeEvent) => void
```

Called when handler stops recognizing gestures. The event object contains a `canceled` property — if the handler failed to activate or was interrupted, `canceled` is set to `true`. If the handler managed to activate and completed successfully, `canceled` is set to `false` and `onFinalize` will be called right after `onDeactivate`.
Expand Down Expand Up @@ -109,22 +111,23 @@ Called when there will be no more information about this pointer. It may be call

## Events

### GestureEvent
### Gesture events

Each gesture exports one event type per callback. For example, the [`Pan`](/docs/gestures/use-pan-gesture) gesture exports `PanGestureBeginEvent`, `PanGestureActiveEvent`, `PanGestureDeactivateEvent` and `PanGestureFinalizeEvent`. Other gestures follow the same pattern, such as `TapGestureBeginEvent` for [`Tap`](/docs/gestures/use-tap-gesture). [`onUpdate`](#onupdate) receives the same event type as [`onActivate`](#onactivate).

All of them share the shape below, shown for `PanGestureBeginEvent`, along with the gesture-specific data listed on each gesture's page:

<CollapsibleCode
label="Show composed types definitions"
expandedLabel="Hide composed types definitions"
lineBounds={[0, 8]}
lineBounds={[0, 5]}
src={`
export type GestureEvent<HandlerData> = {
type PanGestureBeginEvent = {
handlerTag: number;
numberOfPointers: number;
pointerType: PointerType;
} & HandlerData;

export type GestureEndEvent<HandlerData> = {
canceled: boolean;
} & GestureEvent<HandlerData>;
// ...
};

export enum PointerType {
TOUCH,
Expand All @@ -135,11 +138,9 @@ export enum PointerType {
}
`}/>

`GestureEvent` contains properties common to all gestures (`handlerTag`, `numberOfPointers`, `pointerType`) along with gesture-specific data defined in each gesture's documentation.

### GestureEndEvent
[`onBegin`](#onbegin) and [`onFinalize`](#onfinalize) receive only the data available before the gesture activates. [`onActivate`](#onactivate), [`onUpdate`](#onupdate) and [`onDeactivate`](#ondeactivate) additionally carry the data computed while the gesture is active, such as [`translationX`](/docs/gestures/use-pan-gesture#translationx) of [`Pan`](/docs/gestures/use-pan-gesture) or [`scale`](/docs/gestures/use-pinch-gesture#scale) of [`Pinch`](/docs/gestures/use-pinch-gesture).

`GestureEndEvent` extends `GestureEvent` with a `canceled` property. It is used in the [`onDeactivate`](#ondeactivate) and [`onFinalize`](#onfinalize) callbacks. When `canceled` is `true`, the gesture was interrupted or failed to activate. When `false`, the gesture completed successfully.
Events passed to [`onDeactivate`](#ondeactivate) and [`onFinalize`](#onfinalize) also contain a `canceled` property. When `canceled` is `true`, the gesture was interrupted or failed to activate.

### TouchEvent

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CodeBlock from '@theme/CodeBlock';

{
<CodeBlock className="language-ts">
{`onUpdate: (event: ${props.gesture}HandlerData) => void`}
{`onUpdate: (event: ${props.gesture}GestureActiveEvent) => void`}
Comment thread
m-bert marked this conversation as resolved.
Resolved
</CodeBlock>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CodeBlock from '@theme/CodeBlock';

{
<CodeBlock className="language-ts">
{`onBegin: (event: ${props.gesture}HandlerData) => void`}
{`onBegin: (event: ${props.gesture}GestureBeginEvent) => void`}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
Comment thread
m-bert marked this conversation as resolved.
Resolved
</CodeBlock>
}

Expand All @@ -14,7 +14,7 @@ Set the callback that is being called when given gesture handler starts receivin

{
<CodeBlock className="language-ts">
{`onActivate: (event: ${props.gesture}HandlerData) => void`}
{`onActivate: (event: ${props.gesture}GestureActiveEvent) => void`}
</CodeBlock>
}

Expand All @@ -24,7 +24,7 @@ Set the callback that is being called when the gesture is recognized by the hand

{
<CodeBlock className="language-ts">
{`onDeactivate: (event: ${props.gesture}HandlerData & { canceled: boolean }) => void`}
{`onDeactivate: (event: ${props.gesture}GestureDeactivateEvent) => void`}
</CodeBlock>
}

Expand All @@ -34,7 +34,7 @@ Set the callback that is being called when the gesture that was recognized by th

{
<CodeBlock className="language-ts">
{`onFinalize: (event: ${props.gesture}HandlerData & { canceled: boolean }) => void`}
{`onFinalize: (event: ${props.gesture}GestureFinalizeEvent) => void`}
</CodeBlock>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ On iOS this controls [`delaysContentTouches`](https://developer.apple.com/docume

## Callbacks

<BaseGestureCallbacks gesture={"NativeView"}/>
<BaseGestureCallbacks gesture={"Native"}/>

## Event data

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ The `state` and `oldState` properties are no longer available in event objects.

### Event types

The types of events have been unified for all callbacks. Each event falls into one of two categories: [`GestureEvent`](/docs/fundamentals/callbacks-events#gestureevent) for gesture callbacks, or [`GestureTouchEvent`](/docs/fundamentals/callbacks-events#touchevent) for `TouchEvent` callbacks.
The types of events have been unified for all callbacks. Each event falls into one of two categories: a [gesture-specific event type](/docs/fundamentals/callbacks-events#gesture-events) such as `PanGestureBeginEvent` for gesture callbacks, or [`GestureTouchEvent`](/docs/fundamentals/callbacks-events#touchevent) for `TouchEvent` callbacks.

### StateManager

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import type {
HoverGestureConfig,
HoverGestureDeactivateEvent,
HoverGestureFinalizeEvent,
PanGestureActiveEvent,
PanGestureBeginEvent,
PanGestureConfig,
PanGestureDeactivateEvent,
PanGestureEvent,
PanGestureFinalizeEvent,
TapGestureActiveEvent,
TapGestureBeginEvent,
TapGestureConfig,
TapGestureDeactivateEvent,
TapGestureFinalizeEvent,
} from '../src/v3';

type StaticAssert<T extends true> = T;
type Same<A, B> = A extends B ? (B extends A ? true : false) : false;
type EventOf<TConfig, TKey extends keyof TConfig> = Parameters<
NonNullable<Extract<TConfig[TKey], (...args: never[]) => void>>
>[0];

// The exported event aliases must match the callback parameter types exactly,
// both for a gesture with extended data (Pan) and one without (Tap).
type PanBegin = StaticAssert<
Same<PanGestureBeginEvent, EventOf<PanGestureConfig, 'onBegin'>>
>;
type PanActive = StaticAssert<
Same<PanGestureActiveEvent, EventOf<PanGestureConfig, 'onActivate'>>
>;
type PanDeactivate = StaticAssert<
Same<PanGestureDeactivateEvent, EventOf<PanGestureConfig, 'onDeactivate'>>
>;
type PanFinalize = StaticAssert<
Same<PanGestureFinalizeEvent, EventOf<PanGestureConfig, 'onFinalize'>>
>;
type PanDeprecated = StaticAssert<Same<PanGestureEvent, PanGestureBeginEvent>>;

type TapBegin = StaticAssert<
Same<TapGestureBeginEvent, EventOf<TapGestureConfig, 'onBegin'>>
>;
type TapActive = StaticAssert<
Same<TapGestureActiveEvent, EventOf<TapGestureConfig, 'onActivate'>>
>;
type TapDeactivate = StaticAssert<
Same<TapGestureDeactivateEvent, EventOf<TapGestureConfig, 'onDeactivate'>>
>;
type TapFinalize = StaticAssert<
Same<TapGestureFinalizeEvent, EventOf<TapGestureConfig, 'onFinalize'>>
>;

// Deactivate carries the extended data, Finalize only the base data.
type HoverDeactivate = StaticAssert<
Same<HoverGestureDeactivateEvent, EventOf<HoverGestureConfig, 'onDeactivate'>>
>;
type HoverFinalize = StaticAssert<
Same<HoverGestureFinalizeEvent, EventOf<HoverGestureConfig, 'onFinalize'>>
>;
type HoverEndEventsDiffer = StaticAssert<
Same<HoverGestureDeactivateEvent, HoverGestureFinalizeEvent> extends false
? true
: false
>;
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import type {
HoverGestureHandlerEventPayload,
LongPressGestureHandlerEventPayload,
} from '../../handlers/GestureHandlerEventPayload';
import type { HoverGestureEvent, LongPressGestureEvent } from '../../v3';
import type { HoverGestureActiveEvent } from '../../v3/hooks';
import type {
HoverGestureBeginEvent,
HoverGestureFinalizeEvent,
} from '../../v3';
import type {
InnerPressableEvent,
PressableDimensions,
Expand Down Expand Up @@ -52,9 +54,8 @@ const gestureToPressEvent = (
| GestureStateChangeEvent<
HoverGestureHandlerEventPayload | LongPressGestureHandlerEventPayload
>
| HoverGestureEvent
| HoverGestureActiveEvent
| LongPressGestureEvent,
| HoverGestureBeginEvent
| HoverGestureFinalizeEvent,
timestamp: number,
targetId: number
): InnerPressableEvent => ({
Expand Down Expand Up @@ -84,9 +85,8 @@ const gestureToPressableEvent = (
| GestureStateChangeEvent<
HoverGestureHandlerEventPayload | LongPressGestureHandlerEventPayload
>
| HoverGestureEvent
| HoverGestureActiveEvent
| LongPressGestureEvent
| HoverGestureBeginEvent
| HoverGestureFinalizeEvent
): PressableEvent => {
const timestamp = Date.now();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
InterceptingGestureDetector,
VirtualGestureDetector,
} from '../v3/detectors';
import type { PanGestureActiveEvent } from '../v3/hooks/gestures';
import type { PanGestureDeactivateEvent } from '../v3/hooks/gestures';
import { usePanGesture, useTapGesture } from '../v3/hooks/gestures';
import type { WithSharedValue } from '../v3/types';

Expand Down Expand Up @@ -454,7 +454,7 @@ const DrawerLayout = function DrawerLayout(
);

const handleRelease = useCallback(
(event: PanGestureActiveEvent & { canceled: boolean }) => {
(event: PanGestureDeactivateEvent) => {
'worklet';
if (event.canceled) {
// Settle the drawer where it rested before the gesture.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import {

import { tagMessage } from '../../utils';
import { GestureDetector } from '../../v3/detectors';
import type { PanGestureActiveEvent } from '../../v3/hooks/gestures';
import type {
PanGestureActiveEvent,
PanGestureDeactivateEvent,
} from '../../v3/hooks/gestures';
import { usePanGesture, useTapGesture } from '../../v3/hooks/gestures';
import {
maybeUnpackValue,
Expand Down Expand Up @@ -507,7 +510,7 @@ const Swipeable = (props: SwipeableProps) => {
);

const handleRelease = useCallback(
(event: PanGestureActiveEvent & { canceled: boolean }) => {
(event: PanGestureDeactivateEvent) => {
'worklet';
if (event.canceled) {
// Restore the row to where it rested before the gesture.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import { Animated, Platform, StyleSheet } from 'react-native';
import GestureHandlerButton from '../../components/GestureHandlerButton';
import { getTVProps } from '../../components/utils';
import createNativeWrapper from '../createNativeWrapper';
import type { NativeHandlerData } from '../hooks/gestures/native/NativeTypes';
import type { GestureEndEvent, GestureEvent } from '../types';
import type {
NativeGestureActiveEvent,
NativeGestureBeginEvent,
NativeGestureDeactivateEvent,
NativeGestureFinalizeEvent,
} from '../hooks/gestures';
import type {
BaseButtonProps,
BorderlessButtonProps,
RawButtonProps,
RectButtonProps,
} from './GestureButtonsProps';

type CallbackEventType = GestureEvent<NativeHandlerData>;
type EndCallbackEventType = GestureEndEvent<NativeHandlerData>;

type RawButtonInnerProps = RawButtonProps & {
needsOffscreenAlphaCompositing?: boolean | undefined;
};
Expand Down Expand Up @@ -54,7 +55,7 @@ export const BaseButton = (props: BaseButtonProps) => {
onLongPress?.();
};

const onBegin = (e: CallbackEventType) => {
const onBegin = (e: NativeGestureBeginEvent) => {
if (!e.pointerInside) {
return;
}
Expand All @@ -69,7 +70,7 @@ export const BaseButton = (props: BaseButtonProps) => {
props.onBegin?.(e);
};

const onActivate = (e: CallbackEventType) => {
const onActivate = (e: NativeGestureActiveEvent) => {
if (!e.pointerInside && longPressTimeout.current !== undefined) {
clearTimeout(longPressTimeout.current);
longPressTimeout.current = undefined;
Expand All @@ -78,11 +79,11 @@ export const BaseButton = (props: BaseButtonProps) => {
props.onActivate?.(e);
};

const onDeactivate = (e: EndCallbackEventType) => {
const onDeactivate = (e: NativeGestureDeactivateEvent) => {
props.onDeactivate?.(e);
};

const onFinalize = (e: EndCallbackEventType) => {
const onFinalize = (e: NativeGestureFinalizeEvent) => {
onActiveStateChange?.(false);

if (!e.canceled && !longPressDetected.current) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@ import type {
ButtonEvent,
ButtonProps,
} from '../../../components/GestureHandlerButton';
import type { NativeHandlerData } from '../../hooks/gestures/native/NativeTypes';
import type { GestureEndEvent, GestureEvent } from '../../types';
import type { BaseButtonProps, RawButtonProps } from '../GestureButtonsProps';

export type CallbackEventType = GestureEvent<NativeHandlerData>;
export type EndCallbackEventType = GestureEndEvent<NativeHandlerData>;

type PressableAndroidRippleConfig = {
[K in keyof RNPressableAndroidRippleConfig]?: Exclude<
RNPressableAndroidRippleConfig[K],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
BaseDiscreteGestureConfig,
ExcludeInternalConfigProps,
GestureEndEvent,
GestureEvent,
SingleGesture,
WithSharedValue,
Expand Down Expand Up @@ -51,8 +52,12 @@ export type FlingGestureInternalConfig = BaseDiscreteGestureConfig<
export type FlingGestureConfig =
ExcludeInternalConfigProps<FlingGestureInternalConfig>;

export type FlingGestureEvent = GestureEvent<FlingHandlerData>;
export type FlingGestureActiveEvent = FlingGestureEvent;
export type FlingGestureBeginEvent = GestureEvent<FlingHandlerData>;
export type FlingGestureActiveEvent = FlingGestureBeginEvent;
export type FlingGestureDeactivateEvent = GestureEndEvent<FlingHandlerData>;
export type FlingGestureFinalizeEvent = GestureEndEvent<FlingHandlerData>;
/** @deprecated Use `FlingGestureBeginEvent` instead. */
export type FlingGestureEvent = FlingGestureBeginEvent;

export type FlingGesture = SingleGesture<
FlingGestureProperties,
Expand Down
Loading
Loading