Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | 1x 6x 6x 6x 6x 5x 6x 6x 3x 1x 1x 1x 6x 6x 16x 16x 2x 6x 2x 2x 1x 1x 1x 1x 6x 16x 1x | import { View, StyleProp, ViewStyle, StyleSheet, Pressable, Text } from 'react-native';
import { useNavigation, NavigationProp } from '@react-navigation/native';
import { NavMenuItemProps, NavMenuProps } from './NavMenu.native.types';
import React, { useEffect, useState } from 'react';
import { colors } from '@sb/styles/colors';
import { useTheme } from '@sb/ui/components/Themes/ThemeProvider';
import { RootStackParamList } from '@sb/types';
type IndexProps = number | undefined;
export const NavMenu: React.FC<NavMenuProps> = ({
id,
style,
direction,
variant,
items,
disabled,
activeIndex,
}) => {
const [selectedIndex, setSelectedIndex] = useState<IndexProps>(activeIndex);
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
const { theme } = useTheme();
useEffect(() => {
setSelectedIndex(activeIndex);
}, [activeIndex]);
const getVariantStyle = () => {
switch (variant) {
case 'primary':
return { backgroundColor: colors[theme].colorPrimary };
case 'secondary':
return { backgroundColor: colors[theme].colorSecondary };
case 'outlined':
return { borderWidth: 1, borderColor: colors[theme].colorText_Main };
case 'text':
return { backgroundColor: 'transparent' };
default:
return { backgroundColor: colors[theme].colorPrimary };
}
};
const navMenuStyles: StyleProp<ViewStyle> = {
flexDirection: direction === 'horizontal' ? 'row' : 'column',
gap: 3,
...getVariantStyle(),
};
const renderItem = (item: NavMenuItemProps, index: number) => {
const isVertical = item.iconPosition === 'top' || item.iconPosition === 'bottom';
return (
<Pressable
testID={`nav-item-${index}`}
accessibilityRole="button"
accessibilityState={{ disabled, selected: selectedIndex === index }}
style={[item.style, styles.navItem, { flexDirection: isVertical ? 'column' : 'row' }]}
disabled={disabled}
onPress={() => handleOnClick(item, index)}
>
{item.iconPosition === 'top' && item.icon}
<Text
style={[
styles.label,
{
color:
selectedIndex === index ? colors[theme].colorAccent : colors[theme].colorText_Main,
},
]}
>
{item.label}
</Text>
{item.iconPosition !== 'top' && item.icon}
</Pressable>
);
};
const handleOnClick = (item: NavMenuItemProps, index: number) => {
Iif (disabled) return;
if (item.onClick) {
item.onClick();
return;
}
setSelectedIndex(index);
Iif (item.path && item.path !== '' && item.path in navigation) {
navigation.navigate(item.path);
}
};
return (
<View id={id} style={[style, navMenuStyles]}>
{items &&
items.map((item, index) => (
<View key={`item-${index}`} style={styles.itemWrapper}>
{item.body ? item.body(item, index) : renderItem(item, index)}
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
itemWrapper: {
width: 'auto',
alignItems: 'center',
justifyContent: 'center',
padding: 10,
},
navItem: {
position: 'relative',
flexDirection: 'row',
alignItems: 'center',
gap: 2,
},
label: {
fontWeight: 'bold',
},
});
|