@ermis-network/ermis-chat-react 1.0.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 (88) hide show
  1. package/dist/index.cjs +6593 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.css +3375 -0
  4. package/dist/index.css.map +1 -0
  5. package/dist/index.d.mts +1138 -0
  6. package/dist/index.d.ts +1138 -0
  7. package/dist/index.mjs +6500 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +42 -0
  10. package/src/components/Avatar.tsx +102 -0
  11. package/src/components/Channel.tsx +77 -0
  12. package/src/components/ChannelHeader.tsx +85 -0
  13. package/src/components/ChannelInfo/AddMemberModal.tsx +204 -0
  14. package/src/components/ChannelInfo/ChannelInfo.tsx +455 -0
  15. package/src/components/ChannelInfo/ChannelInfoTabs.tsx +282 -0
  16. package/src/components/ChannelInfo/ChannelSettingsPanel.tsx +479 -0
  17. package/src/components/ChannelInfo/EditChannelModal.tsx +272 -0
  18. package/src/components/ChannelInfo/FileListItem.tsx +49 -0
  19. package/src/components/ChannelInfo/LinkListItem.tsx +62 -0
  20. package/src/components/ChannelInfo/MediaGridItem.tsx +90 -0
  21. package/src/components/ChannelInfo/MemberListItem.tsx +85 -0
  22. package/src/components/ChannelInfo/MessageSearchPanel.tsx +333 -0
  23. package/src/components/ChannelInfo/States.tsx +36 -0
  24. package/src/components/ChannelInfo/index.ts +10 -0
  25. package/src/components/ChannelInfo/utils.tsx +49 -0
  26. package/src/components/ChannelList.tsx +395 -0
  27. package/src/components/Dropdown.tsx +120 -0
  28. package/src/components/EditPreview.tsx +102 -0
  29. package/src/components/FilesPreview.tsx +108 -0
  30. package/src/components/ForwardMessageModal.tsx +234 -0
  31. package/src/components/MentionSuggestions.tsx +59 -0
  32. package/src/components/MessageActionsBox.tsx +186 -0
  33. package/src/components/MessageInput.tsx +513 -0
  34. package/src/components/MessageInputDefaults.tsx +50 -0
  35. package/src/components/MessageItem.tsx +218 -0
  36. package/src/components/MessageQuickReactions.tsx +73 -0
  37. package/src/components/MessageReactions.tsx +59 -0
  38. package/src/components/MessageRenderers.tsx +565 -0
  39. package/src/components/Modal.tsx +58 -0
  40. package/src/components/Panel.tsx +64 -0
  41. package/src/components/PinnedMessages.tsx +165 -0
  42. package/src/components/QuotedMessagePreview.tsx +55 -0
  43. package/src/components/ReadReceipts.tsx +80 -0
  44. package/src/components/ReplyPreview.tsx +98 -0
  45. package/src/components/TypingIndicator.tsx +57 -0
  46. package/src/components/VirtualMessageList.tsx +425 -0
  47. package/src/context/ChatProvider.tsx +73 -0
  48. package/src/hooks/useBannedState.ts +48 -0
  49. package/src/hooks/useBlockedState.ts +55 -0
  50. package/src/hooks/useChannel.ts +18 -0
  51. package/src/hooks/useChannelCapabilities.ts +42 -0
  52. package/src/hooks/useChannelData.ts +55 -0
  53. package/src/hooks/useChannelListUpdates.ts +224 -0
  54. package/src/hooks/useChannelMessages.ts +159 -0
  55. package/src/hooks/useChannelRowUpdates.ts +78 -0
  56. package/src/hooks/useChatClient.ts +11 -0
  57. package/src/hooks/useEmojiPicker.ts +53 -0
  58. package/src/hooks/useFileUpload.ts +128 -0
  59. package/src/hooks/useLoadMessages.ts +178 -0
  60. package/src/hooks/useMentions.ts +287 -0
  61. package/src/hooks/useMessageActions.ts +87 -0
  62. package/src/hooks/useMessageSend.ts +164 -0
  63. package/src/hooks/usePendingState.ts +63 -0
  64. package/src/hooks/useScrollToMessage.ts +155 -0
  65. package/src/hooks/useTypingIndicator.ts +86 -0
  66. package/src/index.ts +129 -0
  67. package/src/styles/_add-member-modal.css +122 -0
  68. package/src/styles/_base.css +32 -0
  69. package/src/styles/_channel-info.css +941 -0
  70. package/src/styles/_channel-list.css +217 -0
  71. package/src/styles/_dropdown.css +69 -0
  72. package/src/styles/_forward-modal.css +191 -0
  73. package/src/styles/_mentions.css +102 -0
  74. package/src/styles/_message-actions.css +61 -0
  75. package/src/styles/_message-bubble.css +656 -0
  76. package/src/styles/_message-input.css +389 -0
  77. package/src/styles/_message-list.css +416 -0
  78. package/src/styles/_message-quick-reactions.css +62 -0
  79. package/src/styles/_message-reactions.css +67 -0
  80. package/src/styles/_modal.css +113 -0
  81. package/src/styles/_panel.css +69 -0
  82. package/src/styles/_pinned-messages.css +140 -0
  83. package/src/styles/_search-panel.css +219 -0
  84. package/src/styles/_tokens.css +92 -0
  85. package/src/styles/_typing-indicator.css +59 -0
  86. package/src/styles/index.css +24 -0
  87. package/src/types.ts +955 -0
  88. package/src/utils.ts +242 -0
