import React, { useState, useRef, useEffect } from 'react'; import { View, Text, Pressable, Animated, StyleSheet, LayoutChangeEvent, } from 'react-native'; import { useTheme } from '../../theme/useTheme'; import type { AccordionProps, AccordionItem } from './Accordion.types'; interface AccordionItemViewProps { item: AccordionItem; isExpanded: boolean; onPress: () => void; theme: ReturnType; } const AccordionItemView: React.FC = ({ item, isExpanded, onPress, theme, }) => { const heightAnim = useRef(new Animated.Value(0)).current; const rotateAnim = useRef(new Animated.Value(0)).current; const contentHeight = useRef(0); const handleContentLayout = (e: LayoutChangeEvent) => { const { height } = e.nativeEvent.layout; contentHeight.current = height; if (isExpanded && height > 0) { Animated.timing(heightAnim, { toValue: height, duration: 250, useNativeDriver: false, }).start(); } }; useEffect(() => { if (!isExpanded) { Animated.parallel([ Animated.timing(heightAnim, { toValue: 0, duration: 250, useNativeDriver: false, }), Animated.timing(rotateAnim, { toValue: 0, duration: 200, useNativeDriver: true, }), ]).start(); } else { Animated.timing(rotateAnim, { toValue: 1, duration: 200, useNativeDriver: true, }).start(); if (contentHeight.current > 0) { Animated.timing(heightAnim, { toValue: contentHeight.current, duration: 250, useNativeDriver: false, }).start(); } } }, [isExpanded, heightAnim, rotateAnim]); const chevronRotate = rotateAnim.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '180deg'], }); return ( {item.title} {'\u203A'} {item.content} ); }; export const Accordion: React.FC = ({ items, allowMultiple = false, defaultExpandedKeys = [], style, }) => { const theme = useTheme(); const [expandedKeys, setExpandedKeys] = useState>( () => new Set(defaultExpandedKeys) ); const toggleItem = (key: string) => { setExpandedKeys((prev) => { const next = new Set(prev); if (next.has(key)) { next.delete(key); } else { if (!allowMultiple) { next.clear(); } next.add(key); } return next; }); }; return ( {items.map((item) => ( toggleItem(item.key)} theme={theme} /> ))} ); }; const styles = StyleSheet.create({ container: {}, item: {}, header: { flexDirection: 'row', alignItems: 'center', }, title: {}, chevron: { lineHeight: 24, }, contentWrapper: {}, content: {}, });