@rootnative/inertia-gestures 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@rootnative/inertia-gestures` are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Pre-`1.0`, breaking changes may land in minor versions and are called out under their release.
4
+
5
+ This package ships in lockstep with `@rootnative/inertia` — version numbers track the core release that introduced or last touched the adapter.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.0.0-alpha.0]
10
+
11
+ Initial alpha publish alongside `@rootnative/inertia@0.0.0-alpha.0`. Optional adapter package wrapping `react-native-gesture-handler`; the core library has no required gesture-handler dependency.
12
+
13
+ ### Added
14
+
15
+ - `useDrag({ onRelease })` — release worklet returns per-axis Inertia transitions (snap-to-tick spring, decay with bounds, etc.). Velocity stays on the UI thread; no JS round-trip.
16
+ - `useSwipe`, `usePan` hooks composable with any `Motion.*` primitive via `<GestureDetector>`.
17
+
18
+ [unreleased]: https://github.com/rootnative/inertia/compare/v0.0.0-alpha.0...HEAD
19
+ [0.0.0-alpha.0]: https://github.com/rootnative/inertia/releases/tag/v0.0.0-alpha.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RootNative
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @rootnative/inertia-gestures
2
+
3
+ [![npm](https://img.shields.io/npm/v/@rootnative/inertia-gestures.svg)](https://www.npmjs.com/package/@rootnative/inertia-gestures)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
5
+
6
+ Drag / pan / swipe hooks for [`@rootnative/inertia`](../core), built on [`react-native-gesture-handler`](https://docs.swmansion.com/react-native-gesture-handler/). Optional sibling package — install only when you need richer-than-`pressable` gestures. The core library has no required `gesture-handler` dependency.
7
+
8
+ The hooks compose with any `Motion.*` primitive via a `<GestureDetector>` and a single `style` slot — they don't replace the core `gesture` prop, they extend what's reachable beside it.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ pnpm add @rootnative/inertia-gestures react-native-gesture-handler
14
+ ```
15
+
16
+ Then follow the [`react-native-gesture-handler` install guide](https://docs.swmansion.com/react-native-gesture-handler/docs/installation) — it needs `<GestureHandlerRootView>` near the root of your app.
17
+
18
+ **Peer dependencies:** `@rootnative/inertia` (workspace or installed), `react >=19.0.0`, `react-native >=0.81.0`, `react-native-reanimated >=4.0.0`, `react-native-gesture-handler >=2.0.0`.
19
+
20
+ ## What ships
21
+
22
+ - **`useDrag`** — one- or two-axis drag with optional bounds and rubber-band overshoot. Accepts an `onRelease` worklet that returns per-axis Inertia release transitions (snap-to-tick spring, decay with bounds, etc.). The release velocity stays on the UI thread — no JS round-trip.
23
+ - **`usePan`** — camera-style pan with momentum on release.
24
+ - **`useSwipe`** — directional commit-or-snap-back (distance + velocity thresholds).
25
+
26
+ ## Usage
27
+
28
+ ```tsx
29
+ import { GestureDetector } from 'react-native-gesture-handler'
30
+ import { Motion } from '@rootnative/inertia'
31
+ import { useDrag } from '@rootnative/inertia-gestures'
32
+
33
+ function DraggableBox() {
34
+ const drag = useDrag({
35
+ axis: 'both',
36
+ bounds: { left: -120, right: 120, top: -120, bottom: 120 },
37
+ })
38
+
39
+ return (
40
+ <GestureDetector gesture={drag.gesture}>
41
+ <Motion.View style={drag.style} />
42
+ </GestureDetector>
43
+ )
44
+ }
45
+ ```
46
+
47
+ ## Documentation
48
+
49
+ - Full docs: [https://rootnative.github.io/inertia/docs/gestures-adapter](https://rootnative.github.io/inertia/docs/gestures-adapter)
50
+ - Core library: [`@rootnative/inertia`](../core)
51
+
52
+ ## License
53
+
54
+ [MIT](./LICENSE) © RootNative
@@ -0,0 +1,250 @@
1
+ import { PanGesture } from 'react-native-gesture-handler';
2
+ import { useAnimatedStyle, SharedValue } from 'react-native-reanimated';
3
+ import { SpringTransition, TimingTransition, DecayTransition, NoAnimationTransition } from '@rootnative/inertia';
4
+
5
+ /**
6
+ * Public types for `@rootnative/inertia-gestures`.
7
+ */
8
+
9
+ /**
10
+ * Bounds the dragged value can reach. Each side is optional — omit to leave
11
+ * that direction unbounded. Coordinates are in the same space the drag
12
+ * publishes (pixels of translation from the dragged element's resting
13
+ * position), so `{ left: -100, right: 100 }` allows ±100 px of horizontal
14
+ * travel.
15
+ */
16
+ interface DragConstraints {
17
+ left?: number;
18
+ right?: number;
19
+ top?: number;
20
+ bottom?: number;
21
+ }
22
+ /**
23
+ * UI-thread payload delivered to `onRelease` when the drag finishes. `x` and
24
+ * `y` are the final translations the SVs are sitting at; `velocity.x` /
25
+ * `velocity.y` are the release velocities in px/sec.
26
+ */
27
+ interface ReleaseInfo {
28
+ x: number;
29
+ y: number;
30
+ velocity: {
31
+ x: number;
32
+ y: number;
33
+ };
34
+ }
35
+ /**
36
+ * Per-axis release transition. Spring / timing / no-animation animate to a
37
+ * target value (`to`); decay decelerates from the current position via its
38
+ * own physics and has no `to`. Pass the release velocity from `ReleaseInfo`
39
+ * into the transition's own `velocity` field for natural continuation.
40
+ */
41
+ type ReleaseTransition = (SpringTransition & {
42
+ to: number;
43
+ }) | (TimingTransition & {
44
+ to: number;
45
+ }) | DecayTransition | (NoAnimationTransition & {
46
+ to: number;
47
+ });
48
+ /**
49
+ * Per-axis release transitions returned by `onRelease`. Omit an axis to leave
50
+ * its SV where it landed (no release animation on that axis).
51
+ */
52
+ interface ReleaseResult {
53
+ x?: ReleaseTransition;
54
+ y?: ReleaseTransition;
55
+ }
56
+ /**
57
+ * Configuration for `useDrag`. All fields are optional; the defaults give an
58
+ * unconstrained two-axis drag with no elasticity.
59
+ */
60
+ interface DragOptions {
61
+ /**
62
+ * Restrict the drag to one axis. Defaults to `'both'`. When `'x'` is set
63
+ * the y-axis shared value never updates (and vice versa); the gesture
64
+ * still tracks both for velocity reporting on `onDragEnd`.
65
+ */
66
+ axis?: 'x' | 'y' | 'both';
67
+ /**
68
+ * Travel bounds. Out-of-bounds values clamp to the limit unless `elastic`
69
+ * is non-zero, in which case overshoot is dampened (rubber-band feel).
70
+ */
71
+ constraints?: DragConstraints;
72
+ /**
73
+ * Rubber-band coefficient applied to overshoot past `constraints`. `0`
74
+ * (default) hard-clamps; `1` is fully elastic (no resistance). Typical
75
+ * Framer-Motion-style feel sits around `0.2`–`0.4`.
76
+ */
77
+ elastic?: number;
78
+ /**
79
+ * Fired on the JS thread when the drag begins.
80
+ */
81
+ onDragStart?: () => void;
82
+ /**
83
+ * Fired on the JS thread when the drag finishes (release or cancel). The
84
+ * payload is the final translation and the release velocity in px/sec.
85
+ */
86
+ onDragEnd?: (info: ReleaseInfo) => void;
87
+ /**
88
+ * UI-thread callback fired on release. Return per-axis release transitions
89
+ * to animate the SVs to a settled position via Inertia's transition
90
+ * resolver — spring snap-to-tick, decay with bounds, timing settle, etc.
91
+ * Omit an axis (or return nothing) to leave that SV where it landed.
92
+ *
93
+ * This callback runs as a worklet so the release velocity stays on the UI
94
+ * thread. Author it with the `'worklet'` directive at the top of the body.
95
+ *
96
+ * Composes with `onDragEnd`: both fire on release. `onRelease` controls SV
97
+ * animation on the UI thread; `onDragEnd` is for JS-thread side effects
98
+ * (analytics, state updates).
99
+ */
100
+ onRelease?: (info: ReleaseInfo) => ReleaseResult | void;
101
+ }
102
+
103
+ interface UseDragResult {
104
+ /** Pan gesture to pass to a `<GestureDetector>`. */
105
+ gesture: PanGesture;
106
+ /**
107
+ * Animated style fragment (a single `transform` entry) to stack onto the
108
+ * dragged Motion primitive's `style` prop. Stable across renders.
109
+ */
110
+ animatedStyle: ReturnType<typeof useAnimatedStyle>;
111
+ /** Current x translation in pixels. UI-thread shared value. */
112
+ dragX: SharedValue<number>;
113
+ /** Current y translation in pixels. UI-thread shared value. */
114
+ dragY: SharedValue<number>;
115
+ /** True while the gesture is active. */
116
+ isDragging: SharedValue<boolean>;
117
+ }
118
+ /**
119
+ * Drag a Motion primitive with `react-native-gesture-handler`'s pan gesture.
120
+ *
121
+ * The hook owns a pair of shared values (`dragX`, `dragY`) and a `Pan`
122
+ * gesture that updates them on the UI thread. The returned `animatedStyle`
123
+ * is a self-contained `transform: [{ translateX }, { translateY }]` fragment;
124
+ * stack it onto the dragged component without colliding with Motion's own
125
+ * `animate` transforms.
126
+ *
127
+ * Usage:
128
+ * ```tsx
129
+ * const drag = useDrag({ axis: 'x', constraints: { left: -100, right: 100 } })
130
+ * return (
131
+ * <GestureDetector gesture={drag.gesture}>
132
+ * <Motion.View style={drag.animatedStyle} />
133
+ * </GestureDetector>
134
+ * )
135
+ * ```
136
+ */
137
+ declare function useDrag(options?: DragOptions): UseDragResult;
138
+
139
+ type SwipeDirection = 'left' | 'right' | 'up' | 'down';
140
+ interface SwipeOptions {
141
+ /**
142
+ * Allowed swipe directions. Defaults to all four. The gesture only commits
143
+ * for directions in this list — a horizontal swipe with `directions:
144
+ * ['up', 'down']` will not fire `onSwipe`.
145
+ */
146
+ directions?: SwipeDirection[];
147
+ /**
148
+ * Pixel distance threshold past which a release commits the swipe. Defaults
149
+ * to `80`.
150
+ */
151
+ distanceThreshold?: number;
152
+ /**
153
+ * Velocity threshold (px/sec) past which a release commits the swipe even
154
+ * before the distance threshold is reached — flick-style gestures. Defaults
155
+ * to `800`.
156
+ */
157
+ velocityThreshold?: number;
158
+ /**
159
+ * Fired on the JS thread when the gesture commits in an allowed direction.
160
+ */
161
+ onSwipe?: (direction: SwipeDirection, info: {
162
+ distance: number;
163
+ velocity: number;
164
+ }) => void;
165
+ }
166
+ interface UseSwipeResult {
167
+ /** Pan gesture to pass to a `<GestureDetector>`. */
168
+ gesture: PanGesture;
169
+ /**
170
+ * Animated style fragment exposing live translation while the gesture is
171
+ * active. Snaps back to `{ 0, 0 }` after release (whether or not the swipe
172
+ * committed) via a default spring.
173
+ */
174
+ animatedStyle: ReturnType<typeof useAnimatedStyle>;
175
+ /** Live x translation. */
176
+ swipeX: SharedValue<number>;
177
+ /** Live y translation. */
178
+ swipeY: SharedValue<number>;
179
+ /** True while the user is actively swiping. */
180
+ isActive: SharedValue<boolean>;
181
+ }
182
+ /**
183
+ * Directional commit-or-snap-back gesture. Tracks live translation while the
184
+ * user drags and fires `onSwipe(direction)` on release if either the distance
185
+ * or velocity threshold is exceeded in an allowed direction. The position
186
+ * shared values always animate back to zero — the consumer is responsible
187
+ * for whatever side effect the commit drives (delete a row, dismiss a sheet,
188
+ * etc.).
189
+ *
190
+ * Usage:
191
+ * ```tsx
192
+ * const swipe = useSwipe({
193
+ * directions: ['left'],
194
+ * onSwipe: (dir) => deleteRow(),
195
+ * })
196
+ * return (
197
+ * <GestureDetector gesture={swipe.gesture}>
198
+ * <Motion.View style={swipe.animatedStyle}>...</Motion.View>
199
+ * </GestureDetector>
200
+ * )
201
+ * ```
202
+ */
203
+ declare function useSwipe(options?: SwipeOptions): UseSwipeResult;
204
+
205
+ interface PanOptions {
206
+ /**
207
+ * Translation bounds. Each side is optional; out-of-bounds motion during
208
+ * the active gesture and during the post-release decay is hard-clamped
209
+ * (Reanimated's `withDecay` `clamp` param). Decay-style overshoot is not
210
+ * supported here — for rubber-banded bounds, prefer `useDrag` with
211
+ * `elastic`.
212
+ */
213
+ constraints?: DragConstraints;
214
+ /**
215
+ * Deceleration applied to the post-release momentum. Higher = momentum
216
+ * dies faster. Reanimated default is `0.998`; lower values feel more
217
+ * "slippy". Range: roughly `0.99` (slow) to `0.999` (long glide).
218
+ */
219
+ deceleration?: number;
220
+ /**
221
+ * Disable the post-release momentum entirely. Defaults to `false` — pan
222
+ * coasts after release. Set to `true` for a hard stop on release (drag-like
223
+ * behavior).
224
+ */
225
+ disableMomentum?: boolean;
226
+ }
227
+ interface UsePanResult {
228
+ /** Pan gesture to pass to a `<GestureDetector>`. */
229
+ gesture: PanGesture;
230
+ /** Stable animated `transform` style. */
231
+ animatedStyle: ReturnType<typeof useAnimatedStyle>;
232
+ /** Live x translation, persistent across gestures. */
233
+ panX: SharedValue<number>;
234
+ /** Live y translation, persistent across gestures. */
235
+ panY: SharedValue<number>;
236
+ /** True while the user is actively panning. Decay phase reads `false`. */
237
+ isPanning: SharedValue<boolean>;
238
+ }
239
+ /**
240
+ * Camera-pan-style drag with momentum on release. Translation persists
241
+ * across separate pan gestures (the next pan starts from the current
242
+ * position, not zero), and on release the translation continues to glide
243
+ * via Reanimated's `withDecay` until friction stops it.
244
+ *
245
+ * Use for map / zoom-canvas / large-image navigation. For dragging an
246
+ * element to a position with no momentum, use `useDrag` instead.
247
+ */
248
+ declare function usePan(options?: PanOptions): UsePanResult;
249
+
250
+ export { type DragConstraints, type DragOptions, type PanOptions, type ReleaseInfo, type ReleaseResult, type ReleaseTransition, type SwipeDirection, type SwipeOptions, type UseDragResult, type UsePanResult, type UseSwipeResult, useDrag, usePan, useSwipe };
@@ -0,0 +1,250 @@
1
+ import { PanGesture } from 'react-native-gesture-handler';
2
+ import { useAnimatedStyle, SharedValue } from 'react-native-reanimated';
3
+ import { SpringTransition, TimingTransition, DecayTransition, NoAnimationTransition } from '@rootnative/inertia';
4
+
5
+ /**
6
+ * Public types for `@rootnative/inertia-gestures`.
7
+ */
8
+
9
+ /**
10
+ * Bounds the dragged value can reach. Each side is optional — omit to leave
11
+ * that direction unbounded. Coordinates are in the same space the drag
12
+ * publishes (pixels of translation from the dragged element's resting
13
+ * position), so `{ left: -100, right: 100 }` allows ±100 px of horizontal
14
+ * travel.
15
+ */
16
+ interface DragConstraints {
17
+ left?: number;
18
+ right?: number;
19
+ top?: number;
20
+ bottom?: number;
21
+ }
22
+ /**
23
+ * UI-thread payload delivered to `onRelease` when the drag finishes. `x` and
24
+ * `y` are the final translations the SVs are sitting at; `velocity.x` /
25
+ * `velocity.y` are the release velocities in px/sec.
26
+ */
27
+ interface ReleaseInfo {
28
+ x: number;
29
+ y: number;
30
+ velocity: {
31
+ x: number;
32
+ y: number;
33
+ };
34
+ }
35
+ /**
36
+ * Per-axis release transition. Spring / timing / no-animation animate to a
37
+ * target value (`to`); decay decelerates from the current position via its
38
+ * own physics and has no `to`. Pass the release velocity from `ReleaseInfo`
39
+ * into the transition's own `velocity` field for natural continuation.
40
+ */
41
+ type ReleaseTransition = (SpringTransition & {
42
+ to: number;
43
+ }) | (TimingTransition & {
44
+ to: number;
45
+ }) | DecayTransition | (NoAnimationTransition & {
46
+ to: number;
47
+ });
48
+ /**
49
+ * Per-axis release transitions returned by `onRelease`. Omit an axis to leave
50
+ * its SV where it landed (no release animation on that axis).
51
+ */
52
+ interface ReleaseResult {
53
+ x?: ReleaseTransition;
54
+ y?: ReleaseTransition;
55
+ }
56
+ /**
57
+ * Configuration for `useDrag`. All fields are optional; the defaults give an
58
+ * unconstrained two-axis drag with no elasticity.
59
+ */
60
+ interface DragOptions {
61
+ /**
62
+ * Restrict the drag to one axis. Defaults to `'both'`. When `'x'` is set
63
+ * the y-axis shared value never updates (and vice versa); the gesture
64
+ * still tracks both for velocity reporting on `onDragEnd`.
65
+ */
66
+ axis?: 'x' | 'y' | 'both';
67
+ /**
68
+ * Travel bounds. Out-of-bounds values clamp to the limit unless `elastic`
69
+ * is non-zero, in which case overshoot is dampened (rubber-band feel).
70
+ */
71
+ constraints?: DragConstraints;
72
+ /**
73
+ * Rubber-band coefficient applied to overshoot past `constraints`. `0`
74
+ * (default) hard-clamps; `1` is fully elastic (no resistance). Typical
75
+ * Framer-Motion-style feel sits around `0.2`–`0.4`.
76
+ */
77
+ elastic?: number;
78
+ /**
79
+ * Fired on the JS thread when the drag begins.
80
+ */
81
+ onDragStart?: () => void;
82
+ /**
83
+ * Fired on the JS thread when the drag finishes (release or cancel). The
84
+ * payload is the final translation and the release velocity in px/sec.
85
+ */
86
+ onDragEnd?: (info: ReleaseInfo) => void;
87
+ /**
88
+ * UI-thread callback fired on release. Return per-axis release transitions
89
+ * to animate the SVs to a settled position via Inertia's transition
90
+ * resolver — spring snap-to-tick, decay with bounds, timing settle, etc.
91
+ * Omit an axis (or return nothing) to leave that SV where it landed.
92
+ *
93
+ * This callback runs as a worklet so the release velocity stays on the UI
94
+ * thread. Author it with the `'worklet'` directive at the top of the body.
95
+ *
96
+ * Composes with `onDragEnd`: both fire on release. `onRelease` controls SV
97
+ * animation on the UI thread; `onDragEnd` is for JS-thread side effects
98
+ * (analytics, state updates).
99
+ */
100
+ onRelease?: (info: ReleaseInfo) => ReleaseResult | void;
101
+ }
102
+
103
+ interface UseDragResult {
104
+ /** Pan gesture to pass to a `<GestureDetector>`. */
105
+ gesture: PanGesture;
106
+ /**
107
+ * Animated style fragment (a single `transform` entry) to stack onto the
108
+ * dragged Motion primitive's `style` prop. Stable across renders.
109
+ */
110
+ animatedStyle: ReturnType<typeof useAnimatedStyle>;
111
+ /** Current x translation in pixels. UI-thread shared value. */
112
+ dragX: SharedValue<number>;
113
+ /** Current y translation in pixels. UI-thread shared value. */
114
+ dragY: SharedValue<number>;
115
+ /** True while the gesture is active. */
116
+ isDragging: SharedValue<boolean>;
117
+ }
118
+ /**
119
+ * Drag a Motion primitive with `react-native-gesture-handler`'s pan gesture.
120
+ *
121
+ * The hook owns a pair of shared values (`dragX`, `dragY`) and a `Pan`
122
+ * gesture that updates them on the UI thread. The returned `animatedStyle`
123
+ * is a self-contained `transform: [{ translateX }, { translateY }]` fragment;
124
+ * stack it onto the dragged component without colliding with Motion's own
125
+ * `animate` transforms.
126
+ *
127
+ * Usage:
128
+ * ```tsx
129
+ * const drag = useDrag({ axis: 'x', constraints: { left: -100, right: 100 } })
130
+ * return (
131
+ * <GestureDetector gesture={drag.gesture}>
132
+ * <Motion.View style={drag.animatedStyle} />
133
+ * </GestureDetector>
134
+ * )
135
+ * ```
136
+ */
137
+ declare function useDrag(options?: DragOptions): UseDragResult;
138
+
139
+ type SwipeDirection = 'left' | 'right' | 'up' | 'down';
140
+ interface SwipeOptions {
141
+ /**
142
+ * Allowed swipe directions. Defaults to all four. The gesture only commits
143
+ * for directions in this list — a horizontal swipe with `directions:
144
+ * ['up', 'down']` will not fire `onSwipe`.
145
+ */
146
+ directions?: SwipeDirection[];
147
+ /**
148
+ * Pixel distance threshold past which a release commits the swipe. Defaults
149
+ * to `80`.
150
+ */
151
+ distanceThreshold?: number;
152
+ /**
153
+ * Velocity threshold (px/sec) past which a release commits the swipe even
154
+ * before the distance threshold is reached — flick-style gestures. Defaults
155
+ * to `800`.
156
+ */
157
+ velocityThreshold?: number;
158
+ /**
159
+ * Fired on the JS thread when the gesture commits in an allowed direction.
160
+ */
161
+ onSwipe?: (direction: SwipeDirection, info: {
162
+ distance: number;
163
+ velocity: number;
164
+ }) => void;
165
+ }
166
+ interface UseSwipeResult {
167
+ /** Pan gesture to pass to a `<GestureDetector>`. */
168
+ gesture: PanGesture;
169
+ /**
170
+ * Animated style fragment exposing live translation while the gesture is
171
+ * active. Snaps back to `{ 0, 0 }` after release (whether or not the swipe
172
+ * committed) via a default spring.
173
+ */
174
+ animatedStyle: ReturnType<typeof useAnimatedStyle>;
175
+ /** Live x translation. */
176
+ swipeX: SharedValue<number>;
177
+ /** Live y translation. */
178
+ swipeY: SharedValue<number>;
179
+ /** True while the user is actively swiping. */
180
+ isActive: SharedValue<boolean>;
181
+ }
182
+ /**
183
+ * Directional commit-or-snap-back gesture. Tracks live translation while the
184
+ * user drags and fires `onSwipe(direction)` on release if either the distance
185
+ * or velocity threshold is exceeded in an allowed direction. The position
186
+ * shared values always animate back to zero — the consumer is responsible
187
+ * for whatever side effect the commit drives (delete a row, dismiss a sheet,
188
+ * etc.).
189
+ *
190
+ * Usage:
191
+ * ```tsx
192
+ * const swipe = useSwipe({
193
+ * directions: ['left'],
194
+ * onSwipe: (dir) => deleteRow(),
195
+ * })
196
+ * return (
197
+ * <GestureDetector gesture={swipe.gesture}>
198
+ * <Motion.View style={swipe.animatedStyle}>...</Motion.View>
199
+ * </GestureDetector>
200
+ * )
201
+ * ```
202
+ */
203
+ declare function useSwipe(options?: SwipeOptions): UseSwipeResult;
204
+
205
+ interface PanOptions {
206
+ /**
207
+ * Translation bounds. Each side is optional; out-of-bounds motion during
208
+ * the active gesture and during the post-release decay is hard-clamped
209
+ * (Reanimated's `withDecay` `clamp` param). Decay-style overshoot is not
210
+ * supported here — for rubber-banded bounds, prefer `useDrag` with
211
+ * `elastic`.
212
+ */
213
+ constraints?: DragConstraints;
214
+ /**
215
+ * Deceleration applied to the post-release momentum. Higher = momentum
216
+ * dies faster. Reanimated default is `0.998`; lower values feel more
217
+ * "slippy". Range: roughly `0.99` (slow) to `0.999` (long glide).
218
+ */
219
+ deceleration?: number;
220
+ /**
221
+ * Disable the post-release momentum entirely. Defaults to `false` — pan
222
+ * coasts after release. Set to `true` for a hard stop on release (drag-like
223
+ * behavior).
224
+ */
225
+ disableMomentum?: boolean;
226
+ }
227
+ interface UsePanResult {
228
+ /** Pan gesture to pass to a `<GestureDetector>`. */
229
+ gesture: PanGesture;
230
+ /** Stable animated `transform` style. */
231
+ animatedStyle: ReturnType<typeof useAnimatedStyle>;
232
+ /** Live x translation, persistent across gestures. */
233
+ panX: SharedValue<number>;
234
+ /** Live y translation, persistent across gestures. */
235
+ panY: SharedValue<number>;
236
+ /** True while the user is actively panning. Decay phase reads `false`. */
237
+ isPanning: SharedValue<boolean>;
238
+ }
239
+ /**
240
+ * Camera-pan-style drag with momentum on release. Translation persists
241
+ * across separate pan gestures (the next pan starts from the current
242
+ * position, not zero), and on release the translation continues to glide
243
+ * via Reanimated's `withDecay` until friction stops it.
244
+ *
245
+ * Use for map / zoom-canvas / large-image navigation. For dragging an
246
+ * element to a position with no momentum, use `useDrag` instead.
247
+ */
248
+ declare function usePan(options?: PanOptions): UsePanResult;
249
+
250
+ export { type DragConstraints, type DragOptions, type PanOptions, type ReleaseInfo, type ReleaseResult, type ReleaseTransition, type SwipeDirection, type SwipeOptions, type UseDragResult, type UsePanResult, type UseSwipeResult, useDrag, usePan, useSwipe };