@@ -7,26 +7,34 @@ import type { Properties as DOMComponentProperties } from '@ts/core/widget/dom_c
77import DOMComponent from '@ts/core/widget/dom_component' ;
88import type { OptionChanged } from '@ts/core/widget/types' ;
99
10- import type { EnterKeyEvent } from '../../../ui/text_area' ;
10+ import type { EnterKeyEvent , InputEvent } from '../../../ui/text_area' ;
1111import type dxTextArea from '../../../ui/text_area' ;
1212import TextArea from '../m_text_area' ;
1313
1414const CHAT_MESSAGEBOX_CLASS = 'dx-chat-messagebox' ;
1515const CHAT_MESSAGEBOX_TEXTAREA_CLASS = 'dx-chat-messagebox-textarea' ;
1616const CHAT_MESSAGEBOX_BUTTON_CLASS = 'dx-chat-messagebox-button' ;
1717
18+ export const TYPING_END_DELAY = 2000 ;
19+
1820export type MessageSendEvent =
1921 NativeEventInfo < MessageBox , KeyboardEvent | PointerEvent | MouseEvent | TouchEvent > &
2022 { text ?: string } ;
2123
22- export interface Properties extends DOMComponentProperties < MessageBox > {
23- onMessageSend ?: ( e : MessageSendEvent ) => void ;
24+ export type TypingStartEvent = NativeEventInfo < MessageBox , UIEvent & { target : HTMLInputElement } > ;
2425
26+ export interface Properties extends DOMComponentProperties < MessageBox > {
2527 activeStateEnabled ?: boolean ;
2628
2729 focusStateEnabled ?: boolean ;
2830
2931 hoverStateEnabled ?: boolean ;
32+
33+ onMessageSend ?: ( e : MessageSendEvent ) => void ;
34+
35+ onTypingStart ?: ( e : TypingStartEvent ) => void ;
36+
37+ onTypingEnd ?: ( e : NativeEventInfo < MessageBox > ) => void ;
3038}
3139
3240class MessageBox extends DOMComponent < MessageBox , Properties > {
@@ -36,20 +44,30 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
3644
3745 _messageSendAction ?: ( e : Partial < MessageSendEvent > ) => void ;
3846
47+ _typingStartAction ?: ( e : Partial < TypingStartEvent > ) => void ;
48+
49+ _typingEndAction ?: ( ) => void ;
50+
51+ _typingEndTimeoutId ?: ReturnType < typeof setTimeout > | undefined ;
52+
3953 _getDefaultOptions ( ) : Properties {
4054 return {
4155 ...super . _getDefaultOptions ( ) ,
42- onMessageSend : undefined ,
4356 activeStateEnabled : true ,
4457 focusStateEnabled : true ,
4558 hoverStateEnabled : true ,
59+ onMessageSend : undefined ,
60+ onTypingStart : undefined ,
61+ onTypingEnd : undefined ,
4662 } ;
4763 }
4864
4965 _init ( ) : void {
5066 super . _init ( ) ;
5167
5268 this . _createMessageSendAction ( ) ;
69+ this . _createTypingStartAction ( ) ;
70+ this . _createTypingEndAction ( ) ;
5371 }
5472
5573 _initMarkup ( ) : void {
@@ -81,10 +99,13 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
8199 autoResizeEnabled : true ,
82100 valueChangeEvent : 'input' ,
83101 maxHeight : '8em' ,
84- onInput : ( ) : void => {
102+ onInput : ( e : InputEvent ) : void => {
85103 const shouldButtonBeDisabled = ! this . _isValuableTextEntered ( ) ;
86104
87105 this . _toggleButtonDisableState ( shouldButtonBeDisabled ) ;
106+
107+ this . _triggerTypingStartAction ( e ) ;
108+ this . _updateTypingEndTimeout ( ) ;
88109 } ,
89110 onEnterKey : ( e : EnterKeyEvent ) : void => {
90111 if ( ! e . event ?. shiftKey ) {
@@ -129,15 +150,54 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
129150 _createMessageSendAction ( ) : void {
130151 this . _messageSendAction = this . _createActionByOption (
131152 'onMessageSend' ,
132- { excludeValidators : [ 'disabled' , 'readOnly' ] } ,
153+ { excludeValidators : [ 'disabled' ] } ,
154+ ) ;
155+ }
156+
157+ _createTypingStartAction ( ) : void {
158+ this . _typingStartAction = this . _createActionByOption (
159+ 'onTypingStart' ,
160+ { excludeValidators : [ 'disabled' ] } ,
161+ ) ;
162+ }
163+
164+ _createTypingEndAction ( ) : void {
165+ this . _typingEndAction = this . _createActionByOption (
166+ 'onTypingEnd' ,
167+ { excludeValidators : [ 'disabled' ] } ,
133168 ) ;
134169 }
135170
171+ _triggerTypingStartAction ( e : InputEvent ) : void {
172+ if ( ! this . _typingEndTimeoutId ) {
173+ this . _typingStartAction ?.( { event : e . event } ) ;
174+ }
175+ }
176+
177+ _updateTypingEndTimeout ( ) : void {
178+ clearTimeout ( this . _typingEndTimeoutId ) ;
179+
180+ this . _typingEndTimeoutId = setTimeout ( ( ) => {
181+ this . _typingEndAction ?.( ) ;
182+
183+ this . _clearTypingEndTimeout ( ) ;
184+ } , TYPING_END_DELAY ) ;
185+ }
186+
187+ _clearTypingEndTimeout ( ) : void {
188+ clearTimeout ( this . _typingEndTimeoutId ) ;
189+
190+ this . _typingEndTimeoutId = undefined ;
191+ }
192+
136193 _sendHandler ( e : ClickEvent | EnterKeyEvent ) : void {
137194 if ( ! this . _isValuableTextEntered ( ) ) {
138195 return ;
139196 }
140197
198+ this . _clearTypingEndTimeout ( ) ;
199+ this . _typingEndAction ?.( ) ;
200+
141201 const { text } = this . _textArea . option ( ) ;
142202
143203 this . _textArea . reset ( ) ;
@@ -170,12 +230,27 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
170230 }
171231 case 'onMessageSend' :
172232 this . _createMessageSendAction ( ) ;
233+
234+ break ;
235+ case 'onTypingStart' :
236+ this . _createTypingStartAction ( ) ;
237+
238+ break ;
239+ case 'onTypingEnd' :
240+ this . _createTypingEndAction ( ) ;
241+
173242 break ;
174243 default :
175244 super . _optionChanged ( args ) ;
176245 }
177246 }
178247
248+ _clean ( ) : void {
249+ this . _clearTypingEndTimeout ( ) ;
250+
251+ super . _clean ( ) ;
252+ }
253+
179254 updateInputAria ( emptyViewId : string | null ) : void {
180255 this . _textArea . option ( {
181256 inputAttr : {
0 commit comments