import type { PropsWithChildren, ReactElement } from 'react'; import React, { useState } from 'react'; import type { FlatListProps as RNFlatListProps, RefreshControlProps as RNRefreshControlProps, ScrollViewProps as RNScrollViewProps, SwitchProps as RNSwitchProps, TextInputProps as RNTextInputProps, } from 'react-native'; import { FlatList as RNFlatList, RefreshControl as RNRefreshControl, ScrollView as RNScrollView, Switch as RNSwitch, TextInput as RNTextInput, } from 'react-native'; import { ghQueueMicrotask } from '../../ghQueueMicrotask'; import createNativeWrapper from '../createNativeWrapper'; import { GestureDetectorType } from '../detectors'; import type { NativeGesture } from '../hooks/gestures/native/NativeTypes'; import { NativeWrapperProps } from '../hooks/utils'; import type { NativeWrapperProperties } from '../types/NativeWrapperType'; import { ScrollViewResponderProvider } from './ScrollViewResponderInterceptor'; export const RefreshControl: React.ComponentType< RNRefreshControlProps & NativeWrapperProperties | null> > = createNativeWrapper< React.ComponentRef, RNRefreshControlProps >( RNRefreshControl, { disallowInterruption: true, shouldCancelWhenOutside: false, }, GestureDetectorType.Virtual ); // eslint-disable-next-line @typescript-eslint/no-redeclare export type RefreshControl = typeof RefreshControl & RNRefreshControl; const GHScrollView = createNativeWrapper< React.ComponentRef, PropsWithChildren >( RNScrollView, { disallowInterruption: true, shouldCancelWhenOutside: false, }, GestureDetectorType.Intercepting ); export const ScrollView = ( props: RNScrollViewProps & NativeWrapperProperties | null> ) => { const { children, refreshControl, onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER, keyboardShouldPersistTaps, ...rest } = props; const [scrollGesture, setScrollGesture] = useState( null ); const updateGesture = (gesture: NativeGesture) => { ghQueueMicrotask(() => { if (!scrollGesture || scrollGesture.handlerTag !== gesture.handlerTag) { setScrollGesture(gesture); onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?.(gesture); } }); }; return ( {children} ); }; // eslint-disable-next-line @typescript-eslint/no-redeclare export type ScrollView = typeof ScrollView & RNScrollView; export const Switch: React.ComponentType< RNSwitchProps & NativeWrapperProperties | null> > = createNativeWrapper, RNSwitchProps>( RNSwitch, { shouldCancelWhenOutside: false, shouldActivateOnStart: true, disallowInterruption: true, } ); // eslint-disable-next-line @typescript-eslint/no-redeclare export type Switch = typeof Switch & RNSwitch; export const TextInput: React.ComponentType< RNTextInputProps & NativeWrapperProperties | null> > = createNativeWrapper< React.ComponentRef, RNTextInputProps >(RNTextInput); // eslint-disable-next-line @typescript-eslint/no-redeclare export type TextInput = typeof TextInput & RNTextInput; export const FlatList = ((props) => { const { refreshControl, ref, onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER, ...rest } = props; const [scrollGesture, setScrollGesture] = useState( null ); const updateGesture = (gesture: NativeGesture) => { ghQueueMicrotask(() => { if (!scrollGesture || scrollGesture.handlerTag !== gesture.handlerTag) { setScrollGesture(gesture); onGestureUpdate_CAN_CAUSE_INFINITE_RERENDER?.(gesture); } }); }; const flatListProps = {}; const scrollViewProps = {}; for (const [propName, value] of Object.entries(rest)) { // @ts-ignore https://github.com/microsoft/TypeScript/issues/26255 if (NativeWrapperProps.has(propName)) { // @ts-ignore - this function cannot have generic type so we have to ignore this error // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment scrollViewProps[propName] = value; } else { // @ts-ignore - this function cannot have generic type so we have to ignore this error // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment flatListProps[propName] = value; } } return ( // @ts-ignore - this function cannot have generic type so we have to ignore this error ( )} // @ts-ignore we don't pass `refreshing` prop as we only want to override the ref refreshControl={ refreshControl ? React.cloneElement( refreshControl, // @ts-ignore block exists (on our RefreshControl) scrollGesture ? { block: scrollGesture } : {} ) : undefined } /> ); }) as ( props: PropsWithChildren< Omit, 'renderScrollComponent' | 'ref'> & NativeWrapperProperties | null> > ) => ReactElement | null; // eslint-disable-next-line @typescript-eslint/no-redeclare export type FlatList = typeof FlatList & RNFlatList;