@@ -48,6 +48,67 @@ export const TimeRangeModal: React.FC<TimeRangeModalProps> = ({ id, isModalOpen,
4848 : t ( 'To date must be after From date' ) ;
4949 } ;
5050
51+ //this is a hack to allow user to type into date / time inputs without having to delete previous content
52+ const onInput = ( e : React . FormEvent < HTMLDivElement > , type : 'date' | 'time' ) => {
53+ const input = e . target as HTMLInputElement ;
54+ const inputEvent = e . nativeEvent as InputEvent ;
55+
56+ //save cursor position
57+ let start = input . selectionStart as number ;
58+ let end = input . selectionEnd as number ;
59+
60+ //split date / time accordingly
61+ const delimiter = type === 'date' ? '-' : ':' ;
62+ const valueParts = input . value . split ( delimiter ) ;
63+
64+ //hack delimiters only when caracters are added one by one
65+ if ( start === end && inputEvent . inputType === 'insertText' && inputEvent . data !== delimiter ) {
66+ //new caracter has been added before the delimiter, we need to move it to the next part
67+ switch ( type ) {
68+ case 'date' :
69+ if ( start === 5 && valueParts . length > 1 ) {
70+ valueParts [ 1 ] = inputEvent . data + valueParts [ 1 ] ;
71+ start ++ ;
72+ } else if ( start === 8 && valueParts . length > 2 ) {
73+ valueParts [ 2 ] = inputEvent . data + valueParts [ 2 ] ;
74+ start ++ ;
75+ }
76+ break ;
77+ case 'time' :
78+ if ( start === 3 && valueParts . length > 1 ) {
79+ valueParts [ 1 ] = inputEvent . data + valueParts [ 1 ] ;
80+ start ++ ;
81+ } else if ( start === 6 && valueParts . length > 2 ) {
82+ valueParts [ 2 ] = inputEvent . data + valueParts [ 2 ] ;
83+ start ++ ;
84+ }
85+ break ;
86+ }
87+ end = start ;
88+ }
89+
90+ let truncatedValue = '' ;
91+ for ( let i = 0 ; i < 3 ; i ++ ) {
92+ if ( truncatedValue . length ) {
93+ truncatedValue += delimiter ;
94+ }
95+
96+ const isYear = type === 'date' && i === 0 ;
97+ if ( valueParts . length > i ) {
98+ const len = isYear ? 4 : 2 ;
99+ truncatedValue += valueParts [ i ] . slice ( 0 , len ) . padEnd ( len , '0' ) ;
100+ } else {
101+ truncatedValue += isYear ? '0000' : '00' ;
102+ }
103+ }
104+
105+ //update input value
106+ input . value = truncatedValue ;
107+
108+ //restore position
109+ input . setSelectionRange ( start , end ) ;
110+ } ;
111+
51112 const resetInputs = React . useCallback ( ( ) => {
52113 let from : Date ;
53114 let to : Date ;
@@ -156,6 +217,7 @@ export const TimeRangeModal: React.FC<TimeRangeModalProps> = ({ id, isModalOpen,
156217 data-test = "from-date-picker"
157218 validators = { [ date => dateValidator ( true , date ) ] }
158219 onChange = { str => setFromDate ( str ) }
220+ onInput = { e => onInput ( e , 'date' ) }
159221 value = { fromDate }
160222 />
161223 </ FlexItem >
@@ -166,6 +228,7 @@ export const TimeRangeModal: React.FC<TimeRangeModalProps> = ({ id, isModalOpen,
166228 includeSeconds
167229 placeholder = "hh:mm:ss"
168230 onChange = { setFromTime }
231+ onInput = { e => onInput ( e , 'time' ) }
169232 time = { displayedFromTime }
170233 />
171234 </ FlexItem >
@@ -180,6 +243,7 @@ export const TimeRangeModal: React.FC<TimeRangeModalProps> = ({ id, isModalOpen,
180243 validators = { [ date => dateValidator ( false , date ) ] }
181244 rangeStart = { fromDate ? new Date ( Date . parse ( fromDate ) ) : undefined }
182245 onChange = { str => setToDate ( str ) }
246+ onInput = { e => onInput ( e , 'date' ) }
183247 value = { toDate }
184248 />
185249 </ FlexItem >
@@ -190,6 +254,7 @@ export const TimeRangeModal: React.FC<TimeRangeModalProps> = ({ id, isModalOpen,
190254 includeSeconds
191255 placeholder = "hh:mm:ss"
192256 onChange = { setToTime }
257+ onInput = { e => onInput ( e , 'time' ) }
193258 time = { displayedToTime }
194259 />
195260 </ FlexItem >
0 commit comments