Carousel Pan Gesture API#
Overview#
The carousel exposes pan gesture configuration through a restricted public API built around three pieces: the CarouselPanGesture facade interface, the onConfigurePanGesture prop on CarouselProps, and the usePanGestureProxy hook that mediates between user callbacks and the carousel's internal gesture handlers.
The CarouselPanGesture Facade#
CarouselPanGesture is a hand-written TypeScript interface that exposes a subset of the underlying RNGH PanGesture API. All methods return this, enabling chaining. It covers:
- Configuration:
config(read-only view exposing the web-onlytouchActionoption) - Activation thresholds:
activeOffsetX/Y,failOffsetX/Y,minDistance,minVelocity* - Pointer constraints:
minPointers,maxPointers,averageTouches - Gesture relationships:
simultaneousWithExternalGesture,requireExternalGestureToFail,blocksExternalGesture - Worklet lifecycle hooks:
onBegin,onStart,onUpdate,onChange,onEnd,onFinalize - Miscellaneous:
hitSlop,mouseButton,enableTrackpadTwoFingerGesture,activateAfterLongPress
Deliberately excluded from the facade : enabled, runOnJS, and manualActivation. The JSDoc on the interface explains why:
"Methods return this facade so chaining never exposes ownership-changing RNGH methods such as
enabled,runOnJS, ormanualActivation."
The carousel owns reactive gesture enablement (via scrollEnabled → useUpdateGestureConfig), so exposing enabled() would let callers conflict with it. Callbacks must remain UI-thread worklets; runOnJS would break that invariant.
The facade does expose a read-only config property limited to the web-only touchAction option. This allows mobile-web consumers to configure how the browser's native touch handling interacts with the carousel (for example, setting "pan-y" so a horizontal carousel nested in a vertically scrollable page keeps native vertical scrolling) without casting to the raw PanGesture type. Ownership-changing options such as enabled, runOnJS, or manualActivation remain hidden.
The usePanGestureProxy Hook#
usePanGestureProxy is the internal hook that wires user configuration into the real RNGH gesture while ensuring the carousel's own handlers always run. Its strategy :
- Snapshot the real
onBegin/onStart/onUpdate/onEnd/onFinalizemethods on the gesture object. - Swap in fake methods that capture any user-supplied callbacks without applying them.
- Invoke
onConfigurePanGesture(gesture)— the user configures the gesture against the fake methods, which intercepts any lifecycle callbacks they register. - Restore the real methods, then set up final handlers that call the carousel's internal logic first, followed by the user callbacks.
This guarantees that internal translation handling always runs before any user-provided onUpdate callback — preventing users from intercepting or replacing core gesture processing.
The hook also calls useUpdateGestureConfig to reactively apply the enabled flag (controlled internally via scrollEnabled) after user configuration, keeping ownership of that flag firmly inside the carousel.
Gesture Inversion Is Not Supported#
Inverting swipe direction (e.g., right-to-left swipe scrolls left-to-right) cannot be achieved via onConfigurePanGesture. As confirmed by the maintainer :
"
onConfigurePanGesturecannot safely replace the carousel's internal translation handling."
The carousel processes translationX/translationY internally in ScrollViewGesture.tsx, and the proxy hook ensures that processing always runs first. A user onUpdate callback receives the event but cannot intercept or negate the translation before it is applied. The legacy fixedDirection prop constrained gesture direction but did not invert the gesture-to-scroll mapping. Adding a public inversion option is explicitly not planned for v5, as it would require defined behavior across horizontal/vertical layouts, RTL, loop boundaries, autoplay, and imperative navigation .
Entry Points and Key Files#
| File | Purpose |
|---|---|
src/public-types.ts:150-175 | CarouselPanGesture facade interface definition |
src/public-types.ts:88 | onConfigurePanGesture prop on CarouselProps |
src/hooks/usePanGestureProxy.ts | Proxy hook that mediates user vs. internal gesture handlers |
src/hooks/useUpdateGestureConfig.ts | Reactive enabled flag application after gesture setup |
Common Usage Patterns#
Preventing Gesture Conflicts with Parent ScrollView#
The canonical use case is preventing a horizontal carousel from capturing a parent ScrollView's vertical scroll — use activeOffsetX to set a threshold before the carousel claims the gesture :
<Carousel
onConfigurePanGesture={(gesture) => {
gesture.activeOffsetX([-10, 10]);
}}
/>
Configuring Touch Action for Mobile Web#
On mobile web, a horizontal carousel inside a vertically scrollable page can interfere with native vertical scrolling. Set gesture.config.touchAction = "pan-y" to allow vertical panning while the carousel handles horizontal swipes:
<Carousel
onConfigurePanGesture={(gesture) => {
"worklet";
if (Platform.OS === "web") {
gesture.config.touchAction = "pan-y";
}
}}
/>
The config.touchAction property is web-only and controls how the browser interprets touch events. Common values include "pan-y" (allow vertical panning), "pan-x" (allow horizontal panning), and "none" (disable native touch handling entirely).