diff --git a/packages/react-native-gesture-handler/src/components/GestureHandlerButton.tsx b/packages/react-native-gesture-handler/src/components/GestureHandlerButton.tsx index 6e6e268903..eef70ddb43 100644 --- a/packages/react-native-gesture-handler/src/components/GestureHandlerButton.tsx +++ b/packages/react-native-gesture-handler/src/components/GestureHandlerButton.tsx @@ -1,16 +1,110 @@ -import { HostComponent, StyleSheet, View } from 'react-native'; -import type { RawButtonProps } from '../v3/components/GestureButtonsProps'; +import { + AccessibilityProps, + ColorValue, + HostComponent, + LayoutChangeEvent, + StyleProp, + StyleSheet, + View, + ViewProps, + ViewStyle, +} from 'react-native'; import RNGestureHandlerButtonNativeComponent from '../specs/RNGestureHandlerButtonNativeComponent'; import RNGestureHandlerButtonWrapperNativeComponent from '../specs/RNGestureHandlerButtonWrapperNativeComponent'; import { useMemo } from 'react'; +export interface ButtonProps extends ViewProps, AccessibilityProps { + children?: React.ReactNode; + + /** + * Defines if buttons should respond to touches. By default set to true. + */ + enabled?: boolean; + + /** + * Defines if more than one button could be pressed simultaneously. By default + * set true. + */ + exclusive?: boolean; + + /** + * Android only. + * + * Defines color of native ripple animation used since API level 21. + */ + rippleColor?: number | ColorValue | null; + + /** + * Android only. + * + * Defines radius of native ripple animation used since API level 21. + */ + rippleRadius?: number | null; + + /** + * Android only. + * + * Set this to true if you want the ripple animation to render outside the view bounds. + */ + borderless?: boolean; + + /** + * Android only. + * + * Defines whether the ripple animation should be drawn on the foreground of the view. + */ + foreground?: boolean; + + /** + * Android only. + * + * Set this to true if you don't want the system to play sound when the button is pressed. + */ + touchSoundDisabled?: boolean; + + /** + * Style object, use it to set additional styles. + */ + style?: StyleProp; + + /** + * Invoked on mount and layout changes. + */ + onLayout?: (event: LayoutChangeEvent) => void; + + /** + * Used for testing-library compatibility, not passed to the native component. + * @deprecated test-only props are deprecated and will be removed in the future. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + testOnly_onPress?: Function | null; + + /** + * Used for testing-library compatibility, not passed to the native component. + * @deprecated test-only props are deprecated and will be removed in the future. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + testOnly_onPressIn?: Function | null; + + /** + * Used for testing-library compatibility, not passed to the native component. + * @deprecated test-only props are deprecated and will be removed in the future. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + testOnly_onPressOut?: Function | null; + + /** + * Used for testing-library compatibility, not passed to the native component. + * @deprecated test-only props are deprecated and will be removed in the future. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + testOnly_onLongPress?: Function | null; +} + const ButtonComponent = - RNGestureHandlerButtonNativeComponent as HostComponent; + RNGestureHandlerButtonNativeComponent as HostComponent; -export default function GestureHandlerButton({ - style, - ...rest -}: RawButtonProps) { +export default function GestureHandlerButton({ style, ...rest }: ButtonProps) { const flattenedStyle = useMemo(() => StyleSheet.flatten(style), [style]); const { diff --git a/packages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts b/packages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts index 0f4f282d8f..d5dc9e930a 100644 --- a/packages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts +++ b/packages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts @@ -1,98 +1,15 @@ -import * as React from 'react'; -import { - AccessibilityProps, - ColorValue, - LayoutChangeEvent, - StyleProp, - ViewStyle, -} from 'react-native'; -import type { NativeViewGestureHandlerProps } from '../../handlers/NativeViewGestureHandler'; +import { StyleProp, ViewStyle } from 'react-native'; +import type { NativeWrapperProperties } from '../types/NativeWrapperType'; +import GestureHandlerButton, { + ButtonProps, +} from '../../components/GestureHandlerButton'; export interface RawButtonProps - extends NativeViewGestureHandlerProps, - AccessibilityProps { - /** - * Defines if more than one button could be pressed simultaneously. By default - * set true. - */ - exclusive?: boolean; - // TODO: we should transform props in `createNativeWrapper` - /** - * Android only. - * - * Defines color of native ripple animation used since API level 21. - */ - rippleColor?: number | ColorValue | null; - - /** - * Android only. - * - * Defines radius of native ripple animation used since API level 21. - */ - rippleRadius?: number | null; - - /** - * Android only. - * - * Set this to true if you want the ripple animation to render outside the view bounds. - */ - borderless?: boolean; - - /** - * Android only. - * - * Defines whether the ripple animation should be drawn on the foreground of the view. - */ - foreground?: boolean; - - /** - * Android only. - * - * Set this to true if you don't want the system to play sound when the button is pressed. - */ - touchSoundDisabled?: boolean; - - /** - * Style object, use it to set additional styles. - */ - style?: StyleProp; - - /** - * Invoked on mount and layout changes. - */ - onLayout?: (event: LayoutChangeEvent) => void; - - /** - * Used for testing-library compatibility, not passed to the native component. - * @deprecated test-only props are deprecated and will be removed in the future. - */ - // eslint-disable-next-line @typescript-eslint/ban-types - testOnly_onPress?: Function | null; - - /** - * Used for testing-library compatibility, not passed to the native component. - * @deprecated test-only props are deprecated and will be removed in the future. - */ - // eslint-disable-next-line @typescript-eslint/ban-types - testOnly_onPressIn?: Function | null; - - /** - * Used for testing-library compatibility, not passed to the native component. - * @deprecated test-only props are deprecated and will be removed in the future. - */ - // eslint-disable-next-line @typescript-eslint/ban-types - testOnly_onPressOut?: Function | null; - - /** - * Used for testing-library compatibility, not passed to the native component. - * @deprecated test-only props are deprecated and will be removed in the future. - */ - // eslint-disable-next-line @typescript-eslint/ban-types - testOnly_onLongPress?: Function | null; -} -interface ButtonWithRefProps { - ref?: React.RefObject; -} + extends ButtonProps, + Omit< + NativeWrapperProperties>, + 'hitSlop' | 'enabled' + > {} export interface BaseButtonProps extends RawButtonProps { /** @@ -121,9 +38,6 @@ export interface BaseButtonProps extends RawButtonProps { */ delayLongPress?: number; } -export interface BaseButtonWithRefProps - extends BaseButtonProps, - ButtonWithRefProps {} export interface RectButtonProps extends BaseButtonProps { /** @@ -138,9 +52,6 @@ export interface RectButtonProps extends BaseButtonProps { */ activeOpacity?: number; } -export interface RectButtonWithRefProps - extends RectButtonProps, - ButtonWithRefProps {} export interface BorderlessButtonProps extends BaseButtonProps { /** @@ -150,6 +61,3 @@ export interface BorderlessButtonProps extends BaseButtonProps { */ activeOpacity?: number; } -export interface BorderlessButtonWithRefProps - extends BorderlessButtonProps, - ButtonWithRefProps {} diff --git a/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx b/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx index 2a43af7b28..076a8020a8 100644 --- a/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx +++ b/packages/react-native-gesture-handler/src/v3/components/GestureComponents.tsx @@ -1,9 +1,4 @@ -import React, { - PropsWithChildren, - ReactElement, - useState, - RefObject, -} from 'react'; +import React, { PropsWithChildren, ReactElement, useState } from 'react'; import { ScrollView as RNScrollView, ScrollViewProps as RNScrollViewProps, @@ -14,6 +9,7 @@ import { FlatList as RNFlatList, FlatListProps as RNFlatListProps, RefreshControl as RNRefreshControl, + RefreshControlProps as RNRefreshControlProps, } from 'react-native'; import createNativeWrapper from '../createNativeWrapper'; @@ -24,7 +20,10 @@ import { GestureDetectorType } from '../detectors'; import { NativeGesture } from '../hooks/gestures/native/useNativeGesture'; import { ghQueueMicrotask } from '../../ghQueueMicrotask'; -export const RefreshControl = createNativeWrapper( +export const RefreshControl = createNativeWrapper< + RNRefreshControl, + RNRefreshControlProps +>( RNRefreshControl, { disallowInterruption: true, @@ -36,7 +35,10 @@ export const RefreshControl = createNativeWrapper( // eslint-disable-next-line @typescript-eslint/no-redeclare export type RefreshControl = typeof RefreshControl & RNRefreshControl; -const GHScrollView = createNativeWrapper>( +const GHScrollView = createNativeWrapper< + RNScrollView, + PropsWithChildren +>( RNScrollView, { disallowInterruption: true, @@ -46,13 +48,7 @@ const GHScrollView = createNativeWrapper>( ); export const ScrollView = ( - props: RNScrollViewProps & - NativeWrapperProperties & { - ref?: React.RefObject; - onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: ( - gesture: NativeGesture - ) => void; - } + props: RNScrollViewProps & NativeWrapperProperties ) => { const { refreshControl, @@ -95,7 +91,7 @@ export const ScrollView = ( // eslint-disable-next-line @typescript-eslint/no-redeclare export type ScrollView = typeof ScrollView & RNScrollView; -export const Switch = createNativeWrapper(RNSwitch, { +export const Switch = createNativeWrapper(RNSwitch, { shouldCancelWhenOutside: false, shouldActivateOnStart: true, disallowInterruption: true, @@ -104,7 +100,9 @@ export const Switch = createNativeWrapper(RNSwitch, { // eslint-disable-next-line @typescript-eslint/no-redeclare export type Switch = typeof Switch & RNSwitch; -export const TextInput = createNativeWrapper(RNTextInput); +export const TextInput = createNativeWrapper( + RNTextInput +); // eslint-disable-next-line @typescript-eslint/no-redeclare export type TextInput = typeof TextInput & RNTextInput; @@ -175,12 +173,7 @@ export const FlatList = ((props) => { }) as ( props: PropsWithChildren< Omit, 'renderScrollComponent' | 'ref'> & - NativeWrapperProperties & { - ref?: RefObject | null>; - onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: ( - gesture: NativeGesture - ) => void; - } + NativeWrapperProperties | null> > ) => ReactElement | null; diff --git a/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx b/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx index d92d6e75a3..139a56e59f 100644 --- a/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx +++ b/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx @@ -3,24 +3,22 @@ import React, { useEffect } from 'react'; import { NativeWrapperProps } from './hooks/utils'; import { useNativeGesture } from './hooks/gestures'; import { NativeDetector } from './detectors/NativeDetector'; -import type { NativeWrapperProperties } from './types/NativeWrapperType'; -import { NativeGesture } from './hooks/gestures/native/useNativeGesture'; +import type { + NativeWrapperProperties, + WrapperSpecificProperties, +} from './types/NativeWrapperType'; import { GestureDetectorType, InterceptingGestureDetector } from './detectors'; import { VirtualDetector } from './detectors/VirtualDetector/VirtualDetector'; -export default function createNativeWrapper

( - Component: React.ComponentType

, - config: Readonly = {}, +export default function createNativeWrapper( + Component: React.ComponentType, + config: Readonly< + Omit, keyof WrapperSpecificProperties> + > = {}, detectorType: GestureDetectorType = GestureDetectorType.Native ) { const ComponentWrapper = ( - props: P & - NativeWrapperProperties & { - ref?: React.RefObject; - onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: ( - gesture: NativeGesture - ) => void; - } + props: TProps & NativeWrapperProperties ) => { const { ref, onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER, ...restProps } = props; @@ -43,7 +41,7 @@ export default function createNativeWrapper

( enabled: props.enabled, hitSlop: props.hitSlop, testID: props.testID, - } as P, + } as TProps, } ); diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts index f3758bfd7b..1698bf9456 100644 --- a/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts +++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts @@ -91,7 +91,9 @@ export const PropsWhiteLists = new Map< export const EMPTY_WHITE_LIST = new Set(); -export const NativeWrapperProps = new Set([ +export const NativeWrapperProps = new Set< + keyof NativeWrapperProperties +>([ ...CommonConfig, ...HandlerCallbacks, ...NativeHandlerNativeProperties, diff --git a/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts b/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts index e54792bcbe..4b0543a3f2 100644 --- a/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts +++ b/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts @@ -1,8 +1,19 @@ import { CommonGestureConfig, ExternalRelations, GestureCallbacks } from '.'; import { NativeGestureNativeProperties } from '../hooks/gestures/native/NativeProperties'; -import { NativeViewHandlerData } from '../hooks/gestures/native/useNativeGesture'; +import { + NativeGesture, + NativeViewHandlerData, +} from '../hooks/gestures/native/useNativeGesture'; -export type NativeWrapperProperties = CommonGestureConfig & +export type WrapperSpecificProperties = { + ref?: React.RefObject; + onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: ( + gesture: NativeGesture + ) => void; +}; + +export type NativeWrapperProperties = CommonGestureConfig & GestureCallbacks & NativeGestureNativeProperties & - ExternalRelations; + ExternalRelations & + WrapperSpecificProperties;