Page MenuHomePhabricator

D7822.id26879.diff
No OneTemporary

D7822.id26879.diff

diff --git a/web/chat/chat-input-text-area.react.js b/web/chat/chat-input-text-area.react.js
new file mode 100644
--- /dev/null
+++ b/web/chat/chat-input-text-area.react.js
@@ -0,0 +1,94 @@
+// @flow
+
+import invariant from 'invariant';
+import * as React from 'react';
+
+import css from './chat-input-bar.css';
+
+type Props = {
+ +send?: () => mixed,
+ +escape?: () => void,
+ +focus: boolean,
+ +currentText: string,
+};
+
+const ChatInputTextArea: React.ComponentType<Props> = React.memo<Props>(
+ function ChatInputTextArea(props: Props) {
+ const { currentText, focus, escape, send } = props;
+ const textareaRef = React.useRef(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, 150);
+ textarea.style.height = `${newHeight}px`;
+ }
+ }, []);
+
+ React.useEffect(() => {
+ updateHeight();
+ focusAndUpdateText();
+ // 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 = () => {
+ 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/plain
Expires
Sun, Nov 24, 6:52 AM (19 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2573735
Default Alt Text
D7822.id26879.diff (2 KB)

Event Timeline