1
- import React , { useState , useRef , useEffect } from 'react' ;
1
+ import React , { useState , useRef , useCallback , useEffect } from 'react' ;
2
2
import PropTypes from 'prop-types' ;
3
3
import { handleInputChange , normalizeOptions } from './helpers/form-helpers' ;
4
4
import { Dropdown } from '../mixed/Dropdown' ;
@@ -19,27 +19,35 @@ export function FormAutocomplete({
19
19
const [ searchValue , setSearchValue ] = useState ( '' ) ;
20
20
const { isOpen, open, close } = useOpenState ( ) ;
21
21
const [ ignoreBlur , setIgnoreBlur ] = useState ( false ) ;
22
- const { getValue, setValue, register } = useFormControl ( name ) ;
23
- const inputRef = useRef ( null ) ;
22
+ const [ isFocused , setFocus ] = useState ( false ) ;
23
+ const { getValue, setValue, register, isValid, getFormSubmitedAttempted } = useFormControl ( name ) ;
24
+ const registerRef = useCallback ( register , [ ] ) ;
25
+ const searchInputRef = useRef ( null ) ;
26
+
27
+ const items = normalizeOptions ( options , FormData ) ;
28
+ const value = getValue ( ) ;
29
+ const selectedItem = items . find ( ( item ) => item . value === value ) ;
30
+
31
+ const controlFeedback = `${ getFormSubmitedAttempted ( ) ? ( isValid ( ) ? 'is-valid' : 'is-invalid' ) : '' } ` ;
24
32
25
33
useEffect ( ( ) => {
26
- register ( inputRef . current ) ;
27
- } , [ ] ) ;
34
+ searchInputRef . current . setCustomValidity ( controlFeedback === 'is-invalid' ? 'invalid' : '' ) ;
35
+ } , [ controlFeedback ] ) ;
28
36
29
37
return (
30
38
< >
31
39
< input
32
- { ...{ required , name , id , placeholder } }
40
+ { ...{ placeholder } }
33
41
type = "text"
34
- ref = { inputRef }
35
- className = " form-control"
42
+ ref = { searchInputRef }
43
+ className = { ` form-control ${ isFocused ? '' : 'd-none' } ${ controlFeedback } ` }
36
44
onChange = { handleInputChange . bind ( null , {
37
45
update ( _ , value ) {
38
46
setSearchValue ( value ) ;
39
47
onSearch ( value ) ;
40
48
open ( ) ;
41
49
42
- if ( getValue ( ) ) {
50
+ if ( value ) {
43
51
setValue ( null ) ;
44
52
}
45
53
} ,
@@ -52,14 +60,15 @@ export function FormAutocomplete({
52
60
}
53
61
} }
54
62
onBlur = { ( ) => {
55
- if ( ! getValue ( ) ) {
63
+ if ( ! value ) {
56
64
setSearchValue ( '' ) ;
57
65
}
58
66
59
67
if ( ignoreBlur ) {
60
- inputRef . current . focus ( ) ;
68
+ searchInputRef . current . focus ( ) ;
61
69
} else {
62
70
close ( ) ;
71
+ setFocus ( false ) ;
63
72
}
64
73
} }
65
74
value = { searchValue }
@@ -68,13 +77,40 @@ export function FormAutocomplete({
68
77
aria-expanded = "false"
69
78
autoComplete = "off"
70
79
/>
80
+
81
+ { ! isFocused && (
82
+ < div
83
+ className = { `form-control ${ controlFeedback } ` }
84
+ onClick = { ( ) => {
85
+ setFocus ( true ) ;
86
+ setTimeout ( ( ) => {
87
+ searchInputRef . current . focus ( ) ;
88
+ } ) ;
89
+ } }
90
+ >
91
+ { selectedItem ? ( template ? template ( selectedItem . label ) : selectedItem . label ) : placeholder }
92
+ </ div >
93
+ ) }
94
+
95
+ < input
96
+ type = "text"
97
+ className = { `form-control d-none` }
98
+ { ...{ name, required, id } }
99
+ onChange = { ( ) => { } }
100
+ value = { getValue ( ) }
101
+ ref = { registerRef }
102
+ />
71
103
< Dropdown
72
104
isOpen = { isOpen ( ) }
73
- items = { normalizeOptions ( options , FormData ) . filter ( filter ( searchValue ) ) }
105
+ items = { items . filter ( filter ( searchValue ) ) }
74
106
onSelect = { ( { value, label } ) => {
75
107
setValue ( value ) ;
76
108
setSearchValue ( label ) ;
77
- close ( ) ;
109
+ setIgnoreBlur ( false ) ;
110
+ setTimeout ( ( ) => {
111
+ setFocus ( false ) ;
112
+ close ( ) ;
113
+ } , 250 ) ;
78
114
} }
79
115
template = { template }
80
116
onTouchStart = { ( ) => setIgnoreBlur ( true ) }
0 commit comments