Skip to content

Commit 81c5b06

Browse files
authored
Update GestureButton props type (#3973)
## Description I've noticed that our buttons still had props like `onBegan` available, even though it was a reference to the old API. This PR changes that, so that additional properties on buttons come only from `NativeWrapper`. It also changes `hitSlop` type to the one from React Native. ## Test plan - `yarn ts-check` - `yarn lint-js` - Example with buttons in **basic-example** (with `console.log` in `onPress` added)
1 parent 0e74233 commit 81c5b06

6 files changed

Lines changed: 155 additions & 149 deletions

File tree

packages/react-native-gesture-handler/src/components/GestureHandlerButton.tsx

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,110 @@
1-
import { HostComponent, StyleSheet, View } from 'react-native';
2-
import type { RawButtonProps } from '../v3/components/GestureButtonsProps';
1+
import {
2+
AccessibilityProps,
3+
ColorValue,
4+
HostComponent,
5+
LayoutChangeEvent,
6+
StyleProp,
7+
StyleSheet,
8+
View,
9+
ViewProps,
10+
ViewStyle,
11+
} from 'react-native';
312
import RNGestureHandlerButtonNativeComponent from '../specs/RNGestureHandlerButtonNativeComponent';
413
import RNGestureHandlerButtonWrapperNativeComponent from '../specs/RNGestureHandlerButtonWrapperNativeComponent';
514
import { useMemo } from 'react';
615

16+
export interface ButtonProps extends ViewProps, AccessibilityProps {
17+
children?: React.ReactNode;
18+
19+
/**
20+
* Defines if buttons should respond to touches. By default set to true.
21+
*/
22+
enabled?: boolean;
23+
24+
/**
25+
* Defines if more than one button could be pressed simultaneously. By default
26+
* set true.
27+
*/
28+
exclusive?: boolean;
29+
30+
/**
31+
* Android only.
32+
*
33+
* Defines color of native ripple animation used since API level 21.
34+
*/
35+
rippleColor?: number | ColorValue | null;
36+
37+
/**
38+
* Android only.
39+
*
40+
* Defines radius of native ripple animation used since API level 21.
41+
*/
42+
rippleRadius?: number | null;
43+
44+
/**
45+
* Android only.
46+
*
47+
* Set this to true if you want the ripple animation to render outside the view bounds.
48+
*/
49+
borderless?: boolean;
50+
51+
/**
52+
* Android only.
53+
*
54+
* Defines whether the ripple animation should be drawn on the foreground of the view.
55+
*/
56+
foreground?: boolean;
57+
58+
/**
59+
* Android only.
60+
*
61+
* Set this to true if you don't want the system to play sound when the button is pressed.
62+
*/
63+
touchSoundDisabled?: boolean;
64+
65+
/**
66+
* Style object, use it to set additional styles.
67+
*/
68+
style?: StyleProp<ViewStyle>;
69+
70+
/**
71+
* Invoked on mount and layout changes.
72+
*/
73+
onLayout?: (event: LayoutChangeEvent) => void;
74+
75+
/**
76+
* Used for testing-library compatibility, not passed to the native component.
77+
* @deprecated test-only props are deprecated and will be removed in the future.
78+
*/
79+
// eslint-disable-next-line @typescript-eslint/ban-types
80+
testOnly_onPress?: Function | null;
81+
82+
/**
83+
* Used for testing-library compatibility, not passed to the native component.
84+
* @deprecated test-only props are deprecated and will be removed in the future.
85+
*/
86+
// eslint-disable-next-line @typescript-eslint/ban-types
87+
testOnly_onPressIn?: Function | null;
88+
89+
/**
90+
* Used for testing-library compatibility, not passed to the native component.
91+
* @deprecated test-only props are deprecated and will be removed in the future.
92+
*/
93+
// eslint-disable-next-line @typescript-eslint/ban-types
94+
testOnly_onPressOut?: Function | null;
95+
96+
/**
97+
* Used for testing-library compatibility, not passed to the native component.
98+
* @deprecated test-only props are deprecated and will be removed in the future.
99+
*/
100+
// eslint-disable-next-line @typescript-eslint/ban-types
101+
testOnly_onLongPress?: Function | null;
102+
}
103+
7104
const ButtonComponent =
8-
RNGestureHandlerButtonNativeComponent as HostComponent<RawButtonProps>;
105+
RNGestureHandlerButtonNativeComponent as HostComponent<ButtonProps>;
9106

10-
export default function GestureHandlerButton({
11-
style,
12-
...rest
13-
}: RawButtonProps) {
107+
export default function GestureHandlerButton({ style, ...rest }: ButtonProps) {
14108
const flattenedStyle = useMemo(() => StyleSheet.flatten(style), [style]);
15109

16110
const {
Lines changed: 10 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,15 @@
1-
import * as React from 'react';
2-
import {
3-
AccessibilityProps,
4-
ColorValue,
5-
LayoutChangeEvent,
6-
StyleProp,
7-
ViewStyle,
8-
} from 'react-native';
9-
import type { NativeViewGestureHandlerProps } from '../../handlers/NativeViewGestureHandler';
1+
import { StyleProp, ViewStyle } from 'react-native';
2+
import type { NativeWrapperProperties } from '../types/NativeWrapperType';
3+
import GestureHandlerButton, {
4+
ButtonProps,
5+
} from '../../components/GestureHandlerButton';
106

117
export interface RawButtonProps
12-
extends NativeViewGestureHandlerProps,
13-
AccessibilityProps {
14-
/**
15-
* Defines if more than one button could be pressed simultaneously. By default
16-
* set true.
17-
*/
18-
exclusive?: boolean;
19-
// TODO: we should transform props in `createNativeWrapper`
20-
/**
21-
* Android only.
22-
*
23-
* Defines color of native ripple animation used since API level 21.
24-
*/
25-
rippleColor?: number | ColorValue | null;
26-
27-
/**
28-
* Android only.
29-
*
30-
* Defines radius of native ripple animation used since API level 21.
31-
*/
32-
rippleRadius?: number | null;
33-
34-
/**
35-
* Android only.
36-
*
37-
* Set this to true if you want the ripple animation to render outside the view bounds.
38-
*/
39-
borderless?: boolean;
40-
41-
/**
42-
* Android only.
43-
*
44-
* Defines whether the ripple animation should be drawn on the foreground of the view.
45-
*/
46-
foreground?: boolean;
47-
48-
/**
49-
* Android only.
50-
*
51-
* Set this to true if you don't want the system to play sound when the button is pressed.
52-
*/
53-
touchSoundDisabled?: boolean;
54-
55-
/**
56-
* Style object, use it to set additional styles.
57-
*/
58-
style?: StyleProp<ViewStyle>;
59-
60-
/**
61-
* Invoked on mount and layout changes.
62-
*/
63-
onLayout?: (event: LayoutChangeEvent) => void;
64-
65-
/**
66-
* Used for testing-library compatibility, not passed to the native component.
67-
* @deprecated test-only props are deprecated and will be removed in the future.
68-
*/
69-
// eslint-disable-next-line @typescript-eslint/ban-types
70-
testOnly_onPress?: Function | null;
71-
72-
/**
73-
* Used for testing-library compatibility, not passed to the native component.
74-
* @deprecated test-only props are deprecated and will be removed in the future.
75-
*/
76-
// eslint-disable-next-line @typescript-eslint/ban-types
77-
testOnly_onPressIn?: Function | null;
78-
79-
/**
80-
* Used for testing-library compatibility, not passed to the native component.
81-
* @deprecated test-only props are deprecated and will be removed in the future.
82-
*/
83-
// eslint-disable-next-line @typescript-eslint/ban-types
84-
testOnly_onPressOut?: Function | null;
85-
86-
/**
87-
* Used for testing-library compatibility, not passed to the native component.
88-
* @deprecated test-only props are deprecated and will be removed in the future.
89-
*/
90-
// eslint-disable-next-line @typescript-eslint/ban-types
91-
testOnly_onLongPress?: Function | null;
92-
}
93-
interface ButtonWithRefProps {
94-
ref?: React.RefObject<any>;
95-
}
8+
extends ButtonProps,
9+
Omit<
10+
NativeWrapperProperties<ReturnType<typeof GestureHandlerButton>>,
11+
'hitSlop' | 'enabled'
12+
> {}
9613

9714
export interface BaseButtonProps extends RawButtonProps {
9815
/**
@@ -121,9 +38,6 @@ export interface BaseButtonProps extends RawButtonProps {
12138
*/
12239
delayLongPress?: number;
12340
}
124-
export interface BaseButtonWithRefProps
125-
extends BaseButtonProps,
126-
ButtonWithRefProps {}
12741

12842
export interface RectButtonProps extends BaseButtonProps {
12943
/**
@@ -138,9 +52,6 @@ export interface RectButtonProps extends BaseButtonProps {
13852
*/
13953
activeOpacity?: number;
14054
}
141-
export interface RectButtonWithRefProps
142-
extends RectButtonProps,
143-
ButtonWithRefProps {}
14455

14556
export interface BorderlessButtonProps extends BaseButtonProps {
14657
/**
@@ -150,6 +61,3 @@ export interface BorderlessButtonProps extends BaseButtonProps {
15061
*/
15162
activeOpacity?: number;
15263
}
153-
export interface BorderlessButtonWithRefProps
154-
extends BorderlessButtonProps,
155-
ButtonWithRefProps {}

packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import React, {
2-
PropsWithChildren,
3-
ReactElement,
4-
useState,
5-
RefObject,
6-
} from 'react';
1+
import React, { PropsWithChildren, ReactElement, useState } from 'react';
72
import {
83
ScrollView as RNScrollView,
94
ScrollViewProps as RNScrollViewProps,
@@ -14,6 +9,7 @@ import {
149
FlatList as RNFlatList,
1510
FlatListProps as RNFlatListProps,
1611
RefreshControl as RNRefreshControl,
12+
RefreshControlProps as RNRefreshControlProps,
1713
} from 'react-native';
1814

1915
import createNativeWrapper from '../createNativeWrapper';
@@ -24,7 +20,10 @@ import { GestureDetectorType } from '../detectors';
2420
import { NativeGesture } from '../hooks/gestures/native/useNativeGesture';
2521
import { ghQueueMicrotask } from '../../ghQueueMicrotask';
2622

27-
export const RefreshControl = createNativeWrapper(
23+
export const RefreshControl = createNativeWrapper<
24+
RNRefreshControl,
25+
RNRefreshControlProps
26+
>(
2827
RNRefreshControl,
2928
{
3029
disallowInterruption: true,
@@ -36,7 +35,10 @@ export const RefreshControl = createNativeWrapper(
3635
// eslint-disable-next-line @typescript-eslint/no-redeclare
3736
export type RefreshControl = typeof RefreshControl & RNRefreshControl;
3837

39-
const GHScrollView = createNativeWrapper<PropsWithChildren<RNScrollViewProps>>(
38+
const GHScrollView = createNativeWrapper<
39+
RNScrollView,
40+
PropsWithChildren<RNScrollViewProps>
41+
>(
4042
RNScrollView,
4143
{
4244
disallowInterruption: true,
@@ -46,13 +48,7 @@ const GHScrollView = createNativeWrapper<PropsWithChildren<RNScrollViewProps>>(
4648
);
4749

4850
export const ScrollView = (
49-
props: RNScrollViewProps &
50-
NativeWrapperProperties & {
51-
ref?: React.RefObject<RNScrollView | null>;
52-
onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: (
53-
gesture: NativeGesture
54-
) => void;
55-
}
51+
props: RNScrollViewProps & NativeWrapperProperties<RNScrollView | null>
5652
) => {
5753
const {
5854
refreshControl,
@@ -95,7 +91,7 @@ export const ScrollView = (
9591
// eslint-disable-next-line @typescript-eslint/no-redeclare
9692
export type ScrollView = typeof ScrollView & RNScrollView;
9793

98-
export const Switch = createNativeWrapper<RNSwitchProps>(RNSwitch, {
94+
export const Switch = createNativeWrapper<RNSwitch, RNSwitchProps>(RNSwitch, {
9995
shouldCancelWhenOutside: false,
10096
shouldActivateOnStart: true,
10197
disallowInterruption: true,
@@ -104,7 +100,9 @@ export const Switch = createNativeWrapper<RNSwitchProps>(RNSwitch, {
104100
// eslint-disable-next-line @typescript-eslint/no-redeclare
105101
export type Switch = typeof Switch & RNSwitch;
106102

107-
export const TextInput = createNativeWrapper<RNTextInputProps>(RNTextInput);
103+
export const TextInput = createNativeWrapper<RNTextInput, RNTextInputProps>(
104+
RNTextInput
105+
);
108106

109107
// eslint-disable-next-line @typescript-eslint/no-redeclare
110108
export type TextInput = typeof TextInput & RNTextInput;
@@ -175,12 +173,7 @@ export const FlatList = ((props) => {
175173
}) as <ItemT = any>(
176174
props: PropsWithChildren<
177175
Omit<RNFlatListProps<ItemT>, 'renderScrollComponent' | 'ref'> &
178-
NativeWrapperProperties & {
179-
ref?: RefObject<RNFlatList<ItemT> | null>;
180-
onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: (
181-
gesture: NativeGesture
182-
) => void;
183-
}
176+
NativeWrapperProperties<RNFlatList<ItemT> | null>
184177
>
185178
) => ReactElement | null;
186179

packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,22 @@ import React, { useEffect } from 'react';
33
import { NativeWrapperProps } from './hooks/utils';
44
import { useNativeGesture } from './hooks/gestures';
55
import { NativeDetector } from './detectors/NativeDetector';
6-
import type { NativeWrapperProperties } from './types/NativeWrapperType';
7-
import { NativeGesture } from './hooks/gestures/native/useNativeGesture';
6+
import type {
7+
NativeWrapperProperties,
8+
WrapperSpecificProperties,
9+
} from './types/NativeWrapperType';
810
import { GestureDetectorType, InterceptingGestureDetector } from './detectors';
911
import { VirtualDetector } from './detectors/VirtualDetector/VirtualDetector';
1012

11-
export default function createNativeWrapper<P>(
12-
Component: React.ComponentType<P>,
13-
config: Readonly<NativeWrapperProperties> = {},
13+
export default function createNativeWrapper<TRef = unknown, TProps = unknown>(
14+
Component: React.ComponentType<TProps>,
15+
config: Readonly<
16+
Omit<NativeWrapperProperties<TRef>, keyof WrapperSpecificProperties<TRef>>
17+
> = {},
1418
detectorType: GestureDetectorType = GestureDetectorType.Native
1519
) {
1620
const ComponentWrapper = (
17-
props: P &
18-
NativeWrapperProperties & {
19-
ref?: React.RefObject<unknown>;
20-
onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: (
21-
gesture: NativeGesture
22-
) => void;
23-
}
21+
props: TProps & NativeWrapperProperties<TRef | null>
2422
) => {
2523
const { ref, onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER, ...restProps } =
2624
props;
@@ -43,7 +41,7 @@ export default function createNativeWrapper<P>(
4341
enabled: props.enabled,
4442
hitSlop: props.hitSlop,
4543
testID: props.testID,
46-
} as P,
44+
} as TProps,
4745
}
4846
);
4947

0 commit comments

Comments
 (0)