@@ -0,0 +1,1138 @@
1
+ import React$1 from 'react';
2
+ import { Channel as Channel$1, Attachment, FormatMessageResponse, ChannelFilters, ChannelSort, ChannelQueryOptions, ErmisChat, MessageLabel } from '@ermis-network/ermis-chat-sdk';
3
+ import { VListHandle } from 'virtua';
4
+
5
+ type Theme = 'dark' | 'light';
6
+ type ReadStateEntry = {
7
+ last_read: Date | string;
8
+ last_read_message_id?: string;
9
+ unread_messages: number;
10
+ user: {
11
+ id: string;
12
+ name?: string;
13
+ avatar?: string;
14
+ };
15
+ last_send?: string;
16
+ };
17
+ type ChatContextValue = {
18
+ client: ErmisChat;
19
+ activeChannel: Channel$1 | null;
20
+ setActiveChannel: (channel: Channel$1 | null) => void;
21
+ theme: Theme;
22
+ setTheme: (theme: Theme) => void;
23
+ messages: FormatMessageResponse[];
24
+ setMessages: React.Dispatch<React.SetStateAction<FormatMessageResponse[]>>;
25
+ /** Re-read messages from SDK state into React state */
26
+ syncMessages: () => void;
27
+ /** Message being replied to (shown as preview in MessageInput) */
28
+ quotedMessage: FormatMessageResponse | null;
29
+ setQuotedMessage: (message: FormatMessageResponse | null) => void;
30
+ /** Message being edited (shown as preview in MessageInput and alters send behavior) */
31
+ editingMessage: FormatMessageResponse | null;
32
+ setEditingMessage: (message: FormatMessageResponse | null) => void;
33
+ /** Read state per user — maps userId to their read status */
34
+ readState: Record<string, ReadStateEntry>;
35
+ setReadState: React.Dispatch<React.SetStateAction<Record<string, ReadStateEntry>>>;
36
+ /** Message being forwarded (triggers ForwardMessageModal) */
37
+ forwardingMessage: FormatMessageResponse | null;
38
+ setForwardingMessage: (message: FormatMessageResponse | null) => void;
39
+ /** Message ID to jump/scroll to (set by search, cleared after scroll) */
40
+ jumpToMessageId: string | null;
41
+ setJumpToMessageId: (id: string | null) => void;
42
+ };
43
+ type ChatProviderProps = {
44
+ client: ErmisChat;
45
+ children: React.ReactNode;
46
+ /** Initial theme, defaults to 'dark' */
47
+ initialTheme?: Theme;
48
+ };
49
+ type AvatarProps = {
50
+ /** Image URL */
51
+ image?: string | null;
52
+ /** Name used for fallback initials */
53
+ name?: string;
54
+ /** Size in pixels (default: 36) */
55
+ size?: number;
56
+ /** Additional CSS class name */
57
+ className?: string;
58
+ };
59
+ type ChannelProps = {
60
+ children: React.ReactNode;
61
+ /** Additional CSS class name */
62
+ className?: string;
63
+ /** Custom component shown when no channel is selected */
64
+ EmptyStateIndicator?: React.ComponentType;
65
+ /** Replace the default ChannelHeader entirely */
66
+ HeaderComponent?: React.ComponentType<ChannelHeaderData>;
67
+ /** Replace the default ForwardMessageModal entirely */
68
+ ForwardMessageModalComponent?: React.ComponentType<ForwardMessageModalProps>;
69
+ };
70
+ type ChannelHeaderProps = {
71
+ /** Additional CSS class name */
72
+ className?: string;
73
+ /** Custom avatar component */
74
+ AvatarComponent?: React.ComponentType<AvatarProps>;
75
+ /** Override channel name */
76
+ title?: string;
77
+ /** Override channel image */
78
+ image?: string;
79
+ /** Subtitle text (e.g. member count, online status) */
80
+ subtitle?: string;
81
+ /** Render custom content on the right side */
82
+ renderRight?: (channel: Channel$1, actionDisabled?: boolean) => React.ReactNode;
83
+ /** Override default title rendering */
84
+ renderTitle?: (channel: Channel$1) => React.ReactNode;
85
+ };
86
+ /** Data passed to a fully custom HeaderComponent */
87
+ type ChannelHeaderData = {
88
+ channel: Channel$1;
89
+ name: string;
90
+ image?: string;
91
+ };
92
+ type ChannelItemProps = {
93
+ channel: Channel$1;
94
+ isActive: boolean;
95
+ hasUnread: boolean;
96
+ unreadCount: number;
97
+ lastMessageText: string;
98
+ lastMessageUser: string;
99
+ onSelect: (channel: Channel$1) => void;
100
+ AvatarComponent: React.ComponentType<AvatarProps>;
101
+ /** Whether the current user has blocked this channel (messaging only) */
102
+ isBlocked?: boolean;
103
+ /** Whether the current user is pending an invitation for this channel */
104
+ isPending?: boolean;
105
+ /** Label for the pending channel badge indicator */
106
+ pendingBadgeLabel?: string;
107
+ /** Label for the blocked channel badge indicator */
108
+ blockedBadgeLabel?: string;
109
+ };
110
+ type ChannelListProps = {
111
+ filters?: ChannelFilters;
112
+ sort?: ChannelSort;
113
+ options?: ChannelQueryOptions;
114
+ renderChannel?: (channel: Channel$1, isActive: boolean) => React.ReactNode;
115
+ onChannelSelect?: (channel: Channel$1) => void;
116
+ className?: string;
117
+ LoadingIndicator?: React.ComponentType<{
118
+ text?: string;
119
+ }>;
120
+ EmptyStateIndicator?: React.ComponentType<{
121
+ text?: string;
122
+ }>;
123
+ AvatarComponent?: React.ComponentType<AvatarProps>;
124
+ /** Replace the default channel list item component */
125
+ ChannelItemComponent?: React.ComponentType<ChannelItemProps>;
126
+ /** Label for the pending invites accordion header */
127
+ pendingInvitesLabel?: string | ((count: number) => string);
128
+ /** Label for the regular channels section header */
129
+ channelsLabel?: string;
130
+ /** Label for the pending channel badge indicator */
131
+ pendingBadgeLabel?: string;
132
+ /** Label for the loading indicator */
133
+ loadingLabel?: string;
134
+ /** Label for the empty state indicator */
135
+ emptyStateLabel?: string;
136
+ /** Label for the blocked channel badge hover */
137
+ blockedBadgeLabel?: string;
138
+ };
139
+ type AttachmentProps = {
140
+ attachment: Attachment;
141
+ };
142
+ type MessageRendererProps = {
143
+ message: FormatMessageResponse;
144
+ isOwnMessage: boolean;
145
+ };
146
+ type MessageBubbleProps = {
147
+ message: FormatMessageResponse;
148
+ isOwnMessage: boolean;
149
+ children: React.ReactNode;
150
+ };
151
+ type DateSeparatorProps = {
152
+ label: string;
153
+ };
154
+ type JumpToLatestProps = {
155
+ onClick: () => void;
156
+ };
157
+ type MessageListProps = {
158
+ /** Fully custom render for each message */
159
+ renderMessage?: (message: FormatMessageResponse, isOwnMessage: boolean) => React.ReactNode;
160
+ /** Additional CSS class name */
161
+ className?: string;
162
+ /** Custom empty state component */
163
+ EmptyStateIndicator?: React.ComponentType;
164
+ /** Custom avatar component */
165
+ AvatarComponent?: React.ComponentType<AvatarProps>;
166
+ /** Custom message bubble wrapper */
167
+ MessageBubble?: React.ComponentType<MessageBubbleProps>;
168
+ /** Custom renderers per message type */
169
+ messageRenderers?: Partial<Record<MessageLabel, React.ComponentType<MessageRendererProps>>>;
170
+ /** Number of older messages to load per page (default: 25) */
171
+ loadMoreLimit?: number;
172
+ /** Custom date separator component */
173
+ DateSeparatorComponent?: React.ComponentType<DateSeparatorProps>;
174
+ /** Custom message item component (replaces the entire row) */
175
+ MessageItemComponent?: React.ComponentType<MessageItemProps>;
176
+ /** Custom system message item component */
177
+ SystemMessageItemComponent?: React.ComponentType<SystemMessageItemProps>;
178
+ /** Custom "Jump to latest" button */
179
+ JumpToLatestButton?: React.ComponentType<JumpToLatestProps>;
180
+ /** Custom quoted message preview inside message items */
181
+ QuotedMessagePreviewComponent?: React.ComponentType<QuotedMessagePreviewProps>;
182
+ /** Custom message actions component (hover buttons + dropdown) */
183
+ MessageActionsBoxComponent?: React.ComponentType<MessageActionsBoxProps>;
184
+ /** Show pinned messages bar (default: true) */
185
+ showPinnedMessages?: boolean;
186
+ /** Custom pinned messages component */
187
+ PinnedMessagesComponent?: React.ComponentType<any>;
188
+ /** Custom reply preview component in MessageInput */
189
+ ReplyPreviewComponent?: React.ComponentType<ReplyPreviewProps>;
190
+ /** Show read receipts (default: true) */
191
+ showReadReceipts?: boolean;
192
+ /** Custom read receipts component (replaces the entire read-receipts row) */
193
+ ReadReceiptsComponent?: React.ComponentType<ReadReceiptsProps>;
194
+ /** Custom read receipts tooltip component */
195
+ ReadReceiptsTooltipComponent?: React.ComponentType<ReadReceiptsTooltipProps>;
196
+ /** Max visible avatars in read receipts before showing +N (default: 5) */
197
+ readReceiptsMaxAvatars?: number;
198
+ /** Show typing indicator (default: true) */
199
+ showTypingIndicator?: boolean;
200
+ /** Custom typing indicator component */
201
+ TypingIndicatorComponent?: React.ComponentType;
202
+ /** Custom component for message reactions */
203
+ MessageReactionsComponent?: React.ComponentType<MessageReactionsProps>;
204
+ /** I18n Labels */
205
+ emptyTitle?: string;
206
+ emptySubtitle?: string;
207
+ jumpToLatestLabel?: string;
208
+ bannedOverlayTitle?: string;
209
+ bannedOverlaySubtitle?: string;
210
+ blockedOverlayTitle?: string;
211
+ blockedOverlaySubtitle?: string;
212
+ pendingOverlayTitle?: string;
213
+ pendingOverlaySubtitle?: string;
214
+ pendingAcceptLabel?: string;
215
+ pendingRejectLabel?: string;
216
+ };
217
+ type ReactionUser = {
218
+ id: string;
219
+ name?: string;
220
+ avatar?: string;
221
+ };
222
+ type LatestReaction = {
223
+ user: ReactionUser;
224
+ type: string;
225
+ };
226
+ type MessageReactionsProps = {
227
+ /** Map of reaction type to count */
228
+ reactionCounts?: Record<string, number>;
229
+ /** Array of current user's reactions */
230
+ ownReactions?: LatestReaction[];
231
+ /** Array of latest reactions to show in tooltip/hover */
232
+ latestReactions?: LatestReaction[];
233
+ /** Avatar Component if consumer wants to use it in tooltips */
234
+ AvatarComponent?: React.ComponentType<AvatarProps>;
235
+ /** Callback when clicking a reaction */
236
+ onClickReaction?: (type: string) => void;
237
+ };
238
+ type ReadReceiptUser = {
239
+ id: string;
240
+ name?: string;
241
+ avatar?: string;
242
+ last_read?: Date | string;
243
+ };
244
+ type ReadReceiptsTooltipProps = {
245
+ /** All users who have read this message */
246
+ readers: ReadReceiptUser[];
247
+ /** Avatar component for rendering user avatars */
248
+ AvatarComponent: React.ComponentType<AvatarProps>;
249
+ };
250
+ type ReadReceiptsProps = {
251
+ /** Users who have read the message */
252
+ readers: ReadReceiptUser[];
253
+ /** Max number of visible avatars before showing +N overflow (default: 5) */
254
+ maxAvatars?: number;
255
+ /** Avatar component for rendering user avatars */
256
+ AvatarComponent: React.ComponentType<AvatarProps>;
257
+ /** Custom tooltip component */
258
+ TooltipComponent?: React.ComponentType<ReadReceiptsTooltipProps>;
259
+ /** Whether to show the tooltip on hover (default: true) */
260
+ showTooltip?: boolean;
261
+ /** Whether the message belongs to the current user (used to show 'Sent/Delivered' status when nobody has read it) */
262
+ isOwnMessage?: boolean;
263
+ /** Whether the message is the last in a group of consecutive messages by the same user */
264
+ isLastInGroup?: boolean;
265
+ /** The message status (e.g., 'sending', 'failed', 'sent') */
266
+ status?: string;
267
+ };
268
+ type MessageItemProps = {
269
+ message: FormatMessageResponse;
270
+ isOwnMessage: boolean;
271
+ isFirstInGroup: boolean;
272
+ isLastInGroup: boolean;
273
+ isHighlighted: boolean;
274
+ AvatarComponent: React.ComponentType<AvatarProps>;
275
+ MessageBubble: React.ComponentType<MessageBubbleProps>;
276
+ MessageRenderer: React.ComponentType<MessageRendererProps>;
277
+ onClickQuote?: (messageId: string) => void;
278
+ /** Custom quoted message preview component */
279
+ QuotedMessagePreviewComponent?: React.ComponentType<QuotedMessagePreviewProps>;
280
+ /** Custom message actions component (hover buttons + dropdown) */
281
+ MessageActionsBoxComponent?: React.ComponentType<MessageActionsBoxProps>;
282
+ /** Users who have read up to this message */
283
+ readBy?: Array<{
284
+ id: string;
285
+ name?: string;
286
+ avatar?: string;
287
+ }>;
288
+ /** Custom component for message reactions */
289
+ MessageReactionsComponent?: React.ComponentType<MessageReactionsProps>;
290
+ /** I18n Label for forwarded message */
291
+ forwardedLabel?: string;
292
+ /** I18n Label for edited state */
293
+ editedLabel?: string;
294
+ };
295
+ type SystemMessageItemProps = {
296
+ message: FormatMessageResponse;
297
+ isOwnMessage: boolean;
298
+ SystemRenderer: React.ComponentType<MessageRendererProps>;
299
+ };
300
+ type SendButtonProps = {
301
+ disabled: boolean;
302
+ onClick: () => void;
303
+ };
304
+ type AttachButtonProps = {
305
+ disabled: boolean;
306
+ onClick: () => void;
307
+ };
308
+ /** Props passed to a consumer-provided emoji picker component */
309
+ type EmojiPickerProps = {
310
+ /** Called when user selects an emoji — insert the emoji string into the input */
311
+ onSelect: (emoji: string) => void;
312
+ /** Called when the picker should close (e.g. click outside) */
313
+ onClose: () => void;
314
+ };
315
+ /** Props passed to the emoji button component */
316
+ type EmojiButtonProps = {
317
+ /** Whether the picker is currently open */
318
+ active: boolean;
319
+ /** Toggle the picker */
320
+ onClick: () => void;
321
+ };
322
+ type MessageInputProps = {
323
+ /** Placeholder text */
324
+ placeholder?: string;
325
+ /** Callback after message is sent */
326
+ onSend?: (text: string) => void;
327
+ /** Additional CSS class name */
328
+ className?: string;
329
+ /** Custom send button component */
330
+ SendButton?: React.ComponentType<SendButtonProps>;
331
+ /** Custom attach button component */
332
+ AttachButton?: React.ComponentType<AttachButtonProps>;
333
+ /** Custom file preview component */
334
+ FilesPreviewComponent?: React.ComponentType<FilesPreviewProps>;
335
+ /** Custom mention suggestions component */
336
+ MentionSuggestionsComponent?: React.ComponentType<MentionSuggestionsProps>;
337
+ /** Disable file attachments entirely */
338
+ disableAttachments?: boolean;
339
+ /** Disable @mention suggestions (overrides auto-detection) */
340
+ disableMentions?: boolean;
341
+ /** Render custom content above the input row (e.g. reply preview) */
342
+ renderAbove?: () => React.ReactNode;
343
+ /** Hook called before sending — return false to cancel */
344
+ onBeforeSend?: (text: string, attachments: FilePreviewItem[]) => boolean | Promise<boolean>;
345
+ /** Consumer-provided emoji picker component (not bundled — bring your own) */
346
+ EmojiPickerComponent?: React.ComponentType<EmojiPickerProps>;
347
+ /** Custom emoji button component (defaults to 😀 toggle button) */
348
+ EmojiButtonComponent?: React.ComponentType<EmojiButtonProps>;
349
+ /** Custom reply preview component */
350
+ ReplyPreviewComponent?: React.ComponentType<ReplyPreviewProps>;
351
+ /** Custom edit preview component */
352
+ EditPreviewComponent?: React.ComponentType<{
353
+ message: FormatMessageResponse;
354
+ onDismiss: () => void;
355
+ editingMessageLabel?: string;
356
+ }>;
357
+ /** I18n Label for banned state */
358
+ bannedLabel?: string;
359
+ /** I18n Label for blocked state (messaging channels) */
360
+ blockedLabel?: string;
361
+ /** I18n Label for links disabled error */
362
+ linksDisabledLabel?: string;
363
+ /** I18n Label for keyword blocked error */
364
+ keywordBlockedLabel?: (match: string) => string;
365
+ /** I18n Label for sending capability disabled */
366
+ sendDisabledLabel?: string;
367
+ /** I18n Label for slow mode active */
368
+ slowModeLabel?: (cooldown: number) => React.ReactNode;
369
+ };
370
+ type ReplyPreviewProps = {
371
+ message: FormatMessageResponse;
372
+ onDismiss: () => void;
373
+ replyingToLabel?: string;
374
+ };
375
+ type MessageActionsBoxProps = {
376
+ message: FormatMessageResponse;
377
+ isOwnMessage: boolean;
378
+ onReply?: (message: FormatMessageResponse) => void;
379
+ onForward?: (message: FormatMessageResponse) => void;
380
+ onPinToggle?: (message: FormatMessageResponse, isPinned: boolean) => void;
381
+ onEdit?: (message: FormatMessageResponse) => void;
382
+ onCopy?: (message: FormatMessageResponse) => void;
383
+ onDelete?: (message: FormatMessageResponse) => void;
384
+ onDeleteForMe?: (message: FormatMessageResponse) => void;
385
+ /** I18n Labels */
386
+ pinLabel?: string;
387
+ unpinLabel?: string;
388
+ editLabel?: string;
389
+ copyLabel?: string;
390
+ deleteForMeLabel?: string;
391
+ deleteForEveryoneLabel?: string;
392
+ };
393
+ type ForwardChannelItemProps = {
394
+ channel: Channel$1;
395
+ selected: boolean;
396
+ onToggle: (channel: Channel$1) => void;
397
+ AvatarComponent: React.ComponentType<AvatarProps>;
398
+ };
399
+ type ForwardMessageModalProps = {
400
+ message: FormatMessageResponse;
401
+ onDismiss: () => void;
402
+ /** Custom channel list item for the picker */
403
+ ChannelItemComponent?: React.ComponentType<ForwardChannelItemProps>;
404
+ /** Custom search input component */
405
+ SearchInputComponent?: React.ComponentType<{
406
+ value: string;
407
+ onChange: (v: string) => void;
408
+ }>;
409
+ };
410
+ type PinnedMessageItemProps = {
411
+ message: FormatMessageResponse;
412
+ isOwnMessage: boolean;
413
+ onClickMessage?: (messageId: string) => void;
414
+ onUnpin?: (messageId: string) => void;
415
+ AvatarComponent: React.ComponentType<AvatarProps>;
416
+ };
417
+ type PinnedMessagesProps = {
418
+ /** Additional CSS class name */
419
+ className?: string;
420
+ /** Custom avatar component */
421
+ AvatarComponent?: React.ComponentType<AvatarProps>;
422
+ /** Custom pinned message item component */
423
+ PinnedMessageItemComponent?: React.ComponentType<PinnedMessageItemProps>;
424
+ /** Callback when a pinned message is clicked (e.g. scroll to it) */
425
+ onClickMessage?: (messageId: string) => void;
426
+ /** Max messages to show in collapsed state (default: 1) */
427
+ maxCollapsed?: number;
428
+ };
429
+ type QuotedMessagePreviewProps = {
430
+ /** The quoted (replied-to) message object */
431
+ quotedMessage: {
432
+ id: string;
433
+ text?: string;
434
+ user?: {
435
+ id?: string;
436
+ name?: string;
437
+ };
438
+ };
439
+ /** Whether the parent message is from the current user */
440
+ isOwnMessage: boolean;
441
+ /** Callback when the quote box is clicked */
442
+ onClick: (messageId: string) => void;
443
+ };
444
+ type MentionSuggestionsProps = {
445
+ members: MentionMember[];
446
+ highlightIndex: number;
447
+ onSelect: (member: MentionMember) => void;
448
+ };
449
+ type UseChannelReturn = {
450
+ channel: Channel$1 | null;
451
+ loading: boolean;
452
+ error: Error | null;
453
+ };
454
+ type MentionMember = {
455
+ id: string;
456
+ name: string;
457
+ avatar?: string;
458
+ };
459
+ type MentionPayload = {
460
+ text: string;
461
+ mentioned_all: boolean;
462
+ mentioned_users: string[];
463
+ };
464
+ type UseMentionsOptions = {
465
+ members: MentionMember[];
466
+ currentUserId?: string;
467
+ editableRef: React.RefObject<HTMLDivElement | null>;
468
+ };
469
+ type UseMentionsReturn = {
470
+ showSuggestions: boolean;
471
+ filteredMembers: MentionMember[];
472
+ highlightIndex: number;
473
+ /** Call on each input event of the contenteditable */
474
+ handleInput: () => void;
475
+ /** Call on keydown. Returns true if the event was consumed (e.g. Enter for selection). */
476
+ handleKeyDown: (e: React.KeyboardEvent) => boolean;
477
+ /** Select a member from the suggestion list */
478
+ selectMention: (member: MentionMember) => void;
479
+ /** Build the payload from the contenteditable DOM */
480
+ buildPayload: () => MentionPayload;
481
+ /** Reset mention state (call after send) */
482
+ reset: () => void;
483
+ };
484
+ type FilePreviewItem = {
485
+ /** Unique ID for keying */
486
+ id: string;
487
+ /** Original File object (optional for existing server attachments) */
488
+ file?: File;
489
+ /** Blob URL for image/video preview */
490
+ previewUrl?: string;
491
+ /** Upload status */
492
+ status: 'pending' | 'uploading' | 'done' | 'error';
493
+ /** Error message if upload failed */
494
+ error?: string;
495
+ /** URL returned after successful upload */
496
+ uploadedUrl?: string;
497
+ /** Thumbnail URL (video only) */
498
+ thumbUrl?: string;
499
+ /** File with normalized name */
500
+ normalizedFile?: File;
501
+ /** Track original attachments during edits */
502
+ originalAttachment?: Attachment;
503
+ };
504
+ type FilesPreviewProps = {
505
+ files: FilePreviewItem[];
506
+ onRemove: (id: string) => void;
507
+ };
508
+ interface ModalProps {
509
+ isOpen: boolean;
510
+ onClose: () => void;
511
+ title?: React.ReactNode;
512
+ children: React.ReactNode;
513
+ footer?: React.ReactNode;
514
+ maxWidth?: string;
515
+ hideCloseButton?: boolean;
516
+ }
517
+ /** Attachment item from the channel attachment query API */
518
+ type AttachmentItem = {
519
+ id: string;
520
+ attachment_type: string;
521
+ user_id: string;
522
+ cid: string;
523
+ url: string;
524
+ thumb_url: string;
525
+ file_name: string;
526
+ content_type: string;
527
+ content_length: number;
528
+ content_disposition: string;
529
+ message_id: string;
530
+ created_at: string;
531
+ updated_at: string;
532
+ title?: string;
533
+ title_link?: string;
534
+ og_scrape_url?: string;
535
+ image_url?: string;
536
+ text?: string;
537
+ };
538
+ type MediaTab = 'members' | 'media' | 'links' | 'files';
539
+ type ChannelInfoMemberItemProps = {
540
+ member: ChannelInfoMember;
541
+ AvatarComponent: React.ComponentType<AvatarProps>;
542
+ onRemove?: (id: string) => void;
543
+ canRemove?: boolean;
544
+ onBan?: (id: string) => void;
545
+ canBan?: boolean;
546
+ onUnban?: (id: string) => void;
547
+ canUnban?: boolean;
548
+ onPromote?: (id: string) => void;
549
+ canPromote?: boolean;
550
+ onDemote?: (id: string) => void;
551
+ canDemote?: boolean;
552
+ };
553
+ type ChannelInfoMediaItemProps = {
554
+ item: AttachmentItem;
555
+ onClick: (url: string) => void;
556
+ };
557
+ type ChannelInfoLinkItemProps = {
558
+ item: AttachmentItem;
559
+ };
560
+ type ChannelInfoFileItemProps = {
561
+ item: AttachmentItem;
562
+ onClick: (url: string) => void;
563
+ };
564
+ type ChannelInfoEmptyStateProps = {
565
+ label: string;
566
+ };
567
+ type ChannelInfoHeaderProps = {
568
+ title: string;
569
+ onClose?: () => void;
570
+ };
571
+ type ChannelInfoCoverProps = {
572
+ channelName: string;
573
+ channelImage?: string;
574
+ channelDescription?: string;
575
+ AvatarComponent: React.ComponentType<AvatarProps>;
576
+ /** Whether the current user can edit channel info */
577
+ canEdit?: boolean;
578
+ /** Callback when the edit button is clicked */
579
+ onEditClick?: () => void;
580
+ /** Whether the channel is public */
581
+ isPublic?: boolean;
582
+ /** Whether the channel is a team channel */
583
+ isTeamChannel?: boolean;
584
+ };
585
+ type ChannelInfoActionsProps = {
586
+ onSearchClick?: () => void;
587
+ onSettingsClick?: () => void;
588
+ onLeaveChannel?: () => void;
589
+ onDeleteChannel?: () => void;
590
+ onBlockUser?: () => void;
591
+ onUnblockUser?: () => void;
592
+ isTeamChannel?: boolean;
593
+ isBlocked?: boolean;
594
+ currentUserRole?: string;
595
+ searchLabel?: string;
596
+ settingsLabel?: string;
597
+ deleteLabel?: string;
598
+ leaveLabel?: string;
599
+ blockLabel?: string;
600
+ unblockLabel?: string;
601
+ };
602
+ type ChannelInfoMember = {
603
+ id: string;
604
+ name?: string;
605
+ avatar?: string;
606
+ [key: string]: any;
607
+ };
608
+ /** Payload for updating channel profile */
609
+ type EditChannelData = {
610
+ name?: string;
611
+ image?: string;
612
+ description?: string;
613
+ public?: boolean;
614
+ };
615
+ /** Props for the EditChannelModal */
616
+ type EditChannelModalProps = {
617
+ channel: Channel$1;
618
+ onClose: () => void;
619
+ /** Override the default save logic entirely */
620
+ onSave?: (data: EditChannelData) => Promise<void>;
621
+ /** Custom avatar component */
622
+ AvatarComponent: React.ComponentType<AvatarProps>;
623
+ /** Modal title (default: 'Edit Channel') */
624
+ title?: string;
625
+ /** Label for the name input (default: 'Channel Name') */
626
+ nameLabel?: string;
627
+ /** Label for the description input (default: 'Description') */
628
+ descriptionLabel?: string;
629
+ /** Placeholder for name input */
630
+ namePlaceholder?: string;
631
+ /** Placeholder for description input */
632
+ descriptionPlaceholder?: string;
633
+ /** Label for the public toggle (default: 'Public Channel') */
634
+ publicLabel?: string;
635
+ /** Label for the save button (default: 'Save') */
636
+ saveLabel?: string;
637
+ /** Label for the cancel button (default: 'Cancel') */
638
+ cancelLabel?: string;
639
+ /** Label shown while saving (default: 'Saving...') */
640
+ savingLabel?: string;
641
+ /** Label for the change avatar button (default: 'Change Avatar') */
642
+ changeAvatarLabel?: string;
643
+ /** Accept attribute for the file input (default: 'image/*') */
644
+ imageAccept?: string;
645
+ /** Max file size in bytes (default: 5MB = 5242880) */
646
+ maxImageSize?: number;
647
+ /** Error text for exceeding max size (default: 'Image must be less than 5MB') */
648
+ maxImageSizeError?: string;
649
+ };
650
+ /** Props for the Add Member button rendered at the top of the Members tab */
651
+ type AddMemberButtonProps = {
652
+ onClick: () => void;
653
+ /** Label text for the button (default: 'Add Member') */
654
+ label?: string;
655
+ };
656
+ /** Props for individual user items inside the AddMemberModal */
657
+ type AddMemberUserItemProps = {
658
+ user: any;
659
+ /** Whether the user already belongs to the channel */
660
+ isExisting: boolean;
661
+ /** Whether the user is currently being added */
662
+ isAdding: boolean;
663
+ /** Callback to add the user */
664
+ onAdd: (userId: string) => void;
665
+ AvatarComponent: React.ComponentType<AvatarProps>;
666
+ /** Label shown when the user is already in the channel (default: 'Added') */
667
+ addedLabel?: string;
668
+ /** Label shown while adding (default: 'Adding...') */
669
+ addingLabel?: string;
670
+ /** Label for the add button (default: 'Add') */
671
+ addLabel?: string;
672
+ };
673
+ /** Props for the AddMemberModal */
674
+ type AddMemberModalProps = {
675
+ channel: Channel$1;
676
+ currentMembers: any[];
677
+ onClose: () => void;
678
+ AvatarComponent: React.ComponentType<AvatarProps>;
679
+ /** Modal title (default: 'Add Member') */
680
+ title?: string;
681
+ /** Search input placeholder (default: 'Search by name, email or phone...') */
682
+ searchPlaceholder?: string;
683
+ /** Text shown while loading users (default: 'Loading users...') */
684
+ loadingText?: string;
685
+ /** Text shown when no users match the search (default: 'No users found.') */
686
+ emptyText?: string;
687
+ /** Label for the add button on each user row (default: 'Add') */
688
+ addLabel?: string;
689
+ /** Label shown while a user is being added (default: 'Adding...') */
690
+ addingLabel?: string;
691
+ /** Label shown when a user already belongs to the channel (default: 'Added') */
692
+ addedLabel?: string;
693
+ /** Custom user item component (replaces the default row) */
694
+ UserItemComponent?: React.ComponentType<AddMemberUserItemProps>;
695
+ /** Custom search input component */
696
+ SearchInputComponent?: React.ComponentType<{
697
+ value: string;
698
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
699
+ placeholder: string;
700
+ }>;
701
+ };
702
+ type ChannelInfoTabsProps = {
703
+ channel: Channel$1;
704
+ members: ChannelInfoMember[];
705
+ AvatarComponent: React.ComponentType<AvatarProps>;
706
+ currentUserId?: string;
707
+ currentUserRole?: string;
708
+ onAddMemberClick?: () => void;
709
+ onRemoveMember?: (id: string) => void;
710
+ onBanMember?: (id: string) => void;
711
+ onUnbanMember?: (id: string) => void;
712
+ onPromoteMember?: (id: string) => void;
713
+ onDemoteMember?: (id: string) => void;
714
+ /** Label for the 'Add Member' button in the Members tab (default: 'Add Member') */
715
+ addMemberButtonLabel?: string;
716
+ /** Custom component for the 'Add Member' button */
717
+ AddMemberButtonComponent?: React.ComponentType<AddMemberButtonProps>;
718
+ /** Custom sub-component overrides */
719
+ MemberItemComponent?: React.ComponentType<ChannelInfoMemberItemProps>;
720
+ MediaItemComponent?: React.ComponentType<ChannelInfoMediaItemProps>;
721
+ LinkItemComponent?: React.ComponentType<ChannelInfoLinkItemProps>;
722
+ FileItemComponent?: React.ComponentType<ChannelInfoFileItemProps>;
723
+ EmptyStateComponent?: React.ComponentType<ChannelInfoEmptyStateProps>;
724
+ LoadingComponent?: React.ComponentType;
725
+ };
726
+ type ChannelInfoProps = {
727
+ /** Optional channel override. Defaults to activeChannel from context */
728
+ channel?: Channel$1;
729
+ /** Additional CSS class */
730
+ className?: string;
731
+ /** Custom avatar component */
732
+ AvatarComponent?: React.ComponentType<AvatarProps>;
733
+ /** Optional callback when the user clicks a close button */
734
+ onClose?: () => void;
735
+ /** Custom Title String for the banner */
736
+ title?: string;
737
+ /** Custom components to replace internal sections */
738
+ HeaderComponent?: React.ComponentType<ChannelInfoHeaderProps>;
739
+ CoverComponent?: React.ComponentType<ChannelInfoCoverProps>;
740
+ ActionsComponent?: React.ComponentType<ChannelInfoActionsProps>;
741
+ TabsComponent?: React.ComponentType<ChannelInfoTabsProps>;
742
+ /** Custom component replacing the entire AddMemberModal */
743
+ AddMemberModalComponent?: React.ComponentType<AddMemberModalProps>;
744
+ /** Custom component replacing the entire EditChannelModal */
745
+ EditChannelModalComponent?: React.ComponentType<EditChannelModalProps>;
746
+ /** Custom sub-component overrides (passed through to TabsComponent) */
747
+ MemberItemComponent?: React.ComponentType<ChannelInfoMemberItemProps>;
748
+ MediaItemComponent?: React.ComponentType<ChannelInfoMediaItemProps>;
749
+ LinkItemComponent?: React.ComponentType<ChannelInfoLinkItemProps>;
750
+ FileItemComponent?: React.ComponentType<ChannelInfoFileItemProps>;
751
+ EmptyStateComponent?: React.ComponentType<ChannelInfoEmptyStateProps>;
752
+ LoadingComponent?: React.ComponentType;
753
+ /** Add Member customization (passed through to AddMemberModal) */
754
+ addMemberModalTitle?: string;
755
+ addMemberSearchPlaceholder?: string;
756
+ addMemberLoadingText?: string;
757
+ addMemberEmptyText?: string;
758
+ addMemberAddLabel?: string;
759
+ addMemberAddingLabel?: string;
760
+ addMemberAddedLabel?: string;
761
+ /** Label for the 'Add Member' button in Members tab */
762
+ addMemberButtonLabel?: string;
763
+ /** Custom component for the 'Add Member' button */
764
+ AddMemberButtonComponent?: React.ComponentType<AddMemberButtonProps>;
765
+ /** Edit Channel customization (passed through to EditChannelModal) */
766
+ /** Override edit channel save logic */
767
+ onEditChannel?: (data: EditChannelData) => Promise<void>;
768
+ editChannelModalTitle?: string;
769
+ editChannelNameLabel?: string;
770
+ editChannelDescriptionLabel?: string;
771
+ editChannelNamePlaceholder?: string;
772
+ editChannelDescriptionPlaceholder?: string;
773
+ editChannelPublicLabel?: string;
774
+ editChannelSaveLabel?: string;
775
+ editChannelCancelLabel?: string;
776
+ editChannelSavingLabel?: string;
777
+ editChannelChangeAvatarLabel?: string;
778
+ editChannelImageAccept?: string;
779
+ editChannelMaxImageSize?: number;
780
+ editChannelMaxImageSizeError?: string;
781
+ /** Action Labels */
782
+ actionsSearchLabel?: string;
783
+ actionsSettingsLabel?: string;
784
+ actionsDeleteLabel?: string;
785
+ actionsLeaveLabel?: string;
786
+ /** Action callbacks */
787
+ onSearchClick?: () => void;
788
+ onLeaveChannel?: () => void;
789
+ onDeleteChannel?: () => void;
790
+ onAddMemberClick?: () => void;
791
+ onRemoveMember?: (id: string) => void;
792
+ onBanMember?: (id: string) => void;
793
+ onUnbanMember?: (id: string) => void;
794
+ onPromoteMember?: (id: string) => void;
795
+ onDemoteMember?: (id: string) => void;
796
+ /** Block/Unblock callbacks (messaging channels only) */
797
+ onBlockUser?: () => void;
798
+ onUnblockUser?: () => void;
799
+ /** I18n labels for block/unblock actions */
800
+ actionsBlockLabel?: string;
801
+ actionsUnblockLabel?: string;
802
+ };
803
+
804
+ declare const ChatProvider: React$1.FC<ChatProviderProps>;
805
+
806
+ declare const useChatClient: () => ChatContextValue;
807
+
808
+ declare const useChannel: () => UseChannelReturn;
809
+
810
+ /**
811
+ * Subscribes to real-time events and keeps the channel list in sync:
812
+ *
813
+ * 1. `message.new` → moves channel to top, auto-calls `markRead()` if
814
+ * the channel is currently active
815
+ * 2. `message.read` → triggers re-render so the unread badge disappears
816
+ *
817
+ * The SDK already mutates `channel.state.latestMessages` and
818
+ * `channel.state.unreadCount` before our listener fires, so we only
819
+ * need to re-order / flush the React state.
820
+ */
821
+ declare function useChannelListUpdates(channels: Channel$1[], setChannels: React.Dispatch<React.SetStateAction<Channel$1[]>>): void;
822
+
823
+ /**
824
+ * Custom hook to abstract real-time row-level updates for a single channel.
825
+ * Manages the local unread count, last message preview, and banned status for the channel row in the list.
826
+ */
827
+ declare function useChannelRowUpdates(channel: Channel$1, currentUserId?: string): {
828
+ isBannedInChannel: boolean;
829
+ isBlockedInChannel: boolean;
830
+ updateCount: number;
831
+ };
832
+
833
+ /**
834
+ * Hook that tracks whether the current user is banned in the given channel.
835
+ *
836
+ * Reads the initial value from `channel.state.membership.banned` and subscribes
837
+ * to `member.banned` / `member.unbanned` WebSocket events for real-time updates.
838
+ *
839
+ * Only triggers a re-render when the *current user* is the target of the event.
840
+ */
841
+ declare function useBannedState(channel: Channel$1 | null | undefined, currentUserId?: string): {
842
+ isBanned: boolean;
843
+ };
844
+
845
+ /**
846
+ * Hook that tracks whether the current user has blocked the other party
847
+ * in a messaging (1-1) channel.
848
+ *
849
+ * Reads the initial value from `channel.state.membership.blocked` and subscribes
850
+ * to `member.blocked` / `member.unblocked` WebSocket events for real-time updates.
851
+ *
852
+ * Only triggers a re-render when the *current user* is the target of the event
853
+ * (i.e., the blocker). When user A blocks user B, only A's membership has
854
+ * `blocked: true`. B is unaffected.
855
+ *
856
+ * This hook is only meaningful for `messaging` channels. For `team` channels,
857
+ * use `useBannedState` instead.
858
+ */
859
+ declare function useBlockedState(channel: Channel$1 | null | undefined, currentUserId?: string): {
860
+ isBlocked: boolean;
861
+ };
862
+
863
+ /**
864
+ * Hook that tracks whether the current user is in a 'pending' state for the given channel.
865
+ */
866
+ declare function usePendingState(channel: Channel$1 | null | undefined, currentUserId?: string): {
867
+ isPending: boolean;
868
+ };
869
+
870
+ /**
871
+ * Avatar component with image or initial fallback.
872
+ */
873
+ declare const Avatar: React$1.FC<AvatarProps>;
874
+
875
+ declare const ChannelItem: React$1.FC<ChannelItemProps>;
876
+ declare const ChannelList: React$1.FC<ChannelListProps>;
877
+
878
+ /**
879
+ * Channel wrapper component.
880
+ *
881
+ * Customization:
882
+ * - `HeaderComponent` — replace default ChannelHeader with a fully custom component.
883
+ * Receives `{ channel, name, image }` as props.
884
+ * - `EmptyStateIndicator` — custom component when no channel is selected.
885
+ */
886
+ declare const Channel: React$1.FC<ChannelProps>;
887
+
888
+ /**
889
+ * ChannelHeader displays the active channel's avatar and name.
890
+ *
891
+ * Customization:
892
+ * - `title` / `image` — override the channel name and avatar
893
+ * - `subtitle` — add a subtitle line (e.g. member count)
894
+ * - `AvatarComponent` — replace the avatar
895
+ * - `renderTitle(channel)` — fully custom title rendering
896
+ * - `renderRight(channel)` — render content on the right side
897
+ *
898
+ * For a fully custom header, use `Channel`'s `HeaderComponent` prop instead.
899
+ */
900
+ declare const ChannelHeader: React$1.FC<ChannelHeaderProps>;
901
+
902
+ declare const VirtualMessageList: React$1.FC<MessageListProps>;
903
+
904
+ declare const PinnedMessages: React$1.FC<PinnedMessagesProps>;
905
+
906
+ declare const MessageItem: React$1.FC<MessageItemProps>;
907
+ declare const SystemMessageItem: React$1.FC<SystemMessageItemProps>;
908
+
909
+ declare const MessageActionsBox: React$1.FC<MessageActionsBoxProps>;
910
+
911
+ /** Dispatch a global event to close all open dropdowns */
912
+ declare const closeAllDropdowns: () => void;
913
+ interface DropdownProps {
914
+ /** Whether the dropdown is open */
915
+ isOpen: boolean;
916
+ /** Rect from getBoundingClientRect() of the anchor element */
917
+ anchorRect: DOMRect | null;
918
+ /** Callback when dropdown requests to close (e.g., click outside, scroll, Escape) */
919
+ onClose: () => void;
920
+ /** Dropdown menu content */
921
+ children: React$1.ReactNode;
922
+ /** Horizontal alignment relative to the anchor. Default: 'left' */
923
+ align?: 'left' | 'right';
924
+ /** Optional custom CSS class for the container */
925
+ className?: string;
926
+ /** Optional custom CSS style for the container */
927
+ style?: React$1.CSSProperties;
928
+ }
929
+ declare const Dropdown: React$1.FC<DropdownProps>;
930
+
931
+ declare const MessageReactions: React$1.FC<MessageReactionsProps>;
932
+
933
+ declare const MessageQuickReactions: React$1.FC<{
934
+ message: FormatMessageResponse;
935
+ isOwnMessage: boolean;
936
+ }>;
937
+
938
+ type MessageActionList = {
939
+ canEdit: boolean;
940
+ canDelete: boolean;
941
+ canDeleteForMe: boolean;
942
+ canReply: boolean;
943
+ canQuote: boolean;
944
+ canForward: boolean;
945
+ canPin: boolean;
946
+ canCopy: boolean;
947
+ isPinned: boolean;
948
+ hasCapEdit: boolean;
949
+ hasCapDelete: boolean;
950
+ hasCapDeleteForMe: boolean;
951
+ hasCapPin: boolean;
952
+ hasCapReply: boolean;
953
+ hasCapQuote: boolean;
954
+ };
955
+ declare const useMessageActions: (message: FormatMessageResponse, isOwnMessage: boolean) => MessageActionList;
956
+
957
+ /**
958
+ * Format a Date or date-string to a short time string (HH:MM).
959
+ */
960
+ declare function formatTime(date: Date | string | undefined): string;
961
+ /**
962
+ * Return a YYYY-M-D key for date comparison (used by date separators).
963
+ */
964
+ declare function getDateKey(date: Date | string | undefined): string;
965
+ /**
966
+ * Format a date into a human-friendly label (Today / Yesterday / full date).
967
+ */
968
+ declare function formatDateLabel(date: Date | string | undefined): string;
969
+ /**
970
+ * Get the user id from a message, checking multiple possible sources.
971
+ */
972
+ declare function getMessageUserId(message: FormatMessageResponse): string;
973
+ /**
974
+ * Replace @user_id with @UserName for plain text previews.
975
+ * Returns the formatted string.
976
+ */
977
+ declare function replaceMentionsForPreview(text: string, message: FormatMessageResponse | {
978
+ mentioned_users?: string[];
979
+ mentioned_all?: boolean;
980
+ }, userMap: Record<string, string>, renderWrapper?: (userId: string, name: string) => string): string;
981
+
982
+ declare const MessageAttachment: React$1.FC<AttachmentProps>;
983
+ declare const AttachmentList: React$1.FC<{
984
+ attachments?: Attachment[];
985
+ }>;
986
+ /** Regular message: text with @mentions + attachments */
987
+ declare const RegularMessage: React$1.FC<MessageRendererProps>;
988
+ /** System message: centered info text, parsed from raw format */
989
+ declare const SystemMessage: React$1.FC<MessageRendererProps>;
990
+ /** Signal message: call events */
991
+ declare const SignalMessage: React$1.FC<MessageRendererProps>;
992
+ /** Poll message */
993
+ declare const PollMessage: React$1.FC<MessageRendererProps>;
994
+ /** Sticker message */
995
+ declare const StickerMessage: React$1.FC<MessageRendererProps>;
996
+ /** Error message */
997
+ declare const ErrorMessage: React$1.FC<MessageRendererProps>;
998
+ /**
999
+ * Map from MessageLabel → component.
1000
+ * Consumer can override individual renderers via the `messageRenderers` prop.
1001
+ */
1002
+ declare const defaultMessageRenderers: Record<MessageLabel, React$1.ComponentType<MessageRendererProps>>;
1003
+
1004
+ declare const MessageInput: React$1.FC<MessageInputProps>;
1005
+
1006
+ /**
1007
+ * FilesPreview — renders selected files with thumbnails and remove buttons.
1008
+ * Shown above the text input area in MessageInput.
1009
+ */
1010
+ declare const FilesPreview: React$1.FC<FilesPreviewProps>;
1011
+
1012
+ declare const MentionSuggestions: React$1.FC<MentionSuggestionsProps>;
1013
+
1014
+ declare function useMentions({ members, currentUserId, editableRef, }: UseMentionsOptions): UseMentionsReturn;
1015
+
1016
+ type UseScrollToMessageOptions = {
1017
+ vlistRef: React.RefObject<VListHandle | null>;
1018
+ messagesRef: React.MutableRefObject<FormatMessageResponse[]>;
1019
+ setHasMore: React.Dispatch<React.SetStateAction<boolean>>;
1020
+ setHasNewer: React.Dispatch<React.SetStateAction<boolean>>;
1021
+ /** Getter to access the VList DOM element (scoped to container) */
1022
+ getVListElement: () => HTMLElement | null;
1023
+ scrollToBottom: (smooth: boolean) => void;
1024
+ /** Shared guard ref — blocks scroll-triggered loads during jumps */
1025
+ jumpingRef: React.MutableRefObject<boolean>;
1026
+ };
1027
+ type UseScrollToMessageReturn = {
1028
+ highlightedId: string | null;
1029
+ scrollToMessage: (messageId: string) => void;
1030
+ jumpToLatest: () => void;
1031
+ };
1032
+ declare function useScrollToMessage({ vlistRef, messagesRef, setHasMore, setHasNewer, getVListElement, scrollToBottom, jumpingRef, }: UseScrollToMessageOptions): UseScrollToMessageReturn;
1033
+
1034
+ /** Filter out messages whose id already exists in `existing` (or self-dedup if omitted). */
1035
+ declare const dedupMessages: (incoming: any[], existing?: any[]) => any[];
1036
+ type UseLoadMessagesOptions = {
1037
+ vlistRef: React.RefObject<VListHandle | null>;
1038
+ messagesRef: React.MutableRefObject<FormatMessageResponse[]>;
1039
+ /** Shared guard ref — skip scroll-triggered loads during jump transitions */
1040
+ jumpingRef: React.MutableRefObject<boolean>;
1041
+ loadMoreLimit?: number;
1042
+ };
1043
+ type UseLoadMessagesReturn = {
1044
+ /** VList shift mode — true during prepend, auto-resets to false */
1045
+ shiftMode: boolean;
1046
+ hasMore: boolean;
1047
+ setHasMore: React.Dispatch<React.SetStateAction<boolean>>;
1048
+ hasNewer: boolean;
1049
+ setHasNewer: React.Dispatch<React.SetStateAction<boolean>>;
1050
+ hasMoreRef: React.RefObject<boolean>;
1051
+ hasNewerRef: React.RefObject<boolean>;
1052
+ loadingMoreRef: React.MutableRefObject<boolean>;
1053
+ loadingNewerRef: React.MutableRefObject<boolean>;
1054
+ loadMore: () => Promise<void>;
1055
+ loadNewer: () => Promise<void>;
1056
+ handleScroll: (offset: number) => void;
1057
+ isAtBottomRef: React.MutableRefObject<boolean>;
1058
+ };
1059
+ declare function useLoadMessages({ vlistRef, messagesRef, jumpingRef, loadMoreLimit, }: UseLoadMessagesOptions): UseLoadMessagesReturn;
1060
+
1061
+ type UseChannelMessagesOptions = {
1062
+ scrollToBottom: (smooth: boolean) => void;
1063
+ /** Shared guard ref — blocks scroll-triggered loads during channel switch */
1064
+ jumpingRef: React.MutableRefObject<boolean>;
1065
+ isAtBottomRef: React.MutableRefObject<boolean>;
1066
+ /** Called to reset load-more state when channel switches */
1067
+ onChannelSwitch?: () => void;
1068
+ };
1069
+ /**
1070
+ * Subscribes to channel message events and handles:
1071
+ * - message.new → sync + scroll to bottom
1072
+ * - message.updated / message.deleted → sync only
1073
+ * - Channel switch → reset state + scroll to bottom
1074
+ */
1075
+ declare function useChannelMessages({ scrollToBottom, jumpingRef, isAtBottomRef, onChannelSwitch, }: UseChannelMessagesOptions): void;
1076
+
1077
+ declare const QuotedMessagePreview: React$1.FC<QuotedMessagePreviewProps>;
1078
+
1079
+ declare const ReplyPreview: React$1.FC<ReplyPreviewProps>;
1080
+
1081
+ declare const ForwardMessageModal: React$1.FC<ForwardMessageModalProps>;
1082
+
1083
+ type TypingUser = {
1084
+ id: string;
1085
+ name?: string;
1086
+ };
1087
+ /**
1088
+ * Hook that subscribes to typing events on the active channel
1089
+ * and returns the list of currently‑typing users (excluding the current user).
1090
+ *
1091
+ * Stale entries are auto‑cleaned every 7 seconds, consistent with
1092
+ * the SDK's `channel.state.clean()` behaviour.
1093
+ */
1094
+ declare function useTypingIndicator(): {
1095
+ typingUsers: TypingUser[];
1096
+ };
1097
+
1098
+ type TypingIndicatorProps = {
1099
+ /** Custom render function for the typing text */
1100
+ renderText?: (users: TypingUser[]) => React$1.ReactNode;
1101
+ };
1102
+ /**
1103
+ * Displays a "X is typing..." indicator below the message list.
1104
+ * Automatically subscribes to typing events via the useTypingIndicator hook.
1105
+ */
1106
+ declare const TypingIndicator: React$1.FC<TypingIndicatorProps>;
1107
+
1108
+ declare const DefaultChannelInfoHeader: React$1.FC<ChannelInfoHeaderProps>;
1109
+ declare const DefaultChannelInfoCover: React$1.FC<ChannelInfoCoverProps>;
1110
+ declare const DefaultChannelInfoActions: React$1.FC<ChannelInfoActionsProps>;
1111
+ declare const ChannelInfo: React$1.FC<ChannelInfoProps>;
1112
+
1113
+ declare const DefaultChannelInfoTabs: React$1.FC<ChannelInfoTabsProps>;
1114
+
1115
+ declare const Modal: React$1.FC<ModalProps>;
1116
+
1117
+ type PanelProps = {
1118
+ /** Whether the panel is visible */
1119
+ isOpen: boolean;
1120
+ /** Called when user clicks the back button */
1121
+ onClose: () => void;
1122
+ /** Panel title shown in the header */
1123
+ title?: string;
1124
+ /** Panel body content */
1125
+ children: React$1.ReactNode;
1126
+ /** Optional header content (replaces default title + back button) */
1127
+ headerContent?: React$1.ReactNode;
1128
+ /** Additional CSS class name */
1129
+ className?: string;
1130
+ };
1131
+ /**
1132
+ * Reusable sliding panel component.
1133
+ * Slides in from the right to overlay itself on whatever container it's placed in.
1134
+ * Use it like a Modal but inside a sidebar — call `isOpen` to show/hide.
1135
+ */
1136
+ declare const Panel: React$1.FC<PanelProps>;
1137
+
1138
+ export { type AddMemberButtonProps, type AddMemberModalProps, type AddMemberUserItemProps, type AttachButtonProps, type AttachmentItem, AttachmentList, type AttachmentProps, Avatar, type AvatarProps, Channel, ChannelHeader, type ChannelHeaderData, type ChannelHeaderProps, ChannelInfo, type ChannelInfoActionsProps, type ChannelInfoCoverProps, type ChannelInfoEmptyStateProps, type ChannelInfoFileItemProps, type ChannelInfoHeaderProps, type ChannelInfoLinkItemProps, type ChannelInfoMediaItemProps, type ChannelInfoMemberItemProps, type ChannelInfoProps, type ChannelInfoTabsProps, ChannelItem, type ChannelItemProps, ChannelList, type ChannelListProps, type ChannelProps, type ChatContextValue, ChatProvider, type ChatProviderProps, type DateSeparatorProps, DefaultChannelInfoActions, DefaultChannelInfoCover, DefaultChannelInfoHeader, DefaultChannelInfoTabs, Dropdown, type DropdownProps, type EmojiButtonProps, type EmojiPickerProps, ErrorMessage, type FilePreviewItem, FilesPreview, type FilesPreviewProps, type ForwardChannelItemProps, ForwardMessageModal, type ForwardMessageModalProps, type JumpToLatestProps, type LatestReaction, type MediaTab, type MentionMember, type MentionPayload, MentionSuggestions, type MentionSuggestionsProps, MessageActionsBox, type MessageActionsBoxProps, MessageAttachment, type MessageBubbleProps, MessageInput, type MessageInputProps, MessageItem, type MessageItemProps, type MessageListProps, MessageQuickReactions, MessageReactions, type MessageReactionsProps, type MessageRendererProps, Modal, type ModalProps, Panel, type PinnedMessageItemProps, PinnedMessages, type PinnedMessagesProps, PollMessage, QuotedMessagePreview, type QuotedMessagePreviewProps, type ReactionUser, RegularMessage, ReplyPreview, type ReplyPreviewProps, type SendButtonProps, SignalMessage, StickerMessage, SystemMessage, SystemMessageItem, type SystemMessageItemProps, type Theme, TypingIndicator, type TypingIndicatorProps, type TypingUser, type UseChannelMessagesOptions, type UseChannelReturn, type UseLoadMessagesOptions, type UseLoadMessagesReturn, type UseMentionsOptions, type UseMentionsReturn, type UseScrollToMessageOptions, type UseScrollToMessageReturn, VirtualMessageList, closeAllDropdowns, dedupMessages, defaultMessageRenderers, formatDateLabel, formatTime, getDateKey, getMessageUserId, replaceMentionsForPreview, useBannedState, useBlockedState, useChannel, useChannelListUpdates, useChannelMessages, useChannelRowUpdates, useChatClient, useLoadMessages, useMentions, useMessageActions, usePendingState, useScrollToMessage, useTypingIndicator };