Page MenuHomePhorge

chat-input-text-area.react.js
No OneTemporary

Size
3 KB
Referenced Files
None
Subscribers
None

chat-input-text-area.react.js

// @flow
import invariant from 'invariant';
import * as React from 'react';
import { defaultMaxTextAreaHeight } from './chat-constants.js';
import css from './chat-input-bar.css';
type Props = {
+send?: () => mixed,
+escape?: () => void,
+focus: boolean,
+currentText: string,
+setCurrentText: (text: string) => void,
+onChangePosition: () => void,
+maxHeight?: number,
};
const ChatInputTextArea: React.ComponentType<Props> = React.memo<Props>(
function ChatInputTextArea(props: Props) {
const {
currentText,
focus,
escape,
send,
setCurrentText,
onChangePosition,
maxHeight = defaultMaxTextAreaHeight,
} = props;
const textareaRef = React.useRef<?HTMLTextAreaElement>(null);
const focusAndUpdateText = React.useCallback(() => {
if (!focus) {
return;
}
// We need to call focus() first on Safari, otherwise the cursor
// ends up at the start instead of the end for some reason
const textarea = textareaRef.current;
invariant(textarea, 'textarea should be set');
textarea.focus();
// We reset the textarea to an empty string at the start so that
// the cursor always ends up at the end, even if the text doesn't
// actually change
textarea.value = '';
if (currentText) {
textarea.value = currentText;
}
// The above strategies make sure the cursor is at the end,
// but we also need to make sure that we're scrolled to the bottom
textarea.scrollTop = textarea.scrollHeight;
}, [currentText, focus]);
const updateHeight = React.useCallback(() => {
const textarea = textareaRef.current;
if (textarea) {
textarea.style.height = 'auto';
const newHeight = Math.min(textarea.scrollHeight, maxHeight);
textarea.style.height = `${newHeight}px`;
}
onChangePosition();
}, [maxHeight, onChangePosition]);
React.useEffect(() => {
focusAndUpdateText();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(() => {
updateHeight();
// We want to update the height when the text changes. We can't include
// updateHeight in the dep list because it causes a stack overflow... see
// comments on D8035 for more details
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentText]);
const onKeyDown = (event: SyntheticKeyboardEvent<HTMLTextAreaElement>) => {
if (event.key === 'Escape') {
event.preventDefault();
if (!escape) {
return;
}
escape();
} else if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
if (!send) {
return;
}
send();
}
};
const onChangeMessageText = (
event: SyntheticEvent<HTMLTextAreaElement>,
) => {
setCurrentText(event.currentTarget.value);
updateHeight();
};
return (
<div className={css.inputBarTextInput}>
<textarea
rows="1"
placeholder="Type your message"
value={currentText}
onChange={onChangeMessageText}
onKeyDown={onKeyDown}
ref={textareaRef}
autoFocus
/>
</div>
);
},
);
export default ChatInputTextArea;

File Metadata

Mime Type
text/x-java
Expires
Sun, Dec 7, 7:55 AM (2 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5618354
Default Alt Text
chat-input-text-area.react.js (3 KB)

Event Timeline