1+ /* eslint-disable @typescript-eslint/no-unused-vars */
12import EventsEngine from '@js/common/core/events/core/events_engine' ;
23import { addNamespace } from '@js/common/core/events/utils/index' ;
4+ import type { dxElementWrapper } from '@js/core/renderer' ;
35import browser from '@js/core/utils/browser' ;
46import { clipboardText as getClipboardText } from '@js/core/utils/dom' ;
7+ import type { DxEvent } from '@js/events' ;
8+ import type { TextEditorBaseProperties } from '@ts/ui/text_box/m_text_editor.base' ;
9+ import type TextEditorMask from '@ts/ui/text_box/m_text_editor.mask' ;
10+ import type { HandlingArgs } from '@ts/ui/text_box/m_text_editor.mask.rule' ;
11+ import type { CaretRange } from '@ts/ui/text_box/utils.caret' ;
512
613const MASK_EVENT_NAMESPACE = 'dxMask' ;
714const BLUR_EVENT = 'blur beforedeactivate' ;
@@ -10,64 +17,75 @@ const DELETE_INPUT_TYPES = ['deleteContentBackward', 'deleteSoftLineBackward', '
1017const HISTORY_INPUT_TYPES = [ 'historyUndo' , 'historyRedo' ] ;
1118const EVENT_NAMES = [ 'focusIn' , 'focusOut' , 'input' , 'paste' , 'cut' , 'drop' , 'beforeInput' ] ;
1219
13- function getEmptyString ( length ) {
14- return EMPTY_CHAR . repeat ( length ) ;
15- }
20+ const getEmptyString = ( length : number ) : string => EMPTY_CHAR . repeat ( length ) ;
1621
1722export default class MaskStrategy {
18- editor : any ;
23+ editor : TextEditorMask ;
1924
20- _dragTimer ?: any ;
25+ _dragTimer ?: ReturnType < typeof setTimeout > ;
2126
22- _inputHandlerTimer ?: any ;
27+ _inputHandlerTimer ?: ReturnType < typeof setTimeout > ;
2328
24- _caretTimeout ?: any ;
29+ _caretTimeout ?: ReturnType < typeof setTimeout > ;
2530
26- _prevCaret ?: any ;
31+ _prevCaret ?: CaretRange ;
2732
2833 _previousText ?: string ;
2934
30- constructor ( editor ) {
35+ constructor ( editor : TextEditorMask ) {
3136 this . editor = editor ;
3237 }
3338
34- _editorOption ( ) {
39+ _editorOption < K extends keyof TextEditorBaseProperties > ( name : K ) : TextEditorBaseProperties [ K ] ;
40+ _editorOption < K extends keyof TextEditorBaseProperties > (
41+ name : K ,
42+ value : TextEditorBaseProperties [ K ] ,
43+ ) : void ;
44+ _editorOption < K extends keyof TextEditorBaseProperties > (
45+ name : K ,
46+ value ?: TextEditorBaseProperties [ K ] ,
47+ ) : TextEditorBaseProperties [ K ] | void {
48+ // eslint-disable-next-line prefer-rest-params
3549 return this . editor . option ( ...arguments ) ;
3650 }
3751
38- _editorInput ( ) {
52+ _editorInput ( ) : dxElementWrapper {
3953 return this . editor . _input ( ) ;
4054 }
4155
42- _editorCaret ( newCaret ?: any ) {
56+ _editorCaret ( ) : CaretRange ;
57+ _editorCaret ( newCaret : CaretRange | undefined ) : void ;
58+ // eslint-disable-next-line consistent-return
59+ _editorCaret ( newCaret ?: CaretRange | undefined ) : CaretRange | void {
4360 if ( ! newCaret ) {
4461 return this . editor . _caret ( ) ;
4562 }
4663
4764 this . editor . _caret ( newCaret ) ;
4865 }
4966
50- _attachChangeEventHandler ( ) {
51- // @ts -expect-error
67+ _attachChangeEventHandler ( ) : void {
68+ // @ts -expect-error ts-expect-error
5269 if ( ! this . _editorOption ( 'valueChangeEvent' ) . split ( ' ' ) . includes ( 'change' ) ) {
5370 return ;
5471 }
5572
5673 const $input = this . _editorInput ( ) ;
5774 const namespace = addNamespace ( BLUR_EVENT , MASK_EVENT_NAMESPACE ) ;
75+
5876 EventsEngine . on ( $input , namespace , ( e ) => {
5977 this . editor . _changeHandler ( e ) ;
6078 } ) ;
6179 }
6280
63- _beforeInputHandler ( ) {
64- // @ts -expect-error
81+ _beforeInputHandler ( ) : void {
6582 this . _previousText = this . _editorOption ( 'text' ) ;
6683 this . _prevCaret = this . _editorCaret ( ) ;
6784 }
6885
69- _inputHandler ( event ) {
86+ _inputHandler ( event : DxEvent < InputEvent > ) : void {
7087 const { originalEvent } = event ;
88+
7189 if ( ! originalEvent ) {
7290 return ;
7391 }
@@ -81,7 +99,7 @@ export default class MaskStrategy {
8199 } else {
82100 const currentCaret = this . _editorCaret ( ) ;
83101
84- if ( ! currentCaret . end ) {
102+ if ( ! currentCaret ? .end ) {
85103 return ;
86104 }
87105
@@ -90,63 +108,66 @@ export default class MaskStrategy {
90108 this . _editorCaret ( currentCaret ) ;
91109 this . _handleInsertTextInputEvent ( originalEvent . data ) ;
92110 }
93- // @ts -expect-error
111+
94112 if ( this . _editorOption ( 'text' ) === this . _previousText ) {
95113 event . stopImmediatePropagation ( ) ;
96114 }
97115 }
98116
99- _handleHistoryInputEvent ( ) {
117+ _handleHistoryInputEvent ( ) : void {
100118 const caret = this . _editorCaret ( ) ;
101119
102120 this . _updateEditorMask ( {
103- start : caret . start ,
104- length : caret . end - caret . start ,
121+ start : caret ? .start ,
122+ length : ( caret ? .end ?? 0 ) - ( caret ? .start ?? 0 ) ,
105123 text : '' ,
106124 } ) ;
107125
108126 this . _editorCaret ( this . _prevCaret ) ;
109127 }
110128
111- _handleBackwardDeleteInputEvent ( ) {
129+ _handleBackwardDeleteInputEvent ( ) : void {
112130 this . _clearSelectedText ( true ) ;
113131
114132 const caret = this . _editorCaret ( ) ;
133+
115134 this . editor . setForwardDirection ( ) ;
116135 this . editor . _adjustCaret ( ) ;
117136
118137 const adjustedForwardCaret = this . _editorCaret ( ) ;
119- if ( adjustedForwardCaret . start !== caret . start ) {
138+
139+ if ( adjustedForwardCaret ?. start !== caret ?. start ) {
120140 this . editor . setBackwardDirection ( ) ;
121141 this . editor . _adjustCaret ( ) ;
122142 }
123143 }
124144
125145 _clearSelectedText ( isDeleteInputEvent ?: boolean ) : void {
126146 const selectionLength = this . _prevCaret && ( this . _prevCaret . end - this . _prevCaret . start ) ;
127- const length = selectionLength || Number ( isDeleteInputEvent ) ;
147+ const length = selectionLength ?? Number ( isDeleteInputEvent ) ;
128148
129149 const caret = this . _editorCaret ( ) ;
130150
131151 if ( ! this . _isAutoFill ( ) ) {
132152 this . editor . setBackwardDirection ( ) ;
153+
133154 this . _updateEditorMask ( {
134- start : caret . start ,
155+ start : caret ? .start ,
135156 length,
136157 text : getEmptyString ( length ) ,
137158 } ) ;
138159 }
139160 }
140161
141- _handleInsertTextInputEvent ( data ) {
162+ _handleInsertTextInputEvent ( data : DxEvent < InputEvent > [ 'data' ] ) : void {
142163 // NOTE: data has length > 1 when autosuggestion is applied.
143164 const text = data ?? '' ;
144165
145166 this . editor . setForwardDirection ( ) ;
146167
147168 const hasValidChars = this . _updateEditorMask ( {
148169 start : this . _prevCaret ?. start ?? 0 ,
149- length : text . length || 1 ,
170+ length : text . length ?? 1 ,
150171 text,
151172 } ) ;
152173
@@ -155,80 +176,91 @@ export default class MaskStrategy {
155176 }
156177 }
157178
158- _updateEditorMask ( args ) {
159- const textLength = args . text . length ;
160- const processedCharsCount = this . editor . _handleChain ( args ) ;
179+ _updateEditorMask ( args : HandlingArgs ) : boolean {
180+ const textLength = args . text ? .length ?? 0 ;
181+ const processedCharsCount = this . editor . _handleChain ( args ) ?? 0 ;
161182
162183 this . editor . _displayMask ( ) ;
163184
164185 if ( this . editor . isForwardDirection ( ) ) {
165- const { start, end } = this . _editorCaret ( ) ;
166- const correction = processedCharsCount - textLength ;
186+ const { start = 0 , end = 0 } = this . _editorCaret ( ) ?? { } ;
167187
188+ const correction = processedCharsCount - textLength ;
168189 const hasSkippedStub = processedCharsCount > 1 ;
190+
169191 if ( hasSkippedStub && textLength === 1 ) {
170- this . _editorCaret ( { start : start + correction , end : end + correction } ) ;
192+ this . _editorCaret ( {
193+ start : start + correction ,
194+ end : end + correction ,
195+ } ) ;
171196 }
172197
173198 this . editor . _adjustCaret ( ) ;
174199 }
175200
176- return ! ! processedCharsCount ;
201+ return Boolean ( processedCharsCount ) ;
177202 }
178203
179- _focusInHandler ( ) {
204+ _focusInHandler ( ) : void {
180205 this . editor . _showMaskPlaceholder ( ) ;
181206 this . editor . setForwardDirection ( ) ;
182- // @ts -expect-error
207+
183208 if ( ! this . editor . _isValueEmpty ( ) && this . _editorOption ( 'isValid' ) ) {
184209 this . editor . _adjustCaret ( ) ;
185210 } else {
186211 const caret = this . editor . _maskRulesChain . first ( ) ;
212+
213+ // eslint-disable-next-line no-restricted-globals
187214 this . _caretTimeout = setTimeout ( ( ) => {
188215 this . _editorCaret ( { start : caret , end : caret } ) ;
189216 } , 0 ) ;
190217 }
191218 }
192219
193- _focusOutHandler ( event ) {
220+ _focusOutHandler ( event : DxEvent < FocusEvent > ) : void {
194221 this . editor . _changeHandler ( event ) ;
195- // @ts -expect-error
222+
196223 if ( this . _editorOption ( 'showMaskMode' ) === 'onFocus' && this . editor . _isValueEmpty ( ) ) {
197- // @ts -expect-error
198224 this . _editorOption ( 'text' , '' ) ;
199225 this . editor . _renderDisplayText ( '' ) ;
200226 }
201227 }
202228
203- _delHandler ( event ) {
229+ _delHandler ( event : DxEvent < KeyboardEvent > ) : void {
204230 const { editor } = this ;
205231
206- editor . _maskKeyHandler ( event , ( ) => {
232+ editor . _maskKeyHandler ( event , ( ) : undefined => {
207233 if ( ! editor . _hasSelection ( ) ) {
234+ // @ts -expect-error bad editor type
208235 editor . _handleKey ( EMPTY_CHAR ) ;
209236 }
210237 } ) ;
211238 }
212239
213- _cutHandler ( event ) {
240+ _cutHandler ( event : DxEvent < ClipboardEvent > ) : void {
214241 const caret = this . _editorCaret ( ) ;
215- const selectedText = this . _editorInput ( ) . val ( ) . substring ( caret . start , caret . end ) ;
242+ const inputVal = this . _editorInput ( ) . val ( ) ;
243+
244+ // @ts -expect-error dxElementWrapper.val() should return string
245+ const selectedText = inputVal . substring ( caret ?. start , caret ?. end ) ;
216246
217- this . editor . _maskKeyHandler ( event , ( ) => getClipboardText ( event , selectedText ) ) ;
247+ this . editor . _maskKeyHandler ( event , ( ) => ( getClipboardText ( event , selectedText ) ) as string ) ;
218248 }
219249
220- _dropHandler ( ) {
250+ _dropHandler ( ) : void {
221251 this . _clearDragTimer ( ) ;
252+
253+ // eslint-disable-next-line no-restricted-globals
222254 this . _dragTimer = setTimeout ( ( ) => {
223255 const value = this . editor . _convertToValue ( this . _editorInput ( ) . val ( ) ) ;
224- // @ts -expect-error
256+
225257 this . _editorOption ( 'value' , value ) ;
226258 } ) ;
227259 }
228260
229- _pasteHandler ( event ) {
261+ _pasteHandler ( event : DxEvent < ClipboardEvent > ) : void {
230262 const { editor } = this ;
231- // @ts -expect-error
263+
232264 if ( this . _editorOption ( 'disabled' ) ) {
233265 return ;
234266 }
@@ -237,29 +269,36 @@ export default class MaskStrategy {
237269
238270 editor . _maskKeyHandler ( event , ( ) => {
239271 const pastedText = getClipboardText ( event ) ;
240- const restText = editor . _maskRulesChain . text ( ) . substring ( caret . end ) ;
241- const accepted = editor . _handleChain ( { text : pastedText , start : caret . start , length : pastedText . length } ) ;
242- const newCaret = caret . start + accepted ;
272+ const restText = editor . _maskRulesChain . text ( ) . substring ( caret ?. end ) ;
273+ const accepted = editor . _handleChain ( {
274+ text : pastedText ,
275+ start : caret ?. start ,
276+ length : pastedText . length ,
277+ } ) ;
278+ const newCaret = ( caret ?. start ?? 0 ) + accepted ;
243279
244280 editor . _handleChain ( { text : restText , start : newCaret , length : restText . length } ) ;
245281 editor . _caret ( { start : newCaret , end : newCaret } ) ;
246282 } ) ;
247283 }
248284
249- _autoFillHandler ( event ) {
285+ _autoFillHandler ( event : InputEvent ) : void {
250286 const { editor } = this ;
251287 const inputVal = this . _editorInput ( ) . val ( ) ;
288+
289+ // eslint-disable-next-line no-restricted-globals
252290 this . _inputHandlerTimer = setTimeout ( ( ) => {
253291 if ( this . _isAutoFill ( ) ) {
254292 editor . _maskKeyHandler ( event , ( ) => {
255293 editor . _handleChain ( { text : inputVal , start : 0 , length : inputVal . length } ) ;
256294 } ) ;
295+
257296 editor . _validateMask ( ) ;
258297 }
259298 } ) ;
260299 }
261300
262- _isAutoFill ( ) {
301+ _isAutoFill ( ) : boolean {
263302 const $input = this . _editorInput ( ) ;
264303
265304 if ( browser . webkit ) {
@@ -270,23 +309,23 @@ export default class MaskStrategy {
270309 return false ;
271310 }
272311
273- _clearDragTimer ( ) {
312+ _clearDragTimer ( ) : void {
274313 clearTimeout ( this . _dragTimer ) ;
275314 }
276315
277- _clearTimers ( ) {
316+ _clearTimers ( ) : void {
278317 this . _clearDragTimer ( ) ;
279318 clearTimeout ( this . _caretTimeout ) ;
280319 clearTimeout ( this . _inputHandlerTimer ) ;
281320 }
282321
283- getHandler ( handlerName ) {
322+ getHandler ( handlerName : string ) : ( args : unknown ) => void {
284323 return ( args ) => {
285324 this [ `_${ handlerName } Handler` ] ?.( args ) ;
286325 } ;
287326 }
288327
289- attachEvents ( ) {
328+ attachEvents ( ) : void {
290329 const $input = this . _editorInput ( ) ;
291330
292331 EVENT_NAMES . forEach ( ( eventName ) => {
@@ -297,12 +336,13 @@ export default class MaskStrategy {
297336 this . _attachChangeEventHandler ( ) ;
298337 }
299338
300- detachEvents ( ) {
339+ detachEvents ( ) : void {
301340 this . _clearTimers ( ) ;
341+
302342 EventsEngine . off ( this . _editorInput ( ) , `.${ MASK_EVENT_NAMESPACE } ` ) ;
303343 }
304344
305- clean ( ) {
345+ clean ( ) : void {
306346 this . _clearTimers ( ) ;
307347 }
308348}
0 commit comments