@mustapha-ghlissi/react-native-select-picker
Version:
React Native Select Picker: Reanimated dropdown select compatible with Android, IOS and Web
155 lines • 6.15 kB
JavaScript
import { ScrollView, View, Text, Pressable, StyleSheet } from 'react-native';
import React, { useState, isValidElement, useEffect, memo } from 'react';
import Animated, { useAnimatedStyle, useDerivedValue, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import baseStyles from './style';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const Dropdown = /*#__PURE__*/memo(({
items,
displayItems = 4,
placeholder,
styles,
icon = 'chevron-down',
outlineColor = '#145DA0',
borderColor = '#E2E2E2',
borderWidth = 1,
multiple = false,
checkIcon = 'check',
inline = false,
onSelectChange,
animationDuration = 200
}) => {
const [selectedItems, setSelectedItems] = useState([]);
const [selectedItem, setSelectedItem] = useState(null);
const iconRotate = useSharedValue('0deg');
const animatedIconStyles = useAnimatedStyle(() => ({
transform: [{
rotate: withSpring(iconRotate.value)
}]
}));
const maxItemHeight = styles && styles.dropdownItem && styles.dropdownItem.height && typeof styles.dropdownItem.height === 'number' ? styles.dropdownItem.height : baseStyles.dropdownItem.height;
const maxListHeight = displayItems * maxItemHeight;
const [isOpenDropdown, setIsOpendropdown] = useState(false);
const dropdownListHeight = useSharedValue(maxListHeight);
const deviredDropdownListHeight = useDerivedValue(() => withTiming(dropdownListHeight.value * Number(isOpenDropdown), {
duration: animationDuration
}));
const animatedDropdownListStyle = useAnimatedStyle(() => ({
height: deviredDropdownListHeight.value
}));
const activeItemStyle = {
...baseStyles.activeDropdownItem,
...styles?.activeItem
};
const activeItemTextStyle = {
...baseStyles.activeDropdownItemText,
...styles?.activeItemText
};
const togglerHeight = styles && styles.dropdownToggler && styles.dropdownToggler.height ? styles.dropdownToggler.height : baseStyles.dropdownToggler.height;
const getBorderColor = () => ({
borderColor: isOpenDropdown ? outlineColor : borderColor
});
const innerStyles = StyleSheet.create({
dropdownList: {
display: isOpenDropdown ? 'flex' : 'none',
top: inline ? 0 : Number(togglerHeight) + borderWidth * 2,
position: inline ? 'relative' : 'absolute',
...getBorderColor()
}
});
const toggleDropdown = () => {
setIsOpendropdown(!isOpenDropdown);
iconRotate.value = iconRotate.value === '0deg' ? '180deg' : '0deg';
};
const renderIcon = () => {
if ( /*#__PURE__*/isValidElement(icon)) {
return icon;
}
if (typeof icon === 'string') {
return /*#__PURE__*/_jsx(Icon, {
name: icon,
size: 32,
color: "#000"
});
}
return null;
};
const renderSelectedItems = () => {
if (multiple && selectedItems.length) {
return selectedItems.map(_selectedItem => _selectedItem.label).join(', ');
}
if (selectedItem) {
return selectedItem?.label;
}
return placeholder ?? 'Select an option';
};
const isSelectedItem = item => {
if (selectedItems.length) {
return selectedItems.find(_selectedItem => _selectedItem.value === item.value) !== undefined;
}
return selectedItem?.value === item.value;
};
useEffect(() => {
const changedSelected = selectedItem || selectedItems;
onSelectChange(changedSelected);
}, [onSelectChange, selectedItem, selectedItems]);
return /*#__PURE__*/_jsxs(View, {
children: [/*#__PURE__*/_jsx(View, {
style: [baseStyles.dropdownInputContainer, styles && styles.inputContainer, getBorderColor(), {
borderWidth
}, isOpenDropdown && baseStyles.focusedDropdownInputContainer],
children: /*#__PURE__*/_jsxs(Pressable, {
style: [baseStyles.dropdownToggler, styles && styles.dropdownToggler],
android_ripple: {
foreground: true,
color: 'rgba(0,0,0,0.3)'
},
onPress: toggleDropdown,
children: [/*#__PURE__*/_jsx(Text, {
style: [baseStyles.dropdownText, styles && styles.inputText, (selectedItems || selectedItem) && baseStyles.activeDropdownText],
numberOfLines: 1,
children: renderSelectedItems()
}), /*#__PURE__*/_jsx(Animated.View, {
style: [baseStyles.iconContainer, animatedIconStyles, styles && styles.iconContainer],
children: renderIcon()
})]
})
}), /*#__PURE__*/_jsx(Animated.View, {
style: [baseStyles.dropdownList, styles && styles.dropdownList, {
borderWidth
}, animatedDropdownListStyle, innerStyles.dropdownList],
children: /*#__PURE__*/_jsx(ScrollView, {
showsVerticalScrollIndicator: true,
children: items.map((item, itemIndex) => /*#__PURE__*/_jsxs(Pressable, {
android_ripple: {
color: 'rgba(0,0,0,0.3)'
},
style: [baseStyles.dropdownItem, styles && styles.dropdownItem, isSelectedItem(item) && activeItemStyle],
onPress: () => {
if (multiple) {
const existItemIndex = selectedItems.findIndex(selectedItem => selectedItem.value === item.value);
if (existItemIndex > -1) {
setSelectedItems([...selectedItems.filter((_, index) => index !== existItemIndex)]);
} else {
setSelectedItems([...selectedItems, item]);
}
} else {
setSelectedItem(item);
toggleDropdown();
}
},
children: [/*#__PURE__*/_jsx(Text, {
style: [baseStyles.dropdownItemText, styles && styles.dropdownItemText, isSelectedItem(item) && activeItemTextStyle],
children: item.label
}), multiple && isSelectedItem(item) && (typeof checkIcon === 'string' ? /*#__PURE__*/_jsx(Icon, {
name: checkIcon,
size: 26,
color: '#FFF'
}) : checkIcon)]
}, `dropdownItemIndex_${itemIndex}`))
})
})]
});
});
export default Dropdown;
//# sourceMappingURL=Dropdown.js.map