UNPKG

@uiw/react-native

Version:
88 lines 3.05 kB
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;