stream-chat-react 13.6.0 → 13.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,7 +24,7 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
24
24
  useEffect(() => {
25
25
  if (!client)
26
26
  return;
27
- const version = "13.6.0";
27
+ const version = "13.6.1";
28
28
  const userAgent = client.getUserAgent();
29
29
  if (!userAgent.includes('stream-chat-react')) {
30
30
  // result looks like: 'stream-chat-react-2.3.2-stream-chat-javascript-client-browser-2.2.2'
@@ -135,14 +135,14 @@ export const getMessageActions = (actions, { canDelete, canEdit, canFlag, canMar
135
135
  messageActionsAfterPermission.push(MESSAGE_ACTIONS.react);
136
136
  }
137
137
  if (channelConfig?.['user_message_reminders'] &&
138
- messageActions.indexOf(MESSAGE_ACTIONS.remindMe)) {
138
+ messageActions.indexOf(MESSAGE_ACTIONS.remindMe) > -1) {
139
139
  messageActionsAfterPermission.push(MESSAGE_ACTIONS.remindMe);
140
140
  }
141
141
  if (canReply && messageActions.indexOf(MESSAGE_ACTIONS.reply) > -1) {
142
142
  messageActionsAfterPermission.push(MESSAGE_ACTIONS.reply);
143
143
  }
144
144
  if (channelConfig?.['user_message_reminders'] &&
145
- messageActions.indexOf(MESSAGE_ACTIONS.saveForLater)) {
145
+ messageActions.indexOf(MESSAGE_ACTIONS.saveForLater) > -1) {
146
146
  messageActionsAfterPermission.push(MESSAGE_ACTIONS.saveForLater);
147
147
  }
148
148
  return messageActionsAfterPermission;
@@ -1,5 +1,5 @@
1
1
  import clsx from 'clsx';
2
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
3
  import Textarea from 'react-textarea-autosize';
4
4
  import { useMessageComposer } from '../MessageInput';
5
5
  import { useComponentContext, useMessageInputContext, useTranslationContext, } from '../../context';
@@ -116,7 +116,6 @@ export const TextareaComposer = ({ className, closeSuggestionsOnClickOutside, co
116
116
  event.preventDefault();
117
117
  }
118
118
  handleSubmit();
119
- textareaRef.current.selectionEnd = 0;
120
119
  }
121
120
  }, [
122
121
  focusedItemIndex,
@@ -135,23 +134,13 @@ export const TextareaComposer = ({ className, closeSuggestionsOnClickOutside, co
135
134
  textComposer.closeSuggestions();
136
135
  }
137
136
  }, [onScroll, textComposer]);
138
- const setSelectionDebounced = useCallback((e) => {
137
+ const setSelection = useCallback((e) => {
139
138
  onSelect?.(e);
140
139
  textComposer.setSelection({
141
140
  end: e.target.selectionEnd,
142
141
  start: e.target.selectionStart,
143
142
  });
144
143
  }, [onSelect, textComposer]);
145
- useEffect(() => {
146
- // FIXME: find the real reason for cursor being set to the end on each change
147
- // This is a workaround to prevent the cursor from jumping
148
- // to the end of the textarea when the user is typing
149
- // at the position that is not at the end of the textarea value.
150
- if (textareaRef.current && !isComposing) {
151
- textareaRef.current.selectionStart = selection.start;
152
- textareaRef.current.selectionEnd = selection.end;
153
- }
154
- }, [text, textareaRef, selection.start, selection.end, isComposing]);
155
144
  useEffect(() => {
156
145
  if (textComposer.suggestions) {
157
146
  setFocusedItemIndex(0);
@@ -163,24 +152,26 @@ export const TextareaComposer = ({ className, closeSuggestionsOnClickOutside, co
163
152
  return;
164
153
  textareaRef.current.focus();
165
154
  }, [attachments, focus, quotedMessage, textareaRef]);
166
- useEffect(() => {
155
+ useLayoutEffect(() => {
167
156
  /**
168
- * The textarea value has to be overridden outside the render cycle so that the events like compositionend can be triggered.
169
- * If we have overridden the value during the component rendering, the compositionend event would not be triggered, and
170
- * it would not be possible to type composed characters (ô).
171
- * On the other hand, just removing the value override via prop (value={text}) would not allow us to change the text based on
172
- * middleware results (e.g. replace characters with emojis)
157
+ * It is important to perform set text and after that the range
158
+ * to prevent cursor reset to the end of the textarea if doing it in separate effects.
173
159
  */
174
160
  const textarea = textareaRef.current;
175
- if (!textarea)
161
+ if (!textarea || isComposing)
162
+ return;
163
+ const length = textarea.value.length;
164
+ const start = Math.max(0, Math.min(selection.start, length));
165
+ const end = Math.max(start, Math.min(selection.end, length));
166
+ if (textarea.selectionStart === start && textarea.selectionEnd === end)
176
167
  return;
177
- textarea.value = text;
178
- }, [textareaRef, text]);
168
+ textarea.setSelectionRange(start, end, 'forward');
169
+ }, [text, selection.start, selection.end, isComposing, textareaRef]);
179
170
  return (React.createElement("div", { className: clsx('rta', 'str-chat__textarea str-chat__message-textarea-react-host', containerClassName, {
180
171
  ['rta--loading']: isLoadingItems,
181
172
  }), ref: containerRef },
182
- React.createElement(Textarea, { ...additionalTextareaProps, ...restTextareaProps, "aria-label": cooldownRemaining ? t('Slow Mode ON') : placeholder, className: clsx('rta__textarea', 'str-chat__textarea__textarea str-chat__message-textarea', className), "data-testid": 'message-input', disabled: !enabled || !!cooldownRemaining, maxRows: maxRows, minRows: minRows, onBlur: onBlur, onChange: changeHandler, onCompositionEnd: onCompositionEnd, onCompositionStart: onCompositionStart, onKeyDown: keyDownHandler, onPaste: onPaste, onScroll: scrollHandler, onSelect: setSelectionDebounced, placeholder: placeholder || t('Type your message'), ref: (ref) => {
173
+ React.createElement(Textarea, { ...additionalTextareaProps, ...restTextareaProps, "aria-label": cooldownRemaining ? t('Slow Mode ON') : placeholder, className: clsx('rta__textarea', 'str-chat__textarea__textarea str-chat__message-textarea', className), "data-testid": 'message-input', disabled: !enabled || !!cooldownRemaining, maxRows: maxRows, minRows: minRows, onBlur: onBlur, onChange: changeHandler, onCompositionEnd: onCompositionEnd, onCompositionStart: onCompositionStart, onKeyDown: keyDownHandler, onPaste: onPaste, onScroll: scrollHandler, onSelect: setSelection, placeholder: placeholder || t('Type your message'), ref: (ref) => {
183
174
  textareaRef.current = ref;
184
- } }),
175
+ }, value: text }),
185
176
  !isComposing && (React.createElement(AutocompleteSuggestionList, { className: listClassName, closeOnClickOutside: closeSuggestionsOnClickOutside, focusedItemIndex: focusedItemIndex, setFocusedItemIndex: setFocusedItemIndex }))));
186
177
  };