import * as React from 'react' ; import classNames from 'classnames' ; import ToolTip from '../tooltip' ; import InputItem from '../input-item' ; export interface AutoCompleteProps { prefixCls ? : string ; className ? : string ; source : [ ] ; matchedStyle : string ; value : string ; defaultValue ? : string ; onChange ? : ( value : any ) => void ; size ? : string ; disabled ? : boolean ; isOpen ? : boolean ; clear ? : boolean ; placeholder ? : string ; } class AutoComplete extends React . PureComponent < AutoCompleteProps , any > { lastValue : any ; constructor ( props ) { super ( props ) ; this . state = { open : false , index : - 1 , result : props . source , value : props . defaultValue || props . value || '' , } ; } static defaultProps = { prefixCls : 'Yep-auto-complete' , } ; componentWillReceiveProps ( nextProps ) { 'value' in nextProps && this . setState ( { value : nextProps . value } ) ; 'source' in nextProps && this . setState ( { result : nextProps . source } ) ; } handleInput = ( value ) => { this . lastValue = value ; const state = { value } as any ; if ( ! value ) { state . open = true ; state . result = this . props . source ; this . setState ( state ) ; } else { state . index = - 1 ; state . result = this . props . source . filter ( ( item ) => item . indexOf ( value ) > - 1 ) ; state . open = ! ! state . result . length ; this . setState ( state ) ; } this . props . onChange && this . props . onChange ( value ) ; } ; handleSelect ( value ) { this . setState ( { value , open : false , } ) ; this . props . onChange && this . props . onChange ( value ) ; } handleKeyDown = ( e ) => { const { open , result } = this . state ; if ( open ) { const input = e . target ; const key = e . key ; let { index } = this . state ; if ( key === 'ArrowDown' || key === 'ArrowUp' ) { if ( key === 'ArrowDown' ) { if ( index === result . length - 1 ) index = - 1 ; else index ++ ; } if ( key === 'ArrowUp' ) { e . preventDefault ( ) ; if ( index === - 1 ) index = result . length - 1 ; else index -- ; } this . setState ( { index , value : result [ index ] || this . lastValue , } ) ; } if ( key === 'Enter' ) { this . handleSelect ( result [ index ] ) ; input . blur ( ) ; } } } ; render ( ) { const { open , index , result , value } = this . state ; const { prefixCls , source , onChange , disabled , isOpen , matchedStyle , ... other } = this . props ; const inputProps = { ... other , onKeyDown : this . handleKeyDown , } ; return ( < ToolTip open = { isOpen || open } disabled = { disabled } aligned = { true } onToggle = { open => this . setState ( { open } ) } overlay = { < div className = { `${ prefixCls }__popover` } > < ul className = { `${ prefixCls }__result` } > { result . map ( ( item , i ) => ( < li key = { item } className = { classNames ( { [ `${ prefixCls }__option--active` ] : index === i } ) } onClick = { this . handleSelect . bind ( this , item ) } > < div dangerouslySetInnerHTML = { { __html : value === '' ? item : `${ item . replace ( value , '<span style="' + matchedStyle + '">' + value + '</span>' ) }` , } } /> < /li>))} < /ul> < /div>}> < InputItem value = { value } onChange = { this . handleInput } disabled = { disabled } { ... inputProps } /> < /ToolTip>); } } export default AutoComplete ;