stream-chat-react 12.4.1 → 12.5.0

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.
Files changed (180) hide show
  1. package/dist/assets/icons/stream-chat-icons.eot +0 -0
  2. package/dist/assets/icons/stream-chat-icons.svg +4 -0
  3. package/dist/assets/icons/stream-chat-icons.ttf +0 -0
  4. package/dist/assets/icons/stream-chat-icons.woff +0 -0
  5. package/dist/assets/icons/stream-chat-icons.woff2 +0 -0
  6. package/dist/components/Attachment/components/ProgressBar.d.ts +2 -2
  7. package/dist/components/Attachment/components/ProgressBar.js +2 -1
  8. package/dist/components/Channel/Channel.d.ts +1 -1
  9. package/dist/components/Channel/Channel.js +36 -15
  10. package/dist/components/Channel/constants.d.ts +1 -0
  11. package/dist/components/Channel/constants.js +1 -0
  12. package/dist/components/Channel/hooks/useChannelContainerClasses.d.ts +2 -0
  13. package/dist/components/Channel/hooks/useChannelContainerClasses.js +10 -5
  14. package/dist/components/ChannelPreview/utils.js +35 -0
  15. package/dist/components/Chat/hooks/useChat.js +2 -0
  16. package/dist/components/Dialog/DialogAnchor.d.ts +1 -2
  17. package/dist/components/Dialog/DialogMenu.d.ts +3 -0
  18. package/dist/components/Dialog/DialogMenu.js +5 -0
  19. package/dist/components/Dialog/DialogPortal.d.ts +1 -1
  20. package/dist/components/Dialog/DialogPortal.js +4 -12
  21. package/dist/components/Dialog/FormDialog.d.ts +23 -0
  22. package/dist/components/Dialog/FormDialog.js +72 -0
  23. package/dist/components/Dialog/PromptDialog.d.ts +8 -0
  24. package/dist/components/Dialog/PromptDialog.js +7 -0
  25. package/dist/components/DragAndDrop/DragAndDropContainer.d.ts +7 -0
  26. package/dist/components/DragAndDrop/DragAndDropContainer.js +93 -0
  27. package/dist/components/Form/FieldError.d.ts +6 -0
  28. package/dist/components/Form/FieldError.js +3 -0
  29. package/dist/components/Form/SwitchField.d.ts +7 -0
  30. package/dist/components/Form/SwitchField.js +21 -0
  31. package/dist/components/InfiniteScrollPaginator/InfiniteScroll.d.ts +10 -0
  32. package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +10 -0
  33. package/dist/components/InfiniteScrollPaginator/InfiniteScrollPaginator.d.ts +10 -0
  34. package/dist/components/InfiniteScrollPaginator/InfiniteScrollPaginator.js +68 -0
  35. package/dist/components/InfiniteScrollPaginator/hooks/useCursorPaginator.d.ts +18 -0
  36. package/dist/components/InfiniteScrollPaginator/hooks/useCursorPaginator.js +41 -0
  37. package/dist/components/Message/MessageSimple.js +5 -1
  38. package/dist/components/Message/QuotedMessage.js +8 -4
  39. package/dist/components/Message/hooks/useUserRole.js +3 -2
  40. package/dist/components/Message/index.d.ts +1 -0
  41. package/dist/components/MessageInput/AttachmentSelector.d.ts +25 -0
  42. package/dist/components/MessageInput/AttachmentSelector.js +125 -0
  43. package/dist/components/MessageInput/EditMessageForm.js +1 -1
  44. package/dist/components/MessageInput/MessageInput.d.ts +2 -0
  45. package/dist/components/MessageInput/MessageInput.js +9 -4
  46. package/dist/components/MessageInput/MessageInputFlat.js +4 -10
  47. package/dist/components/MessageInput/QuotedMessagePreview.js +7 -3
  48. package/dist/components/MessageInput/hooks/useCreateMessageInputContext.js +3 -1
  49. package/dist/components/MessageInput/hooks/useSubmitHandler.js +4 -1
  50. package/dist/components/MessageInput/index.d.ts +1 -0
  51. package/dist/components/MessageInput/index.js +1 -0
  52. package/dist/components/Modal/ModalHeader.d.ts +8 -0
  53. package/dist/components/Modal/ModalHeader.js +6 -0
  54. package/dist/components/Poll/Poll.d.ts +7 -0
  55. package/dist/components/Poll/Poll.js +8 -0
  56. package/dist/components/Poll/PollActions/AddCommentForm.d.ts +7 -0
  57. package/dist/components/Poll/PollActions/AddCommentForm.js +24 -0
  58. package/dist/components/Poll/PollActions/EndPollDialog.d.ts +6 -0
  59. package/dist/components/Poll/PollActions/EndPollDialog.js +19 -0
  60. package/dist/components/Poll/PollActions/PollAction.d.ts +9 -0
  61. package/dist/components/Poll/PollActions/PollAction.js +5 -0
  62. package/dist/components/Poll/PollActions/PollActions.d.ts +17 -0
  63. package/dist/components/Poll/PollActions/PollActions.js +46 -0
  64. package/dist/components/Poll/PollActions/PollAnswerList.d.ts +7 -0
  65. package/dist/components/Poll/PollActions/PollAnswerList.js +28 -0
  66. package/dist/components/Poll/PollActions/PollOptionsFullList.d.ts +6 -0
  67. package/dist/components/Poll/PollActions/PollOptionsFullList.js +16 -0
  68. package/dist/components/Poll/PollActions/PollResults/PollOptionVotesList.d.ts +7 -0
  69. package/dist/components/Poll/PollActions/PollResults/PollOptionVotesList.js +18 -0
  70. package/dist/components/Poll/PollActions/PollResults/PollOptionWithLatestVotes.d.ts +9 -0
  71. package/dist/components/Poll/PollActions/PollResults/PollOptionWithLatestVotes.js +19 -0
  72. package/dist/components/Poll/PollActions/PollResults/PollOptionWithVotesHeader.d.ts +11 -0
  73. package/dist/components/Poll/PollActions/PollResults/PollOptionWithVotesHeader.js +18 -0
  74. package/dist/components/Poll/PollActions/PollResults/PollResults.d.ts +6 -0
  75. package/dist/components/Poll/PollActions/PollResults/PollResults.js +33 -0
  76. package/dist/components/Poll/PollActions/PollResults/index.d.ts +1 -0
  77. package/dist/components/Poll/PollActions/PollResults/index.js +1 -0
  78. package/dist/components/Poll/PollActions/SuggestPollOptionForm.d.ts +7 -0
  79. package/dist/components/Poll/PollActions/SuggestPollOptionForm.js +37 -0
  80. package/dist/components/Poll/PollActions/index.d.ts +7 -0
  81. package/dist/components/Poll/PollActions/index.js +7 -0
  82. package/dist/components/Poll/PollContent.d.ts +3 -0
  83. package/dist/components/Poll/PollContent.js +18 -0
  84. package/dist/components/Poll/PollCreationDialog/OptionFieldSet.d.ts +9 -0
  85. package/dist/components/Poll/PollCreationDialog/OptionFieldSet.js +70 -0
  86. package/dist/components/Poll/PollCreationDialog/PollCreationDialog.d.ts +5 -0
  87. package/dist/components/Poll/PollCreationDialog/PollCreationDialog.js +87 -0
  88. package/dist/components/Poll/PollCreationDialog/PollCreationDialogControls.d.ts +8 -0
  89. package/dist/components/Poll/PollCreationDialog/PollCreationDialogControls.js +44 -0
  90. package/dist/components/Poll/PollCreationDialog/index.d.ts +1 -0
  91. package/dist/components/Poll/PollCreationDialog/index.js +1 -0
  92. package/dist/components/Poll/PollCreationDialog/types.d.ts +21 -0
  93. package/dist/components/Poll/PollCreationDialog/types.js +1 -0
  94. package/dist/components/Poll/PollHeader.d.ts +3 -0
  95. package/dist/components/Poll/PollHeader.js +31 -0
  96. package/dist/components/Poll/PollOptionList.d.ts +6 -0
  97. package/dist/components/Poll/PollOptionList.js +14 -0
  98. package/dist/components/Poll/PollOptionSelector.d.ts +19 -0
  99. package/dist/components/Poll/PollOptionSelector.js +53 -0
  100. package/dist/components/Poll/PollVote.d.ts +12 -0
  101. package/dist/components/Poll/PollVote.js +31 -0
  102. package/dist/components/Poll/QuotedPoll.d.ts +3 -0
  103. package/dist/components/Poll/QuotedPoll.js +17 -0
  104. package/dist/components/Poll/constants.d.ts +3 -0
  105. package/dist/components/Poll/constants.js +3 -0
  106. package/dist/components/Poll/hooks/index.d.ts +2 -0
  107. package/dist/components/Poll/hooks/index.js +2 -0
  108. package/dist/components/Poll/hooks/useManagePollVotesRealtime.d.ts +4 -0
  109. package/dist/components/Poll/hooks/useManagePollVotesRealtime.js +36 -0
  110. package/dist/components/Poll/hooks/usePollAnswerPagination.d.ts +13 -0
  111. package/dist/components/Poll/hooks/usePollAnswerPagination.js +27 -0
  112. package/dist/components/Poll/hooks/usePollOptionVotesPagination.d.ts +13 -0
  113. package/dist/components/Poll/hooks/usePollOptionVotesPagination.js +27 -0
  114. package/dist/components/Poll/index.d.ts +10 -0
  115. package/dist/components/Poll/index.js +10 -0
  116. package/dist/components/Portal/Portal.d.ts +6 -0
  117. package/dist/components/Portal/Portal.js +14 -0
  118. package/dist/components/ReactFileUtilities/UploadButton.d.ts +11 -1
  119. package/dist/components/ReactFileUtilities/UploadButton.js +22 -4
  120. package/dist/components/Thread/Thread.js +1 -1
  121. package/dist/components/index.d.ts +2 -0
  122. package/dist/components/index.js +1 -0
  123. package/dist/context/AttachmentSelectorContext.d.ts +8 -0
  124. package/dist/context/AttachmentSelectorContext.js +6 -0
  125. package/dist/context/ComponentContext.d.ts +21 -5
  126. package/dist/context/PollContext.d.ts +11 -0
  127. package/dist/context/PollContext.js +7 -0
  128. package/dist/context/index.d.ts +1 -0
  129. package/dist/context/index.js +1 -0
  130. package/dist/css/v2/index.css +2 -2
  131. package/dist/css/v2/index.layout.css +2 -2
  132. package/dist/experimental/index.browser.cjs +129 -117
  133. package/dist/experimental/index.browser.cjs.map +4 -4
  134. package/dist/experimental/index.node.cjs +129 -117
  135. package/dist/experimental/index.node.cjs.map +4 -4
  136. package/dist/i18n/Streami18n.d.ts +45 -0
  137. package/dist/i18n/de.json +70 -25
  138. package/dist/i18n/en.json +46 -1
  139. package/dist/i18n/es.json +74 -25
  140. package/dist/i18n/fr.json +83 -34
  141. package/dist/i18n/hi.json +54 -9
  142. package/dist/i18n/it.json +75 -26
  143. package/dist/i18n/ja.json +46 -5
  144. package/dist/i18n/ko.json +46 -5
  145. package/dist/i18n/nl.json +59 -14
  146. package/dist/i18n/pt.json +66 -17
  147. package/dist/i18n/ru.json +66 -13
  148. package/dist/i18n/tr.json +77 -32
  149. package/dist/index.browser.cjs +4226 -1857
  150. package/dist/index.browser.cjs.map +4 -4
  151. package/dist/index.node.cjs +4166 -1770
  152. package/dist/index.node.cjs.map +4 -4
  153. package/dist/scss/v2/AttachmentPreviewList/AttachmentPreviewList-layout.scss +2 -2
  154. package/dist/scss/v2/AudioRecorder/AudioRecorder-layout.scss +64 -14
  155. package/dist/scss/v2/AudioRecorder/AudioRecorder-theme.scss +11 -1
  156. package/dist/scss/v2/Avatar/Avatar-layout.scss +4 -0
  157. package/dist/scss/v2/ChannelList/ChannelList-layout.scss +15 -0
  158. package/dist/scss/v2/Dialog/Dialog-layout.scss +54 -0
  159. package/dist/scss/v2/Dialog/Dialog-theme.scss +103 -0
  160. package/dist/scss/v2/DragAndDropContainer/DragAmdDropContainer-layout.scss +5 -0
  161. package/dist/scss/v2/DragAndDropContainer/DragAndDropContainer-theme.scss +47 -0
  162. package/dist/scss/v2/Form/Form-layout.scss +9 -0
  163. package/dist/scss/v2/Form/Form-theme.scss +17 -0
  164. package/dist/scss/v2/Icon/Icon-layout.scss +6 -1
  165. package/dist/scss/v2/InfiniteScrollPaginator/InfiniteScrollPaginator-layout.scss +4 -0
  166. package/dist/scss/v2/MessageActionsBox/MessageActionsBox-layout.scss +0 -9
  167. package/dist/scss/v2/MessageInput/MessageInput-layout.scss +29 -4
  168. package/dist/scss/v2/MessageInput/MessageInput-theme.scss +61 -0
  169. package/dist/scss/v2/Modal/Modal-layout.scss +31 -0
  170. package/dist/scss/v2/Modal/Modal-theme.scss +6 -0
  171. package/dist/scss/v2/Notification/MessageNotification-layout.scss +1 -1
  172. package/dist/scss/v2/Poll/Poll-layout.scss +488 -0
  173. package/dist/scss/v2/Poll/Poll-theme.scss +206 -0
  174. package/dist/scss/v2/_base.scss +4 -0
  175. package/dist/scss/v2/_global-theme-variables.scss +1 -1
  176. package/dist/scss/v2/_icons.scss +7 -0
  177. package/dist/scss/v2/index.layout.scss +4 -0
  178. package/dist/scss/v2/index.scss +4 -0
  179. package/dist/types/types.d.ts +6 -0
  180. package/package.json +4 -4
