diff --git a/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx b/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx index 49915ebfbf1b..f8c4a12ec188 100644 --- a/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx +++ b/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx @@ -3,6 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; @@ -79,6 +80,7 @@ function YearPickerModal({isVisible, years, currentYear = new Date().getFullYear showScrollIndicator shouldStopPropagation shouldUseDynamicMaxToRenderPerBatch + ListItem={RadioListItem} /> diff --git a/src/components/SelectionList/BaseListItem.tsx b/src/components/SelectionList/BaseListItem.tsx index 9bfeacbc0ac2..c39d7a05a4f7 100644 --- a/src/components/SelectionList/BaseListItem.tsx +++ b/src/components/SelectionList/BaseListItem.tsx @@ -4,34 +4,31 @@ import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import RadioListItem from './RadioListItem'; import type {BaseListItemProps, ListItem} from './types'; -import UserListItem from './UserListItem'; function BaseListItem({ item, - isFocused = false, + wrapperStyle, + selectMultipleStyle, isDisabled = false, - showTooltip, shouldPreventDefaultFocusOnSelectRow = false, canSelectMultiple = false, onSelectRow, onDismissError = () => {}, rightHandSideComponent, keyForList, + errors, + pendingAction, + FooterComponent, + children, }: BaseListItemProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const {translate} = useLocalize(); - const isUserItem = 'icons' in item && item?.icons?.length && item.icons.length > 0; - const ListItem = isUserItem ? UserListItem : RadioListItem; const rightHandSideComponentRender = () => { if (canSelectMultiple || !rightHandSideComponent) { @@ -48,8 +45,8 @@ function BaseListItem({ return ( onDismissError(item)} - pendingAction={isUserItem ? item.pendingAction : undefined} - errors={isUserItem ? item.errors : undefined} + pendingAction={pendingAction} + errors={errors} errorRowStyles={styles.ph5} > ({ > {({hovered}) => ( <> - + {canSelectMultiple && ( - + {item.isSelected && ( ({ )} - onSelectRow(item)} - showTooltip={showTooltip} - isFocused={isFocused} - isHovered={hovered} - /> + {typeof children === 'function' ? children(hovered) : children} {!canSelectMultiple && item.isSelected && !rightHandSideComponent && ( ({ )} {rightHandSideComponentRender()} - {isUserItem && item.invitedSecondaryLogin && ( - - {translate('workspace.people.invitedBySecondaryLogin', {secondaryLogin: item.invitedSecondaryLogin})} - - )} + {FooterComponent} )} diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 850874b7abc0..b0996a08895a 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -22,12 +22,12 @@ import Log from '@libs/Log'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import BaseListItem from './BaseListItem'; import type {BaseSelectionListProps, ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, Section, SectionListDataType} from './types'; function BaseSelectionList( { sections, + ListItem, canSelectMultiple = false, onSelectRow, onSelectAll, @@ -280,7 +280,7 @@ function BaseSelectionList( const showTooltip = shouldShowTooltips && normalizedIndex < 10; return ( - - - - {!!item.alternateText && ( + + - )} - + + {!!item.alternateText && ( + + )} + + ); } diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index 60e97d887b4d..759c29013b5d 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -2,61 +2,107 @@ import React from 'react'; import {View} from 'react-native'; import MultipleAvatars from '@components/MultipleAvatars'; import SubscriptAvatar from '@components/SubscriptAvatar'; +import Text from '@components/Text'; import TextWithTooltip from '@components/TextWithTooltip'; +import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {ListItemProps} from './types'; +import BaseListItem from './BaseListItem'; +import type {UserListItemProps} from './types'; -function UserListItem({item, textStyles, alternateTextStyles, showTooltip, style, isFocused, isHovered}: ListItemProps) { +function UserListItem({ + item, + isFocused, + showTooltip, + isDisabled, + canSelectMultiple, + onSelectRow, + onDismissError, + shouldPreventDefaultFocusOnSelectRow, + rightHandSideComponent, +}: UserListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); const StyleUtils = useStyleUtils(); + const {translate} = useLocalize(); const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; const subscriptAvatarBorderColor = isFocused ? focusedBackgroundColor : theme.sidebar; const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; return ( - <> - {!!item.icons && ( + + {translate('workspace.people.invitedBySecondaryLogin', {secondaryLogin: item.invitedSecondaryLogin})} + + ) : undefined + } + keyForList={item.keyForList} + > + {(hovered) => ( <> - {item.shouldShowSubscript ? ( - - ) : ( - + {item.shouldShowSubscript ? ( + + ) : ( + + )} + + )} + + - )} + {!!item.alternateText && ( + + )} + + {!!item.rightElement && item.rightElement} )} - - - {!!item.alternateText && ( - - )} - - {!!item.rightElement && item.rightElement} - + ); } diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 6ef0fb742dc3..403ccd91a26b 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -1,18 +1,15 @@ import type {ReactElement, ReactNode} from 'react'; import type {GestureResponderEvent, InputModeOptions, LayoutChangeEvent, SectionListData, StyleProp, TextStyle, ViewStyle} from 'react-native'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; +import type {ReceiptErrors} from '@src/types/onyx/Transaction'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import type RadioListItem from './RadioListItem'; +import type UserListItem from './UserListItem'; type CommonListItemProps = { /** Whether this item is focused (for arrow key controls) */ isFocused?: boolean; - /** Style to be applied to Text */ - textStyles?: StyleProp; - - /** Style to be applied on the alternate text */ - alternateTextStyles?: StyleProp; - /** Whether this item is disabled */ isDisabled?: boolean; @@ -30,6 +27,12 @@ type CommonListItemProps = { /** Component to display on the right side */ rightHandSideComponent?: ((item: TItem) => ReactElement) | ReactElement | null; + + /** Styles for the wrapper view */ + wrapperStyle?: StyleProp; + + /** Styles for the checkbox wrapper view if select multiple option is on */ + selectMultipleStyle?: StyleProp; }; type ListItem = { @@ -87,14 +90,37 @@ type ListItemProps = CommonListItemProps & { /** Is item hovered */ isHovered?: boolean; + + /** Whether the default focus should be prevented on row selection */ + shouldPreventDefaultFocusOnSelectRow?: boolean; + + /** Key used internally by React */ + keyForList?: string; }; type BaseListItemProps = CommonListItemProps & { item: TItem; shouldPreventDefaultFocusOnSelectRow?: boolean; keyForList?: string; + errors?: Errors | ReceiptErrors | null; + pendingAction?: PendingAction | null; + FooterComponent?: ReactElement; + children?: ReactElement | ((hovered: boolean) => ReactElement); }; +type UserListItemProps = ListItemProps & { + /** Errors that this user may contain */ + errors?: Errors | ReceiptErrors | null; + + /** The type of action that's pending */ + pendingAction?: PendingAction | null; + + /** The React element that will be shown as a footer */ + FooterComponent?: ReactElement; +}; + +type RadioListItemProps = ListItemProps; + type Section = { /** Title of the section */ title?: string; @@ -116,6 +142,9 @@ type BaseSelectionListProps = Partial & { /** Sections for the section list */ sections: Array>>; + /** Default renderer for every item in the list */ + ListItem: typeof RadioListItem | typeof UserListItem; + /** Whether this is a multi-select list */ canSelectMultiple?: boolean; @@ -210,7 +239,7 @@ type BaseSelectionListProps = Partial & { shouldDelayFocus?: boolean; /** Component to display on the right side of each child */ - rightHandSideComponent?: ((item: TItem) => ReactElement) | ReactElement | null; + rightHandSideComponent?: ((item: ListItem) => ReactElement) | ReactElement | null; /** Whether to show the loading indicator for new options */ isLoadingNewOptions?: boolean; @@ -241,6 +270,8 @@ export type { CommonListItemProps, Section, BaseListItemProps, + UserListItemProps, + RadioListItemProps, ListItem, ListItemProps, FlattenedSectionsReturn, diff --git a/src/components/StatePicker/StateSelectorModal.tsx b/src/components/StatePicker/StateSelectorModal.tsx index 798d3be7a698..c09c7a25e375 100644 --- a/src/components/StatePicker/StateSelectorModal.tsx +++ b/src/components/StatePicker/StateSelectorModal.tsx @@ -4,6 +4,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import searchCountryOptions from '@libs/searchCountryOptions'; @@ -100,6 +101,7 @@ function StateSelectorModal({currentState, isVisible, onClose = () => {}, onStat initiallyFocusedOptionKey={currentState} shouldStopPropagation shouldUseDynamicMaxToRenderPerBatch + ListItem={RadioListItem} /> diff --git a/src/components/ValuePicker/ValueSelectorModal.tsx b/src/components/ValuePicker/ValueSelectorModal.tsx index 1e7c6088241d..fad59d4e48e4 100644 --- a/src/components/ValuePicker/ValueSelectorModal.tsx +++ b/src/components/ValuePicker/ValueSelectorModal.tsx @@ -3,6 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import type {ValueSelectorModalProps} from './types'; @@ -40,6 +41,7 @@ function ValueSelectorModal({items = [], selectedItem, label = '', isVisible, on initiallyFocusedOptionKey={selectedItem?.value} shouldStopPropagation shouldShowTooltips={shouldShowTooltips} + ListItem={RadioListItem} /> diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx index 2b80b890e4bd..2db3a4fdf7ad 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx @@ -3,6 +3,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; @@ -66,6 +67,7 @@ function BusinessTypeSelectorModal({isVisible, currentBusinessType, onBusinessTy onSelectRow={onBusinessTypeSelected} shouldStopPropagation shouldUseDynamicMaxToRenderPerBatch + ListItem={RadioListItem} /> diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 2c26d148f54c..40a1b009b38d 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -12,6 +12,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import type {Section} from '@components/SelectionList/types'; +import UserListItem from '@components/SelectionList/UserListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; @@ -225,6 +226,7 @@ function RoomInvitePage({betas, personalDetails, report, policies}: RoomInvitePa diff --git a/src/pages/SearchPage/index.js b/src/pages/SearchPage/index.js index 7c472296dfe1..6db69cea13e4 100644 --- a/src/pages/SearchPage/index.js +++ b/src/pages/SearchPage/index.js @@ -6,6 +6,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {usePersonalDetails} from '@components/OnyxProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import UserListItem from '@components/SelectionList/UserListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -153,6 +154,7 @@ function SearchPage({betas, reports, isSearchingForReports}) { ( App.setLocaleAndNavigate(language.value)} initiallyFocusedOptionKey={_.find(localesToLanguages, (locale) => locale.isSelected).keyForList} /> diff --git a/src/pages/settings/Preferences/PriorityModePage.js b/src/pages/settings/Preferences/PriorityModePage.js index 983e3cb26746..05c0546c2e41 100644 --- a/src/pages/settings/Preferences/PriorityModePage.js +++ b/src/pages/settings/Preferences/PriorityModePage.js @@ -5,6 +5,7 @@ import _, {compose} from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import Text from '@components/Text'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -57,6 +58,7 @@ function PriorityModePage(props) { {props.translate('priorityModePage.explainerText')} mode.isSelected).keyForList} /> diff --git a/src/pages/settings/Preferences/ThemePage.js b/src/pages/settings/Preferences/ThemePage.js index 4907056be761..0724eb286620 100644 --- a/src/pages/settings/Preferences/ThemePage.js +++ b/src/pages/settings/Preferences/ThemePage.js @@ -5,6 +5,7 @@ import _ from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -48,6 +49,7 @@ function ThemePage(props) { User.updateTheme(theme.value)} initiallyFocusedOptionKey={_.find(localesToThemes, (theme) => theme.isSelected).keyForList} /> diff --git a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js index 38c4d1eac449..d8327041538d 100644 --- a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js +++ b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js @@ -5,6 +5,7 @@ import _ from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import Navigation from '@libs/Navigation/Navigation'; import searchCountryOptions from '@libs/searchCountryOptions'; @@ -93,6 +94,7 @@ function CountrySelectionPage({route, navigation}) { textInputLabel={translate('common.country')} textInputValue={searchValue} sections={[{data: searchResults, indexOffset: 0}]} + ListItem={RadioListItem} onSelectRow={selectCountry} onChangeText={setSearchValue} initiallyFocusedOptionKey={currentCountry} diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index 5bb528373e8f..1d4675a42b8a 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -7,6 +7,7 @@ import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import Text from '@components/Text'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; @@ -100,6 +101,7 @@ function PronounsPage({currentUserPersonalDetails, isLoadingApp}) { textInputPlaceholder={translate('pronounsPage.placeholderText')} textInputValue={searchValue} sections={[{data: filteredPronounsList, indexOffset: 0}]} + ListItem={RadioListItem} onSelectRow={updatePronouns} onChangeText={setSearchValue} initiallyFocusedOptionKey={currentPronounsKey} diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index 8280d9b5c604..b6c8a5967abc 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -4,6 +4,7 @@ import _ from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; import useInitialValue from '@hooks/useInitialValue'; import useLocalize from '@hooks/useLocalize'; @@ -97,6 +98,7 @@ function TimezoneSelectPage(props) { initiallyFocusedOptionKey={_.get(_.filter(timezoneOptions, (tz) => tz.text === timezone.selected)[0], 'keyForList')} showScrollIndicator shouldShowTooltips={false} + ListItem={RadioListItem} /> ); diff --git a/src/pages/settings/Report/NotificationPreferencePage.tsx b/src/pages/settings/Report/NotificationPreferencePage.tsx index 05f3483f7ce8..3977bdd0233d 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.tsx +++ b/src/pages/settings/Report/NotificationPreferencePage.tsx @@ -4,6 +4,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import * as ReportUtils from '@libs/ReportUtils'; import type {ReportSettingsNavigatorParamList} from '@navigation/types'; @@ -39,6 +40,7 @@ function NotificationPreferencePage({report}: NotificationPreferencePageProps) { /> report && ReportActions.updateNotificationPreference(report.reportID, report.notificationPreference, option.value, true, undefined, undefined, report) } diff --git a/src/pages/settings/Report/WriteCapabilityPage.tsx b/src/pages/settings/Report/WriteCapabilityPage.tsx index 5f5fe73e5199..1f991ef87c9a 100644 --- a/src/pages/settings/Report/WriteCapabilityPage.tsx +++ b/src/pages/settings/Report/WriteCapabilityPage.tsx @@ -6,6 +6,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; @@ -52,6 +53,7 @@ function WriteCapabilityPage({report, policy}: WriteCapabilityPageProps) { /> report && ReportActions.updateWriteCapabilityAndNavigate(report, option.value)} initiallyFocusedOptionKey={writeCapabilityOptions.find((locale) => locale.isSelected)?.keyForList} /> diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js index 14d2867aa1f4..0e1e64dfa415 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.js +++ b/src/pages/tasks/TaskAssigneeSelectorModal.js @@ -11,6 +11,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {useBetas, usePersonalDetails, useSession} from '@components/OnyxProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import UserListItem from '@components/SelectionList/UserListItem'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; @@ -203,6 +204,7 @@ function TaskAssigneeSelectorModal({reports, task, rootParentReportPolicy}) { { diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index c88b3d56cb20..62b96943453c 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -16,6 +16,7 @@ import networkPropTypes from '@components/networkPropTypes'; import {withNetwork} from '@components/OnyxProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import UserListItem from '@components/SelectionList/UserListItem'; import Text from '@components/Text'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; @@ -488,6 +489,7 @@ function WorkspaceMembersPage(props) { { diff --git a/src/pages/workspace/WorkspaceProfileCurrencyPage.js b/src/pages/workspace/WorkspaceProfileCurrencyPage.js index 31b88c7c487b..bd13ce4687f5 100644 --- a/src/pages/workspace/WorkspaceProfileCurrencyPage.js +++ b/src/pages/workspace/WorkspaceProfileCurrencyPage.js @@ -6,6 +6,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; @@ -90,6 +91,7 @@ function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportDat updateUnit(unit.value)} initiallyFocusedOptionKey={unitOptions.find((unit) => unit.isSelected)?.keyForList} /> diff --git a/src/stories/SelectionList.stories.js b/src/stories/SelectionList.stories.js index 835bf67fbfd7..dcd639119886 100644 --- a/src/stories/SelectionList.stories.js +++ b/src/stories/SelectionList.stories.js @@ -2,6 +2,7 @@ import React, {useMemo, useState} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import Text from '@components/Text'; // eslint-disable-next-line no-restricted-imports import {defaultStyles} from '@styles/index'; @@ -89,6 +90,7 @@ function Default(args) { // eslint-disable-next-line react/jsx-props-no-spreading {...args} sections={sections} + ListItem={RadioListItem} onSelectRow={onSelectRow} /> ); @@ -137,6 +139,7 @@ function WithTextInput(args) { // eslint-disable-next-line react/jsx-props-no-spreading {...args} sections={sections} + ListItem={RadioListItem} textInputValue={searchText} onChangeText={setSearchText} onSelectRow={onSelectRow} @@ -260,6 +263,7 @@ function MultipleSelection(args) { // eslint-disable-next-line react/jsx-props-no-spreading {...args} sections={memo.sections} + ListItem={RadioListItem} onSelectRow={onSelectRow} onSelectAll={onSelectAll} /> @@ -322,6 +326,7 @@ function WithSectionHeader(args) { // eslint-disable-next-line react/jsx-props-no-spreading {...args} sections={memo.sections} + ListItem={RadioListItem} onSelectRow={onSelectRow} onSelectAll={onSelectAll} /> @@ -382,6 +387,7 @@ function WithConfirmButton(args) { // eslint-disable-next-line react/jsx-props-no-spreading {...args} sections={memo.sections} + ListItem={RadioListItem} onSelectRow={onSelectRow} onSelectAll={onSelectAll} /> diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index a0edb7fd4e23..d3b2c0e9d0f5 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -1474,6 +1474,14 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ }, getFullscreenCenteredContentStyles: () => [StyleSheet.absoluteFill, styles.justifyContentCenter, styles.alignItemsCenter], + + getMultiselectListStyles: (isSelected: boolean, isDisabled: boolean): ViewStyle => ({ + ...styles.mr3, + ...(isSelected && styles.checkedContainer), + ...(isSelected && styles.borderColorFocus), + ...(isDisabled && styles.cursorDisabled), + ...(isDisabled && styles.buttonOpacityDisabled), + }), }); type StyleUtilsType = ReturnType; diff --git a/tests/perf-test/SelectionList.perf-test.js b/tests/perf-test/SelectionList.perf-test.js index 9decc4361612..a109f92a1501 100644 --- a/tests/perf-test/SelectionList.perf-test.js +++ b/tests/perf-test/SelectionList.perf-test.js @@ -2,6 +2,7 @@ import {fireEvent} from '@testing-library/react-native'; import React, {useState} from 'react'; import {measurePerformance} from 'reassure'; import _ from 'underscore'; +import RadioListItem from '@components/SelectionList/RadioListItem'; import SelectionList from '../../src/components/SelectionList'; import variables from '../../src/styles/variables'; @@ -86,6 +87,7 @@ function SelectionListWrapper(args) { sections={sections} onSelectRow={onSelectRow} initiallyFocusedOptionKey="item-0" + ListItem={RadioListItem} // eslint-disable-next-line react/jsx-props-no-spreading {...args} />