import React, { useState } from 'react'; import type { StyleProp, ViewStyle } from 'react-native'; import { FlatList, TouchableOpacity, View } from 'react-native'; import type { BottomSheetProps } from '../../BottomSheet'; import BottomSheet from '../../BottomSheet'; import Typography from '../../Typography'; import Icon from '../../Icon'; import List from '../../List'; import { deepCompareValue, useKeyboard } from '../../../utils/helpers'; import { StyledHeaderContainer } from './StyledChartSelect'; /** * Represents a selectable option for ChartSelect. * @template V The type of the option value. * @property value The value of the option. Used for selection and comparison. * @property text The display text for the option. * @property key (Optional) A unique key for the option. If provided, used as the FlatList key for better performance and stability. */ type OptionType = { value: V; text: string; key?: string; }; export interface SingleSelectProps { /** * The currently selected value. Should match one of the values in the options array. */ value: V | null; /** * Callback fired when an option is selected. * @param value The value of the selected option. */ onConfirm: (value: V) => void; /** * Array of supported orientations for the Select modal (iOS only). * Defaults to ['portrait']. */ supportedOrientations?: ('portrait' | 'landscape')[]; /** * The list of selectable options. Each option should have a value and display text. */ options: OptionType[]; /** * Callback fired when the selection modal is dismissed without selecting an option. */ onDismiss?: () => void; /** * Configuration for the bottom sheet modal. * - variant: The visual variant of the bottom sheet. * - header: Optional header text to display at the top of the bottom sheet. */ bottomSheetConfig?: { variant?: BottomSheetProps['variant']; header?: BottomSheetProps['header']; }; /** * If true, the select is disabled and cannot be interacted with. * @default false */ disabled?: boolean; /** * Additional style to apply to the select container. */ style?: StyleProp; /** * Optional test ID for testing purposes. Applied to the main touchable area. */ testID?: string; } const SingleSelect = ({ onConfirm, onDismiss, options = [], disabled = false, style, testID, value, supportedOrientations = ['portrait'], bottomSheetConfig = {}, }: SingleSelectProps) => { const { isKeyboardVisible, keyboardHeight } = useKeyboard(); const [open, setOpen] = useState(false); const displayedValue = options.find((opt) => deepCompareValue(opt.value, value))?.text || ''; const { variant: bottomSheetVariant, header: bottomSheetHeader = '' } = bottomSheetConfig; return ( <> setOpen(true)}> {displayedValue} { onDismiss?.(); setOpen(false); }} header={bottomSheetHeader} style={{ paddingBottom: isKeyboardVisible ? keyboardHeight : 0, }} supportedOrientations={supportedOrientations} testID="bottomSheet" > item.key ?? String(item.value)} renderItem={({ item }) => ( { setOpen(false); onConfirm?.(item.value); }} /> )} /> ); }; export default SingleSelect;