diff --git a/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx b/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx index c047d0341e9e..1b1b8204a810 100644 --- a/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx +++ b/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx @@ -6,7 +6,7 @@ import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; @@ -132,12 +132,14 @@ function PaymentCardChangeCurrencyForm({changeBillingCurrency, isSecurityCodeReq { selectCurrency(option.value); }} style={{containerStyle: styles.mhn5}} + initiallyFocusedItemKey={currency} customListHeader={} + shouldStopPropagation /> ); diff --git a/src/components/AddPaymentCard/PaymentCardCurrencyModal.tsx b/src/components/AddPaymentCard/PaymentCardCurrencyModal.tsx index e657d4fc8012..85d0483db6d9 100644 --- a/src/components/AddPaymentCard/PaymentCardCurrencyModal.tsx +++ b/src/components/AddPaymentCard/PaymentCardCurrencyModal.tsx @@ -4,7 +4,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; @@ -67,10 +67,11 @@ function PaymentCardCurrencyModal({isVisible, currencies, currentCurrency = CONS /> { onCurrencyChange(option.value); }} + initiallyFocusedItemKey={currentCurrency} showScrollIndicator /> diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index 203048bb62fb..c68624505d5a 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -251,11 +251,9 @@ function AddPlaidBankAccount({ return ( - - {translate(isDisplayedInWalletFlow ? 'walletPage.chooseYourBankAccount' : 'bankAccount.chooseAnAccount')} - - {!!text && {text}} - + {translate(isDisplayedInWalletFlow ? 'walletPage.chooseYourBankAccount' : 'bankAccount.chooseAnAccount')} + {!!text && {text}} + - {`${translate('bankAccount.chooseAnAccountBelow')}:`} + {`${translate('bankAccount.chooseAnAccountBelow')}:`} diff --git a/src/components/ApproverSelectionList.tsx b/src/components/ApproverSelectionList.tsx index 0c15ceecfbf6..9723f4402178 100644 --- a/src/components/ApproverSelectionList.tsx +++ b/src/components/ApproverSelectionList.tsx @@ -168,7 +168,6 @@ function ApproverSelectionList({ shouldUpdateFocusedIndex={shouldUpdateFocusedIndex} showScrollIndicator isRowMultilineSupported - shouldShowRadioButton /> diff --git a/src/components/BaseVacationDelegateSelectionComponent.tsx b/src/components/BaseVacationDelegateSelectionComponent.tsx index c52f0ae4185b..f95dc2420c5a 100644 --- a/src/components/BaseVacationDelegateSelectionComponent.tsx +++ b/src/components/BaseVacationDelegateSelectionComponent.tsx @@ -187,7 +187,6 @@ function BaseVacationDelegateSelectionComponent({ onEndReached={onListEndReached} shouldSingleExecuteRowSelect shouldShowTextInput - shouldShowRadioButton /> )} diff --git a/src/components/CategoryPicker.tsx b/src/components/CategoryPicker.tsx index 703d6589dc48..7e47123f71c2 100644 --- a/src/components/CategoryPicker.tsx +++ b/src/components/CategoryPicker.tsx @@ -11,7 +11,7 @@ import {getHeaderMessageForNonUserList} from '@libs/OptionsListUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import SingleSelectListItem from './SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from './SelectionList/ListItem/RadioListItem'; import SelectionListWithSections from './SelectionList/SelectionListWithSections'; import type {ListItem} from './SelectionList/types'; @@ -80,7 +80,7 @@ function CategoryPicker({selectedCategory, policyID, onSubmit, addBottomSafeArea = CONST.STANDARD_LIST_ITEM_LIMIT} textInputOptions={textInputOptions} initiallyFocusedItemKey={selectedOptionKey} diff --git a/src/components/CountryPicker/CountrySelectorModal.tsx b/src/components/CountryPicker/CountrySelectorModal.tsx index 36db43f2e08c..a2f7e0fffeeb 100644 --- a/src/components/CountryPicker/CountrySelectorModal.tsx +++ b/src/components/CountryPicker/CountrySelectorModal.tsx @@ -3,7 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -90,7 +90,7 @@ function CountrySelectorModal({isVisible, currentCountry, onCountrySelected, onC data={searchResults} textInputOptions={textInputOptions} onSelectRow={onCountrySelected} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={currentCountry} shouldSingleExecuteRowSelect shouldStopPropagation diff --git a/src/components/CurrencySelectionList/index.tsx b/src/components/CurrencySelectionList/index.tsx index dc65c1f84f34..160ce3443de8 100644 --- a/src/components/CurrencySelectionList/index.tsx +++ b/src/components/CurrencySelectionList/index.tsx @@ -1,10 +1,9 @@ import {Str} from 'expensify-common'; import React, {useState} from 'react'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import SelectionListWithSections from '@components/SelectionList/SelectionListWithSections'; import {useCurrencyListActions, useCurrencyListState} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; import getMatchScore from '@libs/getMatchScore'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {CurrencyListItem, CurrencySelectionListProps} from './types'; @@ -23,7 +22,6 @@ function CurrencySelectionList({ const {getCurrencySymbol} = useCurrencyListActions(); const [searchValue, setSearchValue] = useState(''); const {translate} = useLocalize(); - const styles = useThemeStyles(); const getUnselectedOptions = (options: CurrencyListItem[]) => options.filter((option) => !option.isSelected); const currencyOptions: CurrencyListItem[] = Object.entries(currencyList).reduce((acc, [currencyCode, currencyInfo]) => { @@ -103,11 +101,8 @@ function CurrencySelectionList({ // eslint-disable-next-line react/jsx-props-no-spreading {...restProps} sections={sections} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} onSelectRow={onSelect} - style={{ - listItemWrapperStyle: styles.optionRow, - }} textInputOptions={textInputOptions} shouldShowTextInput={!!searchInputLabel} shouldSingleExecuteRowSelect diff --git a/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx b/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx index aca37cb1114f..26b2909899d2 100644 --- a/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx +++ b/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx @@ -4,7 +4,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; @@ -81,7 +81,7 @@ function YearPickerModal({isVisible, years, currentYear = new Date().getFullYear /> { Keyboard.dismiss(); onYearChange?.(option.value); diff --git a/src/components/DestinationPicker.tsx b/src/components/DestinationPicker.tsx index 919606205438..0cf54b0efaa0 100644 --- a/src/components/DestinationPicker.tsx +++ b/src/components/DestinationPicker.tsx @@ -10,7 +10,7 @@ import type {Destination} from '@libs/PerDiemRequestUtils'; import {getPerDiemCustomUnit} from '@libs/PolicyUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import SingleSelectListItem from './SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from './SelectionList/ListItem/RadioListItem'; import SelectionListWithSections from './SelectionList/SelectionListWithSections'; import type {ListItem, SelectionListWithSectionsHandle} from './SelectionList/types'; @@ -80,7 +80,7 @@ function DestinationPicker({selectedDestination, policyID, onSubmit, ref}: Desti shouldShowTextInput={shouldShowTextInput} textInputOptions={textInputOptions} onSelectRow={onSubmit} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={selectedOptionKey} shouldHideKeyboardOnScroll={false} shouldUpdateFocusedIndex diff --git a/src/components/FeedbackSurvey.tsx b/src/components/FeedbackSurvey.tsx index 99189d8faab2..492614d2e984 100644 --- a/src/components/FeedbackSurvey.tsx +++ b/src/components/FeedbackSurvey.tsx @@ -108,21 +108,19 @@ function FeedbackSurvey({title, description, onSubmit, optionRowStyles, footerTe isSubmitButtonVisible={false} enabledWhenOffline={enabledWhenOffline} > - - - {title} - {description} - + + {title} + {description} {!!reason && ( - + <> {translate('feedbackSurvey.additionalInfoTitle')} - + )} diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 45ffc6bc31c1..6edffb9e7467 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -78,7 +78,7 @@ import MoneyRequestAmountInput from './MoneyRequestAmountInput'; import MoneyRequestConfirmationListFooter from './MoneyRequestConfirmationListFooter'; import {PressableWithFeedback} from './Pressable'; import {useProductTrainingContext} from './ProductTrainingContext'; -import NewChatListItem from './Search/NewChatListItem'; +import UserListItem from './SelectionList/ListItem/UserListItem'; import SelectionListWithSections from './SelectionList/SelectionListWithSections'; import type {Section} from './SelectionList/SelectionListWithSections/types'; import SettlementButton from './SettlementButton'; @@ -1398,7 +1398,7 @@ function MoneyRequestConfirmationList({ sections={sections} - ListItem={NewChatListItem} + ListItem={UserListItem} onSelectRow={navigateToParticipantPage} shouldSingleExecuteRowSelect shouldPreventDefaultFocusOnSelectRow diff --git a/src/components/OptionsPicker/OptionItem.tsx b/src/components/OptionsPicker/OptionItem.tsx index a6b7cbe45a2d..aa792e146ef8 100644 --- a/src/components/OptionsPicker/OptionItem.tsx +++ b/src/components/OptionsPicker/OptionItem.tsx @@ -3,7 +3,7 @@ import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import Icon from '@components/Icon'; import {PressableWithFeedback} from '@components/Pressable'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; +import SelectCircle from '@components/SelectCircle'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -55,15 +55,9 @@ function OptionItem({title, icon, onPress, isSelected = false, isDisabled, style /> {(isSelected || !isDisabled) && ( - onPress?.()} - accessibilityLabel={translate(title)} + )} diff --git a/src/components/PushRowWithModal/PushRowModal.tsx b/src/components/PushRowWithModal/PushRowModal.tsx index e8017c553f41..a2f94504d49a 100644 --- a/src/components/PushRowWithModal/PushRowModal.tsx +++ b/src/components/PushRowWithModal/PushRowModal.tsx @@ -3,7 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import searchOptions from '@libs/searchOptions'; @@ -99,7 +99,7 @@ function PushRowModal({isVisible, selectedOption, onOptionChange, onClose, optio /> { setLocalValue(item.value); onInputChange(item.value); diff --git a/src/components/Search/FilterComponents/DatePresetFilterBase.tsx b/src/components/Search/FilterComponents/DatePresetFilterBase.tsx index 3d37f9c8cadf..5ef860d7c7d6 100644 --- a/src/components/Search/FilterComponents/DatePresetFilterBase.tsx +++ b/src/components/Search/FilterComponents/DatePresetFilterBase.tsx @@ -189,7 +189,7 @@ function DatePresetFilterBase({ }} onSelectRow={() => setDateValue(CONST.SEARCH.DATE_MODIFIERS.ON, preset)} keyForList={preset} - wrapperStyle={(styles.flexReset, styles.optionRowCompact)} + wrapperStyle={styles.flexReset} /> ))} {shouldShowHorizontalRule && ( diff --git a/src/components/Search/NewChatListItem.tsx b/src/components/Search/NewChatListItem.tsx deleted file mode 100644 index 23bcf12d452d..000000000000 --- a/src/components/Search/NewChatListItem.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import {Str} from 'expensify-common'; -import React from 'react'; -import {View} from 'react-native'; -import Icon from '@components/Icon'; -import ReportActionAvatars from '@components/ReportActionAvatars'; -import BaseListItem from '@components/SelectionList/ListItem/BaseListItem'; -import type {ListItem, UserListItemProps} from '@components/SelectionList/ListItem/types'; -import Text from '@components/Text'; -import TextWithTooltip from '@components/TextWithTooltip'; -import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; -import useLocalize from '@hooks/useLocalize'; -import useOnyx from '@hooks/useOnyx'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useTheme from '@hooks/useTheme'; -import useThemeStyles from '@hooks/useThemeStyles'; -import getButtonState from '@libs/getButtonState'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; - -function NewChatListItem({ - item, - isFocused, - showTooltip, - isDisabled, - canSelectMultiple, - onSelectRow, - onDismissError, - shouldPreventEnterKeySubmit, - rightHandSideComponent, - onFocus, - shouldSyncFocus, - wrapperStyle, - pressableStyle, -}: UserListItemProps) { - const styles = useThemeStyles(); - const theme = useTheme(); - const StyleUtils = useStyleUtils(); - const {translate} = useLocalize(); - const icons = useMemoizedLazyExpensifyIcons(['ArrowRight']); - - const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; - const subscriptAvatarBorderColor = isFocused ? focusedBackgroundColor : theme.sidebar; - const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; - - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- some utils that are used to get reportID return empty string "", which would make subscription to the whole collection with nullish coalescing operator, example of this could be found in NewChatPage.tsx where some hooks return reportID as empty strings - const [isReportInOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${item.reportID || undefined}`, { - selector: (report) => !!report, - }); - - const reportExists = isReportInOnyx && !!item.reportID; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const itemAccountID = Number(item.accountID || item.icons?.at(1)?.id) || 0; - - const isThereOnlyWorkspaceIcon = item.icons?.length === 1 && item.icons?.at(0)?.type === CONST.ICON_TYPE_WORKSPACE; - const shouldUseIconPolicyID = !item.reportID && !item.accountID && !item.policyID; - const policyID = isThereOnlyWorkspaceIcon && shouldUseIconPolicyID ? String(item.icons?.at(0)?.id) : item.policyID; - - return ( - {translate('workspace.people.invitedBySecondaryLogin', item.invitedSecondaryLogin)} - ) : undefined - } - keyForList={item.keyForList} - onFocus={onFocus} - shouldSyncFocus={shouldSyncFocus} - > - {(hovered?: boolean) => ( - <> - {(!!reportExists || !!itemAccountID || !!policyID) && ( - - )} - - - {!!item.alternateText && ( - - )} - - {!!item.rightElement && item.rightElement} - {!!item.shouldShowRightCaret && ( - - - - )} - - )} - - ); -} - -NewChatListItem.displayName = 'NewChatListItem'; - -export default NewChatListItem; diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 4cee5c49b5d5..2af5a351b24f 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -5,6 +5,7 @@ import {OptionsListStateContext, useOptionsList} from '@components/OptionListCon import OptionsListSkeletonView from '@components/OptionsListSkeletonView'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; import type {ListItem as NewListItem, UserListItemProps} from '@components/SelectionList/ListItem/types'; +import UserListItem from '@components/SelectionList/ListItem/UserListItem'; import SelectionListWithSections from '@components/SelectionList/SelectionListWithSections'; import type {Section, SelectionListWithSectionsHandle} from '@components/SelectionList/SelectionListWithSections/types'; import useAutocompleteSuggestions from '@hooks/useAutocompleteSuggestions'; @@ -35,7 +36,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {CardFeeds, CardList, PersonalDetailsList, Policy, Report} from '@src/types/onyx'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; -import NewChatListItem from './NewChatListItem'; import type {SearchQueryItem, SearchQueryListItemProps} from './SearchList/ListItem/SearchQueryListItem'; import SearchQueryListItem, {isSearchQueryItem} from './SearchList/ListItem/SearchQueryListItem'; import {getSubstitutionMapKey} from './SearchRouter/getQueryWithSubstitutions'; @@ -118,39 +118,14 @@ function SearchRouterItem(props: UserListItemProps | Searc ); } - const { - item, - isFocused, - showTooltip, - isDisabled, - canSelectMultiple, - onSelectRow, - onDismissError, - shouldPreventEnterKeySubmit, - rightHandSideComponent, - onFocus, - shouldSyncFocus, - wrapperStyle, - } = props; - const fsClass = FS.getChatFSClass((item as SearchOption | undefined)?.item); + const fsClass = FS.getChatFSClass((props.item as SearchOption | undefined)?.item); return ( - ); } diff --git a/src/components/Search/SearchList/BaseSearchList/index.tsx b/src/components/Search/SearchList/BaseSearchList/index.tsx index 8addfae872d7..43b77898839f 100644 --- a/src/components/Search/SearchList/BaseSearchList/index.tsx +++ b/src/components/Search/SearchList/BaseSearchList/index.tsx @@ -3,13 +3,13 @@ import {FlashList} from '@shopify/flash-list'; import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {NativeSyntheticEvent} from 'react-native'; import Animated from 'react-native-reanimated'; -import type {SearchListItem} from '@components/Search/SearchList/ListItem/types'; import type {ExtendedTargetedEvent} from '@components/SelectionList/ListItem/types'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import {isMobileChrome} from '@libs/Browser'; import {addKeyDownPressListener, removeKeyDownPressListener} from '@libs/KeyboardShortcut/KeyDownPressListener'; import CONST from '@src/CONST'; +import type {SearchListItem} from '../ListItem/types'; import type BaseSearchListProps from './types'; const AnimatedFlashListComponent = Animated.createAnimatedComponent(FlashList); @@ -53,7 +53,7 @@ function BaseSearchList({ onFocusedIndexChange: (index: number) => { scrollToIndex?.(index); }, - setHasKeyBeenPressed, + ...(!hasKeyBeenPressed.current && {setHasKeyBeenPressed}), isFocused, captureOnInputs: false, }); diff --git a/src/components/Search/SearchList/ListItem/CardListItem.tsx b/src/components/Search/SearchList/ListItem/CardListItem.tsx new file mode 100644 index 000000000000..112eb6823c2a --- /dev/null +++ b/src/components/Search/SearchList/ListItem/CardListItem.tsx @@ -0,0 +1,185 @@ +import {Str} from 'expensify-common'; +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import Avatar from '@components/Avatar'; +import Checkbox from '@components/Checkbox'; +import Icon from '@components/Icon'; +import PlaidCardFeedIcon from '@components/PlaidCardFeedIcon'; +import BaseListItem from '@components/SelectionList/ListItem/BaseListItem'; +import type {BaseListItemProps} from '@components/SelectionList/ListItem/types'; +import type {ListItem} from '@components/SelectionList/types'; +import TextWithTooltip from '@components/TextWithTooltip'; +import UserDetailsTooltip from '@components/UserDetailsTooltip'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import type {PersonalDetails} from '@src/types/onyx'; +import type {BankIcon} from '@src/types/onyx/Bank'; + +type AdditionalCardProps = { + shouldShowOwnersAvatar?: boolean; + cardOwnerPersonalDetails?: PersonalDetails; + bankIcon?: BankIcon; + lastFourPAN?: string; + isVirtual?: boolean; + cardName?: string; + plaidUrl?: string; +}; +type CardListItemProps = BaseListItemProps; + +function CardListItem({ + item, + isFocused, + showTooltip, + isDisabled, + canSelectMultiple, + onSelectRow, + onCheckboxPress, + onDismissError, + rightHandSideComponent, + onFocus, + shouldSyncFocus, +}: CardListItemProps) { + const icons = useMemoizedLazyExpensifyIcons(['FallbackAvatar']); + const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); + const {translate} = useLocalize(); + const theme = useTheme(); + + const handleCheckboxPress = useCallback(() => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + + const ownersAvatar = { + source: item.cardOwnerPersonalDetails?.avatar ?? icons.FallbackAvatar, + id: item.cardOwnerPersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID, + type: CONST.ICON_TYPE_AVATAR, + name: item.cardOwnerPersonalDetails?.displayName ?? '', + fallbackIcon: item.cardOwnerPersonalDetails?.fallbackIcon, + }; + + const subtitleText = + `${item.lastFourPAN ? `${item.lastFourPAN}` : ''}` + + `${item.cardName ? ` ${CONST.DOT_SEPARATOR} ${item.cardName}` : ''}` + + `${item.isVirtual ? ` ${CONST.DOT_SEPARATOR} ${translate('workspace.expensifyCard.virtual')}` : ''}`; + + return ( + + <> + {!!item.bankIcon && ( + + {item.shouldShowOwnersAvatar ? ( + + + + + + + + {!!item?.plaidUrl && ( + + )} + {!item?.plaidUrl && ( + + )} + + + ) : ( + <> + {!!item?.plaidUrl && } + {!item?.plaidUrl && ( + + )} + + )} + + )} + + + + {!!subtitleText && ( + + )} + + + {!!canSelectMultiple && !item.isDisabled && ( + + )} + + + ); +} + +export default CardListItem; +export type {AdditionalCardProps}; diff --git a/src/components/Search/SearchList/ListItem/UserSelectionListItem.tsx b/src/components/Search/SearchList/ListItem/UserSelectionListItem.tsx new file mode 100644 index 000000000000..84af26998ed4 --- /dev/null +++ b/src/components/Search/SearchList/ListItem/UserSelectionListItem.tsx @@ -0,0 +1,152 @@ +import {Str} from 'expensify-common'; +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import Avatar from '@components/Avatar'; +import Icon from '@components/Icon'; +import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; +import BaseListItem from '@components/SelectionList/ListItem/BaseListItem'; +import type {UserSelectionListItemProps} from '@components/SelectionList/ListItem/types'; +import type {ListItem} from '@components/SelectionList/types'; +import TextWithTooltip from '@components/TextWithTooltip'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {areEmailsFromSamePrivateDomain} from '@libs/LoginUtils'; +import {getDisplayNameForParticipant} from '@libs/ReportUtils'; +import CONST from '@src/CONST'; + +function UserSelectionListItem({ + item, + isFocused, + showTooltip, + isDisabled, + canSelectMultiple, + onSelectRow, + onCheckboxPress, + onDismissError, + shouldPreventEnterKeySubmit, + rightHandSideComponent, + onFocus, + shouldSyncFocus, + wrapperStyle, + pressableStyle, +}: UserSelectionListItemProps) { + const styles = useThemeStyles(); + const theme = useTheme(); + const StyleUtils = useStyleUtils(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const icons = useMemoizedLazyExpensifyIcons(['Checkmark']); + const {formatPhoneNumber} = useLocalize(); + + const handleCheckboxPress = useCallback(() => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + + const userHandle = useMemo(() => { + const login = item.login ?? ''; + + // If the emails are not in the same private domain, we just return the users email + if (!areEmailsFromSamePrivateDomain(login, currentUserPersonalDetails.login ?? '')) { + return Str.removeSMSDomain(login); + } + + // Otherwise, the emails are a part of the same private domain, so we can remove the domain and just show username + return login.split('@').at(0); + }, [currentUserPersonalDetails.login, item.login]); + + const userDisplayName = useMemo(() => { + /* eslint-disable @typescript-eslint/prefer-nullish-coalescing -- need || to handle empty string from getDisplayNameForParticipant */ + return ( + getDisplayNameForParticipant({ + accountID: item.accountID ?? CONST.DEFAULT_NUMBER_ID, + formatPhoneNumber, + }) || + item.text || + '' + ); + /* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ + }, [formatPhoneNumber, item.accountID, item.text]); + + return ( + + + {!!item.icons?.length && ( + + + + )} + + + + {!!userHandle && ( + + )} + + + + + {!!item.isSelected && ( + + )} + + + + {!!item.rightElement && item.rightElement} + + + ); +} + +export default UserSelectionListItem; diff --git a/src/components/Search/SortableHeaderText.tsx b/src/components/Search/SortableHeaderText.tsx index 3a2305194261..88191f284553 100644 --- a/src/components/Search/SortableHeaderText.tsx +++ b/src/components/Search/SortableHeaderText.tsx @@ -3,6 +3,7 @@ import {View} from 'react-native'; import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import Icon from '@components/Icon'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; +import type {SortOrder} from '@components/Search/types'; import Text from '@components/Text'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useTheme from '@hooks/useTheme'; @@ -10,7 +11,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import type IconAsset from '@src/types/utils/IconAsset'; import type WithSentryLabel from '@src/types/utils/SentryLabel'; -import type {SortOrder} from './types'; type SearchTableHeaderColumnProps = WithSentryLabel & { text: string; diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 92e23f44b0c6..2280563fa322 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -17,7 +17,6 @@ import useScrollEnabled from '@hooks/useScrollEnabled'; import useSingleExecution from '@hooks/useSingleExecution'; import {focusedItemRef} from '@hooks/useSyncFocus/useSyncFocusImplementation'; import useThemeStyles from '@hooks/useThemeStyles'; -import {addKeyDownPressListener, removeKeyDownPressListener} from '@libs/KeyboardShortcut/KeyDownPressListener'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import CONST from '@src/CONST'; import getEmptyArray from '@src/types/utils/getEmptyArray'; @@ -90,10 +89,9 @@ function BaseSelectionList({ shouldPreventDefaultFocusOnSelectRow = false, shouldShowTextInput = !!textInputOptions?.label, shouldClearInputOnSelect = false, - shouldHighlightSelectedItem, + shouldHighlightSelectedItem = true, shouldUseDefaultRightHandSideCheckmark, shouldDisableHoverStyle = false, - shouldShowRadioButton, setShouldDisableHoverStyle = () => {}, }: SelectionListProps) { const styles = useThemeStyles(); @@ -159,12 +157,6 @@ function BaseSelectionList({ hasKeyBeenPressed.current = true; }, []); - useEffect(() => { - addKeyDownPressListener(setHasKeyBeenPressed); - - return () => removeKeyDownPressListener(setHasKeyBeenPressed); - }, [setHasKeyBeenPressed]); - const scrollToIndex = useCallback( (index: number) => { // Bounds check: ensure index is valid for current data @@ -371,7 +363,6 @@ function BaseSelectionList({ shouldSyncFocus={!isTextInputFocusedRef.current && hasKeyBeenPressed.current} shouldDisableHoverStyle={shouldDisableHoverStyle} shouldShowRightCaret={shouldShowRightCaret} - shouldShowRadioButton={shouldShowRadioButton} /> ); }; diff --git a/src/components/SelectionList/ListItem/BaseListItem.tsx b/src/components/SelectionList/ListItem/BaseListItem.tsx index adc4ab538c71..cee2367d5c24 100644 --- a/src/components/SelectionList/ListItem/BaseListItem.tsx +++ b/src/components/SelectionList/ListItem/BaseListItem.tsx @@ -5,7 +5,6 @@ import Icon from '@components/Icon'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import type {PressableWithFeedbackProps} from '@components/Pressable/PressableWithFeedback'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; import getAccessibilityLabel from '@components/SelectionList/utils/getAccessibilityLabel'; import useHover from '@hooks/useHover'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -83,8 +82,9 @@ function BaseListItem({ onFocus = () => {}, hoverStyle, onLongPressRow, - shouldUseDefaultRightHandSideCheckmark = false, - shouldHighlightSelectedItem = false, + testID, + shouldUseDefaultRightHandSideCheckmark = true, + shouldHighlightSelectedItem = true, shouldDisableHoverStyle, shouldShowRightCaret = false, accessible, @@ -121,10 +121,12 @@ function BaseListItem({ return rightHandSideComponent; }; - const shouldShowCheckbox = !canSelectMultiple && !rightHandSideComponent && shouldUseDefaultRightHandSideCheckmark; + const shouldShowCheckmark = !canSelectMultiple && !!item.isSelected && !rightHandSideComponent && shouldUseDefaultRightHandSideCheckmark; const shouldShowRBRIndicator = (!item.isSelected || !!item.canShowSeveralIndicators) && !!item.brickRoadIndicator && shouldDisplayRBR; + const shouldShowHiddenCheckmark = shouldShowRBRIndicator && !shouldShowCheckmark && !!item.canShowSeveralIndicators; + const {role, tabIndex, accessibilityState, accessibleAndAccessibilityLabel} = getAccessibilityProps({ role: accessibilityRole, accessible, @@ -190,20 +192,15 @@ function BaseListItem({ accessibilityState={accessibilityState} onMouseLeave={handleMouseLeave} wrapperStyle={pressableWrapperStyle} + testID={`${CONST.BASE_LIST_ITEM_TEST_ID}${item.keyForList}`} > @@ -219,16 +216,17 @@ function BaseListItem({ )} - {shouldShowCheckbox && ( + {(shouldShowCheckmark || shouldShowHiddenCheckmark) && ( - + + + )} diff --git a/src/components/SelectionList/ListItem/CardListItem.tsx b/src/components/SelectionList/ListItem/CardListItem.tsx index 20dfdc48191f..3672043f5963 100644 --- a/src/components/SelectionList/ListItem/CardListItem.tsx +++ b/src/components/SelectionList/ListItem/CardListItem.tsx @@ -2,9 +2,9 @@ import {Str} from 'expensify-common'; import React from 'react'; import {View} from 'react-native'; import Avatar from '@components/Avatar'; +import Checkbox from '@components/Checkbox'; import Icon from '@components/Icon'; import PlaidCardFeedIcon from '@components/PlaidCardFeedIcon'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; import TextWithTooltip from '@components/TextWithTooltip'; import UserDetailsTooltip from '@components/UserDetailsTooltip'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -49,6 +49,14 @@ function CardListItem({ const {translate} = useLocalize(); const theme = useTheme(); + const handleCheckboxPress = () => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }; + const ownersAvatar = { source: item.cardOwnerPersonalDetails?.avatar ?? icons.FallbackAvatar, id: item.cardOwnerPersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID, @@ -158,9 +166,11 @@ function CardListItem({ {!!canSelectMultiple && !item.isDisabled && ( - diff --git a/src/components/SelectionList/ListItem/InviteMemberListItem.tsx b/src/components/SelectionList/ListItem/InviteMemberListItem.tsx index dbf02f781ee6..8c3c111b6ffa 100644 --- a/src/components/SelectionList/ListItem/InviteMemberListItem.tsx +++ b/src/components/SelectionList/ListItem/InviteMemberListItem.tsx @@ -1,9 +1,10 @@ import {Str} from 'expensify-common'; import React, {useCallback} from 'react'; import {View} from 'react-native'; +import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import {useProductTrainingContext} from '@components/ProductTrainingContext'; import ReportActionAvatars from '@components/ReportActionAvatars'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; +import SelectCircle from '@components/SelectCircle'; import {ListItemFocusContext} from '@components/SelectionList/ListItemFocusContext'; import Text from '@components/Text'; import TextWithTooltip from '@components/TextWithTooltip'; @@ -39,7 +40,6 @@ function InviteMemberListItem({ canShowProductTrainingTooltip = true, index = 0, sectionIndex = 0, - shouldShowRadioButton = true, }: InviteMemberListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -61,8 +61,7 @@ function InviteMemberListItem({ const subscriptAvatarBorderColor = isFocused ? focusedBackgroundColor : theme.sidebar; const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we need to check if the item is disabled and if the checkbox or radio button should be shown - const shouldShowCheckbox = !item.isDisabled && (canSelectMultiple || shouldShowRadioButton); + const shouldShowCheckBox = canSelectMultiple && !item.isDisabled; const handleCheckboxPress = useCallback(() => { if (onCheckboxPress) { @@ -98,7 +97,7 @@ function InviteMemberListItem({ keyForList={item.keyForList} onFocus={onFocus} shouldSyncFocus={shouldSyncFocus} - shouldDisplayRBR={!shouldShowCheckbox} + shouldDisplayRBR={!shouldShowCheckBox} testID={item.text} > {(hovered?: boolean) => ( @@ -156,14 +155,20 @@ function InviteMemberListItem({ )} {!!item.rightElement && {item.rightElement}} - {!!shouldShowCheckbox && ( - + sentryLabel={CONST.SENTRY_LABEL.LIST_ITEM.INVITE_MEMBER_CHECKBOX} + > + + )} diff --git a/src/components/SelectionList/ListItem/ListItemRenderer.tsx b/src/components/SelectionList/ListItem/ListItemRenderer.tsx index 618b1583afd8..1d7b34385a9a 100644 --- a/src/components/SelectionList/ListItem/ListItemRenderer.tsx +++ b/src/components/SelectionList/ListItem/ListItemRenderer.tsx @@ -16,8 +16,7 @@ type ListItemRendererProps = Omit['singleExecution']; titleStyles?: StyleProp; titleContainerStyles?: StyleProp; - shouldHighlightSelectedItem?: boolean; - shouldShowRadioButton?: boolean; + shouldHighlightSelectedItem: boolean; }; function ListItemRenderer({ @@ -53,7 +52,6 @@ function ListItemRenderer({ shouldHighlightSelectedItem, shouldDisableHoverStyle, shouldShowRightCaret, - shouldShowRadioButton, errorRowStyles, }: ListItemRendererProps) { const handleOnCheckboxPress = () => { @@ -113,7 +111,6 @@ function ListItemRenderer({ shouldHighlightSelectedItem={shouldHighlightSelectedItem} shouldDisableHoverStyle={shouldDisableHoverStyle} shouldShowRightCaret={shouldShowRightCaret} - shouldShowRadioButton={shouldShowRadioButton} /> {item.footerContent && item.footerContent} diff --git a/src/components/SelectionList/ListItem/MultiSelectListItem.tsx b/src/components/SelectionList/ListItem/MultiSelectListItem.tsx index d1bde21eb269..10bf72dab7d0 100644 --- a/src/components/SelectionList/ListItem/MultiSelectListItem.tsx +++ b/src/components/SelectionList/ListItem/MultiSelectListItem.tsx @@ -1,7 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import Avatar from '@components/Avatar'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; +import Checkbox from '@components/Checkbox'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import RadioListItem from './RadioListItem'; @@ -26,17 +26,17 @@ function MultiSelectListItem({ shouldSyncFocus, wrapperStyle, titleStyles, - accessibilityState, - shouldHighlightSelectedItem = false, }: MultiSelectListItemProps) { const styles = useThemeStyles(); const icon = item.icons?.at(0); const checkboxComponent = useCallback(() => { return ( - onSelectRow(item)} /> ); }, [item, onSelectRow]); @@ -87,8 +87,6 @@ function MultiSelectListItem({ shouldSyncFocus={shouldSyncFocus} wrapperStyle={computedWrapperStyle} titleStyles={titleStyles} - accessibilityState={accessibilityState} - shouldHighlightSelectedItem={shouldHighlightSelectedItem} /> ); } diff --git a/src/components/SelectionList/ListItem/RadioListItem.tsx b/src/components/SelectionList/ListItem/RadioListItem.tsx index 5de7832b02b1..dbf969f7ceff 100644 --- a/src/components/SelectionList/ListItem/RadioListItem.tsx +++ b/src/components/SelectionList/ListItem/RadioListItem.tsx @@ -26,6 +26,7 @@ function RadioListItem({ wrapperStyle, titleStyles, shouldHighlightSelectedItem = true, + shouldDisableHoverStyle, accessibilityRole, shouldUseDefaultRightHandSideComponent, }: RadioListItemProps) { @@ -70,6 +71,7 @@ function RadioListItem({ shouldSyncFocus={shouldSyncFocus} pendingAction={item.pendingAction} shouldHighlightSelectedItem={shouldHighlightSelectedItem} + shouldDisableHoverStyle={shouldDisableHoverStyle} accessibilityRole={accessibilityRole} > <> diff --git a/src/components/SelectionList/ListItem/SingleSelectListItem.tsx b/src/components/SelectionList/ListItem/SingleSelectListItem.tsx index 6ae4040f45fc..b1fd53063dde 100644 --- a/src/components/SelectionList/ListItem/SingleSelectListItem.tsx +++ b/src/components/SelectionList/ListItem/SingleSelectListItem.tsx @@ -1,5 +1,5 @@ import React, {useCallback} from 'react'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; +import Checkbox from '@components/Checkbox'; import useThemeStyles from '@hooks/useThemeStyles'; import RadioListItem from './RadioListItem'; import type {ListItem, SingleSelectListItemProps} from './types'; @@ -23,20 +23,18 @@ function SingleSelectListItem({ shouldSyncFocus, wrapperStyle, titleStyles, - shouldHighlightSelectedItem = false, - rightHandSideComponent = undefined, - shouldShowRadioButton = true, - accessibilityState, + shouldHighlightSelectedItem = true, }: SingleSelectListItemProps) { const styles = useThemeStyles(); const radioCheckboxComponent = useCallback(() => { return ( - onSelectRow(item)} /> ); }, [item, onSelectRow]); @@ -48,7 +46,7 @@ function SingleSelectListItem({ isFocused={isFocused} showTooltip={showTooltip} isDisabled={isDisabled} - rightHandSideComponent={rightHandSideComponent ?? radioCheckboxComponent} + rightHandSideComponent={radioCheckboxComponent} onSelectRow={onSelectRow} onDismissError={onDismissError} shouldPreventEnterKeySubmit={shouldPreventEnterKeySubmit} @@ -57,11 +55,9 @@ function SingleSelectListItem({ alternateTextNumberOfLines={alternateTextNumberOfLines} onFocus={onFocus} shouldSyncFocus={shouldSyncFocus} - wrapperStyle={[styles.optionRow, wrapperStyle]} + wrapperStyle={[styles.optionRowCompact, wrapperStyle]} titleStyles={titleStyles} shouldHighlightSelectedItem={shouldHighlightSelectedItem} - shouldShowRadioButton={shouldShowRadioButton} - accessibilityState={accessibilityState} /> ); } diff --git a/src/components/SelectionList/ListItem/TableListItem.tsx b/src/components/SelectionList/ListItem/TableListItem.tsx index d3b610cc37be..ec40a586e273 100644 --- a/src/components/SelectionList/ListItem/TableListItem.tsx +++ b/src/components/SelectionList/ListItem/TableListItem.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {View} from 'react-native'; +import Checkbox from '@components/Checkbox'; import ReportActionAvatars from '@components/ReportActionAvatars'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; import TextWithTooltip from '@components/TextWithTooltip'; import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -42,6 +42,14 @@ function TableListItem({ const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; const hoveredBackgroundColor = styles.sidebarLinkHover?.backgroundColor ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; + const handleCheckboxPress = () => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }; + return ( ({ {(hovered) => ( <> {!!canSelectMultiple && ( - ({ - item, - isFocused, - showTooltip, - isDisabled, - onSelectRow, - onCheckboxPress, - onFocus, - shouldSyncFocus, - accessibilityState, -}: TravelDomainListItemProps) { +function TravelDomainListItem({item, isFocused, showTooltip, isDisabled, onSelectRow, onCheckboxPress, onFocus, shouldSyncFocus}: TravelDomainListItemProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + + const handleCheckboxPress = useCallback(() => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); const showRecommendedTag = item.isRecommended ?? false; return ( @@ -35,17 +35,21 @@ function TravelDomainListItem({ keyForList={item.keyForList} onFocus={onFocus} shouldSyncFocus={shouldSyncFocus} - accessibilityState={accessibilityState} > <> - + + + ({ shouldUseDefaultRightHandSideCheckmark, forwardedFSClass, shouldDisableHoverStyle, - shouldShowRadioButton, }: UserListItemProps) { const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'Checkmark'] as const); const styles = useThemeStyles(); @@ -54,6 +53,14 @@ function UserListItem({ const subscriptAvatarBorderColor = isFocused ? focusedBackgroundColor : theme.sidebar; const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; + const handleCheckboxPress = useCallback(() => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- some utils that are used to get reportID return empty string "", which would make subscription to the whole collection with nullish coalescing operator, example of this could be found in NewChatPage.tsx where some hooks return reportID as empty strings const [isReportInOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${item.reportID || undefined}`, { selector: reportExistsSelector, @@ -92,7 +99,6 @@ function UserListItem({ {translate('workspace.people.invitedBySecondaryLogin', item.invitedSecondaryLogin)} ) : undefined } - shouldUseDefaultRightHandSideCheckmark={false} keyForList={item.keyForList} onFocus={onFocus} shouldSyncFocus={shouldSyncFocus} @@ -110,13 +116,26 @@ function UserListItem({ style={[styles.flex1, styles.flexRow, styles.alignItemsCenter]} > {!shouldUseDefaultRightHandSideCheckmark && !!canSelectMultiple && ( - + onPress={handleCheckboxPress} + style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled, styles.mr3]} + > + + {!!item.isSelected && ( + + )} + + )} {(!!reportExists || !!itemAccountID || !!policyID) && ( ({ /> )} - {((!!shouldUseDefaultRightHandSideCheckmark && !!canSelectMultiple) || !!shouldShowRadioButton) && ( - + onPress={handleCheckboxPress} + style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled, styles.ml3]} + > + + {!!item.isSelected && ( + + )} + + )} ); diff --git a/src/components/SelectionList/ListItem/UserSelectionListItem.tsx b/src/components/SelectionList/ListItem/UserSelectionListItem.tsx index 81ab3e0726f1..c64895411d90 100644 --- a/src/components/SelectionList/ListItem/UserSelectionListItem.tsx +++ b/src/components/SelectionList/ListItem/UserSelectionListItem.tsx @@ -1,11 +1,15 @@ import {Str} from 'expensify-common'; -import React, {useMemo} from 'react'; +import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import Avatar from '@components/Avatar'; -import SelectionCheckbox from '@components/SelectionList/components/SelectionCheckbox'; +import Icon from '@components/Icon'; +import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import TextWithTooltip from '@components/TextWithTooltip'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {areEmailsFromSamePrivateDomain} from '@libs/LoginUtils'; import {getDisplayNameForParticipant} from '@libs/ReportUtils'; @@ -30,9 +34,20 @@ function UserSelectionListItem({ pressableStyle, }: UserSelectionListItemProps) { const styles = useThemeStyles(); + const theme = useTheme(); + const StyleUtils = useStyleUtils(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const icons = useMemoizedLazyExpensifyIcons(['Checkmark']); const {formatPhoneNumber} = useLocalize(); + const handleCheckboxPress = useCallback(() => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + const userHandle = useMemo(() => { const login = item.login ?? ''; @@ -100,13 +115,25 @@ function UserSelectionListItem({ )} - + onPress={handleCheckboxPress} + style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled, !!item.rightElement && styles.mr3]} + > + + {!!item.isSelected && ( + + )} + + {!!item.rightElement && item.rightElement} diff --git a/src/components/SelectionList/ListItem/types.ts b/src/components/SelectionList/ListItem/types.ts index 98d9700a76ca..286759246408 100644 --- a/src/components/SelectionList/ListItem/types.ts +++ b/src/components/SelectionList/ListItem/types.ts @@ -219,9 +219,6 @@ type CommonListItemProps = { /** Whether product training tooltips can be displayed */ canShowProductTrainingTooltip?: boolean; - - /** Whether to show the radio button */ - shouldShowRadioButton?: boolean; } & TRightHandSideComponent & WithSentryLabel; diff --git a/src/components/SelectionList/SelectionListWithSections/BaseSelectionListWithSections.tsx b/src/components/SelectionList/SelectionListWithSections/BaseSelectionListWithSections.tsx index 693b9dae3776..29dc9f607c47 100644 --- a/src/components/SelectionList/SelectionListWithSections/BaseSelectionListWithSections.tsx +++ b/src/components/SelectionList/SelectionListWithSections/BaseSelectionListWithSections.tsx @@ -76,8 +76,7 @@ function BaseSelectionListWithSections({ isRowMultilineSupported = false, titleNumberOfLines, shouldUseDefaultRightHandSideComponent, - shouldDisableHoverStyle, - shouldShowRadioButton, + shouldDisableHoverStyle = false, setShouldDisableHoverStyle = () => {}, canShowProductTrainingTooltip, }: SelectionListWithSectionsProps) { @@ -356,6 +355,7 @@ function BaseSelectionListWithSections({ singleExecution={singleExecution} canShowProductTrainingTooltip={canShowProductTrainingTooltip} shouldSyncFocus={!isTextInputFocusedRef.current && hasKeyBeenPressed.current} + shouldHighlightSelectedItem shouldIgnoreFocus={shouldIgnoreFocus} wrapperStyle={style?.listItemWrapperStyle} titleStyles={style?.listItemTitleStyles} @@ -363,7 +363,6 @@ function BaseSelectionListWithSections({ titleNumberOfLines={titleNumberOfLines} shouldUseDefaultRightHandSideComponent={shouldUseDefaultRightHandSideComponent} shouldDisableHoverStyle={shouldDisableHoverStyle} - shouldShowRadioButton={shouldShowRadioButton} /> ); } diff --git a/src/components/SelectionList/components/SelectionCheckbox.tsx b/src/components/SelectionList/components/SelectionCheckbox.tsx deleted file mode 100644 index b452d0b56eb6..000000000000 --- a/src/components/SelectionList/components/SelectionCheckbox.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import type {StyleProp, ViewStyle} from 'react-native'; -import Checkbox from '@components/Checkbox'; -import type {ListItem} from '@components/SelectionList/ListItem/types'; -import CONST from '@src/CONST'; - -type SelectionCheckboxProps = { - /** The item to render the checkbox for */ - item: TItem; - - /** Callback to fire when the item is pressed */ - onSelectRow: (item: TItem) => void; - - /** Custom accessibility label for the checkbox */ - accessibilityLabel?: string; - - /** Whether the checkbox should have circular border radius (for single-select style) */ - isCircular?: boolean; - - /** Whether the checkbox is disabled */ - disabled?: boolean; - - /** Additional styles for the checkbox */ - style?: StyleProp; - - /** Additional styles for the checkbox container */ - containerStyle?: StyleProp; - - /** Whether to stop mouse down event propagation */ - shouldStopMouseDownPropagation?: boolean; - - /** Test ID for the checkbox */ - testID?: string; -}; - -function SelectionCheckbox({ - item, - onSelectRow, - accessibilityLabel, - isCircular = false, - disabled, - style, - containerStyle, - shouldStopMouseDownPropagation, - testID, -}: SelectionCheckboxProps) { - return ( - onSelectRow(item)} - disabled={disabled} - style={style} - containerStyle={containerStyle} - shouldStopMouseDownPropagation={shouldStopMouseDownPropagation} - sentryLabel={CONST.SENTRY_LABEL.USER_LIST_ITEM.CHECKBOX} - testID={testID} - /> - ); -} - -export default SelectionCheckbox; diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 87b6ea50be04..8b6b8eca5300 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -115,9 +115,6 @@ type BaseSelectionListProps = { /** Whether to set the hover style */ setShouldDisableHoverStyle?: React.Dispatch>; - - /** Whether to show the radio button */ - shouldShowRadioButton?: boolean; }; /** diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index 5490bb568676..503888f8239c 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -17,7 +17,9 @@ import HeaderWithBackButton from './HeaderWithBackButton'; import OfflineWithFeedback from './OfflineWithFeedback'; import ScreenWrapper from './ScreenWrapper'; import SelectionList from './SelectionList'; -import SingleSelectListItem from './SelectionList/ListItem/SingleSelectListItem'; +import type RadioListItem from './SelectionList/ListItem/RadioListItem'; +import type TableListItem from './SelectionList/ListItem/TableListItem'; +import type UserListItem from './SelectionList/ListItem/UserListItem'; import type {ListItem} from './SelectionList/types'; type SelectorType = ListItem & { @@ -45,6 +47,9 @@ type SelectionScreenProps = { /** Sections for the section list */ data: Array>; + /** Default renderer for every item in the list */ + listItem: typeof RadioListItem | typeof UserListItem | typeof TableListItem; + /** The style is applied for the wrap component of list item */ listItemWrapperStyle?: StyleProp; @@ -115,6 +120,7 @@ function SelectionScreen({ listEmptyContent, listFooterContent, data, + listItem, listItemWrapperStyle, initiallyFocusedOptionKey, onSelectRow, @@ -164,7 +170,7 @@ function SelectionScreen({ > {prompt} @@ -33,7 +33,6 @@ function SingleChoiceQuestion({prompt, errorText, possibleAnswers, currentQuesti key={currentQuestionIndex} onPress={onInputChange} errorText={errorText} - radioButtonStyle={[styles.optionRowCompact, styles.ph5]} forwardedFSClass={forwardedFSClass} /> diff --git a/src/components/StatePicker/StateSelectorModal.tsx b/src/components/StatePicker/StateSelectorModal.tsx index eaad784b256c..d03e8183ca30 100644 --- a/src/components/StatePicker/StateSelectorModal.tsx +++ b/src/components/StatePicker/StateSelectorModal.tsx @@ -4,7 +4,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -90,7 +90,7 @@ function StateSelectorModal({isVisible, currentState, onStateSelected, onClose, /> - {title} - {description} + {title} + {description} ); diff --git a/src/components/TagPicker.tsx b/src/components/TagPicker.tsx index 8efe216af8ae..8cc6712b360d 100644 --- a/src/components/TagPicker.tsx +++ b/src/components/TagPicker.tsx @@ -11,7 +11,7 @@ import {getTagArrayFromName} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PolicyTag, PolicyTags} from '@src/types/onyx'; -import SingleSelectListItem from './SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from './SelectionList/ListItem/RadioListItem'; import SelectionListWithSections from './SelectionList/SelectionListWithSections'; type TagPickerProps = { @@ -137,7 +137,7 @@ function TagPicker({ return ( diff --git a/src/components/UnitPicker.tsx b/src/components/UnitPicker.tsx index cf75a423dec2..31c9e42e9ee5 100644 --- a/src/components/UnitPicker.tsx +++ b/src/components/UnitPicker.tsx @@ -5,7 +5,7 @@ import {getUnitTranslationKey} from '@libs/WorkspacesSettingsUtils'; import CONST from '@src/CONST'; import type {Unit} from '@src/types/onyx/Policy'; import SelectionList from './SelectionList'; -import SingleSelectListItem from './SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from './SelectionList/ListItem/RadioListItem'; type UnitItemType = { value: Unit; @@ -38,7 +38,7 @@ function UnitPicker({defaultValue, onOptionSelected}: UnitPickerProps) { return ( unit.isSelected)?.keyForList} /> diff --git a/src/components/ValuePicker/ValueSelectionList.tsx b/src/components/ValuePicker/ValueSelectionList.tsx index 906dbb140eaa..cde868808598 100644 --- a/src/components/ValuePicker/ValueSelectionList.tsx +++ b/src/components/ValuePicker/ValueSelectionList.tsx @@ -1,6 +1,6 @@ import React, {useMemo} from 'react'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ValueSelectionListProps} from './types'; function ValueSelectionList({ @@ -25,7 +25,7 @@ function ValueSelectionList({ shouldStopPropagation shouldShowTooltips={shouldShowTooltips} shouldUpdateFocusedIndex - ListItem={SingleSelectListItem} + ListItem={RadioListItem} addBottomSafeAreaPadding={addBottomSafeAreaPadding} disableKeyboardShortcuts={disableKeyboardShortcuts} alternateNumberOfSupportedLines={alternateNumberOfSupportedLines} diff --git a/src/components/WorkspaceMemberRoleList.tsx b/src/components/WorkspaceMemberRoleList.tsx index 432dd71ff5ae..1263e0d38d8c 100644 --- a/src/components/WorkspaceMemberRoleList.tsx +++ b/src/components/WorkspaceMemberRoleList.tsx @@ -11,7 +11,7 @@ import type {Route} from '@src/ROUTES'; import type {Policy} from '@src/types/onyx'; import HeaderWithBackButton from './HeaderWithBackButton'; import SelectionList from './SelectionList'; -import SingleSelectListItem from './SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from './SelectionList/ListItem/RadioListItem'; import type {ListItem} from './SelectionList/types'; type ListItemType = ListItem> & { @@ -70,7 +70,7 @@ function WorkspaceMemberRoleList({role, policy, navigateBackTo = undefined, isLo item.isSelected)?.keyForList} diff --git a/src/components/WorkspaceMembersSelectionList.tsx b/src/components/WorkspaceMembersSelectionList.tsx index 93131d36f982..5bdfc3fe0d73 100644 --- a/src/components/WorkspaceMembersSelectionList.tsx +++ b/src/components/WorkspaceMembersSelectionList.tsx @@ -97,7 +97,6 @@ function WorkspaceMembersSelectionList({policyID, selectedApprover, setApprover} addBottomSafeAreaPadding showScrollIndicator isRowMultilineSupported - shouldShowRadioButton /> ); } diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index 639d4b8bc8ca..2b0b3cec08ac 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -1,6 +1,6 @@ import type {OnyxCollection} from 'react-native-onyx'; import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; -import type {AdditionalCardProps} from '@components/SelectionList/ListItem/CardListItem'; +import type {AdditionalCardProps} from '@components/Search/SearchList/ListItem/CardListItem'; import type {FeedKeysWithAssignedCards} from '@hooks/useFeedKeysWithAssignedCards'; import type IllustrationsType from '@styles/theme/illustrations/types'; import CONST from '@src/CONST'; diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 051a6dbca666..4c0e76a1336b 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -3494,7 +3494,6 @@ export type { Option, OptionList, OptionTree, - OptionWithKey, Options, OrderOptionsConfig, OrderReportOptionsConfig, diff --git a/src/libs/ReportFieldOptionsListUtils.ts b/src/libs/ReportFieldOptionsListUtils.ts index 3788f14c8f4c..8c35443508fa 100644 --- a/src/libs/ReportFieldOptionsListUtils.ts +++ b/src/libs/ReportFieldOptionsListUtils.ts @@ -1,21 +1,22 @@ import type {LocalizedTranslate} from '@components/LocaleContextProvider'; -import type {OptionWithKey} from './OptionsListUtils'; +import type {Option} from './OptionsListUtils'; import type {OptionData} from './ReportUtils'; import tokenizedSearch from './tokenizedSearch'; +type ReportFieldOption = Option & {keyForList: string}; + /** * Transforms the provided report field options into option objects. * * @param reportFieldOptions - an initial report field options array */ -function getReportFieldOptions(reportFieldOptions: string[], isSelected = false): OptionWithKey[] { +function getReportFieldOptions(reportFieldOptions: string[]): ReportFieldOption[] { return reportFieldOptions.map((name) => ({ text: name, keyForList: name, searchText: name, tooltipText: name, isDisabled: false, - isSelected, })); } diff --git a/src/pages/Debug/ConstantPicker.tsx b/src/pages/Debug/ConstantPicker.tsx index 9ecbfaf374d6..fd39d6928aac 100644 --- a/src/pages/Debug/ConstantPicker.tsx +++ b/src/pages/Debug/ConstantPicker.tsx @@ -1,7 +1,7 @@ import isObject from 'lodash/isObject'; import React, {useMemo, useState} from 'react'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import useLocalize from '@hooks/useLocalize'; import tokenizedSearch from '@libs/tokenizedSearch'; @@ -67,7 +67,7 @@ function ConstantPicker({formType, fieldName, fieldValue, onSubmit}: ConstantPic data={sections} textInputOptions={textInputOptions} onSelectRow={onSubmit} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={selectedOptionKey} /> ); diff --git a/src/pages/Debug/Report/DebugReportActions.tsx b/src/pages/Debug/Report/DebugReportActions.tsx index 1f7f5fc4aeb9..45a0f70a06a2 100644 --- a/src/pages/Debug/Report/DebugReportActions.tsx +++ b/src/pages/Debug/Report/DebugReportActions.tsx @@ -3,7 +3,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import Button from '@components/Button'; import ScrollView from '@components/ScrollView'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useMappedPersonalDetails, {personalDetailMapper} from '@hooks/useMappedPersonalDetails'; @@ -135,7 +135,7 @@ function DebugReportActions({reportID}: DebugReportActionsProps) { style={{listItemTitleStyles: styles.fontWeightNormal}} textInputOptions={textInputOptions} onSelectRow={(item) => Navigation.navigate(ROUTES.DEBUG_REPORT_ACTION.getRoute(reportID, item.reportActionID))} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} /> ); diff --git a/src/pages/EditReportFieldDropdown.tsx b/src/pages/EditReportFieldDropdown.tsx index f681869f9117..79ff44e9bf76 100644 --- a/src/pages/EditReportFieldDropdown.tsx +++ b/src/pages/EditReportFieldDropdown.tsx @@ -1,6 +1,6 @@ import React from 'react'; import Icon from '@components/Icon'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import SelectionListWithSections from '@components/SelectionList/SelectionListWithSections'; import type {ListItem} from '@components/SelectionList/types'; import useDebouncedState from '@hooks/useDebouncedState'; @@ -29,11 +29,10 @@ type EditReportFieldDropdownPageProps = { function EditReportFieldDropdown({onSubmit, fieldKey, fieldValue, fieldOptions}: EditReportFieldDropdownPageProps) { const [recentlyUsedReportFields] = useOnyx(ONYXKEYS.RECENTLY_USED_REPORT_FIELDS); const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState(''); + const theme = useTheme(); const {translate, localeCompare} = useLocalize(); const recentlyUsedOptions = recentlyUsedReportFields?.[fieldKey]?.sort(localeCompare) ?? []; const icons = useMemoizedLazyExpensifyIcons(['Checkmark'] as const); - const theme = useTheme(); - const itemRightSideComponent = (item: ListItem) => { if (item.text === fieldValue) { return ( @@ -76,7 +75,7 @@ function EditReportFieldDropdown({onSubmit, fieldKey, fieldValue, fieldOptions}: return ( onSubmit({[fieldKey]: !option?.text || fieldValue === option.text ? '' : option.text})} diff --git a/src/pages/EnablePayments/AddBankAccount/substeps/PlaidStep.tsx b/src/pages/EnablePayments/AddBankAccount/substeps/PlaidStep.tsx index 716f4d4e1099..a09c84bc2825 100644 --- a/src/pages/EnablePayments/AddBankAccount/substeps/PlaidStep.tsx +++ b/src/pages/EnablePayments/AddBankAccount/substeps/PlaidStep.tsx @@ -57,7 +57,7 @@ function PlaidStep({onNext}: SubStepProps) { onSubmit={handleNextPress} scrollContextEnabled submitButtonText={translate('common.next')} - style={[styles.flexGrow1]} + style={[styles.mh5, styles.flexGrow1]} isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0} shouldHideFixErrorsAlert > diff --git a/src/pages/EnablePayments/IdologyQuestions.tsx b/src/pages/EnablePayments/IdologyQuestions.tsx index 36b5b9cbeab3..b74e85cb49a5 100644 --- a/src/pages/EnablePayments/IdologyQuestions.tsx +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -117,8 +117,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { key={currentQuestionIndex} validate={validate} scrollContextEnabled - style={[styles.flexGrow1]} - submitButtonStyles={styles.mh5} + style={[styles.flexGrow1, styles.ph5]} submitButtonText={translate('common.saveAndContinue')} shouldHideFixErrorsAlert > @@ -135,7 +134,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { onInputChange={() => {}} forwardedFSClass={CONST.FULLSTORY.CLASS.MASK} /> - + toggleOption(item)} + disabled={item.isDisabled} + role={CONST.ROLE.CHECKBOX} accessibilityLabel={item.text ? translate('selectionList.userSelected', item.text) : ''} - containerStyle={[styles.ml5]} - /> + style={[styles.flexRow, styles.alignItemsCenter, styles.ml5, styles.optionSelectCircle]} + > + + ); } const buttonInnerStyles = isFocused ? styles.buttonDefaultHovered : {}; @@ -486,7 +493,7 @@ function NewChatPage({ref}: NewChatPageProps) { > ref={selectionListRef} - ListItem={NewChatListItem} + ListItem={UserListItem} sections={areOptionsInitialized ? sections : getEmptyArray>()} onSelectRow={selectOption} shouldShowTextInput diff --git a/src/pages/NewReportWorkspaceSelectionPage.tsx b/src/pages/NewReportWorkspaceSelectionPage.tsx index acdcd8b64d80..2a981d3bf937 100644 --- a/src/pages/NewReportWorkspaceSelectionPage.tsx +++ b/src/pages/NewReportWorkspaceSelectionPage.tsx @@ -283,7 +283,6 @@ function NewReportWorkspaceSelectionPage({route}: NewReportWorkspaceSelectionPag onSelectRow={selectPolicy} textInputOptions={textInputOptions} shouldShowLoadingPlaceholder={fetchStatus.status === 'loading' || !didScreenTransitionEnd} - shouldShowRadioButton /> )} diff --git a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx index 7e84ed11f5c6..8f99f144bb2a 100644 --- a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx +++ b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import Button from '@components/Button'; import FixedFooter from '@components/FixedFooter'; @@ -128,56 +128,58 @@ function BaseOnboardingAccounting({shouldUseNativeStyles, route}: BaseOnboarding setOnboardingPolicyID(paidGroupPolicy.id); }, [paidGroupPolicy, onboardingPolicyID]); - const createAccountingOption = (integration: Integration): OnboardingListItem => { - const icon = expensifyIcons[integration.iconName] as IconAsset | undefined; - return { - keyForList: integration.key ?? 'none', - text: translate(integration.translationKey), + const accountingOptions: OnboardingListItem[] = useMemo(() => { + const createAccountingOption = (integration: Integration): OnboardingListItem => { + const icon = expensifyIcons[integration.iconName] as IconAsset | undefined; + return { + keyForList: integration.key ?? 'none', + text: translate(integration.translationKey), + leftElement: ( + + ), + isSelected: userReportedIntegration === integration.key, + }; + }; + + const noneAccountingOption: OnboardingListItem = { + keyForList: 'none', + text: translate('onboarding.accounting.none'), leftElement: ( ), - isSelected: userReportedIntegration === integration.key, + isSelected: userReportedIntegration === null, }; - }; - - const noneAccountingOption: OnboardingListItem = { - keyForList: 'none', - text: translate('onboarding.accounting.none'), - leftElement: ( - - ), - isSelected: userReportedIntegration === null, - }; - const othersAccountingOption: OnboardingListItem = { - keyForList: 'other', - text: translate('workspace.accounting.other'), - leftElement: ( - - ), - isSelected: userReportedIntegration === 'other', - }; + const othersAccountingOption: OnboardingListItem = { + keyForList: 'other', + text: translate('workspace.accounting.other'), + leftElement: ( + + ), + isSelected: userReportedIntegration === 'other', + }; - const accountingOptions: OnboardingListItem[] = [...integrations.map(createAccountingOption), othersAccountingOption, noneAccountingOption]; + return [...integrations.map(createAccountingOption), othersAccountingOption, noneAccountingOption]; + }, [StyleUtils, styles.mr3, styles.onboardingSmallIcon, theme.icon, translate, userReportedIntegration, expensifyIcons]); - const handleContinue = () => { + const handleContinue = useCallback(() => { if (userReportedIntegration === undefined) { setError(translate('onboarding.errorSelection')); return; @@ -187,23 +189,23 @@ function BaseOnboardingAccounting({shouldUseNativeStyles, route}: BaseOnboarding // Navigate to the next onboarding step interested features with the selected integration Navigation.navigate(ROUTES.ONBOARDING_INTERESTED_FEATURES.getRoute(route.params?.backTo)); - }; + }, [translate, userReportedIntegration, route.params?.backTo]); - const handleIntegrationSelect = (integrationKey: OnboardingListItem['keyForList']) => { + const handleIntegrationSelect = useCallback((integrationKey: OnboardingListItem['keyForList']) => { setUserReportedIntegration(integrationKey === 'none' ? null : integrationKey); setError(''); - }; + }, []); - function renderOption(item: OnboardingListItem) { - return ( + const renderOption = useCallback( + (item: OnboardingListItem) => ( handleIntegrationSelect(item.keyForList)} accessibilityLabel={item.text} sentryLabel={CONST.SENTRY_LABEL.ONBOARDING.ACCOUNTING_SELECT_INTEGRATION} accessible={false} - hoverStyle={styles.hoveredComponentBG} - style={[styles.onboardingAccountingItem, isSmallScreenWidth && styles.flexBasis100]} + hoverStyle={!item.isSelected ? styles.hoveredComponentBG : undefined} + style={[styles.onboardingAccountingItem, isSmallScreenWidth && styles.flexBasis100, item.isSelected && styles.activeComponentBG]} > - ); - } + ), + [ + handleIntegrationSelect, + isSmallScreenWidth, + styles.alignItemsCenter, + styles.flexBasis100, + styles.flexRow, + styles.flexRowReverse, + styles.ml0, + styles.onboardingAccountingItem, + styles.textStrong, + styles.hoveredComponentBG, + styles.activeComponentBG, + ], + ); return ( item.keyForList === selectedCompanySize)?.keyForList} shouldUpdateFocusedIndex - ListItem={SingleSelectListItem} + ListItem={RadioListItem} footerContent={footerContent} style={{listItemWrapperStyle: onboardingIsMediumOrLargerScreenWidth ? [styles.pl8, styles.pr8] : []}} /> diff --git a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx index 156682bbbc85..0259a336648f 100644 --- a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx +++ b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx @@ -76,8 +76,7 @@ function Plaid({onNext, setUSDBankAccountStep}: PlaidProps) { onSubmit={handleNextPress} scrollContextEnabled submitButtonText={translate('common.next')} - style={[styles.flexGrow1]} - submitButtonStyles={[styles.mh5]} + style={[styles.mh5, styles.flexGrow1]} isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0} shouldHideFixErrorsAlert > diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx index 81715c013b26..113bd42714d6 100644 --- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx @@ -1,7 +1,7 @@ import React, {useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {ALL_NAICS, NAICS, NAICS_MAPPING_WITH_ID} from '@src/NAICS'; @@ -71,7 +71,7 @@ function IndustryCodeSelector({onInputChange, value, errorText}: IndustryCodeSel { setSearchValue(item.value); setShouldDisplayChildItems(true); diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx index 8d908957e636..63c9f8031470 100644 --- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx @@ -3,7 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; @@ -69,7 +69,7 @@ function BusinessTypeSelectorModal({isVisible, currentBusinessType, onBusinessTy onSelectRow={onBusinessTypeSelected} shouldSingleExecuteRowSelect shouldStopPropagation - ListItem={SingleSelectListItem} + ListItem={RadioListItem} /> diff --git a/src/pages/ReportChangeApproverPage.tsx b/src/pages/ReportChangeApproverPage.tsx index 4b859c619d40..11b9635a4457 100644 --- a/src/pages/ReportChangeApproverPage.tsx +++ b/src/pages/ReportChangeApproverPage.tsx @@ -6,7 +6,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import RenderHTML from '@components/RenderHTML'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; @@ -150,7 +150,7 @@ function ReportChangeApproverPage({report, policy, isLoadingReportData}: ReportC /> { if (!option.keyForList) { diff --git a/src/pages/ReportParticipantRoleSelectionPage.tsx b/src/pages/ReportParticipantRoleSelectionPage.tsx index e855a76d4e09..a988f0aa694e 100644 --- a/src/pages/ReportParticipantRoleSelectionPage.tsx +++ b/src/pages/ReportParticipantRoleSelectionPage.tsx @@ -4,7 +4,7 @@ import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/ListItem/types'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -66,7 +66,7 @@ function ReportParticipantRoleSelectionPage({report, route}: ReportParticipantRo item.isSelected)?.keyForList} diff --git a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersWithdrawalTypePage.tsx b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersWithdrawalTypePage.tsx index dddc432740d6..60f9aa282439 100644 --- a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersWithdrawalTypePage.tsx +++ b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersWithdrawalTypePage.tsx @@ -63,7 +63,6 @@ function SearchFiltersWithdrawalTypePage() { ListItem={SingleSelectListItem} onSelectRow={updateSelectedItem} shouldSingleExecuteRowSelect - style={{listItemWrapperStyle: styles.optionRowCompact}} /> diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 24b7fcd8f87a..eaea655ef94a 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -10,7 +10,7 @@ import {usePersonalDetails} from '@components/OnyxListItemProvider'; import {PressableWithoutFeedback} from '@components/Pressable'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; -import NewChatListItem from '@components/Search/NewChatListItem'; +import UserListItem from '@components/SelectionList/ListItem/UserListItem'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useAncestors from '@hooks/useAncestors'; @@ -207,7 +207,7 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { {translate('common.to')} - ({stepNames, label, optio diff --git a/src/pages/inbox/report/ReportDetailsExportPage.tsx b/src/pages/inbox/report/ReportDetailsExportPage.tsx index 2b1fed2deaed..08abf2e7d883 100644 --- a/src/pages/inbox/report/ReportDetailsExportPage.tsx +++ b/src/pages/inbox/report/ReportDetailsExportPage.tsx @@ -4,6 +4,7 @@ import ConfirmationPage from '@components/ConfirmationPage'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {ModalActions} from '@components/Modal/Global/ModalContext'; import ScreenWrapper from '@components/ScreenWrapper'; +import UserListItem from '@components/SelectionList/ListItem/UserListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import useConfirmModal from '@hooks/useConfirmModal'; @@ -127,6 +128,7 @@ function ReportDetailsExportPage({route}: ReportDetailsExportPageProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="ReportDetailsExportPage" data={exportSelectorOptions} + listItem={UserListItem} shouldBeBlocked={false} onBackButtonPress={() => Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo))} title="common.export" diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index d1a6455ec5e8..3b0e987b6093 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -3,7 +3,7 @@ import React, {useMemo, useState} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import FormHelpMessage from '@components/FormHelpMessage'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; @@ -204,7 +204,7 @@ function IOURequestStepDistanceRate({ selectDistanceRate(value ?? '')} shouldSingleExecuteRowSelect initiallyFocusedItemKey={initiallyFocusedOption} diff --git a/src/pages/settings/Preferences/LanguagePage.tsx b/src/pages/settings/Preferences/LanguagePage.tsx index ace307d307a9..a1a0ce81e1ed 100644 --- a/src/pages/settings/Preferences/LanguagePage.tsx +++ b/src/pages/settings/Preferences/LanguagePage.tsx @@ -3,7 +3,7 @@ import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOffli import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/ListItem/types'; import useLocalize from '@hooks/useLocalize'; import Navigation from '@libs/Navigation/Navigation'; @@ -54,7 +54,7 @@ function LanguagePage() { locale.isSelected)?.keyForList} diff --git a/src/pages/settings/Preferences/PriorityModePage.tsx b/src/pages/settings/Preferences/PriorityModePage.tsx index 9ce79bc230c1..50e9355cdba5 100644 --- a/src/pages/settings/Preferences/PriorityModePage.tsx +++ b/src/pages/settings/Preferences/PriorityModePage.tsx @@ -3,7 +3,7 @@ import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -56,7 +56,7 @@ function PriorityModePage() { {translate('priorityModePage.explainerText')} mode.isSelected)?.keyForList} diff --git a/src/pages/settings/Preferences/ThemePage.tsx b/src/pages/settings/Preferences/ThemePage.tsx index 78e79322adc9..5a5bc77346c9 100644 --- a/src/pages/settings/Preferences/ThemePage.tsx +++ b/src/pages/settings/Preferences/ThemePage.tsx @@ -4,7 +4,7 @@ import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/ListItem/types'; import Switch from '@components/Switch'; import Text from '@components/Text'; @@ -67,7 +67,7 @@ function ThemePage() { theme.isSelected)?.keyForList} diff --git a/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx b/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx index 9ba4a37bdbb4..d67d3488e4d2 100644 --- a/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx +++ b/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx @@ -5,7 +5,7 @@ import type {LocalizedTranslate} from '@components/LocaleContextProvider'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; @@ -190,7 +190,7 @@ function StatusClearAfterPage() { () => ( {translate('pronounsPage.isShownOnProfile')} tz.text === timezone.selected)?.keyForList} diff --git a/src/pages/settings/Report/DynamicVisibilityPage.tsx b/src/pages/settings/Report/DynamicVisibilityPage.tsx index ace3e37dd92c..1edc72dd93f5 100644 --- a/src/pages/settings/Report/DynamicVisibilityPage.tsx +++ b/src/pages/settings/Report/DynamicVisibilityPage.tsx @@ -4,7 +4,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {ModalActions} from '@components/Modal/Global/ModalContext'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useConfirmModal from '@hooks/useConfirmModal'; import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; @@ -92,7 +92,7 @@ function DynamicVisibilityPage({report}: DynamicVisibilityProps) { }} shouldSingleExecuteRowSelect initiallyFocusedItemKey={visibilityOptions.find((visibility) => visibility.isSelected)?.keyForList} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} /> diff --git a/src/pages/settings/Report/DynamicWriteCapabilityPage.tsx b/src/pages/settings/Report/DynamicWriteCapabilityPage.tsx index b8f86ca373bf..07331f73a6b0 100644 --- a/src/pages/settings/Report/DynamicWriteCapabilityPage.tsx +++ b/src/pages/settings/Report/DynamicWriteCapabilityPage.tsx @@ -4,7 +4,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; import useReportIsArchived from '@hooks/useReportIsArchived'; @@ -56,7 +56,7 @@ function DynamicWriteCapabilityPage({report, policy}: DynamicWriteCapabilityPage /> updateWriteCapability(option.value)} shouldSingleExecuteRowSelect initiallyFocusedItemKey={selectedOptionKey} diff --git a/src/pages/settings/Report/NotificationPreferencePage.tsx b/src/pages/settings/Report/NotificationPreferencePage.tsx index a38c48258010..fbd62472e9d9 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.tsx +++ b/src/pages/settings/Report/NotificationPreferencePage.tsx @@ -5,7 +5,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useReportIsArchived from '@hooks/useReportIsArchived'; @@ -62,7 +62,7 @@ function NotificationPreferencePage({report}: NotificationPreferencePageProps) { /> updateNotificationPreferenceForReportAction(option.value)} shouldSingleExecuteRowSelect initiallyFocusedItemKey={notificationPreferenceOptions.find((locale) => locale.isSelected)?.keyForList} diff --git a/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx b/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx index 01a389108113..4adec3d12e24 100644 --- a/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx +++ b/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx @@ -112,9 +112,8 @@ function AddDelegatePage() { }} shouldShowLoadingPlaceholder={!areOptionsInitialized} isLoadingNewOptions={!!isSearchingForReports} - onEndReached={onListEndReached} shouldShowTextInput - shouldShowRadioButton + onEndReached={onListEndReached} /> diff --git a/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx b/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx index e497fd9f25b1..e2b2c71abb4e 100644 --- a/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx +++ b/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx @@ -3,7 +3,7 @@ import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; @@ -71,7 +71,7 @@ function SelectDelegateRolePage({route}: SelectDelegateRolePageProps) { Navigation.navigate(ROUTES.SETTINGS_DELEGATE_CONFIRM.getRoute(login, option.value)); }} data={roleOptions} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} /> diff --git a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx index 640e5cd1d392..a704506cacc8 100644 --- a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx +++ b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx @@ -4,7 +4,7 @@ import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; @@ -79,7 +79,7 @@ function UpdateDelegateRolePage({route}: UpdateDelegateRolePageProps) { Navigation.navigate(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE_CONFIRM_MAGIC_CODE.getRoute(login, option?.value)); }} data={roleOptions} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} /> diff --git a/src/pages/settings/Subscription/DisableAutoRenewSurveyPage/index.tsx b/src/pages/settings/Subscription/DisableAutoRenewSurveyPage/index.tsx index 8cf311e6b3b0..4da2af7be9db 100644 --- a/src/pages/settings/Subscription/DisableAutoRenewSurveyPage/index.tsx +++ b/src/pages/settings/Subscription/DisableAutoRenewSurveyPage/index.tsx @@ -6,7 +6,7 @@ import ScrollView from '@components/ScrollView'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import {updateSubscriptionAutoRenew} from '@userActions/Subscription'; +import * as Subscription from '@userActions/Subscription'; import type {FeedbackSurveyOptionID} from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -15,7 +15,7 @@ function DisableAutoRenewSurveyPage() { const styles = useThemeStyles(); const handleSubmit = (key: FeedbackSurveyOptionID, additionalNote?: string) => { - updateSubscriptionAutoRenew(false, key, additionalNote); + Subscription.updateSubscriptionAutoRenew(false, key, additionalNote); Navigation.goBack(); }; @@ -36,6 +36,7 @@ function DisableAutoRenewSurveyPage() { title={translate('subscription.subscriptionSettings.helpUsImprove')} description={translate('subscription.subscriptionSettings.whatsMainReason')} onSubmit={handleSubmit} + optionRowStyles={styles.flex1} /> diff --git a/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx b/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx index 3e9a78708cf8..82fa8fa1cbe3 100644 --- a/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx +++ b/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx @@ -89,13 +89,14 @@ function RequestEarlyCancellationPage() { title={translate('subscription.subscriptionSettings.helpUsImprove')} description={translate('subscription.requestEarlyCancellation.subtitle')} onSubmit={handleSubmit} + optionRowStyles={styles.flex1} footerText={{acknowledgementText}} isNoteRequired isLoading={isLoading} enabledWhenOffline={false} /> ), - [acknowledgementText, isLoading, styles.mb2, styles.mt4, translate], + [acknowledgementText, isLoading, styles.flex1, styles.mb2, styles.mt4, translate], ); const contentMap: Partial> = { diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx index f66e27602a67..d69ebade16b1 100644 --- a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx +++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx @@ -7,7 +7,7 @@ import getBankIcon from '@components/Icon/BankIcons'; import MenuItem from '@components/MenuItem'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -110,7 +110,7 @@ function ChooseTransferAccountPage() { { const accountType = value?.bankAccount?.accountType; const accountData = value?.bankAccount?.accountData; diff --git a/src/pages/settings/Wallet/CountrySelectionList.tsx b/src/pages/settings/Wallet/CountrySelectionList.tsx index c90581745dc3..30c39317c1f6 100644 --- a/src/pages/settings/Wallet/CountrySelectionList.tsx +++ b/src/pages/settings/Wallet/CountrySelectionList.tsx @@ -2,7 +2,7 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -76,7 +76,7 @@ function CountrySelectionList({isEditing, selectedCountry, countries, onCountryS item.isSelected)?.keyForList} diff --git a/src/pages/workspace/WorkspaceOverviewPlanTypePage.tsx b/src/pages/workspace/WorkspaceOverviewPlanTypePage.tsx index 714e8cb1a789..4fef9a6419de 100644 --- a/src/pages/workspace/WorkspaceOverviewPlanTypePage.tsx +++ b/src/pages/workspace/WorkspaceOverviewPlanTypePage.tsx @@ -8,7 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -137,7 +137,7 @@ function WorkspaceOverviewPlanTypePage({policy}: WithPolicyProps) { { setCurrentPlan(option.value); }} diff --git a/src/pages/workspace/accounting/intacct/SageIntacctEntityPage.tsx b/src/pages/workspace/accounting/intacct/SageIntacctEntityPage.tsx index 30de249b6547..422fe57497c1 100644 --- a/src/pages/workspace/accounting/intacct/SageIntacctEntityPage.tsx +++ b/src/pages/workspace/accounting/intacct/SageIntacctEntityPage.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -46,6 +47,7 @@ function SageIntacctEntityPage({policy}: WithPolicyProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="SageIntacctEntityPage" data={options} + listItem={RadioListItem} onSelectRow={saveSelection} initiallyFocusedOptionKey={options?.find((mode) => mode.isSelected)?.keyForList} onBackButtonPress={() => Navigation.dismissModal()} diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAccountingMethodPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAccountingMethodPage.tsx index e97c01211396..226315c5f954 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAccountingMethodPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAccountingMethodPage.tsx @@ -2,6 +2,7 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -64,6 +65,7 @@ function SageIntacctAccountingMethodPage({policy}: WithPolicyConnectionsProps) { headerTitleAlreadyTranslated={translate('workspace.sageIntacct.accountingMethods.label')} headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExpenseReportApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index b906bcde9afd..3502694bb8c7 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -56,6 +57,7 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="SageIntacctPaymentAccountPage" data={vendorSelectorOptions ?? []} + listItem={RadioListItem} onSelectRow={updateDefaultVendor} initiallyFocusedOptionKey={vendorSelectorOptions.find((mode) => mode.isSelected)?.keyForList} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctDatePage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctDatePage.tsx index 069407c9da39..a8427290ff18 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctDatePage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctDatePage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -70,6 +71,7 @@ function SageIntacctDatePage({policy}: WithPolicyProps) { title="workspace.sageIntacct.exportDate.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExportDate(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctDefaultVendorPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctDefaultVendorPage.tsx index 595e378ec61a..63cac22d6ca3 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctDefaultVendorPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctDefaultVendorPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -100,6 +101,7 @@ function SageIntacctDefaultVendorPage() { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="SageIntacctDefaultVendorPage" data={vendorSelectorOptions ?? []} + listItem={RadioListItem} onSelectRow={updateDefaultVendor} initiallyFocusedOptionKey={vendorSelectorOptions.find((mode) => mode.isSelected)?.keyForList} headerContent={listHeaderComponent} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableCreditCardAccountPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableCreditCardAccountPage.tsx index 237ccfa4c15e..03ae19b04d74 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableCreditCardAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableCreditCardAccountPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -67,6 +68,7 @@ function SageIntacctNonReimbursableCreditCardAccountPage({policy}: WithPolicyCon featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="SageIntacctNonReimbursableCreditCardAccountPage" data={creditCardSelectorOptions ?? []} + listItem={RadioListItem} onSelectRow={updateCreditCardAccount} initiallyFocusedOptionKey={creditCardSelectorOptions.find((mode) => mode.isSelected)?.keyForList} onBackButtonPress={goBack} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesDestinationPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesDestinationPage.tsx index a11dac3f6389..2c6e558c3006 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesDestinationPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesDestinationPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback} from 'react'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -57,6 +58,7 @@ function SageIntacctNonReimbursableExpensesDestinationPage({policy}: WithPolicyC displayName="SageIntacctNonReimbursableExpensesDestinationPage" title="workspace.accounting.exportAs" data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectDestination(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctPreferredExporterPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctPreferredExporterPage.tsx index faec53df8bda..f84da6131ad1 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctPreferredExporterPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctPreferredExporterPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import isEmpty from 'lodash/isEmpty'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -101,6 +102,7 @@ function SageIntacctPreferredExporterPage({policy}: WithPolicyProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="SageIntacctPreferredExporterPage" data={data} + listItem={RadioListItem} headerContent={headerContent} onSelectRow={selectExporter} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesDestinationPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesDestinationPage.tsx index 5c2cdb7bf82f..6215ea532bc2 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesDestinationPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesDestinationPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback} from 'react'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -61,6 +62,7 @@ function SageIntacctReimbursableExpensesDestinationPage({policy}: WithPolicyConn displayName="SageIntacctReimbursableExpensesDestinationPage" title="workspace.accounting.exportAs" data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectDestination(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/intacct/import/DimensionTypeSelector.tsx b/src/pages/workspace/accounting/intacct/import/DimensionTypeSelector.tsx index 8cea931b560d..afd458e7e943 100644 --- a/src/pages/workspace/accounting/intacct/import/DimensionTypeSelector.tsx +++ b/src/pages/workspace/accounting/intacct/import/DimensionTypeSelector.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import FormHelpMessage from '@components/FormHelpMessage'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; @@ -52,7 +52,7 @@ function DimensionTypeSelector({errorText = '', value = '', onInputChange}: Dime {translate('workspace.common.displayedAs')} {selectionOptions.map((option) => ( - option.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/intacct/import/SageIntacctMappingsTypePage.tsx b/src/pages/workspace/accounting/intacct/import/SageIntacctMappingsTypePage.tsx index a7346ecd0582..7481d00e8c16 100644 --- a/src/pages/workspace/accounting/intacct/import/SageIntacctMappingsTypePage.tsx +++ b/src/pages/workspace/accounting/intacct/import/SageIntacctMappingsTypePage.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -80,6 +81,7 @@ function SageIntacctMappingsTypePage({route}: SageIntacctMappingsTypePageProps) featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="SageIntacctMappingsTypePage" data={selectionOptions} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} onSelectRow={updateMapping} initiallyFocusedOptionKey={mappings?.[mappingName]} diff --git a/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx b/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx index ed7f9784fa00..dede5431670e 100644 --- a/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx +++ b/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx @@ -1,6 +1,7 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -86,6 +87,7 @@ function NetSuiteSubsidiarySelector({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteSubsidiarySelector" data={subsidiaryListSections} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} onSelectRow={updateSubsidiary} initiallyFocusedOptionKey={netsuiteConfig?.subsidiaryID ?? subsidiaryListSections?.at(0)?.keyForList} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAccountingMethodPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAccountingMethodPage.tsx index 3c79fd2f5c2d..2a87dfce9ff3 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAccountingMethodPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAccountingMethodPage.tsx @@ -2,6 +2,7 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -70,6 +71,7 @@ function NetSuiteAccountingMethodPage({policy, route}: WithPolicyConnectionsProp title="workspace.netsuite.advancedConfig.accountingMethods.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExpenseReportApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx index 572fa3e8dbcd..4b5fb3848d5c 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -76,6 +77,7 @@ function NetSuiteApprovalAccountSelectPage({policy}: WithPolicyConnectionsProps) displayName="NetSuiteApprovalAccountSelectPage" headerContent={headerContent} data={netsuiteApprovalAccountOptions} + listItem={RadioListItem} onSelectRow={updateCollectionAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx index 99ae1bdf1b13..11ac2d64d7dc 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -74,6 +75,7 @@ function NetSuiteCollectionAccountSelectPage({policy}: WithPolicyConnectionsProp displayName="NetSuiteCollectionAccountSelectPage" headerContent={headerContent} data={netsuiteCollectionAccountOptions} + listItem={RadioListItem} onSelectRow={updateCollectionAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx index 5b2eb09fa429..2302aba38e6c 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/ListItem/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -58,6 +59,7 @@ function NetSuiteExpenseReportApprovalLevelSelectPage({policy}: WithPolicyConnec title="workspace.netsuite.advancedConfig.exportReportsTo.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExpenseReportApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx index 98f32ca34b49..0f0cf14a6075 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/ListItem/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -58,6 +59,7 @@ function NetSuiteJournalEntryApprovalLevelSelectPage({policy}: WithPolicyConnect title="workspace.netsuite.advancedConfig.exportJournalsTo.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectJournalApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx index d94fbb31accf..c3c86c2ac9f0 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -74,6 +75,7 @@ function NetSuiteReimbursementAccountSelectPage({policy}: WithPolicyConnectionsP displayName="NetSuiteReimbursementAccountSelectPage" headerContent={headerContent} data={netsuiteReimbursableAccountOptions} + listItem={RadioListItem} onSelectRow={updateReimbursementAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx index b38e462cc68e..520d84e8ac87 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -58,6 +59,7 @@ function NetSuiteVendorBillApprovalLevelSelectPage({policy}: WithPolicyConnectio title="workspace.netsuite.advancedConfig.exportVendorBillsTo.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectVendorBillApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx index 5e2b918fc2d1..da754ee2b9f1 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -70,6 +71,7 @@ function NetSuiteDateSelectPage({policy}: WithPolicyConnectionsProps) { title="workspace.netsuite.exportDate.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExportDate(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx index 4eb5ebbfecb7..822fd1e71346 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useState} from 'react'; import type {ValueOf} from 'type-fest'; import ConfirmModal from '@components/ConfirmModal'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -79,6 +80,7 @@ function NetSuiteExportExpensesDestinationSelectPage({policy}: WithPolicyConnect displayName="NetSuiteExportExpensesDestinationSelectPage" title="workspace.accounting.exportAs" data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectDestination(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx index f82289e52eeb..5c2badb091af 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback} from 'react'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -64,6 +65,7 @@ function NetSuiteExportExpensesJournalPostingPreferenceSelectPage({policy}: With displayName="NetSuiteExportExpensesJournalPostingPreferenceSelectPage" title="workspace.netsuite.journalPostingPreference.label" data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectPostingPreference(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx index 40ec9d2cc26b..d0cb687b0e30 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -78,6 +79,7 @@ function NetSuiteExportExpensesPayableAccountSelectPage({policy}: WithPolicyConn featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteExportExpensesPayableAccountSelectPage" data={netsuitePayableAccountOptions} + listItem={RadioListItem} onSelectRow={updatePayableAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={goBack} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx index 21914f5585aa..95d20e1c452b 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -72,6 +73,7 @@ function NetSuiteExportExpensesVendorSelectPage({policy}: WithPolicyConnectionsP featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteExportExpensesVendorSelectPage" data={netsuiteVendorOptions} + listItem={RadioListItem} onSelectRow={updateDefaultVendor} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={goBack} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx index 8bf6c1258d6e..6fbd6ab23ad4 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx @@ -6,7 +6,7 @@ import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem, SelectionListHandle} from '@components/SelectionList/types'; import type {SelectorType} from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -103,7 +103,7 @@ function NetSuiteInvoiceItemPreferenceSelectPage({policy}: WithPolicyConnections onSelectRow={(selection: SelectorType) => { selectInvoicePreference(selection as MenuListItem); }} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} showScrollIndicator shouldUpdateFocusedIndex initiallyFocusedItemKey={options.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx index 410e530fd4b9..ad350c55360d 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -59,6 +60,7 @@ function NetSuiteInvoiceItemSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteInvoiceItemSelectPage" data={netsuiteInvoiceItemOptions} + listItem={RadioListItem} onSelectRow={updateInvoiceItem} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_INVOICE_ITEM_PREFERENCE_SELECT.getRoute(policyID), {compareParams: false})} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx index 1de500018e0a..e6f4f85c3ee8 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import isEmpty from 'lodash/isEmpty'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -98,6 +99,7 @@ function NetSuitePreferredExporterSelectPage({policy}: WithPolicyConnectionsProp featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuitePreferredExporterSelectPage" data={data} + listItem={RadioListItem} headerContent={headerContent} onSelectRow={selectExporter} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx index 456e1b7f1b6d..6f81824a5e6e 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -65,6 +66,7 @@ function NetSuiteProvincialTaxPostingAccountSelectPage({policy}: WithPolicyConne featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteProvincialTaxPostingAccountSelectPage" data={netsuiteTaxAccountOptions} + listItem={RadioListItem} onSelectRow={updateTaxAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx index 0239ae546b0c..7cdfa5e1f698 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -70,6 +71,7 @@ function NetSuiteReceivableAccountSelectPage({policy}: WithPolicyConnectionsProp featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteReceivableAccountSelectPage" data={netsuiteReceivableAccountOptions} + listItem={RadioListItem} onSelectRow={updateReceivableAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={goBack} diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx index d4a904aab190..6f43dfc97299 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -67,6 +68,7 @@ function NetSuiteTaxPostingAccountSelectPage({policy}: WithPolicyConnectionsProp featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteTaxPostingAccountSelectPage" data={netsuiteTaxAccountOptions} + listItem={RadioListItem} onSelectRow={updateTaxAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomFieldMappingPicker.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomFieldMappingPicker.tsx index a5f743bb0ec5..e365e8d95b37 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomFieldMappingPicker.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomFieldMappingPicker.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {View} from 'react-native'; import FormHelpMessage from '@components/FormHelpMessage'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; @@ -40,7 +40,7 @@ function NetSuiteCustomFieldMappingPicker({value, errorText, onInputChange}: Net onSelectRow={(selected) => { onInputChange?.(selected.value); }} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={value ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG} shouldSingleExecuteRowSelect shouldUpdateFocusedIndex diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomListSelectorModal.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomListSelectorModal.tsx index 6decd613ed64..98c9fddc69fb 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomListSelectorModal.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomListSelectorModal.tsx @@ -4,7 +4,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import type {CustomListSelectorType} from '@pages/workspace/accounting/netsuite/types'; @@ -92,7 +92,7 @@ function NetSuiteCustomListSelectorModal({isVisible, currentCustomListValue, onC data={options} textInputOptions={textInputOptions} onSelectRow={onCustomListSelected} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={currentCustomListValue} shouldSingleExecuteRowSelect shouldStopPropagation diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomSegmentMappingPicker.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomSegmentMappingPicker.tsx index 538c4c582c5f..1ef9c0d4faae 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomSegmentMappingPicker.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomSegmentMappingPicker.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {View} from 'react-native'; import FormHelpMessage from '@components/FormHelpMessage'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; @@ -44,7 +44,7 @@ function NetSuiteCustomSegmentMappingPicker({value, errorText, onInputChange}: N onSelectRow={(selected) => { onInputChange?.(selected.value); }} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={value ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG} shouldSingleExecuteRowSelect shouldUpdateFocusedIndex diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectSelectPage.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectSelectPage.tsx index 84d3198ccf56..e3b96d5d9025 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectSelectPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -67,6 +68,7 @@ function NetSuiteImportCustomersOrProjectSelectPage({policy}: WithPolicyConnecti featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteImportCustomersOrProjectSelectPage" data={inputSectionData} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} onSelectRow={(selection: SelectorType) => updateImportMapping(selection as ImportListItem)} initiallyFocusedOptionKey={inputSectionData.find((inputOption) => inputOption.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportMappingPage.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportMappingPage.tsx index 414acde28a18..40fb57c6d571 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportMappingPage.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportMappingPage.tsx @@ -2,6 +2,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {TupleToUnion, ValueOf} from 'type-fest'; import RenderHTML from '@components/RenderHTML'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -99,6 +100,7 @@ function NetSuiteImportMappingPage({ featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="NetSuiteImportMappingPage" data={inputSectionData} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} onSelectRow={(selection: SelectorType) => updateImportMapping(selection as ImportListItem)} initiallyFocusedOptionKey={inputSectionData.find((inputOption) => inputOption.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbd/advanced/QuickbooksDesktopAccountingMethodPage.tsx b/src/pages/workspace/accounting/qbd/advanced/QuickbooksDesktopAccountingMethodPage.tsx index c328a3476bb4..c681b746adfa 100644 --- a/src/pages/workspace/accounting/qbd/advanced/QuickbooksDesktopAccountingMethodPage.tsx +++ b/src/pages/workspace/accounting/qbd/advanced/QuickbooksDesktopAccountingMethodPage.tsx @@ -2,6 +2,7 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -68,6 +69,7 @@ function QuickbooksDesktopAccountingMethodPage({policy}: WithPolicyConnectionsPr headerTitleAlreadyTranslated={translate('workspace.qbd.accountingMethods.label')} headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectAccountingMethod(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectCardPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectCardPage.tsx index 03392b2ea453..fb9020742fc7 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectCardPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectCardPage.tsx @@ -1,5 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -101,6 +102,7 @@ function QuickbooksDesktopCompanyCardExpenseAccountSelectCardPage({policy}: With displayName="QuickbooksDesktopCompanyCardExpenseAccountSelectCardPage" title="workspace.accounting.exportAs" data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExportCompanyCard(selection as MenuItem)} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectPage.tsx index eb312b1cdc2e..9bc0ef26c0e2 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -86,6 +87,7 @@ function QuickbooksDesktopCompanyCardExpenseAccountSelectPage({policy}: WithPoli headerTitleAlreadyTranslated={getQBDNonReimbursableExportAccountType(translate, nonReimbursable)} headerContent={nonReimbursable ? {translate(`workspace.qbd.accounts.${nonReimbursable}AccountDescription`)} : null} data={data} + listItem={RadioListItem} onSelectRow={selectExportAccount} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopExportDateSelectPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopExportDateSelectPage.tsx index 4943c97428fa..a50c96055e47 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopExportDateSelectPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopExportDateSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -67,6 +68,7 @@ function QuickbooksDesktopExportDateSelectPage({policy}: WithPolicyConnectionsPr featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksDesktopExportDateSelectPage" data={data} + listItem={RadioListItem} headerContent={{translate('workspace.qbd.exportDate.description')}} onBackButtonPress={goBack} onSelectRow={selectExportDate} diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopNonReimbursableDefaultVendorSelectPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopNonReimbursableDefaultVendorSelectPage.tsx index e3e635ab711e..178ccdea04bd 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopNonReimbursableDefaultVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopNonReimbursableDefaultVendorSelectPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -73,6 +74,7 @@ function QuickbooksDesktopNonReimbursableDefaultVendorSelectPage({policy}: WithP displayName="QuickbooksDesktopNonReimbursableDefaultVendorSelectPage" title="workspace.accounting.defaultVendor" data={data} + listItem={RadioListItem} onSelectRow={selectVendor} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseAccountSelectPage.tsx index ee60cb315d51..b4d6928a0f06 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -108,6 +109,7 @@ function QuickbooksDesktopOutOfPocketExpenseAccountSelectPage({policy}: WithPoli featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksDesktopOutOfPocketExpenseAccountSelectPage" data={data} + listItem={RadioListItem} headerContent={{description}} onBackButtonPress={goBack} onSelectRow={selectExportAccount} diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseEntitySelectPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseEntitySelectPage.tsx index a8df2ab9d9ee..8a797b28a188 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseEntitySelectPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopOutOfPocketExpenseEntitySelectPage.tsx @@ -1,5 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -99,6 +100,7 @@ function QuickbooksDesktopOutOfPocketExpenseEntitySelectPage({policy}: WithPolic featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksDesktopOutOfPocketExpenseEntitySelectPage" data={filteredData} + listItem={RadioListItem} onBackButtonPress={goBack} onSelectRow={(selection: SelectorType) => selectExportEntity(selection as MenuItem)} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopPreferredExporterConfigurationPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopPreferredExporterConfigurationPage.tsx index 0a5d36097760..d6d1efb0e4de 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopPreferredExporterConfigurationPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopPreferredExporterConfigurationPage.tsx @@ -1,5 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -93,6 +94,7 @@ function QuickbooksDesktopPreferredExporterConfigurationPage({policy}: WithPolic featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksDesktopPreferredExporterConfigurationPage" data={data} + listItem={RadioListItem} headerContent={headerContent} onBackButtonPress={goBack} onSelectRow={selectExporter} diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesDisplayedAsPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesDisplayedAsPage.tsx index 595abac9b560..f13f1be974fc 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesDisplayedAsPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesDisplayedAsPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -57,6 +58,7 @@ function QuickbooksDesktopClassesDisplayedAsPage({policy}: WithPolicyConnections featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksDesktopClassesDisplayedAsPage" data={data} + listItem={RadioListItem} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_CLASSES.getRoute(policyID))} onSelectRow={selectDisplayedAs} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersDisplayedAsPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersDisplayedAsPage.tsx index 97b49e4437de..ff780be88174 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersDisplayedAsPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersDisplayedAsPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -57,6 +58,7 @@ function QuickbooksDesktopCustomersDisplayedAsPage({policy}: WithPolicyConnectio featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksDesktopCustomersDisplayedAsPage" data={data} + listItem={RadioListItem} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_CUSTOMERS.getRoute(policyID))} onSelectRow={selectDisplayedAs} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx index b62c2ca4b720..e0f8e2ef6e05 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -82,6 +83,7 @@ function QuickbooksAccountSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksAccountSelectPage" data={qboOnlineSelectorOptions} + listItem={RadioListItem} headerContent={listHeaderComponent} onSelectRow={saveSelection} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountingMethodPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountingMethodPage.tsx index fb8b979799de..a5ae2291733d 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountingMethodPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountingMethodPage.tsx @@ -2,6 +2,7 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -69,6 +70,7 @@ function QuickbooksAccountingMethodPage({policy, route}: WithPolicyConnectionsPr headerTitleAlreadyTranslated={translate('workspace.qbo.accountingMethods.label')} headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExpenseReportApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx index 84947ca34ef0..06948484b317 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -83,6 +84,7 @@ function QuickbooksInvoiceAccountSelectPage({policy}: WithPolicyConnectionsProps featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksInvoiceAccountSelectPage" data={qboOnlineSelectorOptions} + listItem={RadioListItem} headerContent={listHeaderComponent} onSelectRow={updateAccount} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx index 0760c6ad344b..06845f56789b 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx @@ -1,5 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -102,6 +103,7 @@ function QuickbooksCompanyCardExpenseAccountSelectCardPage({policy}: WithPolicyC displayName="QuickbooksCompanyCardExpenseAccountSelectCardPage" title="workspace.accounting.exportAs" data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExportCompanyCard(selection as MenuItem)} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx index ebea42dc1e2d..08e0b0380dad 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -101,6 +102,7 @@ function QuickbooksCompanyCardExpenseAccountSelectPage({policy}: WithPolicyConne ) : null } data={data} + listItem={RadioListItem} onSelectRow={selectExportAccount} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx index 2fc100da1566..41e63071e89e 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -60,6 +61,7 @@ function QuickbooksExportDateSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksExportDateSelectPage" data={data} + listItem={RadioListItem} headerContent={{translate('workspace.qbo.exportDate.description')}} onBackButtonPress={goBack} onSelectRow={selectExportDate} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx index 5586ee019ad8..d8621a0d09fa 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -82,6 +83,7 @@ function QuickbooksExportInvoiceAccountSelectPage({policy}: WithPolicyConnection featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksExportInvoiceAccountSelectPage" data={data} + listItem={RadioListItem} headerContent={{translate('workspace.qbo.exportInvoicesDescription')}} onBackButtonPress={goBack} onSelectRow={selectExportInvoice} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelPayableAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelPayableAccountSelectPage.tsx index bddfa435a0f5..7c36dca21d85 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelPayableAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelPayableAccountSelectPage.tsx @@ -1,5 +1,6 @@ import React from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -71,6 +72,7 @@ function QuickbooksExportTravelPayableAccountSelectPage({policy}: WithPolicyConn displayName="QuickbooksExportTravelPayableAccountSelectPage" title="workspace.qbo.travelInvoicingPayableAccount" data={data} + listItem={RadioListItem} onSelectRow={selectAccount} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelVendorSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelVendorSelectPage.tsx index d94f42400dca..e7d62b23fd7d 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportTravelVendorSelectPage.tsx @@ -1,5 +1,6 @@ import React from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -65,6 +66,7 @@ function QuickbooksExportTravelVendorSelectPage({policy}: WithPolicyConnectionsP displayName="QuickbooksExportTravelVendorSelectPage" title="workspace.qbo.travelInvoicingVendor" data={data} + listItem={RadioListItem} onSelectRow={selectVendor} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx index bc535c9b2c4f..2250c2cbf202 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -70,6 +71,7 @@ function QuickbooksNonReimbursableDefaultVendorSelectPage({policy}: WithPolicyCo displayName="QuickbooksNonReimbursableDefaultVendorSelectPage" title="workspace.accounting.defaultVendor" data={data} + listItem={RadioListItem} onSelectRow={selectVendor} shouldSingleExecuteRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx index 57c679b89094..4e9b0aef5598 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -120,6 +121,7 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksOutOfPocketExpenseAccountSelectPage" data={data} + listItem={RadioListItem} headerContent={{description}} onBackButtonPress={goBack} onSelectRow={selectExportAccount} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx index 65812ba7db96..73a953ed3018 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo, useState} from 'react'; import {View} from 'react-native'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -129,6 +130,7 @@ function QuickbooksOutOfPocketExpenseEntitySelectPage({policy}: WithPolicyConnec featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksOutOfPocketExpenseEntitySelectPage" data={filteredData} + listItem={RadioListItem} onBackButtonPress={goBack} onSelectRow={(selection: SelectorType) => selectExportEntity(selection as MenuItem)} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx index 61167b2acc36..a9ec3f6ae3c2 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx @@ -1,5 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -86,6 +87,7 @@ function QuickbooksPreferredExporterConfigurationPage({policy}: WithPolicyConnec featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksPreferredExporterConfigurationPage" data={data} + listItem={RadioListItem} headerContent={headerContent} onBackButtonPress={goBack} onSelectRow={selectExporter} diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesDisplayedAsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesDisplayedAsPage.tsx index 2998d6c34faa..962b562403c3 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesDisplayedAsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesDisplayedAsPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -64,6 +65,7 @@ function QuickbooksClassesDisplayedAsPage({policy}: WithPolicyProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksClassesDisplayedAsPage" data={data} + listItem={RadioListItem} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CLASSES.getRoute(policyID))} onSelectRow={selectDisplayedAs} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersDisplayedAsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersDisplayedAsPage.tsx index a52c4cd2374a..8f9f47e7a43c 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersDisplayedAsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersDisplayedAsPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -64,6 +65,7 @@ function QuickbooksCustomersDisplayedAsPage({policy}: WithPolicyProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksCustomersDisplayedAsPage" data={data} + listItem={RadioListItem} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CUSTOMERS.getRoute(policyID))} onSelectRow={(selection) => selectDisplayedAs(selection as CardListItem)} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsDisplayedAsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsDisplayedAsPage.tsx index 6636c20fddf4..301fedb1d051 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsDisplayedAsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsDisplayedAsPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useMemo} from 'react'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import useLocalize from '@hooks/useLocalize'; @@ -70,6 +71,7 @@ function QuickbooksLocationsDisplayedAsPage({policy}: WithPolicyProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="QuickbooksLocationsDisplayedAsPage" data={data} + listItem={RadioListItem} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_LOCATIONS.getRoute(policyID))} onSelectRow={(selection) => selectDisplayedAs(selection as CardListItem)} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/reconciliation/ReconciliationAccountSettingsPage.tsx b/src/pages/workspace/accounting/reconciliation/ReconciliationAccountSettingsPage.tsx index e420c2071ccd..517506ed80e1 100644 --- a/src/pages/workspace/accounting/reconciliation/ReconciliationAccountSettingsPage.tsx +++ b/src/pages/workspace/accounting/reconciliation/ReconciliationAccountSettingsPage.tsx @@ -3,7 +3,7 @@ import {View} from 'react-native'; import ConnectionLayout from '@components/ConnectionLayout'; import RenderHTML from '@components/RenderHTML'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useDefaultFundID from '@hooks/useDefaultFundID'; import useEnvironment from '@hooks/useEnvironment'; @@ -110,7 +110,7 @@ function ReconciliationAccountSettingsPage({route}: ReconciliationAccountSetting selectBankAccount(value)} - ListItem={SingleSelectListItem} + ListItem={RadioListItem} initiallyFocusedItemKey={paymentBankAccountID?.toString()} /> diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index f4e3ebd9828d..d9b4e40ba34f 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -1,6 +1,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; @@ -100,6 +101,7 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="XeroMapTrackingCategoryConfigurationPage" data={optionsList} + listItem={RadioListItem} onSelectRow={updateMapping} initiallyFocusedOptionKey={optionsList.find((option) => option.isSelected)?.keyForList} headerContent={listHeaderComponent} diff --git a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx index 7e0ee0e56092..cd9c7084777a 100644 --- a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx @@ -1,6 +1,7 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -84,6 +85,7 @@ function XeroOrganizationConfigurationPage({ featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="XeroOrganizationConfigurationPage" data={sections} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} onSelectRow={saveSelection} initiallyFocusedOptionKey={currentXeroOrganization?.id} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAccountingMethodPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAccountingMethodPage.tsx index d6a958958d22..4d9d131e85f2 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAccountingMethodPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAccountingMethodPage.tsx @@ -2,6 +2,7 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -69,6 +70,7 @@ function XeroAccountingMethodPage({policy, route}: WithPolicyConnectionsProps) { headerTitleAlreadyTranslated={translate('workspace.xero.accountingMethods.label')} headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExpenseReportApprovalLevel(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx index 13c6fb3e68c9..b5ac786369f1 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -68,6 +69,7 @@ function XeroBillPaymentAccountSelectorPage({policy}: WithPolicyConnectionsProps featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="XeroBillPaymentAccountSelectorPage" data={xeroSelectorOptions} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} shouldBeBlocked={!syncReimbursedReports} onSelectRow={updateAccount} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx index cd743a8cf5d9..b94b98409446 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -68,6 +69,7 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="XeroInvoiceAccountSelectorPage" data={xeroSelectorOptions} + listItem={RadioListItem} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} shouldBeBlocked={!syncReimbursedReports} onSelectRow={updateAccount} diff --git a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx index 29ee2be5714d..031e89d6a43d 100644 --- a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -84,6 +85,7 @@ function XeroBankAccountSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="XeroBankAccountSelectPage" data={xeroSelectorOptions} + listItem={RadioListItem} onSelectRow={updateBankAccount} initiallyFocusedOptionKey={initiallyFocusedOptionKey} headerContent={listHeaderComponent} diff --git a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx index 58e144d8f589..a502c94b767b 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import isEmpty from 'lodash/isEmpty'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; @@ -100,6 +101,7 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="XeroPreferredExporterSelectPage" data={data} + listItem={RadioListItem} headerContent={headerContent} onSelectRow={selectExporter} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx index ab11e04eae04..630798d09eba 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -69,6 +70,7 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { title="workspace.xero.exportDate.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectExportDate(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx index 0e6427730e78..f3d9547be48e 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx @@ -3,6 +3,7 @@ import isEmpty from 'lodash/isEmpty'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; @@ -81,6 +82,7 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps title="workspace.xero.invoiceStatus.label" headerContent={headerContent} data={data} + listItem={RadioListItem} onSelectRow={(selection: SelectorType) => selectPurchaseBillStatus(selection as MenuListItem)} initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} policyID={policyID} diff --git a/src/pages/workspace/categories/CategoryDefaultTaxRatePage.tsx b/src/pages/workspace/categories/CategoryDefaultTaxRatePage.tsx index 26fc0978847b..7f838bfe380b 100644 --- a/src/pages/workspace/categories/CategoryDefaultTaxRatePage.tsx +++ b/src/pages/workspace/categories/CategoryDefaultTaxRatePage.tsx @@ -2,7 +2,7 @@ import React, {useCallback, useMemo} from 'react'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import useLocalize from '@hooks/useLocalize'; import usePolicy from '@hooks/usePolicy'; @@ -83,13 +83,12 @@ function CategoryDefaultTaxRatePage({ /> diff --git a/src/pages/workspace/categories/CategoryRequireItemizedReceiptsOverPage.tsx b/src/pages/workspace/categories/CategoryRequireItemizedReceiptsOverPage.tsx index e4f4a530926c..a0f360f58882 100644 --- a/src/pages/workspace/categories/CategoryRequireItemizedReceiptsOverPage.tsx +++ b/src/pages/workspace/categories/CategoryRequireItemizedReceiptsOverPage.tsx @@ -3,7 +3,7 @@ import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import usePolicyData from '@hooks/usePolicyData'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -92,7 +92,7 @@ function CategoryRequireItemizedReceiptsOverPage({ /> { if (typeof item.value === 'number') { if (item.value === 0 && policyCategories?.[categoryName]?.maxAmountNoReceipt !== 0) { diff --git a/src/pages/workspace/categories/CategoryRequireReceiptsOverPage.tsx b/src/pages/workspace/categories/CategoryRequireReceiptsOverPage.tsx index 7e345e636498..f27cb2eb23ae 100644 --- a/src/pages/workspace/categories/CategoryRequireReceiptsOverPage.tsx +++ b/src/pages/workspace/categories/CategoryRequireReceiptsOverPage.tsx @@ -3,7 +3,7 @@ import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import usePolicyData from '@hooks/usePolicyData'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -92,7 +92,7 @@ function CategoryRequireReceiptsOverPage({ /> { if (typeof item.value === 'number') { if (item.value === CONST.DISABLED_MAX_EXPENSE_VALUE && policyCategories?.[categoryName]?.maxAmountNoItemizedReceipt !== CONST.DISABLED_MAX_EXPENSE_VALUE) { diff --git a/src/pages/workspace/categories/ExpenseLimitTypeSelector/ExpenseLimitTypeSelectorModal.tsx b/src/pages/workspace/categories/ExpenseLimitTypeSelector/ExpenseLimitTypeSelectorModal.tsx index b61d9ff2e9a6..a749ec22246d 100644 --- a/src/pages/workspace/categories/ExpenseLimitTypeSelector/ExpenseLimitTypeSelectorModal.tsx +++ b/src/pages/workspace/categories/ExpenseLimitTypeSelector/ExpenseLimitTypeSelectorModal.tsx @@ -3,7 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; @@ -59,7 +59,7 @@ function ExpenseLimitTypeSelectorModal({isVisible, currentExpenseLimitType, onEx /> onExpenseLimitTypeSelected(item.value)} shouldSingleExecuteRowSelect style={{containerStyle: [styles.pt3]}} diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx index a681d20ce63c..aece0570ceee 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx @@ -2,6 +2,7 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; import RenderHTML from '@components/RenderHTML'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; import useCardFeeds from '@hooks/useCardFeeds'; @@ -104,6 +105,7 @@ function WorkspaceCompanyCardAccountSelectCardPage({route}: WorkspaceCompanyCard featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED} displayName="WorkspaceCompanyCardAccountSelectCardPage" data={searchedListOptions ?? []} + listItem={RadioListItem} textInputOptions={{ label: translate('common.search'), value: searchText, diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx index 9104583aedfe..55f766922240 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx @@ -7,7 +7,7 @@ import MenuItem from '@components/MenuItem'; import PlaidCardFeedIcon from '@components/PlaidCardFeedIcon'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import useCardFeedErrors from '@hooks/useCardFeedErrors'; import type {CombinedCardFeed, CompanyCardFeedWithDomainID} from '@hooks/useCardFeeds'; @@ -132,7 +132,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS onBackButtonPress={goBack} /> { setLocalTypeSelected(value); setHasError(false); diff --git a/src/pages/workspace/companyCards/addNew/CardTypeStep.tsx b/src/pages/workspace/companyCards/addNew/CardTypeStep.tsx index 683ede519804..9adeaf2dd486 100644 --- a/src/pages/workspace/companyCards/addNew/CardTypeStep.tsx +++ b/src/pages/workspace/companyCards/addNew/CardTypeStep.tsx @@ -7,7 +7,7 @@ import Icon from '@components/Icon'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import {useCompanyCardBankIcons} from '@hooks/useCompanyCardIcons'; import useLocalize from '@hooks/useLocalize'; @@ -148,7 +148,7 @@ function CardTypeStep() { {translate('workspace.companyCards.addNewCard.yourCardProvider')} { setLocalTypeSelected(value); setIsError(false); diff --git a/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx b/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx index fa7d9bd067e6..01dbbbc669b2 100644 --- a/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx +++ b/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx @@ -7,7 +7,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import {useCompanyCardBankIcons} from '@hooks/useCompanyCardIcons'; import useLocalize from '@hooks/useLocalize'; @@ -114,7 +114,7 @@ function SelectBankStep() { {translate('workspace.companyCards.addNewCard.whoIsYourBankAccount')} { setLocalBankSelected(value); setHasError(false); diff --git a/src/pages/workspace/companyCards/addNew/SelectCountryStep.tsx b/src/pages/workspace/companyCards/addNew/SelectCountryStep.tsx index ea351893a07f..6aac0599a93b 100644 --- a/src/pages/workspace/companyCards/addNew/SelectCountryStep.tsx +++ b/src/pages/workspace/companyCards/addNew/SelectCountryStep.tsx @@ -5,7 +5,7 @@ import FormHelpMessage from '@components/FormHelpMessage'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import {useCurrencyListState} from '@hooks/useCurrencyList'; import useDebouncedState from '@hooks/useDebouncedState'; @@ -116,7 +116,7 @@ function SelectCountryStep({policyID}: CountryStepProps) { {translate('workspace.companyCards.addNewCard.whereIsYourBankLocated')} { setSelectedCountry(countryOption.value ?? null); }} diff --git a/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx b/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx index bfc863df863f..533b311da076 100644 --- a/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx +++ b/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx @@ -6,7 +6,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import RenderHTML from '@components/RenderHTML'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -107,7 +107,7 @@ function SelectFeedType() { { setLocalTypeSelected(value); diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx index 8f6e360b9d6e..c102b4336a8a 100644 --- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx @@ -237,7 +237,6 @@ function AssigneeStep({route}: AssigneeStepProps) { disableMaintainingScrollPosition shouldUpdateFocusedIndex addBottomSafeAreaPadding - shouldShowRadioButton /> ); diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx index 39317e2e5612..769b8497621a 100644 --- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx @@ -8,7 +8,7 @@ import InteractiveStepWrapper from '@components/InteractiveStepWrapper'; import PlaidCardFeedIcon from '@components/PlaidCardFeedIcon'; import RenderHTML from '@components/RenderHTML'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle'; import useCardFeeds from '@hooks/useCardFeeds'; @@ -174,7 +174,7 @@ function CardSelectionStep({route}: CardSelectionStepProps) { ) : ( handleSelectCard(value)} initiallyFocusedItemKey={cardSelected} textInputOptions={textInputOptions} diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardSelectorPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardSelectorPage.tsx index c6625e8a5950..341025219486 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardSelectorPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardSelectorPage.tsx @@ -3,7 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import useDefaultFundID from '@hooks/useDefaultFundID'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; @@ -85,7 +85,7 @@ function WorkspaceExpensifyCardSelectorPage({route}: WorkspaceExpensifyCardSelec onBackButtonPress={goBack} /> {translate('workspace.expensifyCard.settlementFrequencyDescription')} updateSettlementFrequency(value)} initiallyFocusedItemKey={selectedFrequency} shouldUpdateFocusedIndex diff --git a/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx b/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx index cf766ec37501..89e667d6e28a 100644 --- a/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx +++ b/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx @@ -211,7 +211,6 @@ function AssigneeStep({policy, stepNames, startStepIndex, route}: AssigneeStepPr disableMaintainingScrollPosition shouldUpdateFocusedIndex addBottomSafeAreaPadding - shouldShowRadioButton /> ); diff --git a/src/pages/workspace/reports/InitialListValueSelector/ReportFieldsInitialListValuePicker.tsx b/src/pages/workspace/reports/InitialListValueSelector/ReportFieldsInitialListValuePicker.tsx index e57a8b862b06..c2f4cb437f68 100644 --- a/src/pages/workspace/reports/InitialListValueSelector/ReportFieldsInitialListValuePicker.tsx +++ b/src/pages/workspace/reports/InitialListValueSelector/ReportFieldsInitialListValuePicker.tsx @@ -1,6 +1,6 @@ import React, {useMemo} from 'react'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; type ReportFieldsInitialListValuePickerProps = { @@ -36,7 +36,7 @@ function ReportFieldsInitialListValuePicker({listValues, disabledOptions, value, return ( onValueChange(item.value)} initiallyFocusedItemKey={listValueOptions.find((listValue) => listValue.isSelected)?.keyForList} addBottomSafeAreaPadding diff --git a/src/pages/workspace/reports/ReportFieldTypePicker/index.tsx b/src/pages/workspace/reports/ReportFieldTypePicker/index.tsx index df8a4907fc13..e1573e04473c 100644 --- a/src/pages/workspace/reports/ReportFieldTypePicker/index.tsx +++ b/src/pages/workspace/reports/ReportFieldTypePicker/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import {getReportFieldAlternativeTextTranslationKey, getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils'; import CONST from '@src/CONST'; @@ -43,7 +43,7 @@ function ReportFieldTypePicker({defaultValue, onOptionSelected}: ReportFieldType return ( { setPolicyBillableMode(policyID, item.value); Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack); diff --git a/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx b/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx index 065a4dcc0a56..00f215fa0667 100644 --- a/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx +++ b/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx @@ -2,7 +2,7 @@ import React from 'react'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import usePolicy from '@hooks/usePolicy'; @@ -56,7 +56,7 @@ function RulesReimbursableDefaultPage({ { setPolicyReimbursableMode(policyID, item.value, policy?.defaultReimbursable, policy?.disabledFields?.reimbursable); Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack); diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx index 17cbe5df9fc7..0b94b5a3e8a7 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx @@ -7,7 +7,7 @@ import MenuItem from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {getLatestErrorField} from '@libs/ErrorUtils'; @@ -134,11 +134,12 @@ function WorkspaceAutoReportingFrequencyPage({policy, route}: WorkspaceAutoRepor contentContainerStyle={styles.flex1} > diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx index c45a8debd9f3..167c6cfeb448 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx @@ -4,7 +4,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; +import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -105,7 +105,7 @@ function WorkspaceAutoReportingMonthlyOffsetPage({policy, route}: WorkspaceAutoR })), ); -jest.mock('@hooks/useKeyboardShortcut', () => jest.fn()); +let arrowUpCallback = () => {}; +let arrowDownCallback = () => {}; +jest.mock('@hooks/useKeyboardShortcut', () => (key: {shortcutKey: string}, callback: () => void) => { + if (key.shortcutKey === 'ArrowUp') { + arrowUpCallback = callback; + } else if (key.shortcutKey === 'ArrowDown') { + arrowDownCallback = callback; + } +}); describe('BaseSelectionList', () => { const onSelectRowMock = jest.fn(); @@ -319,63 +328,41 @@ describe('BaseSelectionList', () => { expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}3`)).toBeTruthy(); }); - it('should render items from multiple sections', () => { - (NativeNavigation.useIsFocused as jest.Mock).mockReturnValue(true); - const sectionA = Array.from({length: 5}, (_, index) => ({ - text: `Section A Item ${index}`, - keyForList: `a-${index}`, - isSelected: false, - })); - const sectionB = Array.from({length: 5}, (_, index) => ({ - text: `Section B Item ${index}`, - keyForList: `b-${index}`, - isSelected: false, - })); - + it('should focus next/previous item relative to focused item when arrow keys are pressed', async () => { render( , ); - // Items from both sections should be rendered - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}a-0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}a-4`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}b-0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}b-4`)).toBeTruthy(); - }); + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)).toHaveStyle({backgroundColor: colors.productDark400}); - it('should handle item press from second section correctly', () => { - (NativeNavigation.useIsFocused as jest.Mock).mockReturnValue(true); - const sectionA = [{text: 'A0', keyForList: 'a-0', isSelected: false}]; - const sectionB = [{text: 'B0', keyForList: 'b-0', isSelected: false}]; + // eslint-disable-next-line testing-library/no-unnecessary-act + act(() => { + arrowDownCallback(); + }); - render( - , - ); + // The item that gets focused will be the one following the currently focused item + await waitFor(() => { + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}2`)).toHaveStyle({backgroundColor: colors.productDark300}); + }); - fireEvent.press(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}b-0`)); - expect(onSelectRowMock).toHaveBeenCalledWith(expect.objectContaining({keyForList: 'b-0', text: 'B0'})); - }); + act(() => { + arrowUpCallback(); + arrowUpCallback(); + }); - it('should render empty list without crashing when all sections are empty', () => { - render( - , - ); + await waitFor(() => { + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toHaveStyle({backgroundColor: colors.productDark300}); + }); + + act(() => { + arrowDownCallback(); + }); - expect(screen.queryByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeNull(); + await waitFor(() => { + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)).toHaveStyle({backgroundColor: colors.productDark400}); + }); }); }); diff --git a/tests/unit/BaseSelectionListTest.tsx b/tests/unit/BaseSelectionListTest.tsx index 884984929593..db1a2893c3e9 100644 --- a/tests/unit/BaseSelectionListTest.tsx +++ b/tests/unit/BaseSelectionListTest.tsx @@ -1,96 +1,31 @@ -import * as NativeNavigation from '@react-navigation/native'; -import {fireEvent, render, screen} from '@testing-library/react-native'; -import React, {useState} from 'react'; +import {act, fireEvent, render, screen, waitFor} from '@testing-library/react-native'; import type ReactNative from 'react-native'; import OnyxListItemProvider from '@components/OnyxListItemProvider'; import BaseSelectionList from '@components/SelectionList/BaseSelectionList'; +import BaseListItem from '@components/SelectionList/ListItem/BaseListItem'; import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; import type Navigation from '@libs/Navigation/Navigation'; +import colors from '@styles/theme/colors'; import CONST from '@src/CONST'; -// Captures scrollToIndex calls so tests can assert on scroll behaviour -const mockScrollToIndex = jest.fn(); - -// Mock FlashList +// FlashList requires layout events to render items; mock it with FlatList for tests jest.mock('@shopify/flash-list', () => { - const ReactLocal = jest.requireActual('react'); const RN = jest.requireActual('react-native'); - - const FlashList = ReactLocal.forwardRef< - {scrollToIndex: (params: {index: number}) => void}, - Omit, 'children'> & { - data?: unknown[]; - renderItem?: (info: {item: unknown; index: number; target: string}) => React.ReactNode; - keyExtractor?: (item: unknown, index: number) => string; - ListHeaderComponent?: React.ReactNode; - ListFooterComponent?: React.ReactNode; - getItemType?: unknown; - extraData?: unknown; - initialScrollIndex?: number; - onEndReached?: unknown; - onEndReachedThreshold?: unknown; - ListFooterComponentStyle?: unknown; - } - >( - ( - { - data, - renderItem, - keyExtractor, - ListHeaderComponent, - ListFooterComponent, - getItemType: _getItemType, - extraData: _extraData, - initialScrollIndex: _initialScrollIndex, - onEndReached: _onEndReached, - onEndReachedThreshold: _onEndReachedThreshold, - ListFooterComponentStyle: _ListFooterComponentStyle, - ...scrollViewProps - }, - ref, - ) => { - ReactLocal.useImperativeHandle(ref, () => ({scrollToIndex: mockScrollToIndex})); - - return ReactLocal.createElement( - RN.ScrollView, - scrollViewProps, - ListHeaderComponent ?? null, - ...(data ?? []).map((item, index) => - ReactLocal.createElement(ReactLocal.Fragment, {key: keyExtractor?.(item, index) ?? String(index)}, renderItem?.({item, index, target: 'Cell'})), - ), - ListFooterComponent ?? null, - ); - }, - ); - - return {FlashList}; + return { + FlashList: RN.FlatList, + }; }); -type BaseSelectionListTestProps = { +type BaseSelectionListSections = { data: TItem[]; canSelectMultiple?: boolean; - searchText?: string; - setSearchText?: (searchText: string) => void; - isDisabled?: boolean; }; -const mockItems = Array.from({length: 10}, (_, index) => ({ - text: `Item ${index}`, - keyForList: `${index}`, - isSelected: index === 1, -})); - -const largeMockItems = Array.from({length: 100}, (_, index) => ({ +const mockSections = Array.from({length: 10}, (_, index) => ({ text: `Item ${index}`, keyForList: `${index}`, - isSelected: index === 1, -})); - -const largeMockItemsWithSelectedFromSecondPage = Array.from({length: 100}, (_, index) => ({ - text: `Item ${index}`, - keyForList: `${index}`, - isSelected: index === 70, + isSelected: index === 0, })); jest.mock('@src/components/ConfirmedRoute.tsx'); @@ -110,209 +45,104 @@ jest.mock('@hooks/useLocalize', () => })), ); -jest.mock('@hooks/useKeyboardShortcut', () => jest.fn()); +let arrowUpCallback = () => {}; +let arrowDownCallback = () => {}; +jest.mock('@hooks/useKeyboardShortcut', () => (key: {shortcutKey: string}, callback: () => void) => { + if (key.shortcutKey === 'ArrowUp') { + arrowUpCallback = callback; + } else if (key.shortcutKey === 'ArrowDown') { + arrowDownCallback = callback; + } +}); describe('BaseSelectionList', () => { const onSelectRowMock = jest.fn(); - beforeEach(() => { - onSelectRowMock.mockClear(); - mockScrollToIndex.mockClear(); - }); - - function SelectionListRenderer(props: BaseSelectionListTestProps) { - const {data, canSelectMultiple, setSearchText, searchText, isDisabled} = props; - const focusedKey = data.find((item) => item.isSelected)?.keyForList; + function BaseListItemRenderer(props: BaseSelectionListSections) { + const {data, canSelectMultiple} = props; + const focusedKey = data.find((item) => item.isSelected)?.keyForList ?? undefined; return ( ); } - it('should not trigger item press if screen is not focused', () => { - (NativeNavigation.useIsFocused as jest.Mock).mockReturnValue(false); - render(); - fireEvent.press(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)); - expect(onSelectRowMock).toHaveBeenCalledTimes(0); - }); - - it('should handle item press correctly', () => { - (NativeNavigation.useIsFocused as jest.Mock).mockReturnValue(true); - render(); - - fireEvent.press(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)); - expect(onSelectRowMock).toHaveBeenCalledWith( - expect.objectContaining({ - ...mockItems.at(1), - }), - ); - }); - - it('should update selected item on rerender', () => { - (NativeNavigation.useIsFocused as jest.Mock).mockReturnValue(true); - const updatedMockItems = mockItems.map((item) => ({ - ...item, - isSelected: item.keyForList === '2', - })); - const {rerender} = render(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)).toBeSelected(); - rerender(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}2`)).toBeSelected(); - }); - - it('should render all items', () => { + it('should focus next/previous item relative to focused item when arrow keys are pressed', async () => { render( - , - ); - - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}99`)).toBeTruthy(); - }); - - it('should render all items when they fit within initial render limit', () => { - render( - , - ); - - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}9`)).toBeTruthy(); - }); - - it('does not lose items when only selection changes', () => { - const {rerender} = render( - , ); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}99`)).toBeTruthy(); + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toHaveStyle({backgroundColor: colors.productDark400}); - rerender( - ({...item, isSelected: index === 3}))} - canSelectMultiple={false} - />, - ); + // eslint-disable-next-line testing-library/no-unnecessary-act + act(() => { + arrowDownCallback(); + }); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}99`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}3`)).toBeSelected(); - }); + // The item that gets focused will be the one following the currently focused item + await waitFor(() => { + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)).toHaveStyle({backgroundColor: colors.productDark300}); + }); - it('should still render items when text input changes', () => { - const {rerender} = render( - , - ); + act(() => { + arrowUpCallback(); + arrowUpCallback(); + }); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); + await waitFor(() => { + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}9`)).toHaveStyle({backgroundColor: colors.productDark300}); + }); - rerender( - ({...item, isSelected: index === 3}))} - canSelectMultiple={false} - searchText="Item" - />, - ); + act(() => { + arrowDownCallback(); + }); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}3`)).toBeTruthy(); + await waitFor(() => { + expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toHaveStyle({backgroundColor: colors.productDark400}); + }); }); - it('should search for an item then scroll back to preselected item when search is cleared', () => { - function SearchableListWrapper() { - const [searchText, setSearchText] = useState(''); - - const filteredItems = searchText - ? largeMockItemsWithSelectedFromSecondPage.filter((item) => item.text.toLowerCase().includes(searchText.toLowerCase())) - : largeMockItemsWithSelectedFromSecondPage; - - return ( - - ); - } - - render(); - - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}70`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}70`)).toBeSelected(); - - fireEvent.changeText(screen.getByTestId('selection-list-text-input'), 'Item 0'); - - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeTruthy(); - expect(screen.queryByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}70`)).toBeFalsy(); - expect(screen.queryByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`)).toBeFalsy(); - - fireEvent.changeText(screen.getByTestId('selection-list-text-input'), ''); - - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}70`)).toBeTruthy(); - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}70`)).toBeSelected(); - }); - - it('should render the selection-list testID', () => { - render( - , - ); - - expect(screen.getByTestId('selection-list')).toBeTruthy(); - }); - - it('should mark all items as not selected when none are selected', () => { - const noSelectionItems = mockItems.map((item) => ({...item, isSelected: false})); - + it('should not call preventDefault on mouseDown when the target is an INPUT element', () => { render( - , - ); - - for (const item of noSelectionItems) { - expect(screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}${item.keyForList}`)).not.toBeSelected(); - } - }); - - it('should render empty list without crashing when data is empty', () => { - render( - , + + {}} + showTooltip={false} + isFocused={false} + keyForList="1" + > + + + , ); - expect(screen.queryByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}0`)).toBeNull(); + const preventDefault = jest.fn(); + const listItem = screen.getByTestId(`${CONST.BASE_LIST_ITEM_TEST_ID}1`); + + // Test case 1: Target is INPUT + fireEvent(listItem, 'mouseDown', { + target: {tagName: CONST.ELEMENT_NAME.INPUT}, + preventDefault, + }); + expect(preventDefault).not.toHaveBeenCalled(); + + // Test case 2: Target is NOT INPUT (e.g., DIV) + fireEvent(listItem, 'mouseDown', { + target: {tagName: CONST.ELEMENT_NAME.DIV}, + preventDefault, + }); + expect(preventDefault).toHaveBeenCalled(); }); });