import React , { useState , useMemo , useCallback } from 'react' ; import { IStyle , ITextField , mergeStyles , concatStyleSets , Icon } from '@fluentui/react' ; import { sendBoxStyle , sendBoxStyleSet , sendButtonStyle , sendIconStyle } from './styles/SendBox.styles' ; import { BaseCustomStyles } from '../types' ; import { useTheme } from '../theming' ; import { useLocale } from '../localization' ; import { useIdentifiers } from '../identifiers' ; import { InputBoxButton , InputBoxComponent } from './InputBoxComponent' ; const EMPTY_MESSAGE_REGEX = /^\s*$/ ; const MAXIMUM_LENGTH_OF_MESSAGE = 8000 ; /**
 * Fluent styles for  Sendbox .
 *
 *  public export interface SendBoxStylesProps extends BaseCustomStyles { /** Styles for the text field. */ textField ? : IStyle ; /** styles for the text field container */ textFieldContainer ? : IStyle ; /** Styles for the container of the send message icon. */ sendMessageIconContainer ? : IStyle ; /** Styles for the send message icon; These styles will be ignored when a custom send message icon is provided. */ sendMessageIcon ? : IStyle ; /** Styles for the system message; These styles will be ignored when a custom system message component is provided. */ systemMessage ? : IStyle ; } /**
 * Strings of  SendBox that can be overridden.
 *
 *  public export interface SendBoxStrings { /**
     * Placeholder text in SendBox when there is no user input
     */ placeholderText : string ; /**
     * The warning message when send box text length is more than max limit
     */ textTooLong : string ; /**
     * Aria label for send message button
     */ sendButtonAriaLabel : string ; } /**
 * Props for  SendBox .
 *
 *  public export interface SendBoxProps { defaultValue disabled ? : boolean ; /**
     * Optional text for system message below text box
     */ systemMessage ? : string ; /**
     * Optional callback called when message is sent
     */ onSendMessage ? : ( content : string ) => Promise < void > ; /**
     * Optional callback called when user is typing
     */ onTyping ? : ( ) => Promise < void > ; defaultValue onRenderSystemMessage ? : ( systemMessage : string | undefined ) => React . ReactElement ; defaultValue supportNewline ? : boolean ; defaultValue onRenderIcon ? : ( isHover : boolean ) => JSX . Element ; Example styles ? : SendBoxStylesProps ; /**
     * Optional strings to override in component
     */ strings ? : Partial < SendBoxStrings > ; /**
     * boolean to determine if the input box has focus on render or not.
     */ autoFocus ? : 'sendBoxTextField' | false ; } public export const SendBox = ( props ) : JSX . Element => { const { disabled , systemMessage , supportNewline , onSendMessage , onTyping , onRenderIcon , onRenderSystemMessage , styles , autoFocus } = props ; const theme = useTheme ( ) ; const localeStrings = useLocale ( ) . strings . sendBox ; const strings = { ... localeStrings , ... props . strings } ; const ids = useIdentifiers ( ) ; const [ textValue , setTextValue ] = useState ( '' ) ; const [ textValueOverflow , setTextValueOverflow ] = useState ( false ) ; const sendTextFieldRef = React . useRef < ITextField > ( null ) ; const sendMessageOnClick = ( ) : void => { if ( disabled || textValueOverflow ) { return ; } if ( ! EMPTY_MESSAGE_REGEX . test ( textValue ) ) { onSendMessage && onSendMessage ( textValue ) ; setTextValue ( '' ) ; } sendTextFieldRef . current ?. focus ( ) ; } ; const setText = ( event , newValue ? ) : void => { if ( newValue === undefined ) { return ; } if ( newValue . length > MAXIMUM_LENGTH_OF_MESSAGE ) { setTextValueOverflow ( true ) ; } else { setTextValueOverflow ( false ) ; } setTextValue ( newValue ) ; } ; const textTooLongMessage = textValueOverflow ? strings . textTooLong : undefined ; const errorMessage = systemMessage ?? textTooLongMessage ; const mergedSendButtonStyle = useMemo ( ( ) => mergeStyles ( sendButtonStyle , styles ?. sendMessageIconContainer ) , [ styles ?. sendMessageIconContainer ] ) ; const mergedStyles = useMemo ( ( ) => concatStyleSets ( sendBoxStyleSet , styles ) , [ styles ] ) ; const hasText = ! ! textValue ; const mergedSendIconStyle = useMemo ( ( ) => mergeStyles ( sendIconStyle , { color : ! ! errorMessage || ! hasText ? theme . palette . neutralTertiary : theme . palette . themePrimary } , styles ?. sendMessageIcon ) , [ errorMessage , hasText , theme , styles ?. sendMessageIcon ] ) ; const onRenderSendIcon = useCallback ( ( isHover ) => onRenderIcon ? ( onRenderIcon ( isHover ) ) : ( < Icon iconName = { isHover ? 'SendBoxSendHovered' : 'SendBoxSend' } className = { mergedSendIconStyle } / > ) , [ mergedSendIconStyle , onRenderIcon ] ) ; return ( < InputBoxComponent autoFocus = { autoFocus } data - ui - id = { ids . sendboxTextField } inlineChildren = { true } disabled = { disabled } errorMessage = { onRenderSystemMessage ? onRenderSystemMessage ( errorMessage ) : errorMessage } textFieldRef = { sendTextFieldRef } id = "sendbox" inputClassName = { sendBoxStyle } placeholderText = { strings . placeholderText } textValue = { textValue } onChange = { setText } onKeyDown = { ( ) => { onTyping && onTyping ( ) ; } } onEnterKeyDown = { ( ) => { sendMessageOnClick ( ) ; } } styles = { mergedStyles } supportNewline = { supportNewline } maxLength = { MAXIMUM_LENGTH_OF_MESSAGE } > < InputBoxButton onRenderIcon = { onRenderSendIcon } onClick = { ( e ) => { if ( ! textValueOverflow ) { sendMessageOnClick ( ) ; } e . stopPropagation ( ) ; } } id = { 'sendIconWrapper' } className = { mergedSendButtonStyle } ariaLabel = { localeStrings . sendButtonAriaLabel } / > < /InputBoxComponent>); } ;