UNPKG

@janiscommerce/ui-native

Version:
61 lines (60 loc) 2.48 kB
import List from '../List'; import React, { useState } from 'react'; import { StyleSheet, View, Pressable } from 'react-native'; import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'; const Collapsible = ({ header: Header, content: Content, data = [], onPressCallback = null, pressableComponent: PressableComponent = Pressable, duration = 500, wrapperStyle = {}, }) => { const [isOpen, setIsOpen] = useState(false); const [measuredHeight, setMeasuredHeight] = useState(0); const contentHeight = useSharedValue(0); const hasHeightBeenMeasured = !!measuredHeight; const handleOpen = () => { // istanbul ignore next if (!isOpen && measuredHeight > 0) { contentHeight.value = measuredHeight; } setIsOpen(!isOpen); if (onPressCallback) { onPressCallback(); } }; const handleContentLayout = (e) => { // istanbul ignore next if (measuredHeight === 0) { const newHeight = e.nativeEvent.layout.height; setMeasuredHeight(newHeight); contentHeight.value = newHeight; } }; // istanbul ignore next const bodyStyle = useAnimatedStyle(() => ({ maxHeight: withTiming(isOpen ? contentHeight.value : 0, { duration }), overflow: 'hidden', })); const styles = StyleSheet.create({ wrapperView: { flex: 1, width: '100%' }, animatedView: { overflow: 'hidden', width: '100%', }, contentWrapper: { position: 'absolute', opacity: 0, }, }); const renderContent = (contentData) => { const { item, index } = contentData; return <Content {...item} index={index} isOpen={isOpen}/>; }; return (<View style={[wrapperStyle, styles.wrapperView]}> <PressableComponent onPress={handleOpen}> <Header isOpen={isOpen}/> </PressableComponent> {!hasHeightBeenMeasured && (<View style={styles.contentWrapper} onLayout={handleContentLayout}> <List data={data} renderComponent={renderContent} keyExtractor={(_, index) => String(index)} showsVerticalScrollIndicator={false}/> </View>)} <Animated.View style={[styles.animatedView, bodyStyle]}> <List data={data} renderComponent={renderContent} keyExtractor={(_, index) => String(index)} showsVerticalScrollIndicator={false}/> </Animated.View> </View>); }; export default Collapsible;