@react-native-oh-tpl/react-native-gesture-handler 2.12.6-1 → 2.12.6-2
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/harmony/gesture_handler/LICENSE +21 -0
- package/harmony/gesture_handler/OAT.xml +44 -0
- package/harmony/gesture_handler/README.OpenSource +11 -0
- package/harmony/gesture_handler/README.md +1 -0
- package/harmony/gesture_handler/build-profile.json5 +7 -7
- package/harmony/gesture_handler/hvigorfile.ts +2 -2
- package/harmony/gesture_handler/index.ets +2 -2
- package/harmony/gesture_handler/oh-package.json5 +13 -11
- package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -8
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +33 -33
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +14 -14
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonComponentDescriptor.h +60 -60
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.cpp +17 -17
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.h +11 -11
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentDescriptor.h +60 -60
- package/harmony/gesture_handler/src/main/ets/CircularBuffer.ts +42 -42
- package/harmony/gesture_handler/src/main/ets/Event.ts +67 -67
- package/harmony/gesture_handler/src/main/ets/EventDispatcher.ts +37 -37
- package/harmony/gesture_handler/src/main/ets/GestureHandler.ts +663 -663
- package/harmony/gesture_handler/src/main/ets/GestureHandlerArkUIAdapter.ets +201 -201
- package/harmony/gesture_handler/src/main/ets/GestureHandlerFactory.ts +44 -44
- package/harmony/gesture_handler/src/main/ets/GestureHandlerOrchestrator.ts +280 -280
- package/harmony/gesture_handler/src/main/ets/GestureHandlerPackage.ts +22 -22
- package/harmony/gesture_handler/src/main/ets/GestureHandlerRegistry.ts +27 -27
- package/harmony/gesture_handler/src/main/ets/InteractionManager.ts +108 -108
- package/harmony/gesture_handler/src/main/ets/LeastSquareSolver.ts +182 -182
- package/harmony/gesture_handler/src/main/ets/NativeViewGestureHandler.ts +114 -114
- package/harmony/gesture_handler/src/main/ets/OutgoingEvent.ts +33 -33
- package/harmony/gesture_handler/src/main/ets/PanGestureHandler.ts +327 -327
- package/harmony/gesture_handler/src/main/ets/PointerTracker.ts +239 -239
- package/harmony/gesture_handler/src/main/ets/RNGHError.ts +4 -4
- package/harmony/gesture_handler/src/main/ets/RNGHLogger.ts +28 -28
- package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandler.ets +57 -57
- package/harmony/gesture_handler/src/main/ets/RNGestureHandlerButton.ets +36 -36
- package/harmony/gesture_handler/src/main/ets/RNGestureHandlerModule.ts +125 -125
- package/harmony/gesture_handler/src/main/ets/RNGestureHandlerRootView.ets +56 -55
- package/harmony/gesture_handler/src/main/ets/RNOHScrollLocker.ts +10 -10
- package/harmony/gesture_handler/src/main/ets/State.ts +46 -46
- package/harmony/gesture_handler/src/main/ets/TapGestureHandler.ts +205 -205
- package/harmony/gesture_handler/src/main/ets/Vector2D.ts +36 -36
- package/harmony/gesture_handler/src/main/ets/VelocityTracker.ts +98 -98
- package/harmony/gesture_handler/src/main/ets/View.ts +70 -70
- package/harmony/gesture_handler/src/main/ets/ViewRegistry.ts +42 -42
- package/harmony/gesture_handler/src/main/ets/pages/Index.ets +16 -16
- package/harmony/gesture_handler/src/main/ets/webviewability/WebviewAbility.ts +41 -41
- package/harmony/gesture_handler/src/main/module.json5 +6 -6
- package/harmony/gesture_handler/src/main/resources/base/element/color.json +7 -7
- package/harmony/gesture_handler/src/main/resources/base/element/string.json +15 -15
- package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -5
- package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +15 -15
- package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +15 -15
- package/harmony/gesture_handler.har +0 -0
- package/lib/commonjs/components/touchables/GenericTouchable.js +9 -9
- package/lib/commonjs/components/touchables/TouchableOpacity.js +2 -2
- package/lib/commonjs/handlers/createNativeWrapper.js +6 -6
- package/lib/commonjs/handlers/gestures/GestureDetector.js +3 -3
- package/lib/module/components/touchables/GenericTouchable.js +9 -9
- package/lib/module/components/touchables/TouchableOpacity.js +2 -2
- package/lib/module/handlers/createNativeWrapper.js +6 -6
- package/lib/module/handlers/gestures/GestureDetector.js +3 -3
- package/package.json +70 -70
- package/src/RNGestureHandlerModule.ts +6 -6
- package/src/components/GestureButtons.tsx +334 -334
- package/src/components/GestureHandlerButton.tsx +5 -5
- package/src/components/GestureHandlerRootView.tsx +34 -34
- package/src/components/RNGestureHandlerButton.tsx +23 -23
- package/src/components/touchables/GenericTouchable.tsx +301 -301
- package/src/components/touchables/TouchableOpacity.tsx +76 -76
- package/src/components/touchables/TouchableWithoutFeedback.tsx +14 -14
- package/src/components/touchables/index.ts +7 -7
- package/src/handlers/NativeViewGestureHandler.ts +55 -55
- package/src/handlers/PanGestureHandler.ts +327 -327
- package/src/handlers/TapGestureHandler.ts +95 -95
- package/src/handlers/createHandler.tsx +535 -535
- package/src/handlers/createNativeWrapper.tsx +81 -81
- package/src/handlers/gestureHandlerCommon.ts +15 -15
- package/src/handlers/gestures/GestureDetector.tsx +823 -823
- package/src/index.ts +172 -172
- package/src/init.ts +18 -18
|
@@ -1,334 +1,334 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Animated,
|
|
4
|
-
Platform,
|
|
5
|
-
processColor,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
StyleProp,
|
|
8
|
-
ViewStyle,
|
|
9
|
-
} from 'react-native';
|
|
10
|
-
|
|
11
|
-
import createNativeWrapper from '../handlers/createNativeWrapper';
|
|
12
|
-
import GestureHandlerButton from './GestureHandlerButton';
|
|
13
|
-
import { State } from 'react-native-gesture-handler/src/State';
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
GestureEvent,
|
|
17
|
-
HandlerStateChangeEvent,
|
|
18
|
-
} from 'react-native-gesture-handler/src/handlers/gestureHandlerCommon';
|
|
19
|
-
import {
|
|
20
|
-
NativeViewGestureHandlerPayload,
|
|
21
|
-
NativeViewGestureHandlerProps,
|
|
22
|
-
} from 'react-native-gesture-handler/src/handlers/NativeViewGestureHandler';
|
|
23
|
-
|
|
24
|
-
export interface RawButtonProps extends NativeViewGestureHandlerProps {
|
|
25
|
-
/**
|
|
26
|
-
* Defines if more than one button could be pressed simultaneously. By default
|
|
27
|
-
* set true.
|
|
28
|
-
*/
|
|
29
|
-
exclusive?: boolean;
|
|
30
|
-
// TODO: we should transform props in `createNativeWrapper`
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Android only.
|
|
34
|
-
*
|
|
35
|
-
* Defines color of native ripple animation used since API level 21.
|
|
36
|
-
*/
|
|
37
|
-
rippleColor?: any; // it was present in BaseButtonProps before but is used here in code
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Android only.
|
|
41
|
-
*
|
|
42
|
-
* Defines radius of native ripple animation used since API level 21.
|
|
43
|
-
*/
|
|
44
|
-
rippleRadius?: number | null;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Android only.
|
|
48
|
-
*
|
|
49
|
-
* Set this to true if you want the ripple animation to render outside the view bounds.
|
|
50
|
-
*/
|
|
51
|
-
borderless?: boolean;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Android only.
|
|
55
|
-
*
|
|
56
|
-
* Defines whether the ripple animation should be drawn on the foreground of the view.
|
|
57
|
-
*/
|
|
58
|
-
foreground?: boolean;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Android only.
|
|
62
|
-
*
|
|
63
|
-
* Set this to true if you don't want the system to play sound when the button is pressed.
|
|
64
|
-
*/
|
|
65
|
-
touchSoundDisabled?: boolean;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface BaseButtonProps extends RawButtonProps {
|
|
69
|
-
/**
|
|
70
|
-
* Called when the button gets pressed (analogous to `onPress` in
|
|
71
|
-
* `TouchableHighlight` from RN core).
|
|
72
|
-
*/
|
|
73
|
-
onPress?: (pointerInside: boolean) => void;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Called when the button gets pressed and is held for `delayLongPress`
|
|
77
|
-
* milliseconds.
|
|
78
|
-
*/
|
|
79
|
-
onLongPress?: () => void;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Called when button changes from inactive to active and vice versa. It
|
|
83
|
-
* passes active state as a boolean variable as a first parameter for that
|
|
84
|
-
* method.
|
|
85
|
-
*/
|
|
86
|
-
onActiveStateChange?: (active: boolean) => void;
|
|
87
|
-
style?: StyleProp<ViewStyle>;
|
|
88
|
-
testID?: string;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Delay, in milliseconds, after which the `onLongPress` callback gets called.
|
|
92
|
-
* Defaults to 600.
|
|
93
|
-
*/
|
|
94
|
-
delayLongPress?: number;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface RectButtonProps extends BaseButtonProps {
|
|
98
|
-
/**
|
|
99
|
-
* Background color that will be dimmed when button is in active state.
|
|
100
|
-
*/
|
|
101
|
-
underlayColor?: string;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* iOS only.
|
|
105
|
-
*
|
|
106
|
-
* Opacity applied to the underlay when button is in active state.
|
|
107
|
-
*/
|
|
108
|
-
activeOpacity?: number;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export interface BorderlessButtonProps extends BaseButtonProps {
|
|
112
|
-
/**
|
|
113
|
-
* iOS only.
|
|
114
|
-
*
|
|
115
|
-
* Opacity applied to the button when it is in an active state.
|
|
116
|
-
*/
|
|
117
|
-
activeOpacity?: number;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export const RawButton = createNativeWrapper(GestureHandlerButton, {
|
|
121
|
-
shouldCancelWhenOutside: false,
|
|
122
|
-
shouldActivateOnStart: false,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
export class BaseButton extends React.Component<BaseButtonProps> {
|
|
126
|
-
static defaultProps = {
|
|
127
|
-
delayLongPress: 600,
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
private lastActive: boolean;
|
|
131
|
-
private longPressTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
132
|
-
private longPressDetected: boolean;
|
|
133
|
-
|
|
134
|
-
constructor(props: BaseButtonProps) {
|
|
135
|
-
super(props);
|
|
136
|
-
this.lastActive = false;
|
|
137
|
-
this.longPressDetected = false;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private handleEvent = ({
|
|
141
|
-
nativeEvent,
|
|
142
|
-
}: HandlerStateChangeEvent<NativeViewGestureHandlerPayload>) => {
|
|
143
|
-
const { state, oldState, pointerInside } = nativeEvent;
|
|
144
|
-
const active = pointerInside && state === State.ACTIVE;
|
|
145
|
-
|
|
146
|
-
if (active !== this.lastActive && this.props.onActiveStateChange) {
|
|
147
|
-
this.props.onActiveStateChange(active);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
!this.longPressDetected &&
|
|
152
|
-
oldState === State.ACTIVE &&
|
|
153
|
-
state !== State.CANCELLED &&
|
|
154
|
-
this.lastActive &&
|
|
155
|
-
this.props.onPress
|
|
156
|
-
) {
|
|
157
|
-
this.props.onPress(active);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (
|
|
161
|
-
!this.lastActive &&
|
|
162
|
-
// NativeViewGestureHandler sends different events based on platform
|
|
163
|
-
state === (Platform.OS !== 'android' ? State.ACTIVE : State.BEGAN) &&
|
|
164
|
-
pointerInside
|
|
165
|
-
) {
|
|
166
|
-
this.longPressDetected = false;
|
|
167
|
-
if (this.props.onLongPress) {
|
|
168
|
-
this.longPressTimeout = setTimeout(
|
|
169
|
-
this.onLongPress,
|
|
170
|
-
this.props.delayLongPress
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
} else if (
|
|
174
|
-
// cancel longpress timeout if it's set and the finger moved out of the view
|
|
175
|
-
state === State.ACTIVE &&
|
|
176
|
-
!pointerInside &&
|
|
177
|
-
this.longPressTimeout !== undefined
|
|
178
|
-
) {
|
|
179
|
-
clearTimeout(this.longPressTimeout);
|
|
180
|
-
this.longPressTimeout = undefined;
|
|
181
|
-
} else if (
|
|
182
|
-
// cancel longpress timeout if it's set and the gesture has finished
|
|
183
|
-
this.longPressTimeout !== undefined &&
|
|
184
|
-
(state === State.END ||
|
|
185
|
-
state === State.CANCELLED ||
|
|
186
|
-
state === State.FAILED)
|
|
187
|
-
) {
|
|
188
|
-
clearTimeout(this.longPressTimeout);
|
|
189
|
-
this.longPressTimeout = undefined;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
this.lastActive = active;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
private onLongPress = () => {
|
|
196
|
-
this.longPressDetected = true;
|
|
197
|
-
this.props.onLongPress?.();
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// Normally, the parent would execute it's handler first, then forward the
|
|
201
|
-
// event to listeners. However, here our handler is virtually only forwarding
|
|
202
|
-
// events to listeners, so we reverse the order to keep the proper order of
|
|
203
|
-
// the callbacks (from "raw" ones to "processed").
|
|
204
|
-
private onHandlerStateChange = (
|
|
205
|
-
e: HandlerStateChangeEvent<NativeViewGestureHandlerPayload>
|
|
206
|
-
) => {
|
|
207
|
-
this.props.onHandlerStateChange?.(e);
|
|
208
|
-
this.handleEvent(e);
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
private onGestureEvent = (
|
|
212
|
-
e: GestureEvent<NativeViewGestureHandlerPayload>
|
|
213
|
-
) => {
|
|
214
|
-
this.props.onGestureEvent?.(e);
|
|
215
|
-
this.handleEvent(
|
|
216
|
-
e as HandlerStateChangeEvent<NativeViewGestureHandlerPayload>
|
|
217
|
-
); // TODO: maybe it is not correct
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
render() {
|
|
221
|
-
const { rippleColor, ...rest } = this.props;
|
|
222
|
-
|
|
223
|
-
return (
|
|
224
|
-
<RawButton
|
|
225
|
-
rippleColor={processColor(rippleColor)}
|
|
226
|
-
{...rest}
|
|
227
|
-
onGestureEvent={this.onGestureEvent}
|
|
228
|
-
onHandlerStateChange={this.onHandlerStateChange}
|
|
229
|
-
/>
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const AnimatedBaseButton = Animated.createAnimatedComponent(BaseButton);
|
|
235
|
-
|
|
236
|
-
const btnStyles = StyleSheet.create({
|
|
237
|
-
underlay: {
|
|
238
|
-
position: 'absolute',
|
|
239
|
-
left: 0,
|
|
240
|
-
right: 0,
|
|
241
|
-
bottom: 0,
|
|
242
|
-
top: 0,
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
export class RectButton extends React.Component<RectButtonProps> {
|
|
247
|
-
static defaultProps = {
|
|
248
|
-
activeOpacity: 0.105,
|
|
249
|
-
underlayColor: 'black',
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
private opacity: Animated.Value;
|
|
253
|
-
|
|
254
|
-
constructor(props: RectButtonProps) {
|
|
255
|
-
super(props);
|
|
256
|
-
this.opacity = new Animated.Value(0);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
private onActiveStateChange = (active: boolean) => {
|
|
260
|
-
if (Platform.OS !== 'android') {
|
|
261
|
-
this.opacity.setValue(active ? this.props.activeOpacity! : 0);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
this.props.onActiveStateChange?.(active);
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
render() {
|
|
268
|
-
const { children, style, ...rest } = this.props;
|
|
269
|
-
|
|
270
|
-
const resolvedStyle = StyleSheet.flatten(style ?? {});
|
|
271
|
-
|
|
272
|
-
return (
|
|
273
|
-
<BaseButton
|
|
274
|
-
{...rest}
|
|
275
|
-
style={resolvedStyle}
|
|
276
|
-
onActiveStateChange={this.onActiveStateChange}
|
|
277
|
-
>
|
|
278
|
-
<Animated.View
|
|
279
|
-
style={[
|
|
280
|
-
btnStyles.underlay,
|
|
281
|
-
{
|
|
282
|
-
opacity: this.opacity,
|
|
283
|
-
backgroundColor: this.props.underlayColor,
|
|
284
|
-
borderRadius: resolvedStyle.borderRadius,
|
|
285
|
-
borderTopLeftRadius: resolvedStyle.borderTopLeftRadius,
|
|
286
|
-
borderTopRightRadius: resolvedStyle.borderTopRightRadius,
|
|
287
|
-
borderBottomLeftRadius: resolvedStyle.borderBottomLeftRadius,
|
|
288
|
-
borderBottomRightRadius: resolvedStyle.borderBottomRightRadius,
|
|
289
|
-
},
|
|
290
|
-
]}
|
|
291
|
-
/>
|
|
292
|
-
{children}
|
|
293
|
-
</BaseButton>
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
export class BorderlessButton extends React.Component<BorderlessButtonProps> {
|
|
299
|
-
static defaultProps = {
|
|
300
|
-
activeOpacity: 0.3,
|
|
301
|
-
borderless: true,
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
private opacity: Animated.Value;
|
|
305
|
-
|
|
306
|
-
constructor(props: BorderlessButtonProps) {
|
|
307
|
-
super(props);
|
|
308
|
-
this.opacity = new Animated.Value(1);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
private onActiveStateChange = (active: boolean) => {
|
|
312
|
-
if (Platform.OS !== 'android') {
|
|
313
|
-
this.opacity.setValue(active ? this.props.activeOpacity! : 1);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
this.props.onActiveStateChange?.(active);
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
render() {
|
|
320
|
-
const { children, style, ...rest } = this.props;
|
|
321
|
-
|
|
322
|
-
return (
|
|
323
|
-
<AnimatedBaseButton
|
|
324
|
-
{...rest}
|
|
325
|
-
onActiveStateChange={this.onActiveStateChange}
|
|
326
|
-
style={[style, Platform.OS === 'ios' && { opacity: this.opacity }]}
|
|
327
|
-
>
|
|
328
|
-
{children}
|
|
329
|
-
</AnimatedBaseButton>
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export { default as PureNativeButton } from './GestureHandlerButton';
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Animated,
|
|
4
|
+
Platform,
|
|
5
|
+
processColor,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
StyleProp,
|
|
8
|
+
ViewStyle,
|
|
9
|
+
} from 'react-native';
|
|
10
|
+
|
|
11
|
+
import createNativeWrapper from '../handlers/createNativeWrapper';
|
|
12
|
+
import GestureHandlerButton from './GestureHandlerButton';
|
|
13
|
+
import { State } from 'react-native-gesture-handler/src/State';
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
GestureEvent,
|
|
17
|
+
HandlerStateChangeEvent,
|
|
18
|
+
} from 'react-native-gesture-handler/src/handlers/gestureHandlerCommon';
|
|
19
|
+
import {
|
|
20
|
+
NativeViewGestureHandlerPayload,
|
|
21
|
+
NativeViewGestureHandlerProps,
|
|
22
|
+
} from 'react-native-gesture-handler/src/handlers/NativeViewGestureHandler';
|
|
23
|
+
|
|
24
|
+
export interface RawButtonProps extends NativeViewGestureHandlerProps {
|
|
25
|
+
/**
|
|
26
|
+
* Defines if more than one button could be pressed simultaneously. By default
|
|
27
|
+
* set true.
|
|
28
|
+
*/
|
|
29
|
+
exclusive?: boolean;
|
|
30
|
+
// TODO: we should transform props in `createNativeWrapper`
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Android only.
|
|
34
|
+
*
|
|
35
|
+
* Defines color of native ripple animation used since API level 21.
|
|
36
|
+
*/
|
|
37
|
+
rippleColor?: any; // it was present in BaseButtonProps before but is used here in code
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Android only.
|
|
41
|
+
*
|
|
42
|
+
* Defines radius of native ripple animation used since API level 21.
|
|
43
|
+
*/
|
|
44
|
+
rippleRadius?: number | null;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Android only.
|
|
48
|
+
*
|
|
49
|
+
* Set this to true if you want the ripple animation to render outside the view bounds.
|
|
50
|
+
*/
|
|
51
|
+
borderless?: boolean;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Android only.
|
|
55
|
+
*
|
|
56
|
+
* Defines whether the ripple animation should be drawn on the foreground of the view.
|
|
57
|
+
*/
|
|
58
|
+
foreground?: boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Android only.
|
|
62
|
+
*
|
|
63
|
+
* Set this to true if you don't want the system to play sound when the button is pressed.
|
|
64
|
+
*/
|
|
65
|
+
touchSoundDisabled?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface BaseButtonProps extends RawButtonProps {
|
|
69
|
+
/**
|
|
70
|
+
* Called when the button gets pressed (analogous to `onPress` in
|
|
71
|
+
* `TouchableHighlight` from RN core).
|
|
72
|
+
*/
|
|
73
|
+
onPress?: (pointerInside: boolean) => void;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Called when the button gets pressed and is held for `delayLongPress`
|
|
77
|
+
* milliseconds.
|
|
78
|
+
*/
|
|
79
|
+
onLongPress?: () => void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Called when button changes from inactive to active and vice versa. It
|
|
83
|
+
* passes active state as a boolean variable as a first parameter for that
|
|
84
|
+
* method.
|
|
85
|
+
*/
|
|
86
|
+
onActiveStateChange?: (active: boolean) => void;
|
|
87
|
+
style?: StyleProp<ViewStyle>;
|
|
88
|
+
testID?: string;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Delay, in milliseconds, after which the `onLongPress` callback gets called.
|
|
92
|
+
* Defaults to 600.
|
|
93
|
+
*/
|
|
94
|
+
delayLongPress?: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface RectButtonProps extends BaseButtonProps {
|
|
98
|
+
/**
|
|
99
|
+
* Background color that will be dimmed when button is in active state.
|
|
100
|
+
*/
|
|
101
|
+
underlayColor?: string;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* iOS only.
|
|
105
|
+
*
|
|
106
|
+
* Opacity applied to the underlay when button is in active state.
|
|
107
|
+
*/
|
|
108
|
+
activeOpacity?: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface BorderlessButtonProps extends BaseButtonProps {
|
|
112
|
+
/**
|
|
113
|
+
* iOS only.
|
|
114
|
+
*
|
|
115
|
+
* Opacity applied to the button when it is in an active state.
|
|
116
|
+
*/
|
|
117
|
+
activeOpacity?: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const RawButton = createNativeWrapper(GestureHandlerButton, {
|
|
121
|
+
shouldCancelWhenOutside: false,
|
|
122
|
+
shouldActivateOnStart: false,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export class BaseButton extends React.Component<BaseButtonProps> {
|
|
126
|
+
static defaultProps = {
|
|
127
|
+
delayLongPress: 600,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
private lastActive: boolean;
|
|
131
|
+
private longPressTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
132
|
+
private longPressDetected: boolean;
|
|
133
|
+
|
|
134
|
+
constructor(props: BaseButtonProps) {
|
|
135
|
+
super(props);
|
|
136
|
+
this.lastActive = false;
|
|
137
|
+
this.longPressDetected = false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private handleEvent = ({
|
|
141
|
+
nativeEvent,
|
|
142
|
+
}: HandlerStateChangeEvent<NativeViewGestureHandlerPayload>) => {
|
|
143
|
+
const { state, oldState, pointerInside } = nativeEvent;
|
|
144
|
+
const active = pointerInside && state === State.ACTIVE;
|
|
145
|
+
|
|
146
|
+
if (active !== this.lastActive && this.props.onActiveStateChange) {
|
|
147
|
+
this.props.onActiveStateChange(active);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (
|
|
151
|
+
!this.longPressDetected &&
|
|
152
|
+
oldState === State.ACTIVE &&
|
|
153
|
+
state !== State.CANCELLED &&
|
|
154
|
+
this.lastActive &&
|
|
155
|
+
this.props.onPress
|
|
156
|
+
) {
|
|
157
|
+
this.props.onPress(active);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (
|
|
161
|
+
!this.lastActive &&
|
|
162
|
+
// NativeViewGestureHandler sends different events based on platform
|
|
163
|
+
state === (Platform.OS !== 'android' ? State.ACTIVE : State.BEGAN) &&
|
|
164
|
+
pointerInside
|
|
165
|
+
) {
|
|
166
|
+
this.longPressDetected = false;
|
|
167
|
+
if (this.props.onLongPress) {
|
|
168
|
+
this.longPressTimeout = setTimeout(
|
|
169
|
+
this.onLongPress,
|
|
170
|
+
this.props.delayLongPress
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
} else if (
|
|
174
|
+
// cancel longpress timeout if it's set and the finger moved out of the view
|
|
175
|
+
state === State.ACTIVE &&
|
|
176
|
+
!pointerInside &&
|
|
177
|
+
this.longPressTimeout !== undefined
|
|
178
|
+
) {
|
|
179
|
+
clearTimeout(this.longPressTimeout);
|
|
180
|
+
this.longPressTimeout = undefined;
|
|
181
|
+
} else if (
|
|
182
|
+
// cancel longpress timeout if it's set and the gesture has finished
|
|
183
|
+
this.longPressTimeout !== undefined &&
|
|
184
|
+
(state === State.END ||
|
|
185
|
+
state === State.CANCELLED ||
|
|
186
|
+
state === State.FAILED)
|
|
187
|
+
) {
|
|
188
|
+
clearTimeout(this.longPressTimeout);
|
|
189
|
+
this.longPressTimeout = undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.lastActive = active;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
private onLongPress = () => {
|
|
196
|
+
this.longPressDetected = true;
|
|
197
|
+
this.props.onLongPress?.();
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// Normally, the parent would execute it's handler first, then forward the
|
|
201
|
+
// event to listeners. However, here our handler is virtually only forwarding
|
|
202
|
+
// events to listeners, so we reverse the order to keep the proper order of
|
|
203
|
+
// the callbacks (from "raw" ones to "processed").
|
|
204
|
+
private onHandlerStateChange = (
|
|
205
|
+
e: HandlerStateChangeEvent<NativeViewGestureHandlerPayload>
|
|
206
|
+
) => {
|
|
207
|
+
this.props.onHandlerStateChange?.(e);
|
|
208
|
+
this.handleEvent(e);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
private onGestureEvent = (
|
|
212
|
+
e: GestureEvent<NativeViewGestureHandlerPayload>
|
|
213
|
+
) => {
|
|
214
|
+
this.props.onGestureEvent?.(e);
|
|
215
|
+
this.handleEvent(
|
|
216
|
+
e as HandlerStateChangeEvent<NativeViewGestureHandlerPayload>
|
|
217
|
+
); // TODO: maybe it is not correct
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
render() {
|
|
221
|
+
const { rippleColor, ...rest } = this.props;
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<RawButton
|
|
225
|
+
rippleColor={processColor(rippleColor)}
|
|
226
|
+
{...rest}
|
|
227
|
+
onGestureEvent={this.onGestureEvent}
|
|
228
|
+
onHandlerStateChange={this.onHandlerStateChange}
|
|
229
|
+
/>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const AnimatedBaseButton = Animated.createAnimatedComponent(BaseButton);
|
|
235
|
+
|
|
236
|
+
const btnStyles = StyleSheet.create({
|
|
237
|
+
underlay: {
|
|
238
|
+
position: 'absolute',
|
|
239
|
+
left: 0,
|
|
240
|
+
right: 0,
|
|
241
|
+
bottom: 0,
|
|
242
|
+
top: 0,
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
export class RectButton extends React.Component<RectButtonProps> {
|
|
247
|
+
static defaultProps = {
|
|
248
|
+
activeOpacity: 0.105,
|
|
249
|
+
underlayColor: 'black',
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
private opacity: Animated.Value;
|
|
253
|
+
|
|
254
|
+
constructor(props: RectButtonProps) {
|
|
255
|
+
super(props);
|
|
256
|
+
this.opacity = new Animated.Value(0);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private onActiveStateChange = (active: boolean) => {
|
|
260
|
+
if (Platform.OS !== 'android') {
|
|
261
|
+
this.opacity.setValue(active ? this.props.activeOpacity! : 0);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
this.props.onActiveStateChange?.(active);
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
render() {
|
|
268
|
+
const { children, style, ...rest } = this.props;
|
|
269
|
+
|
|
270
|
+
const resolvedStyle = StyleSheet.flatten(style ?? {});
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<BaseButton
|
|
274
|
+
{...rest}
|
|
275
|
+
style={resolvedStyle}
|
|
276
|
+
onActiveStateChange={this.onActiveStateChange}
|
|
277
|
+
>
|
|
278
|
+
<Animated.View
|
|
279
|
+
style={[
|
|
280
|
+
btnStyles.underlay,
|
|
281
|
+
{
|
|
282
|
+
opacity: this.opacity,
|
|
283
|
+
backgroundColor: this.props.underlayColor,
|
|
284
|
+
borderRadius: resolvedStyle.borderRadius,
|
|
285
|
+
borderTopLeftRadius: resolvedStyle.borderTopLeftRadius,
|
|
286
|
+
borderTopRightRadius: resolvedStyle.borderTopRightRadius,
|
|
287
|
+
borderBottomLeftRadius: resolvedStyle.borderBottomLeftRadius,
|
|
288
|
+
borderBottomRightRadius: resolvedStyle.borderBottomRightRadius,
|
|
289
|
+
},
|
|
290
|
+
]}
|
|
291
|
+
/>
|
|
292
|
+
{children}
|
|
293
|
+
</BaseButton>
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export class BorderlessButton extends React.Component<BorderlessButtonProps> {
|
|
299
|
+
static defaultProps = {
|
|
300
|
+
activeOpacity: 0.3,
|
|
301
|
+
borderless: true,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
private opacity: Animated.Value;
|
|
305
|
+
|
|
306
|
+
constructor(props: BorderlessButtonProps) {
|
|
307
|
+
super(props);
|
|
308
|
+
this.opacity = new Animated.Value(1);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private onActiveStateChange = (active: boolean) => {
|
|
312
|
+
if (Platform.OS !== 'android') {
|
|
313
|
+
this.opacity.setValue(active ? this.props.activeOpacity! : 1);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
this.props.onActiveStateChange?.(active);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
render() {
|
|
320
|
+
const { children, style, ...rest } = this.props;
|
|
321
|
+
|
|
322
|
+
return (
|
|
323
|
+
<AnimatedBaseButton
|
|
324
|
+
{...rest}
|
|
325
|
+
onActiveStateChange={this.onActiveStateChange}
|
|
326
|
+
style={[style, Platform.OS === 'ios' && { opacity: this.opacity }]}
|
|
327
|
+
>
|
|
328
|
+
{children}
|
|
329
|
+
</AnimatedBaseButton>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export { default as PureNativeButton } from './GestureHandlerButton';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HostComponent } from 'react-native';
|
|
2
|
-
import { RawButtonProps } from 'react-native-gesture-handler/src/components/GestureButtons';
|
|
3
|
-
import { RNGestureHandlerButton } from './RNGestureHandlerButton';
|
|
4
|
-
|
|
5
|
-
export default RNGestureHandlerButton as HostComponent<RawButtonProps>;
|
|
1
|
+
import { HostComponent } from 'react-native';
|
|
2
|
+
import { RawButtonProps } from 'react-native-gesture-handler/src/components/GestureButtons';
|
|
3
|
+
import { RNGestureHandlerButton } from './RNGestureHandlerButton';
|
|
4
|
+
|
|
5
|
+
export default RNGestureHandlerButton as HostComponent<RawButtonProps>;
|