import React, { useState, useRef, useEffect } from 'react'; import { TextInput, Surface, Divider, HelperText, Searchbar, Text, Provider as PaperProvider, useTheme, } from 'react-native-paper'; import { View, Dimensions, Platform, SectionList, ActivityIndicator, } from 'react-native'; import Modal from 'react-native-modal'; import Lo from 'lodash'; import Item from '../Components/Item'; import { defaultDropdownProps, ITEMLAYOUT } from '../constants'; import styles from '../styles'; import type { IDropdownData, IGroupDropdownData, IGroupDropdownProps, } from '../types'; import { deviceWidth, deviceHeight } from '../util'; import EmptyList from '../Components/EmptyList'; import PressableTouch from '../Components/PressableTouch'; const GroupDropdown: React.FC = props => { const { error, value, label, required, disabled, data, onChange, floating, enableSearch, primaryColor, elevation, borderRadius, activityIndicatorColor, searchPlaceholder, helperText, errorColor, itemTextStyle, itemContainerStyle, showLoader, animationIn = 'fadeIn', animationOut = 'fadeOut', supportedOrientations = ['portrait', 'landscape'], animationInTiming, animationOutTiming, headerTextStyle, headerContainerStyle, stickySectionHeadersEnabled, parentDDContainerStyle, rippleColor, emptyListText, enableAvatar, avatarSize, onBlur, paperTheme, textInputStyle, mainContainerStyle, underlineColor, disableSelectionTick, selectedItemTextStyle, selectedItemViewStyle, removeLabel, mode = 'flat', disabledItemTextStyle, disabledItemViewStyle, dropdownIcon = 'menu-down', dropdownIconSize = 30, itemSelectIcon, itemSelectIconSize, multiline = false, searchInputTheme, } = props; const { colors } = useTheme(); const [selected, setSelected] = useState(); const [labelv, setlabelV] = useState(''); const [isVisible, setIsVisible] = useState(false); const [iconColor, setIconColor] = useState('grey'); const [options, setOptions] = useState([]); const [hasError, setError] = useState(false); const [singluarData, setSingularData] = useState([]); const [contMeasure, setConMeasure] = useState({ vx: 0, vy: 0, vWidth: 0, vHeight: 0, }); const [dimension, setDimension] = useState({ dw: deviceWidth, dh: deviceHeight, }); const [searchQuery, setSearchQuery] = useState(''); const pViewRef = useRef(); const listRef = useRef(); useEffect(() => { Dimensions.addEventListener('change', () => { const { width, height } = Dimensions.get('window'); setDimension({ dw: width, dh: height }); setIsVisible(false); setIconColor('grey'); }); return () => { Dimensions.removeEventListener('change', () => {}); }; }, []); useEffect(() => { const destructuredData: IDropdownData[] = []; Lo.forEach(data, d => { Lo.forEach(d.data, dv => destructuredData.push(dv)); }); setSingularData(destructuredData); setOptions(data); }, [data]); useEffect(() => { if (!Lo.isEmpty(singluarData) && value) { const lFilter = Lo.filter(singluarData, { value: value })[0]; if (!Lo.isEmpty(lFilter)) setlabelV(lFilter.label); setSelected(value); } }, [value, singluarData]); useEffect(() => { if (isVisible && listRef) { listRef.current.flashScrollIndicators(); } }, [isVisible]); useEffect(() => { if (isVisible && selected) { let secionIndex = 0; let itemIndex = 0; if (!Lo.isEmpty(options)) { options.forEach((e, secIndex) => { const itIndex = Lo.findIndex(e.data, { value: selected }); if (itIndex >= 0 && listRef) { itemIndex = itIndex; secionIndex = secIndex; setTimeout(() => { listRef.current.scrollToLocation({ animated: false, sectionIndex: secionIndex, itemIndex: itemIndex, viewPosition: Platform.OS === 'android' ? 0 : 0.5, }); }, 100); } }); } } }, [selected, options, isVisible]); useEffect(() => { if (disabled) { setIconColor('lightgrey'); } }, [disabled]); useEffect(() => { if (required && error) { setError(true); setIconColor(errorColor); } else { setError(false); setIconColor('grey'); } }, [required, error, errorColor]); const onTextInputFocus = () => { if (hasError) { setIconColor('red'); } else { setIconColor(primaryColor); } // if (Platform.OS === 'ios') { pViewRef.current.measureInWindow( (vx: number, vy: number, vWidth: number, vHeight: number) => { const ddTop = vy + vHeight; const bottomMetric = dimension.dh - vy; if (bottomMetric < 300) { setConMeasure({ vx, vy: ddTop - 217, vWidth, vHeight }); } else { setConMeasure({ vx, vy: ddTop, vWidth, vHeight }); } } ); // } setIsVisible(true); }; const androidOnLayout = () => { if (Platform.OS === 'android') { pViewRef.current.measureInWindow( (vx: number, vy: number, vWidth: number, vHeight: number) => { const ddTop = vy + vHeight; const bottomMetric = dimension.dh - vy; // setPx(bottomMetric); if (bottomMetric < 300) { setConMeasure({ vx, vy: ddTop - 217, vWidth, vHeight }); } else { setConMeasure({ vx, vy: ddTop, vWidth, vHeight }); } } ); } }; const onModalBlur = () => { setIsVisible(false); if (hasError) { setIconColor('red'); } else { setIconColor('grey'); } if (onBlur && typeof onBlur === 'function') onBlur(); }; const handleOptionSelect = (v: string | number) => { const lFilter = Lo.filter(singluarData, { value: v })[0]; if (!Lo.isEmpty(lFilter)) setlabelV(lFilter.label); setSelected(v); if (onChange && typeof onChange === 'function') { onChange(v); setIsVisible(false); } if (hasError) { setIconColor('red'); } else { setIconColor('grey'); } setSearchQuery(''); setOptions(data); }; const onChangeSearch = (query: string) => { setSearchQuery(query); if (!Lo.isEmpty(data) && query) { let matches: IGroupDropdownData[] = []; data.forEach(e => { const sF = e.data.filter(c => c.label .toString() .toLowerCase() .trim() .includes(query.toString().toLowerCase()) ); if (!Lo.isEmpty(sF)) matches = matches.concat([{ title: e.title, data: sF }]); }); if (matches.length === 0) setOptions([]); else setOptions(matches); } else if (!Lo.isEmpty(data) && !query) { setOptions(data); } }; const getEmptyComponent = () => { if (typeof emptyListText === 'string') return ; else return <>{emptyListText}; }; const labelAction = () => { if (removeLabel) { return ''; } else { return required ? `${label}*` : label; } }; return ( } mode={mode} /> {required && hasError ? ( {helperText ? helperText : `${label} is required`} ) : null} {showLoader ? ( ) : null} ) : null } stickyHeaderIndices={enableSearch ? [0] : undefined} renderItem={({ item }) => ( )} renderSectionHeader={({ section: { title } }) => ( {title.trim()} )} keyExtractor={() => Math.random().toString()} ItemSeparatorComponent={() => ( )} getItemLayout={(_d, index) => ({ length: ITEMLAYOUT, offset: ITEMLAYOUT * index, index, })} stickySectionHeadersEnabled={stickySectionHeadersEnabled} ListEmptyComponent={getEmptyComponent()} /> ); }; GroupDropdown.defaultProps = defaultDropdownProps; export default GroupDropdown;