license import React from 'react' ; import { ListRenderItemInfo , NativeSyntheticEvent , StyleSheet , TextInputFocusEventData , TextInputSubmitEditingEventData , View , } from 'react-native' ; import { ChildrenWithProps } from '../../devsupport' ; import { Input , InputElement , InputProps , } from '../input/input.component' ; import { List } from '../list/list.component' ; import { Popover , PopoverElement , } from '../popover/popover.component' ; import { AutocompleteItemElement , AutocompleteItemProps , } from './autocompleteItem.component' ; export interface AutocompleteProps extends InputProps { children ? : ChildrenWithProps < AutocompleteItemProps > ; onSelect ? : ( index : number ) => void ; placement ? : string ; } export type AutocompleteElement = React . ReactElement < AutocompleteProps > ; interface State { listVisible : boolean ; } extends React . Component method method method method method method property property property property property property property property property property property overview-example overview-example example example export class Autocomplete extends React . Component < AutocompleteProps , State > { public state : State = { listVisible : false , } ; private popoverRef = React . createRef < Popover > ( ) ; private inputRef = React . createRef < Input > ( ) ; private get data ( ) : any [ ] { return React . Children . toArray ( this . props . children || [ ] ) ; } public show = ( ) : void => { this . popoverRef . current ?. show ( ) ; } ; public hide = ( ) : void => { this . popoverRef . current ?. hide ( ) ; } ; public focus = ( ) : void => { this . inputRef . current ?. focus ( ) ; } ; public blur = ( ) : void => { this . inputRef . current ?. blur ( ) ; } ; public isFocused = ( ) : boolean => { return this . inputRef . current ?. isFocused ( ) ; } ; public clear = ( ) : void => { this . inputRef . current ?. clear ( ) ; } ; public componentDidUpdate ( prevProps ) { const isChildCountChanged = this . data . length !== React . Children . count ( prevProps . children ) ; const shouldBecomeVisible = ! this . state . listVisible && this . isFocused ( ) && isChildCountChanged ; shouldBecomeVisible && this . setState ( { listVisible : shouldBecomeVisible } ) ; } private onInputFocus = ( event ) : void => { this . setOptionsListVisible ( ) ; this . props . onFocus && this . props . onFocus ( event ) ; } ; private onInputSubmitEditing = ( e ) : void => { this . setOptionsListInvisible ( ) ; this . props . onSubmitEditing && this . props . onSubmitEditing ( e ) ; } ; private onBackdropPress = ( ) : void => { this . blur ( ) ; this . setOptionsListInvisible ( ) ; } ; private onItemPress = ( index ) : void => { if ( this . props . onSelect ) { this . setOptionsListInvisible ( ) ; this . props . onSelect ( index ) ; } } ; private setOptionsListVisible = ( ) : void => { const hasData = this . data . length > 0 ; hasData && this . setState ( { listVisible : true } ) ; } ; private setOptionsListInvisible = ( ) : void => { this . setState ( { listVisible : false } ) ; } ; private renderItem = ( info ) : AutocompleteItemElement => { return React . cloneElement ( info . item , { onPress : ( ) => this . onItemPress ( info . index ) } ) ; } ; private renderInputElement = ( props ) : InputElement => { return ( < View > < Input { ... props } ref = { this . inputRef } onFocus = { this . onInputFocus } onSubmitEditing = { this . onInputSubmitEditing } / > < /View>); } ; public render ( ) { const { placement , children , testID , ... inputProps } = this . props ; return ( < Popover ref = { this . popoverRef } style = { styles . popover } placement = { placement } testID = { testID } visible = { this . state . listVisible } fullWidth = { true } anchor = { ( ) => this . renderInputElement ( inputProps ) } onBackdropPress = { this . onBackdropPress } > < List style = { styles . list } keyboardShouldPersistTaps = 'always' data = { this . data } bounces = { false } renderItem = { this . renderItem } / > < /Popover>); } } const styles = StyleSheet . create ( { popover : { maxHeight : 192 , overflow : 'hidden' , } , list : { flexGrow : 0 , overflow : 'hidden' , } , } ) ;