diff --git a/src/components/ActionSheetAwareScrollView/index.ios.tsx b/src/components/ActionSheetAwareScrollView/index.ios.tsx index 6fead4946aea..9fa26e898d6e 100644 --- a/src/components/ActionSheetAwareScrollView/index.ios.tsx +++ b/src/components/ActionSheetAwareScrollView/index.ios.tsx @@ -1,12 +1,10 @@ -import React, {forwardRef, useCallback} from 'react'; -// eslint-disable-next-line no-restricted-imports -import type {ScrollView} from 'react-native'; +import React, {useCallback} from 'react'; import Reanimated, {useAnimatedRef, useAnimatedStyle} from 'react-native-reanimated'; import {Actions, ActionSheetAwareScrollViewContext, ActionSheetAwareScrollViewProvider} from './ActionSheetAwareScrollViewContext'; import type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent} from './types'; import useActionSheetKeyboardSpacing from './useActionSheetKeyboardSpacing'; -const ActionSheetAwareScrollView = forwardRef(({style, children, ...props}, ref) => { +function ActionSheetAwareScrollView({style, children, ref, ...props}: ActionSheetAwareScrollViewProps) { const scrollViewAnimatedRef = useAnimatedRef(); const onRef = useCallback( @@ -38,7 +36,7 @@ const ActionSheetAwareScrollView = forwardRef ); -}); +} export default ActionSheetAwareScrollView; diff --git a/src/components/ActionSheetAwareScrollView/index.tsx b/src/components/ActionSheetAwareScrollView/index.tsx index f2fc64cda8bd..aad22519466e 100644 --- a/src/components/ActionSheetAwareScrollView/index.tsx +++ b/src/components/ActionSheetAwareScrollView/index.tsx @@ -1,20 +1,21 @@ // this whole file is just for other platforms // iOS version has everything implemented -import React, {forwardRef} from 'react'; +import React from 'react'; // eslint-disable-next-line no-restricted-imports import {ScrollView} from 'react-native'; import {Actions, ActionSheetAwareScrollViewContext, ActionSheetAwareScrollViewProvider} from './ActionSheetAwareScrollViewContext'; import type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent} from './types'; -const ActionSheetAwareScrollView = forwardRef((props, ref) => ( - - {props.children} - -)); +function ActionSheetAwareScrollView(props: ActionSheetAwareScrollViewProps) { + return ( + + {props.children} + + ); +} export default ActionSheetAwareScrollView; diff --git a/src/components/ActionSheetAwareScrollView/types.ts b/src/components/ActionSheetAwareScrollView/types.ts index 9d7f7f765fef..c3b1a2ded8c9 100644 --- a/src/components/ActionSheetAwareScrollView/types.ts +++ b/src/components/ActionSheetAwareScrollView/types.ts @@ -1,6 +1,10 @@ -import type {PropsWithChildren} from 'react'; -import type {ScrollViewProps} from 'react-native'; +import type {PropsWithChildren, Ref} from 'react'; +// eslint-disable-next-line no-restricted-imports +import type {ScrollView, ScrollViewProps} from 'react-native'; -type ActionSheetAwareScrollViewProps = PropsWithChildren; +type ActionSheetAwareScrollViewAnimationProps = { + ref?: Ref; +}; +type ActionSheetAwareScrollViewProps = PropsWithChildren & ActionSheetAwareScrollViewAnimationProps; type RenderActionSheetAwareScrollViewComponent = ((props: ActionSheetAwareScrollViewProps) => React.ReactElement) | undefined; export type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent}; diff --git a/src/components/AddressSearch/index.tsx b/src/components/AddressSearch/index.tsx index 4e0fe3d646f7..ac27c32700b3 100644 --- a/src/components/AddressSearch/index.tsx +++ b/src/components/AddressSearch/index.tsx @@ -1,5 +1,4 @@ -import React, {forwardRef, useEffect, useMemo, useRef, useState} from 'react'; -import type {ForwardedRef} from 'react'; +import React, {useEffect, useMemo, useRef, useState} from 'react'; import {Keyboard, LogBox, View} from 'react-native'; import type {LayoutChangeEvent} from 'react-native'; import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete'; @@ -49,40 +48,38 @@ function isPlaceMatchForSearch(search: string, place: PredefinedPlace): boolean // VirtualizedList component with a VirtualizedList-backed instead LogBox.ignoreLogs(['VirtualizedLists should never be nested']); -function AddressSearch( - { - canUseCurrentLocation = false, - containerStyles, - defaultValue, - errorText = '', - hint = '', - inputID, - limitSearchesToCountry, - label, - maxInputLength, - onFocus, - onBlur, - onInputChange, - onPress, - onCountryChange, - predefinedPlaces = [], - renamedInputKeys = { - street: 'addressStreet', - street2: 'addressStreet2', - city: 'addressCity', - state: 'addressState', - zipCode: 'addressZipCode', - lat: 'addressLat', - lng: 'addressLng', - }, - resultTypes = 'address', - shouldSaveDraft = false, - value, - locationBias, - caretHidden, - }: AddressSearchProps, - ref: ForwardedRef, -) { +function AddressSearch({ + canUseCurrentLocation = false, + containerStyles, + defaultValue, + errorText = '', + hint = '', + inputID, + limitSearchesToCountry, + label, + maxInputLength, + onFocus, + onBlur, + onInputChange, + onPress, + onCountryChange, + predefinedPlaces = [], + renamedInputKeys = { + street: 'addressStreet', + street2: 'addressStreet2', + city: 'addressCity', + state: 'addressState', + zipCode: 'addressZipCode', + lat: 'addressLat', + lng: 'addressLng', + }, + resultTypes = 'address', + shouldSaveDraft = false, + value, + locationBias, + caretHidden, + ref, +}: AddressSearchProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -490,6 +487,6 @@ function AddressSearch( AddressSearch.displayName = 'AddressSearchWithRef'; -export default forwardRef(AddressSearch); +export default AddressSearch; export type {AddressSearchProps}; diff --git a/src/components/AddressSearch/types.ts b/src/components/AddressSearch/types.ts index dcf8822c4b5e..4c2979e9427f 100644 --- a/src/components/AddressSearch/types.ts +++ b/src/components/AddressSearch/types.ts @@ -1,4 +1,4 @@ -import type {RefObject} from 'react'; +import type {ForwardedRef, RefObject} from 'react'; import type {NativeSyntheticEvent, StyleProp, TextInputFocusEventData, View, ViewStyle} from 'react-native'; import type {Place} from 'react-native-google-places-autocomplete'; import type {Country} from '@src/CONST'; @@ -90,6 +90,9 @@ type AddressSearchProps = { /** If true, caret is hidden. The default value is false. */ caretHidden?: boolean; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; type IsCurrentTargetInsideContainerType = (event: FocusEvent | NativeSyntheticEvent, containerRef: RefObject) => boolean; diff --git a/src/components/AmountPicker/index.tsx b/src/components/AmountPicker/index.tsx index ec9ff2f4117d..40ad6ed9b752 100644 --- a/src/components/AmountPicker/index.tsx +++ b/src/components/AmountPicker/index.tsx @@ -1,5 +1,4 @@ -import React, {forwardRef, useState} from 'react'; -import type {ForwardedRef} from 'react'; +import React, {useState} from 'react'; import {View} from 'react-native'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import blurActiveElement from '@libs/Accessibility/blurActiveElement'; @@ -8,7 +7,7 @@ import callOrReturn from '@src/types/utils/callOrReturn'; import AmountSelectorModal from './AmountSelectorModal'; import type {AmountPickerProps} from './types'; -function AmountPicker({value, description, title, errorText = '', onInputChange, furtherDetails, rightLabel, ...rest}: AmountPickerProps, forwardedRef: ForwardedRef) { +function AmountPicker({value, description, title, errorText = '', onInputChange, furtherDetails, rightLabel, ref, ...rest}: AmountPickerProps) { const [isPickerVisible, setIsPickerVisible] = useState(false); const showPickerModal = () => { @@ -31,7 +30,7 @@ function AmountPicker({value, description, title, errorText = '', onInputChange, return ( ; } & Pick & Pick< NumberWithSymbolFormProps, diff --git a/src/components/AmountWithoutCurrencyInput.tsx b/src/components/AmountWithoutCurrencyInput.tsx index da1f3855dcf1..211d4050e40f 100644 --- a/src/components/AmountWithoutCurrencyInput.tsx +++ b/src/components/AmountWithoutCurrencyInput.tsx @@ -1,10 +1,9 @@ import React, {useCallback, useMemo} from 'react'; -import type {ForwardedRef} from 'react'; import useLocalize from '@hooks/useLocalize'; import getAmountInputKeyboard from '@libs/getAmountInputKeyboard'; import {replaceAllDigits, replaceCommasWithPeriod, stripSpacesFromAmount} from '@libs/MoneyRequestUtils'; import TextInput from './TextInput'; -import type {BaseTextInputProps, BaseTextInputRef} from './TextInput/BaseTextInput/types'; +import type {BaseTextInputProps} from './TextInput/BaseTextInput/types'; type AmountFormProps = { /** Amount supplied by the FormProvider */ @@ -17,10 +16,19 @@ type AmountFormProps = { shouldAllowNegative?: boolean; } & Partial; -function AmountWithoutCurrencyInput( - {value: amount, shouldAllowNegative = false, inputID, name, defaultValue, accessibilityLabel, role, label, onInputChange, ...rest}: AmountFormProps, - ref: ForwardedRef, -) { +function AmountWithoutCurrencyInput({ + value: amount, + shouldAllowNegative = false, + inputID, + name, + defaultValue, + accessibilityLabel, + role, + label, + onInputChange, + ref, + ...rest +}: AmountFormProps) { const {toLocaleDigit} = useLocalize(); const separator = useMemo( () => @@ -87,4 +95,4 @@ function AmountWithoutCurrencyInput( AmountWithoutCurrencyInput.displayName = 'AmountWithoutCurrencyInput'; -export default React.forwardRef(AmountWithoutCurrencyInput); +export default AmountWithoutCurrencyInput; diff --git a/src/components/Attachments/AttachmentCarousel/Pager/index.tsx b/src/components/Attachments/AttachmentCarousel/Pager/index.tsx index 11875d93473f..4ef7d53d866f 100644 --- a/src/components/Attachments/AttachmentCarousel/Pager/index.tsx +++ b/src/components/Attachments/AttachmentCarousel/Pager/index.tsx @@ -48,12 +48,12 @@ type AttachmentCarouselPagerProps = { /** Callback for attachment errors */ onAttachmentError?: (source: AttachmentSource) => void; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function AttachmentCarouselPager( - {items, activeAttachmentID, initialPage, setShouldShowArrows, onPageSelected, onClose, reportID, onAttachmentError}: AttachmentCarouselPagerProps, - ref: ForwardedRef, -) { +function AttachmentCarouselPager({items, activeAttachmentID, initialPage, setShouldShowArrows, onPageSelected, onClose, reportID, onAttachmentError, ref}: AttachmentCarouselPagerProps) { const {handleTap, handleScaleChange, isScrollEnabled} = useCarouselContextEvents(setShouldShowArrows); const styles = useThemeStyles(); const pagerRef = useRef(null); @@ -153,5 +153,5 @@ function AttachmentCarouselPager( } AttachmentCarouselPager.displayName = 'AttachmentCarouselPager'; -export default React.forwardRef(AttachmentCarouselPager); +export default AttachmentCarouselPager; export type {AttachmentCarouselPagerHandle}; diff --git a/src/components/CheckboxWithLabel.tsx b/src/components/CheckboxWithLabel.tsx index 0647b495bd33..b5ef4f2e974d 100644 --- a/src/components/CheckboxWithLabel.tsx +++ b/src/components/CheckboxWithLabel.tsx @@ -58,12 +58,23 @@ type CheckboxWithLabelProps = RequiredLabelProps & { /** An accessibility label for the checkbox */ accessibilityLabel?: string; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function CheckboxWithLabel( - {errorText = '', isChecked: isCheckedProp = false, defaultValue = false, onInputChange = () => {}, LabelComponent, label, accessibilityLabel, style, value}: CheckboxWithLabelProps, - ref: ForwardedRef, -) { +function CheckboxWithLabel({ + errorText = '', + isChecked: isCheckedProp = false, + defaultValue = false, + onInputChange = () => {}, + LabelComponent, + label, + accessibilityLabel, + style, + value, + ref, +}: CheckboxWithLabelProps) { const styles = useThemeStyles(); // We need to pick the first value that is strictly a boolean // https://github.com/Expensify/App/issues/16885#issuecomment-1520846065 @@ -106,6 +117,6 @@ function CheckboxWithLabel( CheckboxWithLabel.displayName = 'CheckboxWithLabel'; -export default React.forwardRef(CheckboxWithLabel); +export default CheckboxWithLabel; export type {CheckboxWithLabelProps}; diff --git a/src/components/ContextMenuItem.tsx b/src/components/ContextMenuItem.tsx index 6aff89666a07..214e7bd616ec 100644 --- a/src/components/ContextMenuItem.tsx +++ b/src/components/ContextMenuItem.tsx @@ -1,5 +1,5 @@ import type {ForwardedRef} from 'react'; -import React, {forwardRef, useImperativeHandle} from 'react'; +import React, {useImperativeHandle} from 'react'; import type {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -61,34 +61,35 @@ type ContextMenuItemProps = { /** Whether the menu item should show loading icon */ shouldShowLoadingSpinnerIcon?: boolean; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; type ContextMenuItemHandle = { triggerPressAndUpdateSuccess?: () => void; }; -function ContextMenuItem( - { - onPress, - successIcon, - successText = '', - icon, - text, - isMini = false, - description = '', - isAnonymousAction = false, - isFocused = false, - shouldLimitWidth = true, - wrapperStyle, - shouldPreventDefaultFocusOnPress = true, - buttonRef = {current: null}, - onFocus = () => {}, - onBlur = () => {}, - disabled = false, - shouldShowLoadingSpinnerIcon = false, - }: ContextMenuItemProps, - ref: ForwardedRef, -) { +function ContextMenuItem({ + onPress, + successIcon, + successText = '', + icon, + text, + isMini = false, + description = '', + isAnonymousAction = false, + isFocused = false, + shouldLimitWidth = true, + wrapperStyle, + shouldPreventDefaultFocusOnPress = true, + buttonRef = {current: null}, + onFocus = () => {}, + onBlur = () => {}, + disabled = false, + shouldShowLoadingSpinnerIcon = false, + ref, +}: ContextMenuItemProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {windowWidth} = useWindowDimensions(); @@ -151,5 +152,5 @@ function ContextMenuItem( ContextMenuItem.displayName = 'ContextMenuItem'; -export default forwardRef(ContextMenuItem); +export default ContextMenuItem; export type {ContextMenuItemHandle}; diff --git a/src/components/CountrySelector.tsx b/src/components/CountrySelector.tsx index 094f529c66b2..817c49ad03bc 100644 --- a/src/components/CountrySelector.tsx +++ b/src/components/CountrySelector.tsx @@ -1,5 +1,5 @@ import {useIsFocused} from '@react-navigation/native'; -import React, {forwardRef, useEffect, useRef} from 'react'; +import React, {useEffect, useRef} from 'react'; import type {ForwardedRef} from 'react'; import type {View} from 'react-native'; import useGeographicalStateAndCountryFromRoute from '@hooks/useGeographicalStateAndCountryFromRoute'; @@ -27,9 +27,12 @@ type CountrySelectorProps = { /** Callback to call when the picker modal is dismissed */ onBlur?: () => void; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function CountrySelector({errorText = '', value: countryCode, onInputChange = () => {}, onBlur}: CountrySelectorProps, ref: ForwardedRef) { +function CountrySelector({errorText = '', value: countryCode, onInputChange = () => {}, onBlur, ref}: CountrySelectorProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {country: countryFromUrl} = useGeographicalStateAndCountryFromRoute(); @@ -85,4 +88,4 @@ function CountrySelector({errorText = '', value: countryCode, onInputChange = () CountrySelector.displayName = 'CountrySelector'; -export default forwardRef(CountrySelector); +export default CountrySelector; diff --git a/src/components/CurrencySelector.tsx b/src/components/CurrencySelector.tsx index 1d45860f5d32..5c242c7bdc7d 100644 --- a/src/components/CurrencySelector.tsx +++ b/src/components/CurrencySelector.tsx @@ -1,6 +1,6 @@ import {useIsFocused} from '@react-navigation/native'; import type {ForwardedRef} from 'react'; -import React, {forwardRef, useEffect, useRef} from 'react'; +import React, {useEffect, useRef} from 'react'; import type {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -35,20 +35,21 @@ type CurrencySelectorProps = { /** Whether to show currency symbol in the title */ shouldShowCurrencySymbol?: boolean; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function CurrencySelector( - { - errorText = '', - value: currency, - onInputChange = () => {}, - onBlur, - currencySelectorRoute = ROUTES.SETTINGS_CHANGE_CURRENCY, - label, - shouldShowCurrencySymbol = false, - }: CurrencySelectorProps, - ref: ForwardedRef, -) { +function CurrencySelector({ + errorText = '', + value: currency, + onInputChange = () => {}, + onBlur, + currencySelectorRoute = ROUTES.SETTINGS_CHANGE_CURRENCY, + label, + shouldShowCurrencySymbol = false, + ref, +}: CurrencySelectorProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -94,4 +95,4 @@ function CurrencySelector( CurrencySelector.displayName = 'CurrencySelector'; -export default forwardRef(CurrencySelector); +export default CurrencySelector; diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx index e3855f930347..3704be90fd26 100644 --- a/src/components/DatePicker/index.tsx +++ b/src/components/DatePicker/index.tsx @@ -1,6 +1,5 @@ import {format, setYear} from 'date-fns'; -import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import type {ForwardedRef} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {InteractionManager, View} from 'react-native'; import * as Expensicons from '@components/Icon/Expensicons'; import TextInput from '@components/TextInput'; @@ -16,26 +15,24 @@ import type {DateInputWithPickerProps} from './types'; const PADDING_MODAL_DATE_PICKER = 8; -function DatePicker( - { - defaultValue, - disabled, - errorText, - inputID, - label, - minDate = setYear(new Date(), CONST.CALENDAR_PICKER.MIN_YEAR), - maxDate = setYear(new Date(), CONST.CALENDAR_PICKER.MAX_YEAR), - onInputChange, - onTouched = () => {}, - placeholder, - value, - shouldSaveDraft = false, - formID, - autoFocus = false, - shouldHideClearButton = false, - }: DateInputWithPickerProps, - ref: ForwardedRef, -) { +function DatePicker({ + defaultValue, + disabled, + errorText, + inputID, + label, + minDate = setYear(new Date(), CONST.CALENDAR_PICKER.MIN_YEAR), + maxDate = setYear(new Date(), CONST.CALENDAR_PICKER.MAX_YEAR), + onInputChange, + onTouched = () => {}, + placeholder, + value, + shouldSaveDraft = false, + formID, + autoFocus = false, + shouldHideClearButton = false, + ref, +}: DateInputWithPickerProps) { const styles = useThemeStyles(); const {windowHeight, windowWidth} = useWindowDimensions(); const {translate} = useLocalize(); @@ -165,4 +162,4 @@ function DatePicker( DatePicker.displayName = 'DatePicker'; -export default forwardRef(DatePicker); +export default DatePicker; diff --git a/src/components/DatePicker/types.ts b/src/components/DatePicker/types.ts index 1e4bafa5f1d9..24ef3e61f706 100644 --- a/src/components/DatePicker/types.ts +++ b/src/components/DatePicker/types.ts @@ -1,5 +1,6 @@ +import type {ForwardedRef} from 'react'; import type PopoverWithMeasuredContentProps from '@components/PopoverWithMeasuredContent/types'; -import type {BaseTextInputProps} from '@components/TextInput/BaseTextInput/types'; +import type {BaseTextInputProps, BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import type {OnyxFormValuesMapping} from '@src/ONYXKEYS'; type DatePickerBaseProps = { @@ -53,6 +54,11 @@ type DateInputWithPickerProps = DatePickerBaseProps & * @default false */ shouldHideClearButton?: boolean; + + /** + * Reference to the outer element + */ + ref?: ForwardedRef; }; type DatePickerProps = { diff --git a/src/components/FormScrollView.tsx b/src/components/FormScrollView.tsx index 91f5a825a38a..77eed896a968 100644 --- a/src/components/FormScrollView.tsx +++ b/src/components/FormScrollView.tsx @@ -8,9 +8,12 @@ import ScrollView from './ScrollView'; type FormScrollViewProps = ScrollViewProps & { /** Form elements */ children: React.ReactNode; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function FormScrollView({children, ...rest}: FormScrollViewProps, ref: ForwardedRef) { +function FormScrollView({children, ref, ...rest}: FormScrollViewProps) { const styles = useThemeStyles(); return ( ; }; -function HighlightableMenuItem({wrapperStyle, highlighted, ...restOfProps}: Props, ref: ForwardedRef) { +function HighlightableMenuItem({wrapperStyle, highlighted, ref, ...restOfProps}: Props) { const styles = useThemeStyles(); const flattenedWrapperStyles = StyleSheet.flatten(wrapperStyle); @@ -35,4 +38,4 @@ function HighlightableMenuItem({wrapperStyle, highlighted, ...restOfProps}: Prop HighlightableMenuItem.displayName = 'HighlightableMenuItem'; -export default forwardRef(HighlightableMenuItem); +export default HighlightableMenuItem; diff --git a/src/components/InteractiveStepSubHeader.tsx b/src/components/InteractiveStepSubHeader.tsx index aad5f502df47..3be92324e73a 100644 --- a/src/components/InteractiveStepSubHeader.tsx +++ b/src/components/InteractiveStepSubHeader.tsx @@ -1,5 +1,5 @@ import type {ForwardedRef} from 'react'; -import React, {forwardRef, useImperativeHandle, useState} from 'react'; +import React, {useImperativeHandle, useState} from 'react'; import type {ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -20,6 +20,9 @@ type InteractiveStepSubHeaderProps = { /** The index of the step to start with */ startStepIndex?: number; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; type InteractiveStepSubHeaderHandle = { @@ -36,7 +39,7 @@ type InteractiveStepSubHeaderHandle = { const MIN_AMOUNT_FOR_EXPANDING = 3; const MIN_AMOUNT_OF_STEPS = 2; -function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected}: InteractiveStepSubHeaderProps, ref: ForwardedRef) { +function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected, ref}: InteractiveStepSubHeaderProps) { const styles = useThemeStyles(); const containerWidthStyle: ViewStyle = stepNames.length < MIN_AMOUNT_FOR_EXPANDING ? styles.mnw60 : styles.mnw100; @@ -123,4 +126,4 @@ InteractiveStepSubHeader.displayName = 'InteractiveStepSubHeader'; export type {InteractiveStepSubHeaderProps, InteractiveStepSubHeaderHandle}; -export default forwardRef(InteractiveStepSubHeader); +export default InteractiveStepSubHeader; diff --git a/src/components/InteractiveStepWrapper.tsx b/src/components/InteractiveStepWrapper.tsx index d9f6709c47ec..dc5b54669509 100644 --- a/src/components/InteractiveStepWrapper.tsx +++ b/src/components/InteractiveStepWrapper.tsx @@ -1,4 +1,5 @@ -import React, {forwardRef} from 'react'; +import type {ForwardedRef} from 'react'; +import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -56,27 +57,28 @@ type InteractiveStepWrapperProps = { * This flag can be removed, once all components/screens have switched to edge-to-edge safe area handling. */ enableEdgeToEdgeBottomSafeAreaPadding?: boolean; + + // Reference to the outer element + ref?: ForwardedRef; }; -function InteractiveStepWrapper( - { - children, - wrapperID, - handleBackButtonPress, - headerTitle, - headerSubtitle, - startStepIndex, - stepNames, - shouldEnableMaxHeight, - shouldShowOfflineIndicator, - shouldShowOfflineIndicatorInWideScreen, - shouldEnablePickerAvoiding = false, - offlineIndicatorStyle, - shouldKeyboardOffsetBottomSafeAreaPadding, - enableEdgeToEdgeBottomSafeAreaPadding, - }: InteractiveStepWrapperProps, - ref: React.ForwardedRef, -) { +function InteractiveStepWrapper({ + children, + wrapperID, + handleBackButtonPress, + headerTitle, + headerSubtitle, + startStepIndex, + stepNames, + shouldEnableMaxHeight, + shouldShowOfflineIndicator, + shouldShowOfflineIndicatorInWideScreen, + shouldEnablePickerAvoiding = false, + offlineIndicatorStyle, + shouldKeyboardOffsetBottomSafeAreaPadding, + enableEdgeToEdgeBottomSafeAreaPadding, + ref, +}: InteractiveStepWrapperProps) { const styles = useThemeStyles(); return ( @@ -112,4 +114,4 @@ function InteractiveStepWrapper( InteractiveStepWrapper.displayName = 'InteractiveStepWrapper'; -export default forwardRef(InteractiveStepWrapper); +export default InteractiveStepWrapper; diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index 12946ee83693..dea019ea1cd0 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -1,5 +1,5 @@ import type {ForwardedRef, KeyboardEvent} from 'react'; -import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; +import React, {useEffect, useImperativeHandle, useRef, useState} from 'react'; import type {NativeSyntheticEvent, TextInput as RNTextInput, TextInputFocusEventData, TextInputKeyPressEventData} from 'react-native'; import {StyleSheet, View} from 'react-native'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; @@ -99,6 +99,9 @@ type MagicCodeInputProps = { /** TestID for test */ testID?: string; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; type MagicCodeInputHandle = { @@ -132,25 +135,23 @@ const composeToString = (value: string[]): string => value.map((v) => v ?? CONST const getInputPlaceholderSlots = (length: number): number[] => Array.from(Array(length).keys()); -function MagicCodeInput( - { - value = '', - name = '', - autoFocus = true, - errorText = '', - shouldSubmitOnComplete = true, - onChangeText: onChangeTextProp = () => {}, - onFocus: onFocusProps, - maxLength = CONST.MAGIC_CODE_LENGTH, - onFulfill = () => {}, - isDisableKeyboard = false, - lastPressedDigit = '', - autoComplete, - hasError = false, - testID = '', - }: MagicCodeInputProps, - ref: ForwardedRef, -) { +function MagicCodeInput({ + value = '', + name = '', + autoFocus = true, + errorText = '', + shouldSubmitOnComplete = true, + onChangeText: onChangeTextProp = () => {}, + onFocus: onFocusProps, + maxLength = CONST.MAGIC_CODE_LENGTH, + onFulfill = () => {}, + isDisableKeyboard = false, + lastPressedDigit = '', + autoComplete, + hasError = false, + testID = '', + ref, +}: MagicCodeInputProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const inputRef = useRef(null); @@ -540,5 +541,5 @@ function MagicCodeInput( MagicCodeInput.displayName = 'MagicCodeInput'; -export default forwardRef(MagicCodeInput); +export default MagicCodeInput; export type {AutoCompleteVariant, MagicCodeInputHandle, MagicCodeInputProps}; diff --git a/src/components/PercentageForm.tsx b/src/components/PercentageForm.tsx index aee231de526c..3c3b78e3ad82 100644 --- a/src/components/PercentageForm.tsx +++ b/src/components/PercentageForm.tsx @@ -1,5 +1,5 @@ import type {ForwardedRef} from 'react'; -import React, {forwardRef, useCallback, useMemo, useRef} from 'react'; +import React, {useCallback, useMemo, useRef} from 'react'; import useLocalize from '@hooks/useLocalize'; import {replaceAllDigits, stripCommaFromAmount, stripSpacesFromAmount, validatePercentage} from '@libs/MoneyRequestUtils'; import CONST from '@src/CONST'; @@ -18,9 +18,12 @@ type PercentageFormProps = { /** Custom label for the TextInput */ label?: string; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function PercentageForm({value: amount, errorText, onInputChange, label, ...rest}: PercentageFormProps, forwardedRef: ForwardedRef) { +function PercentageForm({value: amount, errorText, onInputChange, label, ref, ...rest}: PercentageFormProps) { const {toLocaleDigit, numberFormat} = useLocalize(); const textInput = useRef(null); @@ -56,14 +59,14 @@ function PercentageForm({value: amount, errorText, onInputChange, label, ...rest value={formattedAmount} onChangeText={setNewAmount} placeholder={numberFormat(0)} - ref={(ref: BaseTextInputRef | null) => { - if (typeof forwardedRef === 'function') { - forwardedRef(ref); - } else if (forwardedRef && 'current' in forwardedRef) { + ref={(newRef: BaseTextInputRef | null) => { + if (typeof ref === 'function') { + ref(newRef); + } else if (ref && 'current' in ref) { // eslint-disable-next-line no-param-reassign - forwardedRef.current = ref; + ref.current = newRef; } - textInput.current = ref; + textInput.current = newRef; }} suffixCharacter="%" keyboardType={CONST.KEYBOARD_TYPE.DECIMAL_PAD} @@ -78,4 +81,4 @@ function PercentageForm({value: amount, errorText, onInputChange, label, ...rest PercentageForm.displayName = 'PercentageForm'; -export default forwardRef(PercentageForm); +export default PercentageForm; diff --git a/src/components/RadioButtons.tsx b/src/components/RadioButtons.tsx index 07e8fe38f772..afbc8879c68c 100644 --- a/src/components/RadioButtons.tsx +++ b/src/components/RadioButtons.tsx @@ -1,4 +1,4 @@ -import React, {forwardRef, useEffect, useState} from 'react'; +import React, {useEffect, useState} from 'react'; import type {ForwardedRef} from 'react'; import {View} from 'react-native'; import type {StyleProp, ViewStyle} from 'react-native'; @@ -33,9 +33,12 @@ type RadioButtonsProps = { /** The checked value, if you're using this component as a controlled input. */ value?: string; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function RadioButtons({items, onPress, defaultCheckedValue = '', radioButtonStyle, errorText, onInputChange = () => {}, value}: RadioButtonsProps, ref: ForwardedRef) { +function RadioButtons({items, onPress, defaultCheckedValue = '', radioButtonStyle, errorText, onInputChange = () => {}, value, ref}: RadioButtonsProps) { const styles = useThemeStyles(); const [checkedValue, setCheckedValue] = useState(defaultCheckedValue); @@ -74,4 +77,4 @@ function RadioButtons({items, onPress, defaultCheckedValue = '', radioButtonStyl RadioButtons.displayName = 'RadioButtons'; export type {Choice}; -export default forwardRef(RadioButtons); +export default RadioButtons; diff --git a/src/components/Share/ShareTabParticipantsSelector.tsx b/src/components/Share/ShareTabParticipantsSelector.tsx index 4d8bee4f9cce..015576d5eb45 100644 --- a/src/components/Share/ShareTabParticipantsSelector.tsx +++ b/src/components/Share/ShareTabParticipantsSelector.tsx @@ -1,4 +1,5 @@ -import React, {forwardRef} from 'react'; +import type {Ref} from 'react'; +import React from 'react'; import {saveUnknownUserDetails} from '@libs/actions/Share'; import Navigation from '@libs/Navigation/Navigation'; import MoneyRequestParticipantsSelector from '@pages/iou/request/MoneyRequestParticipantsSelector'; @@ -8,13 +9,14 @@ import type ROUTES from '@src/ROUTES'; type ShareTabParticipantsSelectorProps = { detailsPageRouteObject: typeof ROUTES.SHARE_SUBMIT_DETAILS | typeof ROUTES.SHARE_DETAILS; + ref?: Ref; }; type InputFocusRef = { focus?: () => void; }; -function ShareTabParticipantsSelectorComponent({detailsPageRouteObject}: ShareTabParticipantsSelectorProps, ref: React.Ref) { +function ShareTabParticipantsSelectorComponent({detailsPageRouteObject, ref}: ShareTabParticipantsSelectorProps) { return ( (ShareTabParticipantsSelectorComponent); +export default ShareTabParticipantsSelectorComponent; diff --git a/src/components/SingleChoiceQuestion.tsx b/src/components/SingleChoiceQuestion.tsx index e52007850475..a6e29661debd 100644 --- a/src/components/SingleChoiceQuestion.tsx +++ b/src/components/SingleChoiceQuestion.tsx @@ -1,5 +1,5 @@ import type {ForwardedRef} from 'react'; -import React, {forwardRef} from 'react'; +import React from 'react'; // eslint-disable-next-line no-restricted-imports import type {Text as RNText} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -13,9 +13,10 @@ type SingleChoiceQuestionProps = { possibleAnswers: Choice[]; currentQuestionIndex: number; onInputChange: (value: string) => void; + ref?: ForwardedRef; }; -function SingleChoiceQuestion({prompt, errorText, possibleAnswers, currentQuestionIndex, onInputChange}: SingleChoiceQuestionProps, ref: ForwardedRef) { +function SingleChoiceQuestion({prompt, errorText, possibleAnswers, currentQuestionIndex, onInputChange, ref}: SingleChoiceQuestionProps) { const styles = useThemeStyles(); return ( @@ -38,4 +39,4 @@ function SingleChoiceQuestion({prompt, errorText, possibleAnswers, currentQuesti SingleChoiceQuestion.displayName = 'SingleChoiceQuestion'; -export default forwardRef(SingleChoiceQuestion); +export default SingleChoiceQuestion; diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index e2be9281d0bb..b32a63523aac 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -35,12 +35,12 @@ type StateSelectorProps = { /** object to get route details from */ stateSelectorRoute?: typeof ROUTES.SETTINGS_ADDRESS_STATE | typeof ROUTES.MONEY_REQUEST_STATE_SELECTOR; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function StateSelector( - {errorText, onBlur, value: stateCode, label, onInputChange, wrapperStyle, stateSelectorRoute = ROUTES.SETTINGS_ADDRESS_STATE}: StateSelectorProps, - ref: ForwardedRef, -) { +function StateSelector({errorText, onBlur, value: stateCode, label, onInputChange, wrapperStyle, stateSelectorRoute = ROUTES.SETTINGS_ADDRESS_STATE, ref}: StateSelectorProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {state: stateFromUrl} = useGeographicalStateAndCountryFromRoute(); @@ -100,6 +100,6 @@ function StateSelector( StateSelector.displayName = 'StateSelector'; -export default React.forwardRef(StateSelector); +export default StateSelector; export type {State}; diff --git a/src/components/TextLink.tsx b/src/components/TextLink.tsx index 715d25e040a9..9dcb790a536e 100644 --- a/src/components/TextLink.tsx +++ b/src/components/TextLink.tsx @@ -1,7 +1,7 @@ -import type {ForwardedRef, KeyboardEvent, KeyboardEventHandler, MouseEventHandler} from 'react'; -import React, {forwardRef} from 'react'; +import type {KeyboardEvent, KeyboardEventHandler, MouseEventHandler} from 'react'; +import React from 'react'; // eslint-disable-next-line no-restricted-imports -import type {GestureResponderEvent, Text as RNText, StyleProp, TextStyle} from 'react-native'; +import type {GestureResponderEvent, StyleProp, TextStyle} from 'react-native'; import useEnvironment from '@hooks/useEnvironment'; import useThemeStyles from '@hooks/useThemeStyles'; import {openLink as openLinkUtil} from '@userActions/Link'; @@ -32,7 +32,7 @@ type TextLinkProps = (LinkProps | PressProps) & onMouseDown?: MouseEventHandler; }; -function TextLink({href, onPress, children, style, onMouseDown = (event) => event.preventDefault(), ...rest}: TextLinkProps, ref: ForwardedRef) { +function TextLink({href, onPress, children, style, onMouseDown = (event) => event.preventDefault(), ref, ...rest}: TextLinkProps) { const {environmentURL} = useEnvironment(); const styles = useThemeStyles(); @@ -81,4 +81,4 @@ TextLink.displayName = 'TextLink'; export type {LinkProps, PressProps, TextLinkProps}; -export default forwardRef(TextLink); +export default TextLink; diff --git a/src/components/TimeModalPicker.tsx b/src/components/TimeModalPicker.tsx index be85fb719839..fdd399b01200 100644 --- a/src/components/TimeModalPicker.tsx +++ b/src/components/TimeModalPicker.tsx @@ -1,4 +1,4 @@ -import React, {forwardRef, useState} from 'react'; +import React, {useState} from 'react'; import type {ForwardedRef} from 'react'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -22,9 +22,12 @@ type TimeModalPickerProps = { /** Label for the picker */ label: string; + + /** Reference to the outer element */ + ref?: ForwardedRef; }; -function TimeModalPicker({value, errorText, label, onInputChange = () => {}}: TimeModalPickerProps, ref: ForwardedRef) { +function TimeModalPicker({value, errorText, label, onInputChange = () => {}, ref}: TimeModalPickerProps) { const styles = useThemeStyles(); const [isPickerVisible, setIsPickerVisible] = useState(false); const currentTime = value ? DateUtils.extractTime12Hour(value) : undefined; @@ -81,4 +84,4 @@ function TimeModalPicker({value, errorText, label, onInputChange = () => {}}: Ti } TimeModalPicker.displayName = 'TimeModalPicker'; -export default forwardRef(TimeModalPicker); +export default TimeModalPicker; diff --git a/src/components/withToggleVisibilityView.tsx b/src/components/withToggleVisibilityView.tsx index 809f2898aaa7..f9703eb34d24 100644 --- a/src/components/withToggleVisibilityView.tsx +++ b/src/components/withToggleVisibilityView.tsx @@ -1,4 +1,4 @@ -import type {ComponentType, ForwardedRef, ReactElement, RefAttributes} from 'react'; +import type {ComponentType, ReactElement} from 'react'; import React from 'react'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -9,10 +9,8 @@ type WithToggleVisibilityViewProps = { isVisible?: boolean; }; -export default function withToggleVisibilityView( - WrappedComponent: ComponentType>, -): (props: TProps & WithToggleVisibilityViewProps & RefAttributes) => ReactElement | null { - function WithToggleVisibilityView({isVisible = false, ...rest}: WithToggleVisibilityViewProps, ref: ForwardedRef) { +export default function withToggleVisibilityView(WrappedComponent: ComponentType): (props: TProps & WithToggleVisibilityViewProps) => ReactElement | null { + function WithToggleVisibilityView({isVisible = false, ...rest}: WithToggleVisibilityViewProps) { const styles = useThemeStyles(); return ( ( @@ -30,7 +27,7 @@ export default function withToggleVisibilityView( } WithToggleVisibilityView.displayName = `WithToggleVisibilityViewWithRef(${getComponentDisplayName(WrappedComponent)})`; - return React.forwardRef(WithToggleVisibilityView); + return WithToggleVisibilityView; } export type {WithToggleVisibilityViewProps}; diff --git a/src/components/withViewportOffsetTop.tsx b/src/components/withViewportOffsetTop.tsx index d3e9b63ad3ee..51e56d447c0f 100644 --- a/src/components/withViewportOffsetTop.tsx +++ b/src/components/withViewportOffsetTop.tsx @@ -1,5 +1,5 @@ -import type {ComponentType, ForwardedRef, RefAttributes} from 'react'; -import React, {forwardRef, useEffect, useState} from 'react'; +import type {ComponentType} from 'react'; +import React, {useEffect, useState} from 'react'; import getComponentDisplayName from '@libs/getComponentDisplayName'; import addViewportResizeListener from '@libs/VisualViewport'; @@ -9,8 +9,8 @@ type ViewportOffsetTopProps = { viewportOffsetTop: number; }; -export default function withViewportOffsetTop(WrappedComponent: ComponentType>) { - function WithViewportOffsetTop(props: Omit, ref: ForwardedRef) { +export default function withViewportOffsetTop(WrappedComponent: ComponentType) { + function WithViewportOffsetTop(props: Omit) { const [viewportOffsetTop, setViewportOffsetTop] = useState(0); useEffect(() => { @@ -30,7 +30,6 @@ export default function withViewportOffsetTop ); @@ -38,5 +37,5 @@ export default function withViewportOffsetTop