@eslam-elmeniawy/react-native-common-components
Version:
Common `ReactNative` components packed in library for usage in projects.
128 lines (124 loc) • 4.05 kB
JavaScript
"use strict";
// External imports.
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { withTheme, TouchableRipple } from 'react-native-paper';
// Types imports.
// Internal imports.
import styles from "./Accordion.styles.js";
import { IconButton } from "../IconButton/index.js";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const SafeAccordion = /*#__PURE__*/React.memo(props => {
const {
containerStyle,
headerContainerStyle,
headerContent,
iconButtonProps,
children,
theme
} = props;
const {
iconName,
color,
onPress: onIconPress,
...restIconProps
} = iconButtonProps ?? {};
const Animated = require('react-native-reanimated').default;
const useSharedValue = require('react-native-reanimated').useSharedValue;
const useAnimatedStyle = require('react-native-reanimated').useAnimatedStyle;
const withTiming = require('react-native-reanimated').withTiming;
const Easing = require('react-native-reanimated').Easing;
const [isExpanded, setIsExpanded] = React.useState(false);
const [measuredHeight, setMeasuredHeight] = React.useState(0);
const height = useSharedValue(0);
const rotation = useSharedValue(0);
const onTogglePress = React.useCallback(() => {
setIsExpanded(!isExpanded);
if (!isExpanded) {
height.value = withTiming(measuredHeight, {
duration: 300,
easing: Easing.inOut(Easing.ease)
});
rotation.value = withTiming(180, {
duration: 300,
easing: Easing.inOut(Easing.ease)
});
} else {
height.value = withTiming(0, {
duration: 300,
easing: Easing.inOut(Easing.ease)
});
rotation.value = withTiming(0, {
duration: 300,
easing: Easing.inOut(Easing.ease)
});
}
onIconPress?.();
}, [Easing, height, isExpanded, measuredHeight, onIconPress, rotation, withTiming]);
const onLayout = React.useCallback(event => {
if (measuredHeight === 0) {
setMeasuredHeight(event.nativeEvent.layout.height);
}
}, [measuredHeight]);
const animatedHeightStyle = useAnimatedStyle(() => ({
height: height.value,
overflow: 'hidden'
}));
const animatedArrowStyle = useAnimatedStyle(() => ({
transform: [{
rotateZ: `${rotation.value}deg`
}]
}));
return /*#__PURE__*/_jsxs(View, {
style: StyleSheet.flatten([{
backgroundColor: theme.colors.background
}, containerStyle]),
children: [/*#__PURE__*/_jsxs(View, {
style: styles.headerRow,
children: [/*#__PURE__*/_jsx(TouchableRipple, {
style: styles.headerRipple,
onPress: onTogglePress,
children: /*#__PURE__*/_jsx(View, {
style: headerContainerStyle,
children: headerContent
})
}), /*#__PURE__*/_jsx(Animated.View, {
style: animatedArrowStyle,
children: /*#__PURE__*/_jsx(IconButton, {
iconName: iconName ?? 'chevron-down',
color: color ?? (theme.isV3 ? theme.colors.onBackground : theme.colors.text),
onPress: onTogglePress,
...restIconProps
})
})]
}), /*#__PURE__*/_jsxs(Animated.View, {
style: animatedHeightStyle,
children: [/*#__PURE__*/_jsx(View, {
style: styles.measuringContainer,
onLayout: onLayout,
children: children
}), /*#__PURE__*/_jsx(View, {
children: children
})]
})]
});
});
const AccordionWithFallback = /*#__PURE__*/React.memo(props => {
try {
require('react-native-reanimated');
return /*#__PURE__*/_jsx(SafeAccordion, {
...props
});
} catch (error) {
console.warn('Error loading `react-native-reanimated`:', error);
return null;
}
});
const Accordion = withTheme(AccordionWithFallback);
/**
* AccordionComponent (unwrapped, for testing)
* @internal For testing purposes only. Do not use in production code.
*/
export { AccordionWithFallback as AccordionComponent };
export default Accordion;
//# sourceMappingURL=Accordion.js.map