react-native-gesture-handler 2.20.1 → 2.21.0
Sign up to get free protection for your applications and to get access to all the features.
- package/RNGestureHandler.podspec +9 -0
- package/android/build.gradle +19 -0
- package/android/paper/src/main/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +1 -1
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +6 -2
- package/android/src/main/java/com/swmansion/gesturehandler/core/RotationGestureDetector.kt +53 -21
- package/apple/Handlers/RNPanHandler.m +5 -1
- package/apple/RNGestureHandlerButton.h +17 -1
- package/apple/{RNGestureHandlerButton.m → RNGestureHandlerButton.mm} +64 -0
- package/apple/RNGestureHandlerButtonComponentView.h +4 -0
- package/apple/RNGestureHandlerButtonComponentView.mm +12 -3
- package/apple/{RNGestureHandlerButtonManager.m → RNGestureHandlerButtonManager.mm} +1 -1
- package/apple/RNGestureHandlerPointerTracker.m +4 -2
- package/lib/commonjs/RNGestureHandlerModule.web.js +15 -2
- package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/commonjs/components/Pressable/Pressable.js +2 -6
- package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
- package/lib/commonjs/components/ReanimatedDrawerLayout.js +389 -0
- package/lib/commonjs/components/ReanimatedDrawerLayout.js.map +1 -0
- package/lib/commonjs/components/ReanimatedSwipeable.js +117 -148
- package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/commonjs/findNodeHandle.js +12 -0
- package/lib/commonjs/findNodeHandle.js.map +1 -0
- package/lib/commonjs/findNodeHandle.web.js +40 -0
- package/lib/commonjs/findNodeHandle.web.js.map +1 -0
- package/lib/commonjs/handlers/createHandler.js +4 -2
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js +51 -0
- package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
- package/lib/commonjs/handlers/gestures/GestureDetector/index.js +3 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +5 -3
- package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +4 -2
- package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js +4 -0
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js +59 -0
- package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/commonjs/web/interfaces.js +10 -1
- package/lib/commonjs/web/interfaces.js.map +1 -1
- package/lib/commonjs/web/tools/EventManager.js +6 -0
- package/lib/commonjs/web/tools/EventManager.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +1 -3
- package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +5 -2
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/commonjs/web/tools/KeyboardEventManager.js +2 -2
- package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -1
- package/lib/commonjs/web/tools/PointerTracker.js +6 -30
- package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
- package/lib/commonjs/web/tools/WheelEventManager.js +74 -0
- package/lib/commonjs/web/tools/WheelEventManager.js.map +1 -0
- package/lib/commonjs/web/utils.js +16 -0
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.web.js +16 -3
- package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/module/components/Pressable/Pressable.js +2 -6
- package/lib/module/components/Pressable/Pressable.js.map +1 -1
- package/lib/module/components/ReanimatedDrawerLayout.js +365 -0
- package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -0
- package/lib/module/components/ReanimatedSwipeable.js +119 -145
- package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/module/findNodeHandle.js +3 -0
- package/lib/module/findNodeHandle.js.map +1 -0
- package/lib/module/findNodeHandle.web.js +32 -0
- package/lib/module/findNodeHandle.web.js.map +1 -0
- package/lib/module/handlers/createHandler.js +2 -1
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js +34 -0
- package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
- package/lib/module/handlers/gestures/GestureDetector/index.js +2 -1
- package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -2
- package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +1 -1
- package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +4 -0
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PanGestureHandler.js +58 -0
- package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/module/web/interfaces.js +8 -0
- package/lib/module/web/interfaces.js.map +1 -1
- package/lib/module/web/tools/EventManager.js +6 -0
- package/lib/module/web/tools/EventManager.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerOrchestrator.js +1 -3
- package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js +3 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/module/web/tools/KeyboardEventManager.js +2 -2
- package/lib/module/web/tools/KeyboardEventManager.js.map +1 -1
- package/lib/module/web/tools/PointerTracker.js +6 -30
- package/lib/module/web/tools/PointerTracker.js.map +1 -1
- package/lib/module/web/tools/WheelEventManager.js +60 -0
- package/lib/module/web/tools/WheelEventManager.js.map +1 -0
- package/lib/module/web/utils.js +15 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/components/ReanimatedDrawerLayout.d.ts +162 -0
- package/lib/typescript/components/ReanimatedSwipeable.d.ts +22 -16
- package/lib/typescript/findNodeHandle.d.ts +2 -0
- package/lib/typescript/findNodeHandle.web.d.ts +2 -0
- package/lib/typescript/handlers/gestures/GestureDetector/Wrap.web.d.ts +7 -0
- package/lib/typescript/web/handlers/GestureHandler.d.ts +2 -1
- package/lib/typescript/web/handlers/PanGestureHandler.d.ts +5 -0
- package/lib/typescript/web/interfaces.d.ts +16 -0
- package/lib/typescript/web/tools/EventManager.d.ts +2 -0
- package/lib/typescript/web/tools/PointerTracker.d.ts +2 -8
- package/lib/typescript/web/tools/WheelEventManager.d.ts +11 -0
- package/lib/typescript/web/utils.d.ts +2 -1
- package/package.json +2 -2
- package/src/RNGestureHandlerModule.web.ts +23 -4
- package/src/components/Pressable/Pressable.tsx +2 -6
- package/src/components/ReanimatedDrawerLayout.tsx +741 -0
- package/src/components/ReanimatedSwipeable.tsx +361 -305
- package/src/findNodeHandle.ts +3 -0
- package/src/findNodeHandle.web.ts +35 -0
- package/src/handlers/createHandler.tsx +2 -1
- package/src/handlers/gestures/GestureDetector/Wrap.web.tsx +44 -0
- package/src/handlers/gestures/GestureDetector/index.tsx +2 -1
- package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +1 -1
- package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +1 -1
- package/src/web/handlers/GestureHandler.ts +5 -1
- package/src/web/handlers/PanGestureHandler.ts +69 -1
- package/src/web/interfaces.ts +17 -0
- package/src/web/tools/EventManager.ts +4 -0
- package/src/web/tools/GestureHandlerOrchestrator.ts +1 -7
- package/src/web/tools/GestureHandlerWebDelegate.ts +3 -1
- package/src/web/tools/KeyboardEventManager.ts +2 -2
- package/src/web/tools/PointerTracker.ts +6 -28
- package/src/web/tools/WheelEventManager.ts +48 -0
- package/src/web/utils.ts +47 -1
@@ -7,7 +7,7 @@ import React, {
|
|
7
7
|
forwardRef,
|
8
8
|
useCallback,
|
9
9
|
useImperativeHandle,
|
10
|
-
|
10
|
+
useMemo,
|
11
11
|
} from 'react';
|
12
12
|
import { GestureObjects as Gesture } from '../handlers/gestures/gestureObjects';
|
13
13
|
import { GestureDetector } from '../handlers/gestures/GestureDetector';
|
@@ -18,7 +18,6 @@ import {
|
|
18
18
|
import type { PanGestureHandlerProps } from '../handlers/PanGestureHandler';
|
19
19
|
import type { PanGestureHandlerEventPayload } from '../handlers/GestureHandlerEventPayload';
|
20
20
|
import Animated, {
|
21
|
-
Extrapolation,
|
22
21
|
SharedValue,
|
23
22
|
interpolate,
|
24
23
|
runOnJS,
|
@@ -42,6 +41,11 @@ type SwipeableExcludes = Exclude<
|
|
42
41
|
'onGestureEvent' | 'onHandlerStateChange'
|
43
42
|
>;
|
44
43
|
|
44
|
+
enum SwipeDirection {
|
45
|
+
LEFT = 'left',
|
46
|
+
RIGHT = 'right',
|
47
|
+
}
|
48
|
+
|
45
49
|
export interface SwipeableProps
|
46
50
|
extends Pick<PanGestureHandlerProps, SwipeableExcludes> {
|
47
51
|
/**
|
@@ -111,65 +115,74 @@ export interface SwipeableProps
|
|
111
115
|
* Called when action panel gets open (either right or left).
|
112
116
|
*/
|
113
117
|
onSwipeableOpen?: (
|
114
|
-
direction:
|
115
|
-
swipeable: SwipeableMethods
|
118
|
+
direction: SwipeDirection.LEFT | SwipeDirection.RIGHT
|
116
119
|
) => void;
|
117
120
|
|
118
121
|
/**
|
119
122
|
* Called when action panel is closed.
|
120
123
|
*/
|
121
124
|
onSwipeableClose?: (
|
122
|
-
direction:
|
123
|
-
swipeable: SwipeableMethods
|
125
|
+
direction: SwipeDirection.LEFT | SwipeDirection.RIGHT
|
124
126
|
) => void;
|
125
127
|
|
126
128
|
/**
|
127
129
|
* Called when action panel starts animating on open (either right or left).
|
128
130
|
*/
|
129
|
-
onSwipeableWillOpen?: (
|
131
|
+
onSwipeableWillOpen?: (
|
132
|
+
direction: SwipeDirection.LEFT | SwipeDirection.RIGHT
|
133
|
+
) => void;
|
130
134
|
|
131
135
|
/**
|
132
136
|
* Called when action panel starts animating on close.
|
133
137
|
*/
|
134
|
-
onSwipeableWillClose?: (
|
138
|
+
onSwipeableWillClose?: (
|
139
|
+
direction: SwipeDirection.LEFT | SwipeDirection.RIGHT
|
140
|
+
) => void;
|
135
141
|
|
136
142
|
/**
|
137
143
|
* Called when action panel starts being shown on dragging to open.
|
138
144
|
*/
|
139
|
-
onSwipeableOpenStartDrag?: (
|
145
|
+
onSwipeableOpenStartDrag?: (
|
146
|
+
direction: SwipeDirection.LEFT | SwipeDirection.RIGHT
|
147
|
+
) => void;
|
140
148
|
|
141
149
|
/**
|
142
150
|
* Called when action panel starts being shown on dragging to close.
|
143
151
|
*/
|
144
|
-
onSwipeableCloseStartDrag?: (
|
152
|
+
onSwipeableCloseStartDrag?: (
|
153
|
+
direction: SwipeDirection.LEFT | SwipeDirection.RIGHT
|
154
|
+
) => void;
|
145
155
|
|
146
156
|
/**
|
157
|
+
* `progress`: Equals `0` when `swipeable` is closed, `1` when `swipeable` is opened.
|
158
|
+
* - When the element overshoots it's opened position the value tends towards `Infinity`.
|
159
|
+
* - Goes back to `1` when `swipeable` is released.
|
147
160
|
*
|
148
|
-
*
|
149
|
-
*
|
150
|
-
*
|
151
|
-
* progressAnimatedValue: [0, 1] dragAnimatedValue: [0, +]
|
161
|
+
* `translation`: a horizontal offset of the `swipeable` relative to its closed position.\
|
162
|
+
* `swipeableMethods`: provides an object exposing methods for controlling the `swipeable`.
|
152
163
|
*
|
153
164
|
* To support `rtl` flexbox layouts use `flexDirection` styling.
|
154
165
|
* */
|
155
166
|
renderLeftActions?: (
|
156
|
-
|
157
|
-
|
158
|
-
|
167
|
+
progress: SharedValue<number>,
|
168
|
+
translation: SharedValue<number>,
|
169
|
+
swipeableMethods: SwipeableMethods
|
159
170
|
) => React.ReactNode;
|
171
|
+
|
160
172
|
/**
|
173
|
+
* `progress`: Equals `0` when `swipeable` is closed, `1` when `swipeable` is opened.
|
174
|
+
* - When the element overshoots it's opened position the value tends towards `Infinity`.
|
175
|
+
* - Goes back to `1` when `swipeable` is released.
|
161
176
|
*
|
162
|
-
*
|
163
|
-
*
|
164
|
-
*
|
165
|
-
* progressAnimatedValue: [0, 1] dragAnimatedValue: [0, -]
|
177
|
+
* `translation`: a horizontal offset of the `swipeable` relative to its closed position.\
|
178
|
+
* `swipeableMethods`: provides an object exposing methods for controlling the `swipeable`.
|
166
179
|
*
|
167
180
|
* To support `rtl` flexbox layouts use `flexDirection` styling.
|
168
181
|
* */
|
169
182
|
renderRightActions?: (
|
170
|
-
|
171
|
-
|
172
|
-
|
183
|
+
progress: SharedValue<number>,
|
184
|
+
translation: SharedValue<number>,
|
185
|
+
swipeableMethods: SwipeableMethods
|
173
186
|
) => React.ReactNode;
|
174
187
|
|
175
188
|
animationOptions?: Record<string, unknown>;
|
@@ -199,86 +212,69 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
|
|
199
212
|
props: SwipeableProps,
|
200
213
|
ref: ForwardedRef<SwipeableMethods>
|
201
214
|
) {
|
215
|
+
const defaultProps = {
|
216
|
+
friction: 1,
|
217
|
+
overshootFriction: 1,
|
218
|
+
dragOffset: 10,
|
219
|
+
enableTrackpadTwoFingerGesture: false,
|
220
|
+
};
|
221
|
+
|
202
222
|
const {
|
203
223
|
leftThreshold,
|
204
224
|
rightThreshold,
|
205
|
-
onSwipeableOpenStartDrag,
|
206
|
-
onSwipeableCloseStartDrag,
|
207
|
-
enableTrackpadTwoFingerGesture,
|
208
225
|
enabled,
|
209
226
|
containerStyle,
|
210
227
|
childrenContainerStyle,
|
211
228
|
animationOptions,
|
212
229
|
overshootLeft,
|
213
230
|
overshootRight,
|
231
|
+
testID,
|
232
|
+
children,
|
233
|
+
enableTrackpadTwoFingerGesture = defaultProps.enableTrackpadTwoFingerGesture,
|
234
|
+
dragOffsetFromLeftEdge = defaultProps.dragOffset,
|
235
|
+
dragOffsetFromRightEdge = defaultProps.dragOffset,
|
236
|
+
friction = defaultProps.friction,
|
237
|
+
overshootFriction = defaultProps.overshootFriction,
|
238
|
+
onSwipeableOpenStartDrag,
|
239
|
+
onSwipeableCloseStartDrag,
|
214
240
|
onSwipeableWillOpen,
|
215
241
|
onSwipeableWillClose,
|
216
242
|
onSwipeableOpen,
|
217
243
|
onSwipeableClose,
|
218
|
-
|
244
|
+
renderLeftActions,
|
245
|
+
renderRightActions,
|
219
246
|
...remainingProps
|
220
247
|
} = props;
|
221
248
|
|
222
249
|
const rowState = useSharedValue<number>(0);
|
223
250
|
|
224
251
|
const userDrag = useSharedValue<number>(0);
|
252
|
+
|
225
253
|
const appliedTranslation = useSharedValue<number>(0);
|
226
254
|
|
227
255
|
const rowWidth = useSharedValue<number>(0);
|
228
256
|
const leftWidth = useSharedValue<number>(0);
|
229
257
|
const rightWidth = useSharedValue<number>(0);
|
230
|
-
const rightOffset = useSharedValue<number>(0);
|
231
258
|
|
232
|
-
|
233
|
-
const
|
259
|
+
// used for synchronizing layout measurements between JS and UI
|
260
|
+
const rightOffset = useSharedValue<number | null>(null);
|
234
261
|
|
235
262
|
const showLeftProgress = useSharedValue<number>(0);
|
236
263
|
const showRightProgress = useSharedValue<number>(0);
|
237
264
|
|
238
|
-
const
|
239
|
-
close: () => {
|
240
|
-
'worklet';
|
241
|
-
},
|
242
|
-
openLeft: () => {
|
243
|
-
'worklet';
|
244
|
-
},
|
245
|
-
openRight: () => {
|
246
|
-
'worklet';
|
247
|
-
},
|
248
|
-
reset: () => {
|
249
|
-
'worklet';
|
250
|
-
},
|
251
|
-
});
|
252
|
-
|
253
|
-
const defaultProps = {
|
254
|
-
friction: 1,
|
255
|
-
overshootFriction: 1,
|
256
|
-
};
|
257
|
-
|
258
|
-
const {
|
259
|
-
friction = defaultProps.friction,
|
260
|
-
overshootFriction = defaultProps.overshootFriction,
|
261
|
-
} = props;
|
262
|
-
|
263
|
-
const overshootLeftProp = overshootLeft;
|
264
|
-
const overshootRightProp = overshootRight;
|
265
|
-
|
266
|
-
const calculateCurrentOffset = useCallback(() => {
|
265
|
+
const updateRightElementWidth = useCallback(() => {
|
267
266
|
'worklet';
|
268
|
-
if (
|
269
|
-
|
270
|
-
} else if (rowState.value === -1) {
|
271
|
-
return -rowWidth.value - rightOffset.value;
|
267
|
+
if (rightOffset.value === null) {
|
268
|
+
rightOffset.value = rowWidth.value;
|
272
269
|
}
|
273
|
-
|
274
|
-
}, [
|
270
|
+
rightWidth.value = Math.max(0, rowWidth.value - rightOffset.value);
|
271
|
+
}, [rightOffset, rightWidth, rowWidth]);
|
275
272
|
|
276
|
-
const updateAnimatedEvent = () => {
|
273
|
+
const updateAnimatedEvent = useCallback(() => {
|
277
274
|
'worklet';
|
278
|
-
rightWidth.value = Math.max(0, rowWidth.value - rightOffset.value);
|
279
275
|
|
280
|
-
const
|
281
|
-
const
|
276
|
+
const shouldOvershootLeft = overshootLeft ?? leftWidth.value > 0;
|
277
|
+
const shouldOvershootRight = overshootRight ?? rightWidth.value > 0;
|
282
278
|
|
283
279
|
const startOffset =
|
284
280
|
rowState.value === 1
|
@@ -298,10 +294,11 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
|
|
298
294
|
leftWidth.value + 1,
|
299
295
|
],
|
300
296
|
[
|
301
|
-
-rightWidth.value -
|
297
|
+
-rightWidth.value -
|
298
|
+
(shouldOvershootRight ? 1 / overshootFriction : 0),
|
302
299
|
-rightWidth.value,
|
303
300
|
leftWidth.value,
|
304
|
-
leftWidth.value + (
|
301
|
+
leftWidth.value + (shouldOvershootLeft ? 1 / overshootFriction : 0),
|
305
302
|
]
|
306
303
|
);
|
307
304
|
|
@@ -313,12 +310,7 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
|
|
313
310
|
[0, 0, 1]
|
314
311
|
)
|
315
312
|
: 0;
|
316
|
-
|
317
|
-
showLeftProgress.value,
|
318
|
-
[0, Number.MIN_VALUE],
|
319
|
-
[-10000, 0],
|
320
|
-
Extrapolation.CLAMP
|
321
|
-
);
|
313
|
+
|
322
314
|
showRightProgress.value =
|
323
315
|
rightWidth.value > 0
|
324
316
|
? interpolate(
|
@@ -327,23 +319,31 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
|
|
327
319
|
[1, 0, 0]
|
328
320
|
)
|
329
321
|
: 0;
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
322
|
+
}, [
|
323
|
+
appliedTranslation,
|
324
|
+
friction,
|
325
|
+
leftWidth,
|
326
|
+
overshootFriction,
|
327
|
+
rightWidth,
|
328
|
+
rowState,
|
329
|
+
showLeftProgress,
|
330
|
+
showRightProgress,
|
331
|
+
userDrag,
|
332
|
+
overshootLeft,
|
333
|
+
overshootRight,
|
334
|
+
]);
|
337
335
|
|
338
336
|
const dispatchImmediateEvents = useCallback(
|
339
337
|
(fromValue: number, toValue: number) => {
|
338
|
+
'worklet';
|
340
339
|
if (toValue > 0 && onSwipeableWillOpen) {
|
341
|
-
onSwipeableWillOpen(
|
340
|
+
runOnJS(onSwipeableWillOpen)(SwipeDirection.RIGHT);
|
342
341
|
} else if (toValue < 0 && onSwipeableWillOpen) {
|
343
|
-
onSwipeableWillOpen(
|
342
|
+
runOnJS(onSwipeableWillOpen)(SwipeDirection.LEFT);
|
344
343
|
} else if (onSwipeableWillClose) {
|
345
|
-
|
346
|
-
|
344
|
+
runOnJS(onSwipeableWillClose)(
|
345
|
+
fromValue > 0 ? SwipeDirection.LEFT : SwipeDirection.RIGHT
|
346
|
+
);
|
347
347
|
}
|
348
348
|
},
|
349
349
|
[onSwipeableWillClose, onSwipeableWillOpen]
|
@@ -351,255 +351,311 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
|
|
351
351
|
|
352
352
|
const dispatchEndEvents = useCallback(
|
353
353
|
(fromValue: number, toValue: number) => {
|
354
|
+
'worklet';
|
354
355
|
if (toValue > 0 && onSwipeableOpen) {
|
355
|
-
onSwipeableOpen(
|
356
|
+
runOnJS(onSwipeableOpen)(SwipeDirection.RIGHT);
|
356
357
|
} else if (toValue < 0 && onSwipeableOpen) {
|
357
|
-
onSwipeableOpen(
|
358
|
+
runOnJS(onSwipeableOpen)(SwipeDirection.LEFT);
|
358
359
|
} else if (onSwipeableClose) {
|
359
|
-
|
360
|
-
|
360
|
+
runOnJS(onSwipeableClose)(
|
361
|
+
fromValue > 0 ? SwipeDirection.LEFT : SwipeDirection.RIGHT
|
362
|
+
);
|
361
363
|
}
|
362
364
|
},
|
363
365
|
[onSwipeableClose, onSwipeableOpen]
|
364
366
|
);
|
365
367
|
|
366
|
-
const
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
368
|
+
const animateRow: (toValue: number, velocityX?: number) => void =
|
369
|
+
useCallback(
|
370
|
+
(toValue: number, velocityX?: number) => {
|
371
|
+
'worklet';
|
372
|
+
|
373
|
+
const translationSpringConfig = {
|
374
|
+
duration: 1000,
|
375
|
+
dampingRatio: 0.9,
|
376
|
+
stiffness: 500,
|
377
|
+
velocity: velocityX,
|
378
|
+
overshootClamping: true,
|
379
|
+
...animationOptions,
|
380
|
+
};
|
381
|
+
|
382
|
+
const isClosing = toValue === 0;
|
383
|
+
const moveToRight = isClosing ? rowState.value < 0 : toValue > 0;
|
384
|
+
|
385
|
+
const usedWidth = isClosing
|
386
|
+
? moveToRight
|
387
|
+
? rightWidth.value
|
388
|
+
: leftWidth.value
|
389
|
+
: moveToRight
|
390
|
+
? leftWidth.value
|
391
|
+
: rightWidth.value;
|
392
|
+
|
393
|
+
const progressSpringConfig = {
|
394
|
+
...translationSpringConfig,
|
395
|
+
restDisplacementThreshold: 0.01,
|
396
|
+
restSpeedThreshold: 0.01,
|
397
|
+
velocity:
|
398
|
+
velocityX &&
|
399
|
+
interpolate(velocityX, [-usedWidth, usedWidth], [-1, 1]),
|
400
|
+
};
|
401
|
+
|
402
|
+
const frozenRowState = rowState.value;
|
403
|
+
|
404
|
+
appliedTranslation.value = withSpring(
|
405
|
+
toValue,
|
406
|
+
translationSpringConfig,
|
407
|
+
(isFinished) => {
|
408
|
+
if (isFinished) {
|
409
|
+
dispatchEndEvents(frozenRowState, toValue);
|
410
|
+
}
|
393
411
|
}
|
394
|
-
|
395
|
-
);
|
412
|
+
);
|
396
413
|
|
397
|
-
|
414
|
+
const progressTarget = toValue === 0 ? 0 : 1;
|
398
415
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
416
|
+
showLeftProgress.value =
|
417
|
+
leftWidth.value > 0
|
418
|
+
? withSpring(progressTarget, progressSpringConfig)
|
419
|
+
: 0;
|
420
|
+
showRightProgress.value =
|
421
|
+
rightWidth.value > 0
|
422
|
+
? withSpring(progressTarget, progressSpringConfig)
|
423
|
+
: 0;
|
407
424
|
|
408
|
-
|
409
|
-
},
|
410
|
-
[
|
411
|
-
rowState,
|
412
|
-
animationOptionsProp,
|
413
|
-
appliedTranslation,
|
414
|
-
showLeftProgress,
|
415
|
-
leftWidth.value,
|
416
|
-
showRightProgress,
|
417
|
-
rightWidth.value,
|
418
|
-
dispatchImmediateEvents,
|
419
|
-
dispatchEndEvents,
|
420
|
-
]
|
421
|
-
);
|
425
|
+
dispatchImmediateEvents(frozenRowState, toValue);
|
422
426
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
'worklet';
|
438
|
-
animateRow(calculateCurrentOffset(), 0);
|
439
|
-
},
|
440
|
-
openLeft() {
|
441
|
-
'worklet';
|
442
|
-
animateRow(calculateCurrentOffset(), leftWidth.value);
|
443
|
-
},
|
444
|
-
openRight() {
|
445
|
-
'worklet';
|
446
|
-
rightWidth.value = rowWidth.value - rightOffset.value;
|
447
|
-
animateRow(calculateCurrentOffset(), -rightWidth.value);
|
448
|
-
},
|
449
|
-
reset() {
|
450
|
-
'worklet';
|
451
|
-
userDrag.value = 0;
|
452
|
-
showLeftProgress.value = 0;
|
453
|
-
appliedTranslation.value = 0;
|
454
|
-
rowState.value = 0;
|
455
|
-
},
|
456
|
-
};
|
427
|
+
rowState.value = Math.sign(toValue);
|
428
|
+
},
|
429
|
+
[
|
430
|
+
rowState,
|
431
|
+
animationOptions,
|
432
|
+
appliedTranslation,
|
433
|
+
showLeftProgress,
|
434
|
+
leftWidth,
|
435
|
+
showRightProgress,
|
436
|
+
rightWidth,
|
437
|
+
dispatchImmediateEvents,
|
438
|
+
dispatchEndEvents,
|
439
|
+
]
|
440
|
+
);
|
457
441
|
|
458
|
-
const
|
442
|
+
const swipeableMethods = useMemo<SwipeableMethods>(
|
459
443
|
() => ({
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
444
|
+
close() {
|
445
|
+
'worklet';
|
446
|
+
animateRow(0);
|
447
|
+
},
|
448
|
+
openLeft() {
|
449
|
+
'worklet';
|
450
|
+
animateRow(leftWidth.value);
|
451
|
+
},
|
452
|
+
openRight() {
|
453
|
+
'worklet';
|
454
|
+
// rightOffset and rowWidth are already much sooner than rightWidth
|
455
|
+
animateRow((rightOffset.value ?? 0) - rowWidth.value);
|
456
|
+
},
|
457
|
+
reset() {
|
458
|
+
'worklet';
|
459
|
+
userDrag.value = 0;
|
460
|
+
showLeftProgress.value = 0;
|
461
|
+
appliedTranslation.value = 0;
|
462
|
+
rowState.value = 0;
|
463
|
+
},
|
465
464
|
}),
|
466
|
-
[
|
465
|
+
[
|
466
|
+
leftWidth,
|
467
|
+
rightOffset,
|
468
|
+
rowWidth,
|
469
|
+
userDrag,
|
470
|
+
showLeftProgress,
|
471
|
+
appliedTranslation,
|
472
|
+
rowState,
|
473
|
+
animateRow,
|
474
|
+
]
|
467
475
|
);
|
468
476
|
|
469
|
-
const
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
swipeableMethods.current
|
475
|
-
)}
|
476
|
-
<View
|
477
|
-
onLayout={({ nativeEvent }) =>
|
478
|
-
(leftWidth.value = nativeEvent.layout.x)
|
479
|
-
}
|
480
|
-
/>
|
481
|
-
</Animated.View>
|
477
|
+
const onRowLayout = useCallback(
|
478
|
+
({ nativeEvent }: LayoutChangeEvent) => {
|
479
|
+
rowWidth.value = nativeEvent.layout.width;
|
480
|
+
},
|
481
|
+
[rowWidth]
|
482
482
|
);
|
483
483
|
|
484
|
-
const
|
485
|
-
() => (
|
486
|
-
|
487
|
-
{
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
484
|
+
const leftElement = useCallback(
|
485
|
+
() => (
|
486
|
+
<Animated.View style={[styles.leftActions]}>
|
487
|
+
{renderLeftActions?.(
|
488
|
+
showLeftProgress,
|
489
|
+
appliedTranslation,
|
490
|
+
swipeableMethods
|
491
|
+
)}
|
492
|
+
<View
|
493
|
+
onLayout={({ nativeEvent }) =>
|
494
|
+
(leftWidth.value = nativeEvent.layout.x)
|
495
|
+
}
|
496
|
+
/>
|
497
|
+
</Animated.View>
|
498
|
+
),
|
499
|
+
[
|
500
|
+
appliedTranslation,
|
501
|
+
leftWidth,
|
502
|
+
renderLeftActions,
|
503
|
+
showLeftProgress,
|
504
|
+
swipeableMethods,
|
505
|
+
]
|
493
506
|
);
|
494
507
|
|
495
|
-
const rightElement =
|
496
|
-
|
497
|
-
{
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
(
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
+
const rightElement = useCallback(
|
509
|
+
() => (
|
510
|
+
<Animated.View style={[styles.rightActions]}>
|
511
|
+
{renderRightActions?.(
|
512
|
+
showRightProgress,
|
513
|
+
appliedTranslation,
|
514
|
+
swipeableMethods
|
515
|
+
)}
|
516
|
+
<View
|
517
|
+
onLayout={({ nativeEvent }) => {
|
518
|
+
rightOffset.value = nativeEvent.layout.x;
|
519
|
+
}}
|
520
|
+
/>
|
521
|
+
</Animated.View>
|
522
|
+
),
|
523
|
+
[
|
524
|
+
appliedTranslation,
|
525
|
+
renderRightActions,
|
526
|
+
rightOffset,
|
527
|
+
showRightProgress,
|
528
|
+
swipeableMethods,
|
529
|
+
]
|
508
530
|
);
|
509
531
|
|
510
|
-
const
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
) => {
|
516
|
-
'worklet';
|
517
|
-
const { velocityX } = event;
|
518
|
-
userDrag.value = event.translationX;
|
532
|
+
const handleRelease = useCallback(
|
533
|
+
(event: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
|
534
|
+
'worklet';
|
535
|
+
const { velocityX } = event;
|
536
|
+
userDrag.value = event.translationX;
|
519
537
|
|
520
|
-
|
538
|
+
updateRightElementWidth();
|
521
539
|
|
522
|
-
|
523
|
-
|
540
|
+
const leftThresholdProp = leftThreshold ?? leftWidth.value / 2;
|
541
|
+
const rightThresholdProp = rightThreshold ?? rightWidth.value / 2;
|
524
542
|
|
525
|
-
|
526
|
-
|
543
|
+
const translationX =
|
544
|
+
(userDrag.value + DRAG_TOSS * velocityX) / friction;
|
527
545
|
|
528
|
-
|
546
|
+
let toValue = 0;
|
529
547
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
548
|
+
if (rowState.value === 0) {
|
549
|
+
if (translationX > leftThresholdProp) {
|
550
|
+
toValue = leftWidth.value;
|
551
|
+
} else if (translationX < -rightThresholdProp) {
|
552
|
+
toValue = -rightWidth.value;
|
553
|
+
}
|
554
|
+
} else if (rowState.value === 1) {
|
555
|
+
// Swiped to left
|
556
|
+
if (translationX > -leftThresholdProp) {
|
557
|
+
toValue = leftWidth.value;
|
558
|
+
}
|
559
|
+
} else {
|
560
|
+
// Swiped to right
|
561
|
+
if (translationX < rightThresholdProp) {
|
562
|
+
toValue = -rightWidth.value;
|
563
|
+
}
|
545
564
|
}
|
546
|
-
}
|
547
565
|
|
548
|
-
|
549
|
-
|
566
|
+
animateRow(toValue, velocityX / friction);
|
567
|
+
},
|
568
|
+
[
|
569
|
+
animateRow,
|
570
|
+
friction,
|
571
|
+
leftThreshold,
|
572
|
+
leftWidth,
|
573
|
+
rightThreshold,
|
574
|
+
rightWidth,
|
575
|
+
rowState,
|
576
|
+
userDrag,
|
577
|
+
updateRightElementWidth,
|
578
|
+
]
|
579
|
+
);
|
550
580
|
|
551
|
-
const close = () => {
|
581
|
+
const close = useCallback(() => {
|
552
582
|
'worklet';
|
553
|
-
animateRow(
|
554
|
-
};
|
555
|
-
|
556
|
-
const
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
: rowState.value === 1
|
570
|
-
? 'left'
|
571
|
-
: event.translationX > 0
|
572
|
-
? 'left'
|
573
|
-
: 'right';
|
574
|
-
|
575
|
-
if (rowState.value === 0 && onSwipeableOpenStartDrag) {
|
576
|
-
runOnJS(onSwipeableOpenStartDrag)(direction);
|
577
|
-
} else if (rowState.value !== 0 && onSwipeableCloseStartDrag) {
|
578
|
-
runOnJS(onSwipeableCloseStartDrag)(direction);
|
579
|
-
}
|
580
|
-
updateAnimatedEvent();
|
581
|
-
})
|
582
|
-
.onEnd(
|
583
|
-
(event: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
|
584
|
-
handleRelease(event);
|
585
|
-
}
|
586
|
-
);
|
587
|
-
|
588
|
-
if (enableTrackpadTwoFingerGesture) {
|
589
|
-
panGesture.enableTrackpadTwoFingerGesture(enableTrackpadTwoFingerGesture);
|
590
|
-
}
|
591
|
-
|
592
|
-
panGesture.activeOffsetX([
|
593
|
-
-dragOffsetFromRightEdge,
|
594
|
-
dragOffsetFromLeftEdge,
|
595
|
-
]);
|
596
|
-
tapGesture.shouldCancelWhenOutside(true);
|
583
|
+
animateRow(0);
|
584
|
+
}, [animateRow]);
|
585
|
+
|
586
|
+
const dragStarted = useSharedValue<boolean>(false);
|
587
|
+
|
588
|
+
const tapGesture = useMemo(
|
589
|
+
() =>
|
590
|
+
Gesture.Tap()
|
591
|
+
.shouldCancelWhenOutside(true)
|
592
|
+
.onStart(() => {
|
593
|
+
if (rowState.value !== 0) {
|
594
|
+
close();
|
595
|
+
}
|
596
|
+
}),
|
597
|
+
[close, rowState]
|
598
|
+
);
|
597
599
|
|
598
|
-
|
599
|
-
|
600
|
-
|
600
|
+
const panGesture = useMemo(
|
601
|
+
() =>
|
602
|
+
Gesture.Pan()
|
603
|
+
.enabled(enabled !== false)
|
604
|
+
.enableTrackpadTwoFingerGesture(enableTrackpadTwoFingerGesture)
|
605
|
+
.activeOffsetX([-dragOffsetFromRightEdge, dragOffsetFromLeftEdge])
|
606
|
+
.onStart(() => {
|
607
|
+
updateRightElementWidth();
|
608
|
+
})
|
609
|
+
.onUpdate(
|
610
|
+
(event: GestureUpdateEvent<PanGestureHandlerEventPayload>) => {
|
611
|
+
userDrag.value = event.translationX;
|
612
|
+
|
613
|
+
const direction =
|
614
|
+
rowState.value === -1
|
615
|
+
? SwipeDirection.RIGHT
|
616
|
+
: rowState.value === 1
|
617
|
+
? SwipeDirection.LEFT
|
618
|
+
: event.translationX > 0
|
619
|
+
? SwipeDirection.RIGHT
|
620
|
+
: SwipeDirection.LEFT;
|
621
|
+
|
622
|
+
if (!dragStarted.value) {
|
623
|
+
dragStarted.value = true;
|
624
|
+
if (rowState.value === 0 && onSwipeableOpenStartDrag) {
|
625
|
+
runOnJS(onSwipeableOpenStartDrag)(direction);
|
626
|
+
} else if (onSwipeableCloseStartDrag) {
|
627
|
+
runOnJS(onSwipeableCloseStartDrag)(direction);
|
628
|
+
}
|
629
|
+
}
|
630
|
+
|
631
|
+
updateAnimatedEvent();
|
632
|
+
}
|
633
|
+
)
|
634
|
+
.onEnd(
|
635
|
+
(event: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
|
636
|
+
handleRelease(event);
|
637
|
+
}
|
638
|
+
)
|
639
|
+
.onFinalize(() => {
|
640
|
+
dragStarted.value = false;
|
641
|
+
}),
|
642
|
+
[
|
643
|
+
dragOffsetFromLeftEdge,
|
644
|
+
dragOffsetFromRightEdge,
|
645
|
+
dragStarted,
|
646
|
+
enableTrackpadTwoFingerGesture,
|
647
|
+
enabled,
|
648
|
+
handleRelease,
|
649
|
+
onSwipeableCloseStartDrag,
|
650
|
+
onSwipeableOpenStartDrag,
|
651
|
+
rowState,
|
652
|
+
updateAnimatedEvent,
|
653
|
+
updateRightElementWidth,
|
654
|
+
userDrag,
|
655
|
+
]
|
656
|
+
);
|
601
657
|
|
602
|
-
|
658
|
+
useImperativeHandle(ref, () => swipeableMethods, [swipeableMethods]);
|
603
659
|
|
604
660
|
const animatedStyle = useAnimatedStyle(
|
605
661
|
() => ({
|
@@ -615,8 +671,8 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
|
|
615
671
|
{...remainingProps}
|
616
672
|
onLayout={onRowLayout}
|
617
673
|
style={[styles.container, containerStyle]}>
|
618
|
-
{leftElement}
|
619
|
-
{rightElement}
|
674
|
+
{leftElement()}
|
675
|
+
{rightElement()}
|
620
676
|
<GestureDetector gesture={tapGesture} touchAction="pan-y">
|
621
677
|
<Animated.View style={[animatedStyle, childrenContainerStyle]}>
|
622
678
|
{children}
|