@@ -41,6 +41,10 @@
41
41
  <glyph glyph-name="send" unicode="&#xe810;" d="M167-67l833 417-833 417 0-324 595-93-595-93 0-324z" horiz-adv-x="1000" />
42
42
 
43
43
  <glyph glyph-name="attach" unicode="&#xe811;" d="M542 558h-84v-166h-166v-84h166v-166h84v166h166v84h-166v166z m-42 209c-230 0-417-187-417-417 0-230 187-417 417-417 230 0 417 187 417 417 0 230-187 417-417 417z m0-750c-184 0-333 149-333 333 0 184 149 333 333 333 184 0 333-149 333-333 0-184-149-333-333-333z" horiz-adv-x="1000" />
44
+
45
+ <glyph glyph-name="mic" unicode="&#xe812;" d="M350 225c83 0 150 67 150 150v300c0 83-67 150-150 150-83 0-150-67-150-150v-300c0-83 67-150 150-150z m250 150c0-138-112-250-250-250-138 0-250 112-250 250h-100c0-176 131-321 300-346v-154h100v154c170 25 300 170 300 346h-100z" horiz-adv-x="700" />
46
+
47
+ <glyph glyph-name="bin" unicode="&#xe813;" d="M250 58c0-45 38-83 83-83h334c46 0 83 38 83 83v417c0 46-37 83-83 83h-334c-45 0-83-37-83-83v-417z m500 625h-104l-30 30c-7 7-18 12-29 12h-174c-11 0-22-5-29-12l-30-30h-104c-23 0-42-18-42-41 0-23 19-42 42-42h500c23 0 42 19 42 42 0 23-19 41-42 41z" horiz-adv-x="1000" />
44
48
  </font>
