react-native-modal-select
Version:
Simple select component for iOS and Android
265 lines (249 loc) • 8.86 kB
JavaScript
import React, {Fragment, useState, useEffect} from 'react';
import { StyleSheet, View, Text, Platform, TouchableOpacity, Modal, Dimensions, FlatList } from 'react-native';
import Icon from './Icon'
const ReactNativeModalSelect = ({
backgroundColor = "white",
textColor = "black",
iconColor = "black",
iconType = "ionicons",
iconName = "md-person",
iconPadding = 5,
iconSize = 25,
inputHeight = 40,
inputWidth = '100%',
inputBackgroundColor = "white",
labelSize = 16,
labelColor = "black",
marginBottom = 25,
selectedValue = {
id: 1,
label: 'Spiderman',
value: 'Peter Parker',
},
labelText = "Superheros",
clearable = true,
onRequestClose = () => console.log("Closing"),
onSelect = (val) => console.log("selected hero: " + val),
items = [
{
id: 0,
label: 'Batman',
value: 'Bruce Wayne',
},
{
id: 1,
label: 'Spiderman',
value: 'Peter Parker',
},
{
id: 2,
label: 'The Punisher',
value: 'Frank Castle',
},
{
id: 3,
label: 'Superman',
value: 'Clark Kent',
},
{
id: 4,
label: 'The Hulk',
value: 'Bruce Banner',
},
{
id: 5,
label: 'Iron Man',
value: 'Tony Stark',
}
],
...props
}) => {
const [optionsModalVisible, setOptionsModalVisible] = useState(false)
const [optionSelected, setOptionSelected] = useState({id: 0, label: '', value: ''})
const DEVICE_HEIGHT = Dimensions.get("screen").height
var options = props.items || items
var bgColor = props.backgroundColor || backgroundColor
var textColor = props.textColor || textColor
var icon_color = props.iconColor || iconColor
var icon_type = props.iconType || iconType
var icon_padding = props.iconPadding || iconPadding
var icon_name = props.iconName || iconName
var icon_size = props.iconSize || iconSize
var input_height = props.inputHeight || inputHeight
var input_width = props.inputWidth || inputWidth
var input_bg_color = props.inputBackgroundColor || inputBackgroundColor
var label_size = props.labelSize || labelSize
var label_color = props.labelcolor || labelColor
var label_text = props.labelText || labelText
var is_clearable = props.clearable || clearable
var selected_value = props.selectedValue || optionSelected === null ? '' : optionSelected.value
var margin_bottom = props.marginBottom || marginBottom
var onRequestModalClose = props.onRequestClose || onRequestClose
var onItemSelect = props.onSelect || onSelect
const clear = () => {
setOptionSelected(null)
}
const Item = ({ title }) => (
<View style={[styles.item, { backgroundColor: bgColor }]}>
<Text
style={[styles.title, { color: textColor }]}
>
{title}
</Text>
</View>
);
const renderItem = ({ item }) => (
<TouchableOpacity
onPress={() => {
setOptionSelected(item)
setOptionsModalVisible(false)
}}
>
<Item title={item.label} />
</TouchableOpacity>
);
useEffect(() => {
if(optionSelected != null) {
onItemSelect(optionSelected)
}
}, [optionSelected])
return (
<Fragment>
<Modal
animationType="fade"
transparent={ true }
visible={ optionsModalVisible }
onRequestClose={ onRequestModalClose }
style={ styles.modalContainer }
>
<View
style={{
backgroundColor: 'rgba(0,0,0,0.5)',
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: DEVICE_HEIGHT
}}>
<TouchableOpacity
activeOpacity={ 1 }
style={{
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center'
}}
onPress={ () => setOptionsModalVisible(false) }
>
<View style={ [styles.optionsModal, {backgroundColor: bgColor} ]}>
{/* necessary to overload the higher level backdrop-click dismissal */}
<TouchableOpacity activeOpacity={ 1 }>
<FlatList
data={ options }
renderItem={ renderItem }
keyExtractor={ item => item.value }
/>
</TouchableOpacity>
</View>
</TouchableOpacity>
</View>
</Modal>
<View style={{ maxWidth: input_width }}>
<Text style={{ fontSize: label_size, color: label_color }}>{ label_text }</Text>
<TouchableOpacity
style={[ styles.selectContainer, {
backgroundColor: input_bg_color,
width: '100%',
borderRadius: Platform.OS == 'ios' ? 10 : 0,
borderWidth: Platform.OS == 'ios' ? 0 : 1,
marginBottom: margin_bottom,
zIndex: 5
}]}
onPress={() => {
setOptionsModalVisible(true)
}}
>
<Icon
iconColor={icon_color}
iconType={icon_type}
iconPadding={icon_padding}
iconName={icon_name}
iconSize={icon_size}
inputHeight={input_height}
/>
<View style={{
width: icon_name != null ? '70%' : '80%',
minHeight: input_height,
backgroundColor: input_bg_color,
borderRadius: Platform.OS == 'ios' ? 10 : 0,
alignItems: 'flex-end',
flexDirection: 'row'
}}>
<View style={{
width: '100%',
minHeight: input_height,
backgroundColor: input_bg_color,
borderRadius: Platform.OS == 'ios' ? 10 : 0,
paddingLeft: '6%',
justifyContent: 'center',
}}>
<Text
style={{
color: textColor,
}}
>
{ selected_value }
</Text>
</View>
</View>
{
is_clearable ?
<TouchableOpacity style={{ position: 'absolute', right: 10 }} onPress={ clear }>
<Icon
iconType="antdesign"
iconName="closecircle"
iconSize={24}
iconColor={iconColor}
/>
</TouchableOpacity>
:
<View></View>
}
</TouchableOpacity>
</View>
</Fragment>
)
}
const styles = StyleSheet.create({
selectContainer: {
flexDirection: 'row',
alignItems: 'center',
},
optionsModal: {
width: '85%',
alignSelf: 'center',
height: '60%',
},
modalContainer: {
height: '60%',
width: '90%'
},
modalBodyContainer: {
backgroundColor: '#f0eff1',
width: '100%',
height: '98%'
},
container: {
flex: 1,
marginTop: 0,
},
item: {
padding: 10,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 18,
},
})
export default ReactNativeModalSelect