Last active
January 18, 2023 09:04
-
-
Save sajjadjaved01/f4d8bd0678103fca48c7a2ab67cd94d9 to your computer and use it in GitHub Desktop.
Multiselect / Single-Select dropdown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { MaterialIcons } from "@expo/vector-icons"; | |
import React, { useEffect, useState } from "react"; | |
import { FlatList, Image, Pressable, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from "react-native"; | |
import DashedLine from "react-native-dashed-line"; | |
import { RFValue } from "react-native-responsive-fontsize"; | |
var dropItem: DropdownItem[] = [{ itemName: "Pakistan" }, { selected: false, itemName: "United States" }]; | |
const handler = (item: DropdownItem) => { | |
console.log("This is callback", item); | |
}; | |
/** | |
* This is a dropdown component. Designed to be used with the `DropdownList` component. | |
* If you found this component useful, please star it on [Github](https://www.github.com/sajjadjaved01) | |
*/ | |
function Dropdown({ | |
title = "Select", | |
clkHandler = handler, | |
listItems = dropItem, | |
selectedBoxColor = "green", | |
unselectedBoxColor = "grey", | |
multiSelect = false, | |
selectedValue = "", | |
showLeadingIcon = false, | |
leadingIcon = "", | |
boxStyle = { | |
borderColor: "#E0E0E0", | |
}, | |
itemStyle = {}, | |
titleStyle = {}, | |
dropdownStyle = {}, | |
}: DropdownProps) { | |
const [displayCheck, setDisplayCheck] = useState(false); | |
const [selectedItem, setSelectedItem] = useState<DropdownItem>({ | |
selected: false, | |
itemName: "Google", | |
leadingIcon: leadingIcon, | |
}); | |
const [header, setTitle] = useState(selectedValue ?? title); | |
const touched = (index: number) => { | |
var item = listItems[index]; | |
setSelectedItem(item); | |
setTitle(item.itemName); | |
clkHandler(item); | |
}; | |
const toogleDropDown = () => { | |
setDisplayCheck(!displayCheck); | |
}; | |
useEffect(() => { | |
if (typeof selectedValue == "string" && selectedValue != "") { | |
var index = listItems.findIndex((i) => i.itemName.toLowerCase() == selectedValue.toLowerCase()); | |
if (index != -1) { | |
touched(index); | |
} | |
} else if (typeof selectedValue == "number") { | |
touched(selectedValue); | |
} | |
}, []); | |
return ( | |
<View style={styles.mainCont}> | |
<Pressable style={{ ...styles.btnDropDown, ...boxStyle }} onPress={() => toogleDropDown()}> | |
<View style={{ flexDirection: "row", alignItems: "center" }}> | |
{showLeadingIcon && ( | |
<Image | |
source={selectedItem.leadingIcon} | |
style={{ height: RFValue(30), width: RFValue(30), marginStart: 5 }} | |
resizeMode="contain" | |
/> | |
)} | |
<Text style={styles.inputDropDown}>{header}</Text> | |
</View> | |
<MaterialIcons | |
style={{ marginRight: 8 }} | |
name={!displayCheck ? "expand-more" : "expand-less"} | |
size={RFValue(30)} | |
/> | |
</Pressable> | |
{displayCheck && ( | |
<View style={styles.innerOptionsCont}> | |
<View style={{ ...styles.innerOptionsTxt, width: "100%", height: "auto" }}> | |
<FlatList | |
style={{ flexGrow: 0 }} | |
data={listItems} | |
ItemSeparatorComponent={() => <DashedLine style={{ marginRight: 10 }} dashColor={"#fff"} />} | |
keyExtractor={(t, i) => i.toString()} | |
renderItem={(item) => ( | |
<TouchableOpacity | |
activeOpacity={0.2} | |
onPress={() => { | |
item.item.selected = item.item.selected ? false : true; | |
touched(item.index); | |
if (!multiSelect) { | |
toogleDropDown(); | |
} | |
// setchangeTitle(listItems[index]) | |
}} | |
key={item.index.toString()} | |
style={{ margin: 10, zIndex: 0 }} | |
> | |
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}> | |
<Text style={styles.itemText}>{item.item.itemName}</Text> | |
{multiSelect && ( | |
<MaterialIcons | |
color={ | |
item.item.selected ? (selectedBoxColor ? selectedBoxColor : "#B3DBA1") : unselectedBoxColor | |
} | |
name={item.item.selected ? "check-box" : "check-box-outline-blank"} | |
size={RFValue(25)} | |
/> | |
)} | |
</View> | |
</TouchableOpacity> | |
)} | |
/> | |
</View> | |
</View> | |
)} | |
</View> | |
); | |
} | |
export class DropdownItem { | |
itemName: string = ""; | |
selected?: boolean = false; | |
itemValue?: string = ""; | |
leadingIcon?: any; | |
} | |
interface DropdownProps { | |
title?: string; | |
/** | |
* @default dropItem | |
* @type {DropdownItem[]} | |
* @description This is the list of items that will be displayed in the dropdown. | |
* @example | |
* ``` | |
* const dropItem = [ | |
* { selected: false, itemName: "Pakistan" }, | |
* { selected: false, itemName: "United States" }, | |
* ]; | |
* ``` | |
*/ | |
listItems?: DropdownItem[]; | |
boxStyle?: ViewStyle; | |
dropdownStyle?: ViewStyle; | |
itemStyle?: TextStyle; | |
titleStyle?: TextStyle; | |
/** | |
* This is `callback` function will return selected item. | |
*/ | |
clkHandler?: (i: DropdownItem) => void; | |
selectedBoxColor?: string; | |
unselectedBoxColor?: string; | |
multiSelect?: boolean; | |
selectedValue?: string; | |
leadingIcon?: typeof MaterialIcons["name"]; | |
showLeadingIcon?: boolean; | |
} | |
const styles = StyleSheet.create({ | |
mainCont: { | |
marginVertical: 10, | |
}, | |
btnDropDown: { | |
marginTop: 0, | |
borderRadius: 5, | |
justifyContent: "space-between", | |
borderWidth: 1.5, | |
flexDirection: "row", | |
position: "relative", | |
alignItems: "center", | |
}, | |
inputDropDown: { | |
paddingHorizontal: 20, | |
paddingVertical: 12, | |
color: "black", | |
fontFamily: "bold", | |
fontSize: RFValue(16), | |
}, | |
innerOptionsCont: { | |
display: "flex", | |
position: "absolute", | |
borderWidth: 1, | |
zIndex: 99, | |
top: 46, | |
backgroundColor: "white", | |
borderColor: "#BDBDBD", | |
borderBottomLeftRadius: 5, | |
borderBottomRightRadius: 5, | |
width: "100%", | |
}, | |
innerOptionsTxt: { | |
paddingStart: 10, | |
width: RFValue(30), | |
height: RFValue(30), | |
borderRadius: 4, | |
}, | |
itemText: { fontSize: RFValue(16), color: "#828282", fontFamily: "medium", width: "75%" }, | |
}); | |
export default Dropdown; |
fixed selectedValue issue.
added more style props
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated Box styling.