@uiw/react-native
Version:
UIW for React Native
88 lines • 3.05 kB
JavaScript
import React, { useState, useRef } from 'react';
import { StyleSheet, View, TouchableOpacity, LayoutAnimation, Animated } from 'react-native';
import { useTheme } from '@shopify/restyle';
import Icon from '../Icon';
const Accordion = props => {
const {
sections,
isMultiple = true,
iconShow = true,
iconSize = 18,
accordionStyle,
contentStyle
} = props;
const [activeIndex, setActiveIndex] = useState(isMultiple ? [] : -1);
const theme = useTheme();
const styles = createStyles({
bgColor: theme.colors.mask || '#FFFFFF',
headerColor: theme.colors.background || '#F5F5F5',
borderColor: theme.colors.border || '#CCCCCC'
});
const animatedController = useRef(new Animated.Value(0)).current;
const onPress = index => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (isMultiple) {
const currentIndex = Array.isArray(activeIndex) ? activeIndex.indexOf(index) : -1;
if (currentIndex > -1) {
const newActiveIndex = Array.isArray(activeIndex) ? [...activeIndex] : [];
if (currentIndex > -1) {
newActiveIndex.splice(currentIndex, 1);
}
setActiveIndex(newActiveIndex);
} else {
setActiveIndex(Array.isArray(activeIndex) ? [...activeIndex, index] : [index]);
}
} else {
setActiveIndex(activeIndex === index ? -1 : index);
}
Animated.timing(animatedController, {
toValue: activeIndex === index ? 0 : 1,
duration: 500,
useNativeDriver: true
}).start();
};
const rotateZ = animatedController.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '90deg']
});
return <View>
{sections.map((item, index) => <View key={index}>
<TouchableOpacity disabled={item?.isOnPress || false} activeOpacity={0.8} onPress={() => onPress(index)} style={[styles.header, accordionStyle]}>
<View style={styles.titleBy} key={index}>
{item.title}
{iconShow && <Animated.View style={{
transform: [{
rotateZ: activeIndex === index || Array.isArray(activeIndex) && activeIndex.indexOf(index) > -1 ? rotateZ : '0deg'
}]
}}>
<Icon name="right" size={iconSize} color={theme.colors.border || '#CCCCCC'} />
</Animated.View>}
</View>
</TouchableOpacity>
{(isMultiple && Array.isArray(activeIndex) && activeIndex.indexOf(index) > -1 || !isMultiple && activeIndex === index) && <View style={[styles.content, contentStyle]}>{item.content}</View>}
</View>)}
</View>;
};
function createStyles({
bgColor,
borderColor,
headerColor
}) {
return StyleSheet.create({
titleBy: {
flexDirection: 'row',
justifyContent: 'space-between'
},
header: {
borderBottomWidth: 1,
borderBottomColor: borderColor,
padding: 15,
backgroundColor: headerColor
},
content: {
padding: 15,
backgroundColor: bgColor
}
});
}
export default Accordion;