UNPKG

@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
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