Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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<ViewStyle>;

/**
* 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<RawButtonProps>;
RNGestureHandlerButtonNativeComponent as HostComponent<ButtonProps>;

export default function GestureHandlerButton({
style,
...rest
}: RawButtonProps) {
export default function GestureHandlerButton({ style, ...rest }: ButtonProps) {
const flattenedStyle = useMemo(() => StyleSheet.flatten(style), [style]);

const {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ViewStyle>;

/**
* 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<any>;
}
extends ButtonProps,
Omit<
NativeWrapperProperties<ReturnType<typeof GestureHandlerButton>>,
'hitSlop' | 'enabled'
> {}

export interface BaseButtonProps extends RawButtonProps {
/**
Expand Down Expand Up @@ -121,9 +38,6 @@ export interface BaseButtonProps extends RawButtonProps {
*/
delayLongPress?: number;
}
export interface BaseButtonWithRefProps
extends BaseButtonProps,
ButtonWithRefProps {}

export interface RectButtonProps extends BaseButtonProps {
/**
Expand All @@ -138,9 +52,6 @@ export interface RectButtonProps extends BaseButtonProps {
*/
activeOpacity?: number;
}
export interface RectButtonWithRefProps
extends RectButtonProps,
ButtonWithRefProps {}

export interface BorderlessButtonProps extends BaseButtonProps {
/**
Expand All @@ -150,6 +61,3 @@ export interface BorderlessButtonProps extends BaseButtonProps {
*/
activeOpacity?: number;
}
export interface BorderlessButtonWithRefProps
extends BorderlessButtonProps,
ButtonWithRefProps {}
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -14,6 +9,7 @@ import {
FlatList as RNFlatList,
FlatListProps as RNFlatListProps,
RefreshControl as RNRefreshControl,
RefreshControlProps as RNRefreshControlProps,
} from 'react-native';

import createNativeWrapper from '../createNativeWrapper';
Expand All @@ -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,
Expand All @@ -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<PropsWithChildren<RNScrollViewProps>>(
const GHScrollView = createNativeWrapper<
RNScrollView,
PropsWithChildren<RNScrollViewProps>
>(
RNScrollView,
{
disallowInterruption: true,
Expand All @@ -46,13 +48,7 @@ const GHScrollView = createNativeWrapper<PropsWithChildren<RNScrollViewProps>>(
);

export const ScrollView = (
props: RNScrollViewProps &
NativeWrapperProperties & {
ref?: React.RefObject<RNScrollView | null>;
onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: (
gesture: NativeGesture
) => void;
}
props: RNScrollViewProps & NativeWrapperProperties<RNScrollView | null>
) => {
const {
refreshControl,
Expand Down Expand Up @@ -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<RNSwitchProps>(RNSwitch, {
export const Switch = createNativeWrapper<RNSwitch, RNSwitchProps>(RNSwitch, {
shouldCancelWhenOutside: false,
shouldActivateOnStart: true,
disallowInterruption: true,
Expand All @@ -104,7 +100,9 @@ export const Switch = createNativeWrapper<RNSwitchProps>(RNSwitch, {
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type Switch = typeof Switch & RNSwitch;

export const TextInput = createNativeWrapper<RNTextInputProps>(RNTextInput);
export const TextInput = createNativeWrapper<RNTextInput, RNTextInputProps>(
RNTextInput
);

// eslint-disable-next-line @typescript-eslint/no-redeclare
export type TextInput = typeof TextInput & RNTextInput;
Expand Down Expand Up @@ -175,12 +173,7 @@ export const FlatList = ((props) => {
}) as <ItemT = any>(
props: PropsWithChildren<
Omit<RNFlatListProps<ItemT>, 'renderScrollComponent' | 'ref'> &
NativeWrapperProperties & {
ref?: RefObject<RNFlatList<ItemT> | null>;
onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: (
gesture: NativeGesture
) => void;
}
NativeWrapperProperties<RNFlatList<ItemT> | null>
>
) => ReactElement | null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<P>(
Component: React.ComponentType<P>,
config: Readonly<NativeWrapperProperties> = {},
export default function createNativeWrapper<TRef = unknown, TProps = unknown>(
Component: React.ComponentType<TProps>,
config: Readonly<
Omit<NativeWrapperProperties<TRef>, keyof WrapperSpecificProperties<TRef>>
> = {},
detectorType: GestureDetectorType = GestureDetectorType.Native
) {
const ComponentWrapper = (
props: P &
NativeWrapperProperties & {
ref?: React.RefObject<unknown>;
onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?: (
gesture: NativeGesture
) => void;
}
props: TProps & NativeWrapperProperties<TRef | null>
) => {
const { ref, onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER, ...restProps } =
props;
Expand All @@ -43,7 +41,7 @@ export default function createNativeWrapper<P>(
enabled: props.enabled,
hitSlop: props.hitSlop,
testID: props.testID,
} as P,
} as TProps,
}
);

Expand Down
Loading
Loading