@@ -11,12 +11,14 @@ import { searchDefaultProps } from './defaultProps';
1111import { ENTER_REG } from '../_common/js/common' ;
1212import useDefaultProps from '../hooks/useDefaultProps' ;
1313import { usePrefixClass } from '../hooks/useClass' ;
14+ import Cell from '../cell/Cell' ;
1415
1516export interface SearchProps extends TdSearchProps , StyledProps { }
1617
1718const Search : FC < SearchProps > = ( props ) => {
1819 const {
1920 clearable,
21+ clearTrigger,
2022 action,
2123 center,
2224 disabled,
@@ -26,6 +28,7 @@ const Search: FC<SearchProps> = (props) => {
2628 readonly,
2729 shape,
2830 value,
31+ resultList,
2932 onActionClick,
3033 onBlur,
3134 onChange,
@@ -36,6 +39,7 @@ const Search: FC<SearchProps> = (props) => {
3639 const [ focusState , setFocus ] = useState ( focus ) ;
3740 const inputRef = useRef ( null ) ;
3841 const [ searchValue , setSearchValue ] = useDefault ( value , '' , onChange ) ;
42+ const [ showResultList , setShowResultList ] = useState ( false ) ;
3943
4044 const { classPrefix } = useConfig ( ) ;
4145 const searchClass = usePrefixClass ( 'search' ) ;
@@ -53,6 +57,7 @@ const Search: FC<SearchProps> = (props) => {
5357 } ;
5458
5559 const handleInput = ( e : FormEvent < HTMLInputElement > ) => {
60+ setShowResultList ( true ) ;
5661 if ( e instanceof InputEvent ) {
5762 // 中文输入的时候inputType是insertCompositionText所以中文输入的时候禁止触发。
5863 const checkInputType = e . inputType && e . inputType === 'insertCompositionText' ;
@@ -63,16 +68,18 @@ const Search: FC<SearchProps> = (props) => {
6368 } ;
6469
6570 const handleClear = ( e : MouseEvent < HTMLDivElement > ) => {
66- setSearchValue ( '' , { trigger : 'input-change' } ) ;
71+ setSearchValue ( '' , { trigger : 'clear' , e } ) ;
6772 setFocus ( true ) ;
6873 onClear ?.( { e } ) ;
6974 } ;
7075
7176 const handleFocus = ( e : FocusEvent < HTMLDivElement > ) => {
77+ setFocus ( true ) ;
7278 onFocus ?.( { value : searchValue , e } ) ;
7379 } ;
7480
7581 const handleBlur = ( e : FocusEvent < HTMLDivElement > ) => {
82+ setFocus ( false ) ;
7683 onBlur ?.( { value : searchValue , e } ) ;
7784 } ;
7885
@@ -88,6 +95,7 @@ const Search: FC<SearchProps> = (props) => {
8895 // 如果按的是 enter 键, 13是 enter
8996 if ( ENTER_REG . test ( e . code ) || ENTER_REG . test ( e . key ) ) {
9097 e . preventDefault ( ) ;
98+ setShowResultList ( false ) ;
9199 onSubmit ?.( { value : searchValue , e } ) ;
92100 }
93101 } ;
@@ -100,7 +108,7 @@ const Search: FC<SearchProps> = (props) => {
100108 } ;
101109
102110 const renderClear = ( ) => {
103- if ( clearable && searchValue ) {
111+ if ( clearable && searchValue && ( clearTrigger === 'always' || ( clearTrigger === 'focus' && focusState ) ) ) {
104112 return (
105113 < div className = { `${ searchClass } __clear` } onClick = { handleClear } >
106114 < CloseCircleFilledIcon />
@@ -121,31 +129,71 @@ const Search: FC<SearchProps> = (props) => {
121129 return null ;
122130 } ;
123131
132+ const highlightSearchValue = ( item : string , value : string ) => {
133+ const parts = item . split ( new RegExp ( `(${ value } )` , 'gi' ) ) ;
134+ return parts . map ( ( part , index ) =>
135+ part . toLowerCase ( ) === value . toLowerCase ( ) ? (
136+ < span key = { index } className = { `${ searchClass } __result-item--highLight` } >
137+ { part }
138+ </ span >
139+ ) : (
140+ part
141+ ) ,
142+ ) ;
143+ } ;
144+
145+ const handleSelectOption = ( item : string , e : MouseEvent < HTMLDivElement > ) => {
146+ setShowResultList ( false ) ;
147+ setSearchValue ( item , { trigger : 'option-click' , e } ) ;
148+ } ;
149+
150+ const renderResultList = ( ) => {
151+ if ( ! showResultList || ! resultList || resultList . length === 0 ) {
152+ return null ;
153+ }
154+
155+ return (
156+ < div className = { `${ searchClass } __result-list` } >
157+ { resultList . map ( ( item , index ) => (
158+ < Cell
159+ key = { index }
160+ className = { `${ searchClass } __result-item` }
161+ onClick = { ( context ) => handleSelectOption ( item , context . e ) }
162+ title = { highlightSearchValue ( item , searchValue ) }
163+ />
164+ ) ) }
165+ </ div >
166+ ) ;
167+ } ;
168+
124169 return (
125- < div className = { `${ searchClass } ` } >
126- < div className = { `${ boxClasses } ` } >
127- { renderLeftIcon ( ) }
128- < input
129- ref = { inputRef }
130- value = { searchValue }
131- type = "search"
132- className = { `${ inputClasses } ` }
133- style = {
134- props . cursorColor ? ( { '--td-search-cursor-color' : props . cursorColor } as React . CSSProperties ) : undefined
135- }
136- autoFocus = { focus }
137- placeholder = { placeholder }
138- readOnly = { readonly }
139- disabled = { disabled }
140- onKeyDown = { handleSearch }
141- onFocus = { handleFocus }
142- onBlur = { handleBlur }
143- onInput = { handleInput }
144- onCompositionEnd = { handleCompositionend }
145- />
146- { renderClear ( ) }
170+ < div >
171+ < div className = { `${ searchClass } ` } >
172+ < div className = { `${ boxClasses } ` } >
173+ { renderLeftIcon ( ) }
174+ < input
175+ ref = { inputRef }
176+ value = { searchValue }
177+ type = "search"
178+ className = { `${ inputClasses } ` }
179+ style = {
180+ props . cursorColor ? ( { '--td-search-cursor-color' : props . cursorColor } as React . CSSProperties ) : undefined
181+ }
182+ autoFocus = { focus }
183+ placeholder = { placeholder }
184+ readOnly = { readonly }
185+ disabled = { disabled }
186+ onKeyDown = { handleSearch }
187+ onFocus = { handleFocus }
188+ onBlur = { handleBlur }
189+ onInput = { handleInput }
190+ onCompositionEnd = { handleCompositionend }
191+ />
192+ { renderClear ( ) }
193+ </ div >
194+ { renderAction ( ) }
147195 </ div >
148- { renderAction ( ) }
196+ { renderResultList ( ) }
149197 </ div >
150198 ) ;
151199} ;
0 commit comments