UNPKG

communication-react-19

Version:

React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)

125 lines 8.71 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { concatStyleSets, mergeStyles, Stack } from '@fluentui/react'; import { ChatMyMessage } from '@fluentui-contrib/react-chat'; import { mergeClasses } from '@fluentui/react-components'; import { useTheme } from '../../../theming/FluentThemeProvider'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; /* @conditional-compile-remove(file-sharing-acs) */ import { useReducer } from 'react'; import { editBoxStyle, editingButtonStyle, editBoxStyleSet, inputBoxIcon } from '../../styles/EditBox.styles'; import { InputBoxComponent } from '../../InputBoxComponent'; import { InputBoxButton } from '../../InputBoxButton'; import { useChatMyMessageStyles } from '../../styles/MessageThread.styles'; /* @conditional-compile-remove(file-sharing-acs) */ import { _AttachmentUploadCards } from '../../Attachment/AttachmentUploadCards'; import { chatMessageFailedTagStyle, editChatMessageFailedTagStyle, chatMessageFailedTagStackItemStyle, editChatMessageButtonsStackStyle, useChatMessageEditContainerStyles } from '../../styles/ChatMessageComponent.styles'; import { MAXIMUM_LENGTH_OF_MESSAGE } from '../../utils/SendBoxUtils'; /* @conditional-compile-remove(file-sharing-acs) */ import { attachmentMetadataReducer, doesMessageContainMultipleAttachments } from '../../utils/ChatMessageComponentAsEditBoxUtils'; import { getMessageState, onRenderCancelIcon, onRenderSubmitIcon, getTextValidationErrorMessage } from '../../utils/ChatMessageComponentAsEditBoxUtils'; /* @conditional-compile-remove(file-sharing-acs) */ import { getMessageWithAttachmentMetadata } from '../../utils/ChatMessageComponentAsEditBoxUtils'; /** * @private */ export const ChatMessageComponentAsEditBox = (props) => { var _a; const { onCancel, onSubmit, strings, message } = props; /* @conditional-compile-remove(mention) */ const { mentionLookupOptions } = props; const [textValue, setTextValue] = useState(message.content || ''); /* @conditional-compile-remove(file-sharing-acs) */ const [attachmentMetadata, handleAttachmentAction] = useReducer(attachmentMetadataReducer, (_a = getMessageWithAttachmentMetadata(message)) !== null && _a !== void 0 ? _a : []); const editTextFieldRef = React.useRef(null); const theme = useTheme(); const messageState = getMessageState(textValue, /* @conditional-compile-remove(file-sharing-acs) */ attachmentMetadata !== null && attachmentMetadata !== void 0 ? attachmentMetadata : []); const submitEnabled = messageState === 'OK'; const editContainerStyles = useChatMessageEditContainerStyles(); const chatMyMessageStyles = useChatMyMessageStyles(); useEffect(() => { var _a; (_a = editTextFieldRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, []); const setText = (event, newValue) => { setTextValue(newValue !== null && newValue !== void 0 ? newValue : ''); }; const textValidationErrorMessage = useMemo(() => { return getTextValidationErrorMessage(messageState, strings.editBoxTextLimit, strings.editBoxEmptyWarningText); }, [ messageState, strings.editBoxTextLimit, strings.editBoxEmptyWarningText, ]); const iconClassName = useCallback((isHover) => { const color = isHover ? theme.palette.accent : theme.palette.neutralSecondary; return mergeStyles(inputBoxIcon, { color }); }, [theme.palette.accent, theme.palette.neutralSecondary]); const onRenderThemedCancelIcon = useCallback((isHover) => { return onRenderCancelIcon(iconClassName(isHover)); }, [iconClassName]); const onRenderThemedSubmitIcon = useCallback((isHover) => { return onRenderSubmitIcon(iconClassName(isHover)); }, [iconClassName]); /* @conditional-compile-remove(file-sharing-acs) */ const hasMultipleAttachments = useMemo(() => { return doesMessageContainMultipleAttachments(message); }, [message]); const editBoxStyles = useMemo(() => { return concatStyleSets(editBoxStyleSet, { textField: { borderColor: theme.palette.themePrimary } }); }, [theme.palette.themePrimary]); /* @conditional-compile-remove(file-sharing-acs) */ const onRenderAttachmentUploads = useCallback(() => { return (!!attachmentMetadata && attachmentMetadata.length > 0 && (React.createElement("div", { style: { margin: '0.25rem' } }, React.createElement(_AttachmentUploadCards, { attachments: attachmentMetadata, onCancelAttachmentUpload: (id) => { // edit box only capable of removing attachments // we need to expand attachment actions // if we want to support more actions e.g. add handleAttachmentAction({ type: 'remove', id }); } })))); }, [attachmentMetadata]); const getContent = () => { return (React.createElement(React.Fragment, null, React.createElement(InputBoxComponent, { "data-ui-id": "edit-box", textFieldRef: editTextFieldRef, inputClassName: editBoxStyle, placeholderText: strings.editBoxPlaceholderText, textValue: textValue, onChange: setText, onKeyDown: (ev) => { if (ev.key === 'ArrowUp' || ev.key === 'ArrowDown') { ev.stopPropagation(); } }, onEnterKeyDown: () => { submitEnabled && onSubmit(textValue, /* @conditional-compile-remove(file-sharing-acs) */ attachmentMetadata); }, supportNewline: false, maxLength: MAXIMUM_LENGTH_OF_MESSAGE, errorMessage: textValidationErrorMessage, styles: editBoxStyles, /* @conditional-compile-remove(mention) */ mentionLookupOptions: mentionLookupOptions }), React.createElement(Stack, { horizontal: true, horizontalAlign: "end", className: editChatMessageButtonsStackStyle, tokens: { childrenGap: '0.25rem' } }, message.failureReason && (React.createElement(Stack.Item, { grow: true, align: "stretch", className: chatMessageFailedTagStackItemStyle }, React.createElement("div", { className: mergeStyles(chatMessageFailedTagStyle(theme), editChatMessageFailedTagStyle) }, message.failureReason))), React.createElement(Stack.Item, { align: "end" }, React.createElement(InputBoxButton, { className: editingButtonStyle, ariaLabel: strings.editBoxCancelButton, tooltipContent: strings.editBoxCancelButton, onRenderIcon: onRenderThemedCancelIcon, onClick: () => { onCancel && onCancel(message.messageId); }, id: 'dismissIconWrapper', "data-testId": "chat-message-edit-box-cancel-button" })), React.createElement(Stack.Item, { align: "end" }, React.createElement(InputBoxButton, { className: editingButtonStyle, ariaLabel: strings.editBoxSubmitButton, tooltipContent: strings.editBoxSubmitButton, onRenderIcon: onRenderThemedSubmitIcon, onClick: (e) => { // it's very important to pass an empty attachment here // so when user remvoes all attachments, UI can reflect it instantly // if you set it to undefined, the attachments pre-edited would still be there // until edit message event is received submitEnabled && onSubmit(textValue, /* @conditional-compile-remove(file-sharing-acs) */ attachmentMetadata); e.stopPropagation(); }, id: 'submitIconWrapper', "data-testId": "chat-message-edit-box-submit-button" }))), /* @conditional-compile-remove(file-sharing-acs) */ onRenderAttachmentUploads())); }; const attached = message.attached === true ? 'center' : message.attached === 'bottom' ? 'bottom' : 'top'; return (React.createElement(ChatMyMessage, { attached: attached, root: { className: mergeClasses(chatMyMessageStyles.root, /* @conditional-compile-remove(file-sharing-acs) */ hasMultipleAttachments ? chatMyMessageStyles.multipleAttachmentsInEditing : undefined) }, body: { className: mergeClasses(editContainerStyles.body, message.failureReason !== undefined ? editContainerStyles.bodyError : editContainerStyles.bodyDefault, attached !== 'top' ? editContainerStyles.bodyAttached : undefined) } }, getContent())); }; //# sourceMappingURL=ChatMessageComponentAsEditBox.js.map