@niku/react-native-dropdown-select
Version:
A Dropdown select component for React Native
113 lines (106 loc) • 3.89 kB
JavaScript
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Animated, Easing, FlatList, InteractionManager, Platform, TouchableWithoutFeedback, View } from 'react-native';
import { useSafeAreaFrame, useSafeAreaInsets } from 'react-native-safe-area-context';
import { DROPDOWN_MIN_WIDTH } from '../constants';
import { isDropdownOptionItem } from '../utils';
import { styles } from './styles';
const DropdownModalContent = ({
visible,
onDismiss,
onDismissed,
dropdownContainerStyle,
renderItem,
options,
loading,
loadingComponent,
buttonLayout,
position
}) => {
/**
* Animation
*/
const animationValue = useRef(new Animated.Value(0)).current;
const show = useCallback(() => {
InteractionManager.runAfterInteractions(() => {
Animated.timing(animationValue, {
toValue: 1,
duration: 250,
useNativeDriver: false
}).start();
});
}, [animationValue]);
const hide = useCallback(() => {
InteractionManager.runAfterInteractions(() => {
Animated.timing(animationValue, {
toValue: 0,
duration: 250,
useNativeDriver: false
}).start(result => {
if (result.finished) {
onDismissed && onDismissed();
}
});
});
}, [animationValue, onDismissed]);
useEffect(() => {
visible ? show() : hide();
}, [visible]);
/**
* Dropdown Position
*/
const frame = useSafeAreaFrame();
const insets = useSafeAreaInsets();
const [dropdownContainerHeight, setDropdownContainerHeight] = useState(0);
const measureDropdownContainer = useCallback(e => {
setDropdownContainerHeight(e.nativeEvent.layout.height);
}, []);
const dropdownContainerPositionStyles = useMemo(() => {
const top = buttonLayout.y + buttonLayout.height;
const left = buttonLayout.x;
const width = buttonLayout.width > DROPDOWN_MIN_WIDTH ? buttonLayout.width : DROPDOWN_MIN_WIDTH;
let positionStyles = {
top: top - (Platform.OS === 'ios' || frame.y > 0 ? 0 : insets.top),
left: left,
width
};
if (position === 'top') {
positionStyles.top = buttonLayout.y - dropdownContainerHeight + (Platform.OS === 'ios' || frame.y > 0 ? 0 : insets.top);
}
return positionStyles;
}, [buttonLayout, dropdownContainerHeight, position, frame, insets]);
/**
* Animation translate
*/
const dropdownContainerTranslateY = animationValue.interpolate({
inputRange: [0, 1],
outputRange: [position === 'bottom' ? -dropdownContainerHeight / 2 : dropdownContainerHeight / 2, 0],
easing: Easing.linear,
extrapolate: 'clamp'
});
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TouchableWithoutFeedback, {
style: styles.backdrop,
onPress: onDismiss
}, /*#__PURE__*/React.createElement(View, {
style: styles.backdrop
})), /*#__PURE__*/React.createElement(Animated.View, {
onLayout: measureDropdownContainer,
style: [styles.dropdownContainer, dropdownContainerPositionStyles, position === 'top' ? styles.dropdownContainerPositionTop : {}, {
transform: [{
translateY: dropdownContainerTranslateY
}, {
scaleY: animationValue
}],
opacity: animationValue
}, dropdownContainerStyle]
}, /*#__PURE__*/React.createElement(FlatList, {
renderItem: renderItem,
data: options,
keyExtractor: (item, index) => {
var _item$value;
return isDropdownOptionItem(item) ? (_item$value = item.value) === null || _item$value === void 0 ? void 0 : _item$value.toString() : (typeof item.label === 'string' ? item.label : index) + '-' + item.options.length;
},
ListFooterComponent: () => /*#__PURE__*/React.createElement(React.Fragment, null, loading && loadingComponent)
})));
};
export default DropdownModalContent;
//# sourceMappingURL=index.js.map