import {useTheme} from '../../theme/ThemeProvider'; import {memo, useCallback, useEffect, useState} from 'react'; import {Pressable, StyleSheet, Text, View} from 'react-native'; import type {TabControlProps} from '../../types'; type TabProps = { index: number; isFirst: boolean; isLast: boolean; label: string; selected: boolean; backgroundColor: string; tintColor: string; textColor: string; selectedTextColor: string; testID?: string; onPress: (index: number) => void; }; const Tab = memo( ({ index, isFirst, isLast, label, selected, backgroundColor, tintColor, textColor, selectedTextColor, testID, onPress, }: TabProps) => ( onPress(index)} style={[ styles.tab, {backgroundColor: selected ? tintColor : backgroundColor}, isFirst && styles.first, isLast && styles.last, ]}> {label} ), ); export const TabControl = (props: TabControlProps) => { const {colors} = useTheme(); const { accessibilityLabel, values, selectedIndex = 0, label, labelStyle, backgroundTabColor = colors.surface, tabTintColor = colors.background, textColor = colors.text, selectedTextColor = colors.text, containerStyle, style, testID, } = props; const [selected, setSelected] = useState(selectedIndex); // Keep in sync when `selectedIndex` changes after mount. useEffect(() => { setSelected(selectedIndex); }, [selectedIndex]); const handlePress = useCallback((idx: number) => { setSelected(idx); }, []); // Fall back to the first tab when the index is out of range. const current = values[selected] ?? values[0]; const Component = current?.renderItem; return ( {!!label && {label}} {values.map((value, index) => ( ))} {!!Component && } ); }; const styles = StyleSheet.create({ tabs: { flexDirection: 'row', justifyContent: 'center', paddingTop: 2, paddingLeft: 1, paddingRight: 1, borderTopLeftRadius: 5, borderTopRightRadius: 5, marginTop: 5, }, tab: { flex: 1, paddingVertical: 5, }, first: { borderTopLeftRadius: 5, }, last: { borderTopRightRadius: 5, }, text: { textAlign: 'center', fontWeight: '700', fontSize: 16, }, content: { paddingBottom: 5, }, });