import { LayoutChangeEvent, ScrollView, TextStyle, TouchableWithoutFeedback, View, ViewStyle, } from "react-native"; import { Checkbox, Divider, Menu, TextInput, TouchableRipple, useTheme, } from "react-native-paper"; import React, { ReactNode, forwardRef, useEffect, useState, useCallback, Fragment, } from "react"; import { Theme } from "react-native-paper/lib/typescript/types"; import { TextInputProps } from "react-native-paper/lib/typescript/components/TextInput/TextInput"; type Without = Pick>; export interface DropDownPropsInterface { visible: boolean; multiSelect?: boolean; onDismiss: () => void; showDropDown: () => void; value: any; setValue: (_value: any) => void; disabled?: boolean; label?: string | undefined; placeholder?: string | undefined; mode?: "outlined" | "flat" | undefined; inputProps?: TextInputPropsWithoutTheme; list: Array<{ label: string; value: string | number; custom?: ReactNode; }>; dropDownContainerMaxHeight?: number; dropDownContainerHeight?: number; activeColor?: string; theme?: Theme; dropDownStyle?: ViewStyle; dropDownItemSelectedTextStyle?: TextStyle; dropDownItemSelectedStyle?: ViewStyle; dropDownItemStyle?: ViewStyle; dropDownItemTextStyle?: TextStyle; accessibilityLabel?: string; } type TextInputPropsWithoutTheme = Without; const DropDown = forwardRef( (props: DropDownPropsInterface, ref) => { const activeTheme = useTheme(); const { multiSelect = false, visible, onDismiss, showDropDown, value, setValue, activeColor, mode, label, placeholder, inputProps, list, dropDownContainerMaxHeight, dropDownContainerHeight, theme, dropDownStyle, dropDownItemStyle, dropDownItemSelectedStyle, dropDownItemTextStyle, dropDownItemSelectedTextStyle, accessibilityLabel, } = props; const [displayValue, setDisplayValue] = useState(""); const [inputLayout, setInputLayout] = useState({ height: 0, width: 0, x: 0, y: 0, }); const onLayout = (event: LayoutChangeEvent) => { setInputLayout(event.nativeEvent.layout); }; useEffect(() => { if (multiSelect) { const _labels = list .filter((_) => value.indexOf(_.value) !== -1) .map((_) => _.label) .join(", "); setDisplayValue(_labels); } else { const _label = list.find((_) => _.value === value)?.label; if (_label) { setDisplayValue(_label); } } }, [list, value]); const isActive = useCallback( (currentValue: any) => { if (multiSelect) { return value.indexOf(currentValue) !== -1; } else { return value === currentValue; } }, [value] ); const setActive = useCallback( (currentValue: any) => { if (multiSelect) { const valueIndex = value.indexOf(currentValue); const values = value.split(","); if (valueIndex === -1) { setValue([...values, currentValue].join(",")); } else { setValue( [...values].filter((value) => value !== currentValue).join(",") ); } } else { setValue(currentValue); } }, [value] ); return ( } {...inputProps} /> } style={{ maxWidth: inputLayout?.width, width: inputLayout?.width, marginTop: inputLayout?.height, ...dropDownStyle, }} > {list.map((_item, _index) => ( { setActive(_item.value); if (onDismiss) { onDismiss(); } }} > {multiSelect && ( setActive(_item.value)} /> )} ))} ); } ); export default DropDown;