45
49
  </defs>
46
50
  </svg>
@@ -2,5 +2,5 @@ import React from 'react';
2
2
  export type ProgressBarProps = {
3
3
  /** Progress expressed in fractional number value btw 0 and 100. */
4
4
  progress: number;
5
- } & Pick<React.ComponentProps<'div'>, 'onClick'>;
6
- export declare const ProgressBar: ({ onClick, progress }: ProgressBarProps) => React.JSX.Element;
5
+ } & Pick<React.ComponentProps<'div'>, 'className' | 'onClick'>;
6
+ export declare const ProgressBar: ({ className, onClick, progress }: ProgressBarProps) => React.JSX.Element;
@@ -1,5 +1,6 @@
1
+ import clsx from 'clsx';
1
2
  import React from 'react';
2
- export const ProgressBar = ({ onClick, progress }) => (React.createElement("div", { className: 'str-chat__message-attachment-audio-widget--progress-track', "data-progress": progress, "data-testid": 'audio-progress', onClick: onClick, role: 'progressbar', style: {
3
+ export const ProgressBar = ({ className, onClick, progress }) => (React.createElement("div", { className: clsx('str-chat__message-attachment-audio-widget--progress-track', className), "data-progress": progress, "data-testid": 'audio-progress', onClick: onClick, role: 'progressbar', style: {
3
4
  '--str-chat__message-attachment-audio-widget-progress': progress + '%',
4
5
  } },
5
6
  React.createElement("div", { className: 'str-chat__message-attachment-audio-widget--progress-slider', style: { left: `${progress}px` } })));
@@ -6,7 +6,7 @@ import { ComponentContextValue, StreamMessage } from '../../context';
6
6
  import type { MessageInputProps } from '../MessageInput';
7
7
  import type { ChannelUnreadUiState, CustomTrigger, DefaultStreamChatGenerics, GiphyVersions, ImageAttachmentSizeHandler, SendMessageOptions, UpdateMessageOptions, VideoAttachmentSizeHandler } from '../../types/types';
8
8
  import type { URLEnrichmentConfig } from '../MessageInput/hooks/useLinkPreviews';
9
- type ChannelPropsForwardedToComponentContext<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = Pick<ComponentContextValue<StreamChatGenerics>, 'Attachment' | 'AttachmentPreviewList' | 'AudioRecorder' | 'AutocompleteSuggestionItem' | 'AutocompleteSuggestionList' | 'Avatar' | 'BaseImage' | 'CooldownTimer' | 'CustomMessageActionsList' | 'DateSeparator' | 'EditMessageInput' | 'EmojiPicker' | 'emojiSearchIndex' | 'EmptyStateIndicator' | 'FileUploadIcon' | 'GiphyPreviewMessage' | 'HeaderComponent' | 'Input' | 'LinkPreviewList' | 'LoadingIndicator' | 'Message' | 'MessageActions' | 'MessageBouncePrompt' | 'MessageDeleted' | 'MessageListNotifications' | 'MessageListMainPanel' | 'MessageNotification' | 'MessageOptions' | 'MessageRepliesCountButton' | 'MessageStatus' | 'MessageSystem' | 'MessageTimestamp' | 'ModalGallery' | 'PinIndicator' | 'QuotedMessage' | 'QuotedMessagePreview' | 'reactionOptions' | 'ReactionSelector' | 'ReactionsList' | 'SendButton' | 'StartRecordingAudioButton' | 'ThreadHead' | 'ThreadHeader' | 'ThreadStart' | 'Timestamp' | 'TriggerProvider' | 'TypingIndicator' | 'UnreadMessagesNotification' | 'UnreadMessagesSeparator' | 'VirtualMessage'>;
9
+ type ChannelPropsForwardedToComponentContext<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = Pick<ComponentContextValue<StreamChatGenerics>, 'Attachment' | 'AttachmentPreviewList' | 'AttachmentSelector' | 'AttachmentSelectorInitiationButtonContents' | 'AudioRecorder' | 'AutocompleteSuggestionItem' | 'AutocompleteSuggestionList' | 'Avatar' | 'BaseImage' | 'CooldownTimer' | 'CustomMessageActionsList' | 'DateSeparator' | 'EditMessageInput' | 'EmojiPicker' | 'emojiSearchIndex' | 'EmptyStateIndicator' | 'FileUploadIcon' | 'GiphyPreviewMessage' | 'HeaderComponent' | 'Input' | 'LinkPreviewList' | 'LoadingIndicator' | 'Message' | 'MessageActions' | 'MessageBouncePrompt' | 'MessageDeleted' | 'MessageListNotifications' | 'MessageListMainPanel' | 'MessageNotification' | 'MessageOptions' | 'MessageRepliesCountButton' | 'MessageStatus' | 'MessageSystem' | 'MessageTimestamp' | 'ModalGallery' | 'PinIndicator' | 'PollActions' | 'PollContent' | 'PollCreationDialog' | 'PollHeader' | 'PollOptionSelector' | 'QuotedMessage' | 'QuotedMessagePreview' | 'QuotedPoll' | 'reactionOptions' | 'ReactionSelector' | 'ReactionsList' | 'SendButton' | 'StartRecordingAudioButton' | 'ThreadHead' | 'ThreadHeader' | 'ThreadStart' | 'Timestamp' | 'TriggerProvider' | 'TypingIndicator' | 'UnreadMessagesNotification' | 'UnreadMessagesSeparator' | 'VirtualMessage'>;
10
10
  export type ChannelProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, V extends CustomTrigger = CustomTrigger> = ChannelPropsForwardedToComponentContext<StreamChatGenerics> & {
11
11
  /** List of accepted file types */
12
12
  acceptedFiles?: string[];
@@ -16,30 +16,35 @@ import { DropzoneProvider } from '../MessageInput/DropzoneProvider';
16
16
  import { ChannelActionProvider, ChannelStateProvider, TypingProvider, useChatContext, useTranslationContext, WithComponents, } from '../../context';
17
17
  import { DEFAULT_HIGHLIGHT_DURATION, DEFAULT_INITIAL_CHANNEL_PAGE_SIZE, DEFAULT_JUMP_TO_PAGE_SIZE, DEFAULT_NEXT_CHANNEL_PAGE_SIZE, DEFAULT_THREAD_PAGE_SIZE, } from '../../constants/limits';
18
18
  import { hasMoreMessagesProbably } from '../MessageList';
19
- import { useChannelContainerClasses } from './hooks/useChannelContainerClasses';
19
+ import { getChatContainerClass, useChannelContainerClasses, useImageFlagEmojisOnWindowsClass, } from './hooks/useChannelContainerClasses';
20
20
  import { findInMsgSetByDate, findInMsgSetById, makeAddNotifications } from './utils';
21
21
  import { getChannel } from '../../utils';
22
22
  import { getImageAttachmentConfiguration, getVideoAttachmentConfiguration, } from '../Attachment/attachment-sizing';
23
23
  import { useThreadContext } from '../Threads';
24
+ import { CHANNEL_CONTAINER_ID } from './constants';
24
25
  const isUserResponseArray = (output) => output[0]?.id != null;
25
- const UnMemoizedChannel = (props) => {
26
- const { channel: propsChannel, EmptyPlaceholder = null, LoadingErrorIndicator, LoadingIndicator = DefaultLoadingIndicator, } = props;
27
- const { channel: contextChannel, channelsQueryState, customClasses, theme, } = useChatContext('Channel');
26
+ const ChannelContainer = ({ children, className: additionalClassName, ...props }) => {
27
+ const { customClasses, theme } = useChatContext('Channel');
28
28
  const { channelClass, chatClass } = useChannelContainerClasses({
29
29
  customClasses,
30
30
  });
31
+ const className = clsx(chatClass, theme, channelClass, additionalClassName);
32
+ return (React.createElement("div", { id: CHANNEL_CONTAINER_ID, ...props, className: className }, children));
33
+ };
34
+ const UnMemoizedChannel = (props) => {
35
+ const { channel: propsChannel, EmptyPlaceholder = null, LoadingErrorIndicator, LoadingIndicator = DefaultLoadingIndicator, } = props;
36
+ const { channel: contextChannel, channelsQueryState } = useChatContext('Channel');
31
37
  const channel = propsChannel || contextChannel;
32
- const className = clsx(chatClass, theme, channelClass);
33
38
  if (channelsQueryState.queryInProgress === 'reload' && LoadingIndicator) {
34
- return (React.createElement("div", { className: className },
39
+ return (React.createElement(ChannelContainer, null,
35
40
  React.createElement(LoadingIndicator, null)));
36
41
  }
37
42
  if (channelsQueryState.error && LoadingErrorIndicator) {
38
- return (React.createElement("div", { className: className },
43
+ return (React.createElement(ChannelContainer, null,
39
44
  React.createElement(LoadingErrorIndicator, { error: channelsQueryState.error })));
40
45
  }
41
46
  if (!channel?.cid) {
42
- return React.createElement("div", { className: className }, EmptyPlaceholder);
47
+ return React.createElement(ChannelContainer, null, EmptyPlaceholder);
43
48
  }
44
49
  return React.createElement(ChannelInner, { ...props, channel: channel, key: channel.cid });
45
50
  };
@@ -48,9 +53,10 @@ const ChannelInner = (props) => {
48
53
  const channelQueryOptions = useMemo(() => defaultsDeep(propChannelQueryOptions, {
49
54
  messages: { limit: DEFAULT_INITIAL_CHANNEL_PAGE_SIZE },
50
55
  }), [propChannelQueryOptions]);
51
- const { client, customClasses, latestMessageDatesByChannels, mutes, theme, } = useChatContext('Channel');
56
+ const { client, customClasses, latestMessageDatesByChannels, mutes, } = useChatContext('Channel');
52
57
  const { t } = useTranslationContext('Channel');
53
- const { channelClass, chatClass, chatContainerClass, windowsEmojiClass, } = useChannelContainerClasses({ customClasses });
58
+ const chatContainerClass = getChatContainerClass(customClasses?.chatContainer);
59
+ const windowsEmojiClass = useImageFlagEmojisOnWindowsClass();
54
60
  const thread = useThreadContext();
55
61
  const [channelConfig, setChannelConfig] = useState(channel.getConfig());
56
62
  const [notifications, setNotifications] = useState([]);
@@ -730,6 +736,8 @@ const ChannelInner = (props) => {
730
736
  const componentContextValue = useMemo(() => ({
731
737
  Attachment: props.Attachment,
732
738
  AttachmentPreviewList: props.AttachmentPreviewList,
739
+ AttachmentSelector: props.AttachmentSelector,
740
+ AttachmentSelectorInitiationButtonContents: props.AttachmentSelectorInitiationButtonContents,
733
741
  AudioRecorder: props.AudioRecorder,
734
742
  AutocompleteSuggestionItem: props.AutocompleteSuggestionItem,
735
743
  AutocompleteSuggestionList: props.AutocompleteSuggestionList,
@@ -761,8 +769,14 @@ const ChannelInner = (props) => {
761
769
  MessageTimestamp: props.MessageTimestamp,
762
770
  ModalGallery: props.ModalGallery,
763
771
  PinIndicator: props.PinIndicator,
772
+ PollActions: props.PollActions,
773
+ PollContent: props.PollContent,
774
+ PollCreationDialog: props.PollCreationDialog,
775
+ PollHeader: props.PollHeader,
776
+ PollOptionSelector: props.PollOptionSelector,
764
777
  QuotedMessage: props.QuotedMessage,
765
778
  QuotedMessagePreview: props.QuotedMessagePreview,
779
+ QuotedPoll: props.QuotedPoll,
766
780
  reactionOptions: props.reactionOptions,
767
781
  ReactionSelector: props.ReactionSelector,
768
782
  ReactionsList: props.ReactionsList,
@@ -780,6 +794,8 @@ const ChannelInner = (props) => {
780
794
  }), [
781
795
  props.Attachment,
782
796
  props.AttachmentPreviewList,
797
+ props.AttachmentSelector,
798
+ props.AttachmentSelectorInitiationButtonContents,
783
799
  props.AudioRecorder,
784
800
  props.AutocompleteSuggestionItem,
785
801
  props.AutocompleteSuggestionList,
@@ -810,8 +826,14 @@ const ChannelInner = (props) => {
810
826
  props.MessageTimestamp,
811
827
  props.ModalGallery,
812
828
  props.PinIndicator,
829
+ props.PollActions,
830
+ props.PollContent,
831
+ props.PollCreationDialog,
832
+ props.PollHeader,
833
+ props.PollOptionSelector,
813
834
  props.QuotedMessage,
814
835
  props.QuotedMessagePreview,
836
+ props.QuotedPoll,
815
837
  props.ReactionSelector,
816
838
  props.ReactionsList,
817
839
  props.SendButton,
@@ -831,20 +853,19 @@ const ChannelInner = (props) => {
831
853
  const typingContextValue = useCreateTypingContext({
832
854
  typing,
833
855
  });
834
- const className = clsx(chatClass, theme, channelClass);
835
856
  if (state.error) {
836
- return (React.createElement("div", { className: className },
857
+ return (React.createElement(ChannelContainer, null,
837
858
  React.createElement(LoadingErrorIndicator, { error: state.error })));
838
859
  }
839
860
  if (state.loading) {
840
- return (React.createElement("div", { className: className },
861
+ return (React.createElement(ChannelContainer, null,
841
862
  React.createElement(LoadingIndicator, null)));
842
863
  }
843
864
  if (!channel.watch) {
844
- return (React.createElement("div", { className: className },
865
+ return (React.createElement(ChannelContainer, null,
845
866
  React.createElement("div", null, t('Channel Missing'))));
846
867
  }
847
- return (React.createElement("div", { className: clsx(className, windowsEmojiClass) },
868
+ return (React.createElement(ChannelContainer, { className: windowsEmojiClass },
848
869
  React.createElement(ChannelStateProvider, { value: channelStateContextValue },
849
870
  React.createElement(ChannelActionProvider, { value: channelActionContextValue },
850
871
  React.createElement(WithComponents, { overrides: componentContextValue },
@@ -0,0 +1 @@
1
+ export declare const CHANNEL_CONTAINER_ID = "str-chat__channel";
@@ -0,0 +1 @@
1
+ export const CHANNEL_CONTAINER_ID = 'str-chat__channel';
@@ -1,5 +1,7 @@
1
1
  import type { ChatContextValue } from '../../../context/ChatContext';
2
2
  import type { DefaultStreamChatGenerics } from '../../../types/types';
3
+ export declare const useImageFlagEmojisOnWindowsClass: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>() => "" | "str-chat--windows-flags";
4
+ export declare const getChatContainerClass: (customClass?: string) => string;
3
5
  export declare const useChannelContainerClasses: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ customClasses, }: Pick<ChatContextValue, 'customClasses'>) => {
4
6
  channelClass: string;
5
7
  chatClass: string;
@@ -1,12 +1,17 @@
1
1
  import { useChatContext } from '../../../context/ChatContext';
2
- export const useChannelContainerClasses = ({ customClasses, }) => {
2
+ export const useImageFlagEmojisOnWindowsClass = () => {
3
3
  const { useImageFlagEmojisOnWindows } = useChatContext('Channel');
4
+ return useImageFlagEmojisOnWindows && navigator.userAgent.match(/Win/)
5
+ ? 'str-chat--windows-flags'
6
+ : '';
7
+ };
8
+ export const getChatContainerClass = (customClass) => customClass ?? 'str-chat__container';
9
+ export const useChannelContainerClasses = ({ customClasses, }) => {
10
+ const windowsEmojiClass = useImageFlagEmojisOnWindowsClass();
4
11
  return {
5
12
  channelClass: customClasses?.channel ?? 'str-chat__channel',
6
13
  chatClass: customClasses?.chat ?? 'str-chat',
7
- chatContainerClass: customClasses?.chatContainer ?? 'str-chat__container',
8
- windowsEmojiClass: useImageFlagEmojisOnWindows && navigator.userAgent.match(/Win/)
9
- ? 'str-chat--windows-flags'
10
- : '',
14
+ chatContainerClass: getChatContainerClass(customClasses?.chatContainer),
15
+ windowsEmojiClass,
11
16
  };
12
17
  };
@@ -1,16 +1,51 @@
1
1
  import React from 'react';
2
2
  import ReactMarkdown from 'react-markdown';
3
3
  export const renderPreviewText = (text) => React.createElement(ReactMarkdown, { skipHtml: true }, text);
4
+ const getLatestPollVote = (latestVotesByOption) => {
5
+ let latestVote;
6
+ for (const optionVotes of Object.values(latestVotesByOption)) {
7
+ optionVotes.forEach((vote) => {
8
+ if (latestVote && new Date(latestVote.updated_at) >= new Date(vote.created_at))
9
+ return;
10
+ latestVote = vote;
11
+ });
12
+ }
13
+ return latestVote;
14
+ };
4
15
  export const getLatestMessagePreview = (channel, t, userLanguage = 'en') => {
5
16
  const latestMessage = channel.state.latestMessages[channel.state.latestMessages.length - 1];
6
17
  const previewTextToRender = latestMessage?.i18n?.[`${userLanguage}_text`] ||
7
18
  latestMessage?.text;
19
+ const poll = latestMessage?.poll;
8
20
  if (!latestMessage) {
9
21
  return t('Nothing yet...');
10
22
  }
11
23
  if (latestMessage.deleted_at) {
12
24
  return t('Message deleted');
13
25
  }
26
+ if (poll) {
27
+ if (!poll.vote_count) {
28
+ const createdBy = poll.created_by?.id === channel.getClient().userID
29
+ ? t('You')
30
+ : poll.created_by?.name ?? t('Poll');
31
+ return t('📊 {{createdBy}} created: {{ pollName}}', {
32
+ createdBy,
33
+ pollName: poll.name,
34
+ });
35
+ }
36
+ else {
37
+ const latestVote = getLatestPollVote(poll.latest_votes_by_option);
38
+ const option = latestVote && poll.options.find((opt) => opt.id === latestVote.option_id);
39
+ if (option && latestVote) {
40
+ return t('📊 {{votedBy}} voted: {{pollOptionText}}', {
41
+ pollOptionText: option.text,
42
+ votedBy: latestVote?.user?.id === channel.getClient().userID
43
+ ? t('You')
44
+ : latestVote.user?.name ?? t('Poll'),
45
+ });
46
+ }
47
+ }
48
+ }
14
49
  if (previewTextToRender) {
15
50
  return renderPreviewText(previewTextToRender);
16
51
  }
@@ -31,8 +31,10 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
31
31
  client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
32
32
  }
33
33
  client.threads.registerSubscriptions();
34
+ client.polls.registerSubscriptions();
34
35
  return () => {
35
36
  client.threads.unregisterSubscriptions();
37
+ client.polls.unregisterSubscriptions();
36
38
  };
37
39
  }, [client]);
38
40
  useEffect(() => {
@@ -16,10 +16,9 @@ export declare function useDialogAnchor<T extends HTMLElement>({ open, placement
16
16
  [key: string]: React.CSSProperties;
17
17
  };
18
18
  };
19
- type DialogAnchorProps = PropsWithChildren<Partial<DialogAnchorOptions>> & {
19
+ export type DialogAnchorProps = PropsWithChildren<Partial<DialogAnchorOptions>> & {
20
20
  id: string;
21
21
  focus?: boolean;
22
22
  trapFocus?: boolean;
23
23
  } & ComponentProps<'div'>;
24
24
  export declare const DialogAnchor: ({ children, className, focus, id, placement, referenceElement, trapFocus, ...restDivProps }: DialogAnchorProps) => React.JSX.Element | null;
25
- export {};
@@ -0,0 +1,3 @@
1
+ import React, { ComponentProps } from 'react';
2
+ export type DialogMenuButtonProps = ComponentProps<'button'>;
3
+ export declare const DialogMenuButton: ({ children, className, ...props }: DialogMenuButtonProps) => React.JSX.Element;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import clsx from 'clsx';
3
+ export const DialogMenuButton = ({ children, className, ...props }) => (React.createElement("button", { className: clsx('str-chat__dialog-menu__button', className), ...props },
4
+ React.createElement("div", { className: 'str-chat__dialog-menu__button-icon' }),
5
+ React.createElement("div", { className: 'str-chat__dialog-menu__button-text' }, children)));
@@ -3,5 +3,5 @@ export declare const DialogPortalDestination: () => React.JSX.Element;
3
3
  type DialogPortalEntryProps = {
4
4
  dialogId: string;
5
5
  };
6
- export declare const DialogPortalEntry: ({ children, dialogId, }: PropsWithChildren<DialogPortalEntryProps>) => React.ReactPortal | null;
6
+ export declare const DialogPortalEntry: ({ children, dialogId, }: PropsWithChildren<DialogPortalEntryProps>) => React.JSX.Element;
7
7
  export {};
@@ -1,6 +1,6 @@
1
- import React, { useLayoutEffect, useState } from 'react';
2
- import { createPortal } from 'react-dom';
1
+ import React, { useCallback } from 'react';
3
2
  import { useDialogIsOpen, useOpenedDialogCount } from './hooks';
3
+ import { Portal } from '../Portal/Portal';
4
4
  import { useDialogManager } from '../../context';
5
5
  export const DialogPortalDestination = () => {
6
6
  const { dialogManager } = useDialogManager();
@@ -12,14 +12,6 @@ export const DialogPortalDestination = () => {
12
12
  export const DialogPortalEntry = ({ children, dialogId, }) => {
13
13
  const { dialogManager } = useDialogManager();
14
14
  const dialogIsOpen = useDialogIsOpen(dialogId);
15
- const [portalDestination, setPortalDestination] = useState(null);
16
- useLayoutEffect(() => {
17
- const destination = document.querySelector(`div[data-str-chat__portal-id="${dialogManager.id}"]`);
18
- if (!destination)
19
- return;
20
- setPortalDestination(destination);
21
- }, [dialogManager, dialogIsOpen]);
22
- if (!portalDestination)
23
- return null;
24
- return createPortal(children, portalDestination);
15
+ const getPortalDestination = useCallback(() => document.querySelector(`div[data-str-chat__portal-id="${dialogManager.id}"]`), [dialogManager.id]);
16
+ return (React.createElement(Portal, { getPortalDestination: getPortalDestination, isOpen: dialogIsOpen }, children));
25
17
  };
@@ -0,0 +1,23 @@
1
+ import React, { ComponentProps } from 'react';
2
+ type FormElements = 'input' | 'textarea';
3
+ type FieldId = string;
4
+ type Validator = (value: string | readonly string[] | number | boolean | undefined) => Error | undefined;
5
+ export type FieldConfig = {
6
+ element: FormElements;
7
+ props: ComponentProps<FormElements>;
8
+ label?: React.ReactNode;
9
+ validator?: Validator;
10
+ };
11
+ type TextInputFormProps<F extends FormValue<Record<FieldId, FieldConfig>>> = {
12
+ close: () => void;
13
+ fields: Record<FieldId, FieldConfig>;
14
+ onSubmit: (formValue: F) => Promise<void>;
15
+ className?: string;
16
+ shouldDisableSubmitButton?: (formValue: F) => boolean;
17
+ title?: string;
18
+ };
19
+ type FormValue<F extends Record<FieldId, FieldConfig>> = {
20
+ [K in keyof F]: F[K]['props']['value'];
21
+ };
22
+ export declare const FormDialog: <F extends FormValue<Record<string, FieldConfig>> = FormValue<Record<string, FieldConfig>>>({ className, close, fields, onSubmit, shouldDisableSubmitButton, title, }: TextInputFormProps<F>) => React.JSX.Element;
23
+ export {};
@@ -0,0 +1,72 @@
1
+ import React, { useCallback, useState, } from 'react';
2
+ import clsx from 'clsx';
3
+ import { FieldError } from '../Form/FieldError';
4
+ import { useTranslationContext } from '../../context';
5
+ export const FormDialog = ({ className, close, fields, onSubmit, shouldDisableSubmitButton, title, }) => {
6
+ const { t } = useTranslationContext();
7
+ const [fieldErrors, setFieldErrors] = useState({});
8
+ const [value, setValue] = useState(() => {
9
+ let acc = {};
10
+ for (const [id, config] of Object.entries(fields)) {
11
+ acc = { ...acc, [id]: config.props.value };
12
+ }
13
+ return acc;
14
+ });
15
+ const handleChange = useCallback((event) => {
16
+ const fieldId = event.target.id;
17
+ const fieldConfig = fields[fieldId];
18
+ if (!fieldConfig)
19
+ return;
20
+ const error = fieldConfig.validator?.(event.target.value);
21
+ if (error) {
22
+ setFieldErrors((prev) => ({ [fieldId]: error, ...prev }));
23
+ }
24
+ else {
25
+ setFieldErrors((prev) => {
26
+ delete prev[fieldId];
27
+ return prev;
28
+ });
29
+ }
30
+ setValue((prev) => ({ ...prev, [fieldId]: event.target.value }));
31
+ if (!fieldConfig.props.onChange)
32
+ return;
33
+ if (fieldConfig.element === 'input') {
34
+ fieldConfig.props.onChange(event);
35
+ }
36
+ else if (fieldConfig.element === 'textarea') {
37
+ fieldConfig.props.onChange(event);
38
+ }
39
+ }, [fields]);
40
+ const handleSubmit = async () => {
41
+ if (!Object.keys(value).length)
42
+ return;
43
+ const errors = {};
44
+ for (const [id, fieldValue] of Object.entries(value)) {
45
+ const thisFieldError = fields[id].validator?.(fieldValue);
46
+ if (thisFieldError) {
47
+ errors[id] = thisFieldError;
48
+ }
49
+ }
50
+ if (Object.keys(errors).length) {
51
+ setFieldErrors(errors);
52
+ return;
53
+ }
54
+ await onSubmit(value);
55
+ close();
56
+ };
57
+ return (React.createElement("div", { className: clsx('str-chat__dialog str-chat__dialog--form', className) },
58
+ React.createElement("div", { className: 'str-chat__dialog__body' },
59
+ title && React.createElement("div", { className: 'str-chat__dialog__title' }, title),
60
+ React.createElement("form", { autoComplete: 'off' }, Object.entries(fields).map(([id, fieldConfig]) => (React.createElement("div", { className: 'str-chat__dialog__field', key: `dialog-field-${id}` },
61
+ fieldConfig.label && (React.createElement("label", { className: clsx(`str-chat__dialog__title str-chat__dialog__title--${id}`), htmlFor: id }, fieldConfig.label)),
62
+ React.createElement(fieldConfig.element, {
63
+ id,
64
+ ...fieldConfig.props,
65
+ onChange: handleChange,
66
+ value: value[id],
67
+ }),
68
+ React.createElement(FieldError, { text: fieldErrors[id]?.message })))))),
69
+ React.createElement("div", { className: 'str-chat__dialog__controls' },
70
+ React.createElement("button", { className: 'str-chat__dialog__controls-button str-chat__dialog__controls-button--cancel', onClick: close }, t('Cancel')),
71
+ React.createElement("button", { className: 'str-chat__dialog__controls-button str-chat__dialog__controls-button--submit', disabled: Object.keys(fieldErrors).length > 0 || shouldDisableSubmitButton?.(value), onClick: handleSubmit, type: 'submit' }, t('Send')))));
72
+ };
@@ -0,0 +1,8 @@
1
+ import React, { ComponentProps } from 'react';
2
+ export type ConfirmationDialogProps = {
3
+ actions: ComponentProps<'button'>[];
4
+ prompt: string;
5
+ className?: string;
6
+ title?: string;
7
+ };
8
+ export declare const PromptDialog: ({ actions, className, prompt, title }: ConfirmationDialogProps) => React.JSX.Element;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import clsx from 'clsx';
3
+ export const PromptDialog = ({ actions, className, prompt, title }) => (React.createElement("div", { className: clsx('str-chat__dialog str-chat__dialog--prompt', className) },
4
+ React.createElement("div", { className: 'str-chat__dialog__body' },
5
+ title && React.createElement("div", { className: 'str-chat__dialog__title' }, title),
6
+ React.createElement("div", { className: 'str-chat__dialog__prompt' }, prompt)),
7
+ React.createElement("div", { className: 'str-chat__dialog__controls' }, actions.map(({ className, ...props }, i) => (React.createElement("button", { className: clsx(`str-chat__dialog__controls-button`, className), key: `prompt-dialog__controls-button--${i}`, ...props }))))));
@@ -0,0 +1,7 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ export type DragAndDropContainerProps = PropsWithChildren<{
3
+ className?: string;
4
+ draggable?: boolean;
5
+ onSetNewOrder?: (newOrder: number[]) => void;
6
+ }>;
7
+ export declare const DragAndDropContainer: ({ children, className, draggable, onSetNewOrder, }: DragAndDropContainerProps) => React.JSX.Element;
@@ -0,0 +1,93 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import clsx from 'clsx';
3
+ export const DragAndDropContainer = ({ children, className, draggable, onSetNewOrder, }) => {
4
+ const [order, setOrder] = useState([]);
5
+ const [dragStartIndex, setDragStartIndex] = useState(null);
6
+ const [dragOverIndex, setDragOverIndex] = useState(null);
7
+ const [container, setContainer] = useState(null);
8
+ const moveDirection = dragStartIndex === null || dragOverIndex === null
9
+ ? undefined
10
+ : dragStartIndex <= dragOverIndex
11
+ ? 'down'
12
+ : 'up';
13
+ const childrenArray = React.Children.toArray(children);
14
+ useEffect(() => {
15
+ setOrder(React.Children.map(children, (_, index) => index) || []);
16
+ }, [children]);
17
+ useEffect(() => {
18
+ if (!container)
19
+ return;
20
+ const handleDragStart = (e) => {
21
+ const target = e.target;
22
+ const draggableItem = target.closest('.str-chat__drag-and-drop-container__item');
23
+ if (e.dataTransfer) {
24
+ e.dataTransfer.effectAllowed = 'move';
25
+ }
26
+ if (draggableItem instanceof HTMLElement) {
27
+ const index = Array.from(draggableItem.parentElement?.children || []).indexOf(draggableItem);
28
+ setDragStartIndex(index);
29
+ e.dataTransfer?.setData('text/plain', index.toString());
30
+ draggableItem.style.opacity = '0.3';
31
+ }
32
+ };
33
+ const handleDragOver = (e) => {
34
+ e.preventDefault();
35
+ const target = e.target;
36
+ const draggableItem = target.closest('.str-chat__drag-and-drop-container__item');
37
+ if (draggableItem instanceof HTMLElement) {
38
+ const index = Array.from(draggableItem.parentElement?.children || []).indexOf(draggableItem);
39
+ setDragOverIndex(index);
40
+ }
41
+ };
42
+ const handleDragLeave = () => {
43
+ setDragOverIndex(null);
44
+ };
45
+ const handleDrop = (e) => {
46
+ e.preventDefault();
47
+ const draggedIndex = parseInt(e.dataTransfer?.getData('text/plain') || '-1', 10);
48
+ const target = e.target;
49
+ const draggableItem = target.closest('.str-chat__drag-and-drop-container__item');
50
+ if (draggableItem instanceof HTMLElement) {
51
+ const dropIndex = Array.from(draggableItem.parentElement?.children || []).indexOf(draggableItem);
52
+ if (draggedIndex !== -1 && draggedIndex !== dropIndex) {
53
+ setOrder((prevOrder) => {
54
+ const newOrder = [...prevOrder];
55
+ const [removed] = newOrder.splice(draggedIndex, 1);
56
+ newOrder.splice(dropIndex, 0, removed);
57
+ onSetNewOrder?.(newOrder);
58
+ return newOrder;
59
+ });
60
+ }
61
+ }
62
+ setDragStartIndex(null);
63
+ setDragOverIndex(null);
64
+ };
65
+ const handleDragEnd = (e) => {
66
+ const target = e.target;
67
+ if (target instanceof HTMLElement) {
68
+ target.style.opacity = '';
69
+ }
70
+ setDragStartIndex(null);
71
+ setDragOverIndex(null);
72
+ };
73
+ container.addEventListener('dragstart', handleDragStart);
74
+ container.addEventListener('dragover', handleDragOver);
75
+ container.addEventListener('dragleave', handleDragLeave);
76
+ container.addEventListener('drop', handleDrop);
77
+ container.addEventListener('dragend', handleDragEnd);
78
+ return () => {
79
+ container.removeEventListener('dragstart', handleDragStart);
80
+ container.removeEventListener('dragover', handleDragOver);
81
+ container.removeEventListener('dragleave', handleDragLeave);
82
+ container.removeEventListener('drop', handleDrop);
83
+ container.removeEventListener('dragend', handleDragEnd);
84
+ };
85
+ }, [container, onSetNewOrder]);
86
+ return (React.createElement("div", { className: clsx('str-chat__drag-and-drop-container', className), ref: setContainer }, order.map((originalIndex, currentIndex) => {
87
+ const child = childrenArray[originalIndex];
88
+ return (React.createElement("div", { className: clsx('str-chat__drag-and-drop-container__item', {
89
+ 'str-chat__drag-and-drop-container__item--dragged-over-from-bottom': moveDirection === 'up' && dragOverIndex === currentIndex,
90
+ 'str-chat__drag-and-drop-container__item--dragged-over-from-top': moveDirection === 'down' && dragOverIndex === currentIndex,
91
+ }), draggable: draggable, key: React.isValidElement(child) ? child.key : `draggable-item-${originalIndex}` }, child));
92
+ })));
93
+ };
@@ -0,0 +1,6 @@
1
+ import React, { ComponentProps } from 'react';
2
+ type FieldErrorProps = ComponentProps<'div'> & {
3
+ text?: string;
4
+ };
5
+ export declare const FieldError: ({ className, text, ...props }: FieldErrorProps) => React.JSX.Element;
6
+ export {};
@@ -0,0 +1,3 @@
1
+ import clsx from 'clsx';
2
+ import React from 'react';
3
+ export const FieldError = ({ className, text, ...props }) => (React.createElement("div", { ...props, className: clsx('str-chat__form-field-error', className) }, text));
@@ -0,0 +1,7 @@
1
+ import React, { ComponentProps, PropsWithChildren } from 'react';
2
+ export type SwitchFieldProps = PropsWithChildren<ComponentProps<'input'>>;
3
+ export declare const SwitchField: ({ children, ...props }: SwitchFieldProps) => React.JSX.Element;
4
+ export type SimpleSwitchFieldProps = ComponentProps<'input'> & {
5
+ labelText: string;
6
+ };
7
+ export declare const SimpleSwitchField: ({ labelText, ...props }: SimpleSwitchFieldProps) => React.JSX.Element;
@@ -0,0 +1,21 @@
1
+ import clsx from 'clsx';
2
+ import React, { useRef, } from 'react';
3
+ export const SwitchField = ({ children, ...props }) => {
4
+ const inputRef = useRef(null);
5
+ const handleKeyUp = (event) => {
6
+ if (![' ', 'Enter'].includes(event.key) || !inputRef.current)
7
+ return;
8
+ event.preventDefault();
9
+ inputRef.current.click();
10
+ };
11
+ return (React.createElement("div", { className: 'str-chat__form__field str-chat__form__switch-field' },
12
+ React.createElement("label", null,
13
+ React.createElement("div", { className: 'str-chat__form__field str-chat__form__switch-field-content' }, children),
14
+ React.createElement("input", { type: 'checkbox', ...props, ref: inputRef }),
15
+ React.createElement("div", { className: clsx('str-chat__form__switch-field__switch', {
16
+ 'str-chat__form__switch-field__switch--on': props.checked,
17
+ }), onKeyUp: handleKeyUp, tabIndex: 0 },
18
+ React.createElement("div", { className: 'str-chat__form__switch-field__switch-handle' })))));
19
+ };
20
+ export const SimpleSwitchField = ({ labelText, ...props }) => (React.createElement(SwitchField, { ...props },
21
+ React.createElement("div", { className: 'str-chat__form__field str-chat__form__switch-field__text' }, labelText)));
@@ -31,4 +31,14 @@ export type InfiniteScrollProps = PaginatorProps & {
31
31
  loadMoreNewer?: () => void;
32
32
  useCapture?: boolean;
33
33
  };
34
+ /**
35
+ * This component serves a single purpose - load more items on scroll inside the MessageList component
36
+ * It is not a general purpose infinite scroll controller, because:
37
+ * 1. It is re-rendered whenever isLoading, hasNext, hasPrev changes. This can lead to scrollListener to have stale data.
38
+ * 2. It pretends to invoke scrollListener on resize event even though this event is emitted only on window resize. It should
39
+ * rather use ResizeObserver. But then again, it ResizeObserver would invoke a stale version of scrollListener.
40
+ *
41
+ * In general, the infinite scroll controller should not aim for checking the loading state and whether there is more data to load.
42
+ * That should be controlled by the loading function.
43
+ */
34
44
  export declare const InfiniteScroll: (props: PropsWithChildren<InfiniteScrollProps>) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;