@ermis-network/ermis-chat-react 1.0.9 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +144 -0
  2. package/dist/index.cjs +8320 -3427
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +1277 -291
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.mts +1131 -99
  7. package/dist/index.d.ts +1131 -99
  8. package/dist/index.mjs +8168 -3319
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +9 -4
  11. package/src/channelTypeUtils.ts +1 -1
  12. package/src/components/Avatar.tsx +2 -1
  13. package/src/components/Channel.tsx +6 -5
  14. package/src/components/ChannelActions.tsx +67 -3
  15. package/src/components/ChannelHeader.tsx +27 -37
  16. package/src/components/ChannelInfo/AddMemberModal.tsx +12 -2
  17. package/src/components/ChannelInfo/ChannelInfo.tsx +410 -187
  18. package/src/components/ChannelInfo/ChannelInfoTabs.tsx +59 -297
  19. package/src/components/ChannelInfo/ChannelSettingsPanel.tsx +30 -174
  20. package/src/components/ChannelInfo/EditChannelModal.tsx +6 -3
  21. package/src/components/ChannelInfo/MediaGridItem.tsx +215 -68
  22. package/src/components/ChannelInfo/MemberListItem.tsx +2 -3
  23. package/src/components/ChannelInfo/MessageSearchPanel.tsx +27 -126
  24. package/src/components/ChannelInfo/States.tsx +1 -1
  25. package/src/components/ChannelInfo/index.ts +3 -0
  26. package/src/components/ChannelInfo/useChannelInfoTabs.tsx +427 -0
  27. package/src/components/ChannelInfo/useChannelSettings.ts +212 -0
  28. package/src/components/ChannelInfo/useMessageSearch.tsx +141 -0
  29. package/src/components/ChannelList.tsx +247 -301
  30. package/src/components/CreateChannelModal.tsx +290 -93
  31. package/src/components/Dropdown.tsx +1 -16
  32. package/src/components/EditPreview.tsx +1 -0
  33. package/src/components/ErmisCallProvider.tsx +72 -17
  34. package/src/components/ErmisCallUI.tsx +43 -20
  35. package/src/components/FilesPreview.tsx +8 -12
  36. package/src/components/FlatTopicGroupItem.tsx +243 -0
  37. package/src/components/ForwardMessageModal.tsx +43 -81
  38. package/src/components/MediaLightbox.tsx +454 -292
  39. package/src/components/MentionSuggestions.tsx +47 -35
  40. package/src/components/MessageActionsBox.tsx +6 -1
  41. package/src/components/MessageInput.tsx +165 -17
  42. package/src/components/MessageInputDefaults.tsx +127 -1
  43. package/src/components/MessageItem.tsx +155 -43
  44. package/src/components/MessageQuickReactions.tsx +153 -23
  45. package/src/components/MessageReactions.tsx +49 -3
  46. package/src/components/MessageRenderers.tsx +1114 -445
  47. package/src/components/Panel.tsx +1 -14
  48. package/src/components/PinnedMessages.tsx +55 -15
  49. package/src/components/PreviewOverlay.tsx +24 -0
  50. package/src/components/QuotedMessagePreview.tsx +99 -8
  51. package/src/components/ReadReceipts.tsx +2 -1
  52. package/src/components/RecoveryPin/RecoveryPin.tsx +279 -0
  53. package/src/components/RecoveryPin/index.ts +19 -0
  54. package/src/components/TopicList.tsx +236 -0
  55. package/src/components/TopicModal.tsx +4 -1
  56. package/src/components/TypingIndicator.tsx +17 -8
  57. package/src/components/UserPicker.tsx +94 -16
  58. package/src/components/VirtualMessageList.tsx +419 -113
  59. package/src/context/ChatComponentsContext.tsx +14 -0
  60. package/src/context/ChatProvider.tsx +44 -14
  61. package/src/context/ErmisCallContext.tsx +4 -0
  62. package/src/hooks/useChannelCapabilities.ts +7 -4
  63. package/src/hooks/useChannelData.ts +10 -3
  64. package/src/hooks/useChannelListUpdates.ts +94 -21
  65. package/src/hooks/useChannelMessages.ts +391 -42
  66. package/src/hooks/useChannelRowUpdates.ts +36 -5
  67. package/src/hooks/useChatUser.ts +39 -0
  68. package/src/hooks/useContactChannels.ts +45 -0
  69. package/src/hooks/useContactCount.ts +50 -0
  70. package/src/hooks/useDownloadHandler.ts +36 -0
  71. package/src/hooks/useDragAndDrop.ts +79 -0
  72. package/src/hooks/useE2eeAttachmentRenderer.ts +204 -0
  73. package/src/hooks/useE2eeFileUpload.ts +38 -0
  74. package/src/hooks/useFileUpload.ts +25 -5
  75. package/src/hooks/useForwardMessage.ts +309 -0
  76. package/src/hooks/useInviteChannels.ts +88 -0
  77. package/src/hooks/useInviteCount.ts +104 -0
  78. package/src/hooks/useLoadMessages.ts +16 -4
  79. package/src/hooks/useMentions.ts +60 -7
  80. package/src/hooks/useMessageActions.ts +19 -10
  81. package/src/hooks/useMessageSend.ts +64 -12
  82. package/src/hooks/usePendingE2eeSends.ts +29 -0
  83. package/src/hooks/usePendingState.ts +21 -4
  84. package/src/hooks/usePreviewState.ts +69 -0
  85. package/src/hooks/useRecoveryPin.ts +287 -0
  86. package/src/hooks/useScrollToMessage.ts +29 -4
  87. package/src/hooks/useStickerPicker.ts +62 -0
  88. package/src/hooks/useTopicGroupUpdates.ts +235 -0
  89. package/src/index.ts +79 -6
  90. package/src/messageTypeUtils.ts +27 -1
  91. package/src/styles/_base.css +0 -1
  92. package/src/styles/_call-ui.css +59 -2
  93. package/src/styles/_channel-info.css +50 -4
  94. package/src/styles/_channel-list.css +131 -68
  95. package/src/styles/_create-channel-modal.css +10 -0
  96. package/src/styles/_forward-modal.css +16 -1
  97. package/src/styles/_media-lightbox.css +67 -2
  98. package/src/styles/_mentions.css +1 -1
  99. package/src/styles/_message-actions.css +3 -4
  100. package/src/styles/_message-bubble.css +631 -112
  101. package/src/styles/_message-input.css +139 -0
  102. package/src/styles/_message-list.css +91 -18
  103. package/src/styles/_message-quick-reactions.css +105 -32
  104. package/src/styles/_message-reactions.css +22 -32
  105. package/src/styles/_modal.css +2 -1
  106. package/src/styles/_preview-overlay.css +38 -0
  107. package/src/styles/_recovery-pin.css +97 -0
  108. package/src/styles/_tokens.css +22 -20
  109. package/src/styles/_typing-indicator.css +26 -10
  110. package/src/styles/index.css +2 -0
  111. package/src/types.ts +477 -15
  112. package/src/utils/avatarColors.ts +48 -0
  113. package/src/utils.ts +219 -16
package/src/types.ts CHANGED
@@ -6,7 +6,11 @@ import type {
6
6
  ChannelFilters,
7
7
  ChannelSort,
8
8
  ChannelQueryOptions,
9
+ E2eeRecoveryPolicy,
10
+ E2eeAttachmentManifest,
9
11
  UserCallInfo,
12
+ SystemMessageTranslations,
13
+ SignalMessageTranslations,
10
14
  } from '@ermis-network/ermis-chat-sdk';
11
15
  import type { ErmisChat } from '@ermis-network/ermis-chat-sdk';
12
16
 
@@ -54,11 +58,21 @@ export type ChatContextValue = {
54
58
  setJumpToMessageId: (id: string | null) => void;
55
59
  /** Indicates whether the direct call feature is enabled */
56
60
  enableCall?: boolean;
61
+ /** Save a draft message (innerHTML and files) for a specific channel */
62
+ setDraft: (cid: string, draft: { html: string; files: any[] }) => void;
63
+ /** Retrieve the saved draft for a specific channel */
64
+ getDraft: (cid: string) => { html: string; files: any[] } | undefined;
65
+ /** Clear all saved drafts (e.g. on logout) */
66
+ clearAllDrafts: () => void;
57
67
  };
58
68
 
69
+ import type { ChatComponentsContextValue } from './context/ChatComponentsContext';
70
+
59
71
  export type ChatProviderProps = {
60
72
  client: ErmisChat;
61
73
  children: React.ReactNode;
74
+ /** Global UI primitive components registry */
75
+ components?: ChatComponentsContextValue;
62
76
  /** Initial theme, defaults to 'dark' */
63
77
  initialTheme?: Theme;
64
78
  /** Enable direct call feature (Audio/Video). If enabled, configures internal CallProvider */
@@ -193,6 +207,9 @@ export type ErmisCallRingingProps = {
193
207
  endCallLabel: string;
194
208
  audioCallBadgeLabel: string;
195
209
  videoCallBadgeLabel: string;
210
+ isAccepting?: boolean;
211
+ isRejecting?: boolean;
212
+ isEnding?: boolean;
196
213
  };
197
214
 
198
215
  /** Props for the Connected Audio state view */
@@ -240,6 +257,7 @@ export type ErmisCallControlsBarProps = {
240
257
  selectedVideoDeviceId: string;
241
258
  switchAudioDevice: (id: string) => Promise<void>;
242
259
  switchVideoDevice: (id: string) => Promise<void>;
260
+ isEnding?: boolean;
243
261
  };
244
262
 
245
263
  /* ----------------------------------------------------------
@@ -337,8 +355,10 @@ export type ChannelActionLabels = {
337
355
  closeTopic?: string;
338
356
  reopenTopic?: string;
339
357
  createTopic?: string;
358
+ deleteTopic?: string;
340
359
  deleteChannel?: string;
341
360
  leaveChannel?: string;
361
+ truncateChannel?: string;
342
362
  };
343
363
 
344
364
  export type ChannelActionIcons = {
@@ -350,8 +370,10 @@ export type ChannelActionIcons = {
350
370
  CloseTopicIcon?: React.ReactNode;
351
371
  ReopenTopicIcon?: React.ReactNode;
352
372
  CreateTopicIcon?: React.ReactNode;
373
+ DeleteTopicIcon?: React.ReactNode;
353
374
  DeleteChannelIcon?: React.ReactNode;
354
375
  LeaveChannelIcon?: React.ReactNode;
376
+ TruncateChannelIcon?: React.ReactNode;
355
377
  };
356
378
 
357
379
  export type ChannelActionsProps = {
@@ -365,7 +387,7 @@ export type ChannelItemProps = {
365
387
  isActive: boolean;
366
388
  hasUnread: boolean;
367
389
  unreadCount: number;
368
- lastMessageText: string;
390
+ lastMessageText: React.ReactNode;
369
391
  lastMessageUser: string;
370
392
  lastMessageTimestamp?: Date | string | null;
371
393
  onSelect: (channel: Channel) => void;
@@ -388,6 +410,10 @@ export type ChannelItemProps = {
388
410
  onEditTopic?: (channel: Channel) => void;
389
411
  /** Handler when Close/Reopen Topic action is triggered */
390
412
  onToggleCloseTopic?: (channel: Channel, isClosed: boolean) => void;
413
+ /** Handler when Delete Topic action is triggered */
414
+ onDeleteTopic?: (channel: Channel) => void;
415
+ /** Handler when Truncate Channel action is triggered */
416
+ onTruncateChannel?: (channel: Channel) => void;
391
417
  /** Array of action IDs to hide from the actions dropdown */
392
418
  hiddenActions?: string[];
393
419
  /** Custom labels for default channel actions */
@@ -398,6 +424,70 @@ export type ChannelItemProps = {
398
424
  isOnline?: boolean;
399
425
  };
400
426
 
427
+ /* ----------------------------------------------------------
428
+ TopicPill types (for FlatTopicGroupItem)
429
+ ---------------------------------------------------------- */
430
+ export type TopicPillProps = {
431
+ /** The topic channel to display as a pill */
432
+ topic: Channel;
433
+ /** Size of the topic avatar in pixels (default: 16) */
434
+ avatarSize?: number;
435
+ };
436
+
437
+ /* ----------------------------------------------------------
438
+ TopicList types
439
+ ---------------------------------------------------------- */
440
+ export type TopicListProps = {
441
+ /** Parent channel that has topics enabled */
442
+ channel: Channel;
443
+ /** Custom channel item component for each topic row */
444
+ ChannelItemComponent?: React.ComponentType<ChannelItemProps>;
445
+ /** Custom avatar for the general (parent) topic */
446
+ GeneralAvatarComponent?: React.ComponentType<AvatarProps>;
447
+ /** Custom avatar for sub-topic items */
448
+ TopicAvatarComponent?: React.ComponentType<AvatarProps>;
449
+ /** Custom avatar component (fallback) */
450
+ AvatarComponent?: React.ComponentType<AvatarProps>;
451
+ /** Label for the general topic (default: 'general') */
452
+ generalTopicLabel?: string;
453
+ /** Pinned icon component */
454
+ PinnedIconComponent?: React.ComponentType;
455
+ /** Custom channel actions component */
456
+ ChannelActionsComponent?: React.ComponentType<ChannelActionsProps>;
457
+ /** Called when a topic is selected */
458
+ onSelectTopic?: (topic: Channel) => void;
459
+ /** Handler for Edit Topic action */
460
+ onEditTopic?: (channel: Channel) => void;
461
+ /** Handler for Close/Reopen Topic action */
462
+ onToggleCloseTopic?: (channel: Channel, isClosed: boolean) => void;
463
+ /** Handler for Delete Topic action */
464
+ onDeleteTopic?: (channel: Channel) => void;
465
+ /** Actions to hide */
466
+ hiddenActions?: string[];
467
+ /** Custom action labels */
468
+ actionLabels?: ChannelActionLabels;
469
+ /** Custom action icons */
470
+ actionIcons?: ChannelActionIcons;
471
+ /** Icon for closed topics */
472
+ closedTopicIcon?: React.ReactNode;
473
+ /** Badge label for pending members */
474
+ pendingBadgeLabel?: string;
475
+ /** Badge label for blocked members */
476
+ blockedBadgeLabel?: string;
477
+ /** Auto-scroll the topic list to the top when the current user sends a message (default: true) */
478
+ scrollToTopOnOwnMessage?: boolean;
479
+ deletedMessageLabel?: React.ReactNode;
480
+ stickerMessageLabel?: React.ReactNode;
481
+ photoMessageLabel?: React.ReactNode;
482
+ videoMessageLabel?: React.ReactNode;
483
+ voiceRecordingMessageLabel?: React.ReactNode;
484
+ fileMessageLabel?: React.ReactNode;
485
+ encryptedMessageLabel?: React.ReactNode;
486
+ encryptedMessageUnavailableLabel?: React.ReactNode;
487
+ systemMessageTranslations?: SystemMessageTranslations;
488
+ signalMessageTranslations?: SignalMessageTranslations;
489
+ };
490
+
401
491
  export type ChannelListProps = {
402
492
  filters?: ChannelFilters;
403
493
  sort?: ChannelSort;
@@ -405,6 +495,8 @@ export type ChannelListProps = {
405
495
  renderChannel?: (channel: Channel, isActive: boolean) => React.ReactNode;
406
496
  onChannelSelect?: (channel: Channel) => void;
407
497
  className?: string;
498
+ /** Whether to show pending invites visually in the main list (default: true) */
499
+ showPendingInvites?: boolean;
408
500
  /** Array of action IDs to hide from the actions dropdown */
409
501
  hiddenActions?: string[];
410
502
  LoadingIndicator?: React.ComponentType<{ text?: string }>;
@@ -420,18 +512,34 @@ export type ChannelListProps = {
420
512
  pendingBadgeLabel?: string;
421
513
  /** Label for the loading indicator */
422
514
  loadingLabel?: string;
423
- /** Label for the empty state indicator */
515
+ /** Component to display when there is an error loading channels */
516
+ ErrorIndicator?: React.ComponentType<{ text?: string; onRetry?: () => void }>;
517
+ /** Label to display in the error indicator */
518
+ errorLabel?: string;
519
+ /** Label to display in the empty state indicator */
424
520
  emptyStateLabel?: string;
425
521
  /** Label for the blocked channel badge hover */
426
522
  blockedBadgeLabel?: string;
427
- /** Custom component for rendering topic group */
428
- ChannelTopicGroupComponent?: React.ComponentType<any>;
429
- /** Custom avatar component for general topic */
430
- GeneralTopicAvatarComponent?: React.ComponentType<any>;
431
- /** Custom avatar component for other topics */
432
- TopicAvatarComponent?: React.ComponentType<any>;
433
- /** Name for the general topic (default: "general") */
434
- generalTopicLabel?: string;
523
+ /** Label for deleted messages in the preview strip (default: 'This message was deleted') */
524
+ deletedMessageLabel?: React.ReactNode;
525
+ /** Label for sticker messages in the preview strip (default: 'Sticker') */
526
+ stickerMessageLabel?: React.ReactNode;
527
+ /** Label for photo messages in the preview strip (default: '📷 Photo') */
528
+ photoMessageLabel?: React.ReactNode;
529
+ /** Label for video messages in the preview strip (default: '🎬 Video') */
530
+ videoMessageLabel?: React.ReactNode;
531
+ /** Label for voice message in the preview strip (default: '🎤 Voice message') */
532
+ voiceRecordingMessageLabel?: React.ReactNode;
533
+ /** Label for file messages in the preview strip (default: '📎 File') */
534
+ fileMessageLabel?: React.ReactNode;
535
+ /** Label for encrypted messages in the preview strip (default: 'Encrypted message') */
536
+ encryptedMessageLabel?: React.ReactNode;
537
+ /** Label for encrypted messages that failed in the preview strip (default: 'Encrypted message unavailable') */
538
+ encryptedMessageUnavailableLabel?: React.ReactNode;
539
+ /** Custom translation templates for system messages in the preview strip */
540
+ systemMessageTranslations?: SystemMessageTranslations;
541
+ /** Custom translation templates for signal (call) messages in the preview strip */
542
+ signalMessageTranslations?: SignalMessageTranslations;
435
543
  /** Handler when Add Topic button is clicked on a team channel */
436
544
  onAddTopic?: (channel: Channel) => void;
437
545
  /** Optional custom emoji picker for TopicModal */
@@ -444,12 +552,32 @@ export type ChannelListProps = {
444
552
  onEditTopic?: (channel: Channel) => void;
445
553
  /** Handler when Close/Reopen Topic action is triggered */
446
554
  onToggleCloseTopic?: (channel: Channel, isClosed: boolean) => void;
555
+ /** Handler when Delete Topic action is triggered */
556
+ onDeleteTopic?: (channel: Channel) => void;
557
+ /** Handler when Truncate action is triggered */
558
+ onTruncateChannel?: (channel: Channel) => void;
447
559
  /** Custom labels for default channel actions */
448
560
  actionLabels?: ChannelActionLabels;
449
561
  /** Custom icons for default channel actions */
450
562
  actionIcons?: ChannelActionIcons;
451
563
  /** Show online/offline indicator dots on channel item avatars for friend channels (default: true) */
452
564
  showOnlineStatus?: boolean;
565
+ /** Handler when a topic-enabled channel is clicked — enables drill-down mode */
566
+ onTopicDrillDown?: (channel: Channel) => void;
567
+ /** Max number of topic pills shown in the preview strip (default: 3) */
568
+ maxVisibleTopics?: number;
569
+ /** Label for the overflow indicator when topics exceed maxVisibleTopics (default: '...') */
570
+ moreTopicsLabel?: string;
571
+ /** Label for the general topic pill (default: 'general') */
572
+ generalTopicLabel?: string;
573
+ /** Custom component for rendering each topic pill in the preview strip */
574
+ TopicPillComponent?: React.ComponentType<TopicPillProps>;
575
+ /** Custom component to replace the entire flat topic group item */
576
+ FlatTopicGroupItemComponent?: React.ComponentType<any>;
577
+ /** Auto-scroll the channel list to the top when the current user sends a message (default: true) */
578
+ scrollToTopOnOwnMessage?: boolean;
579
+ /** Whether to show topic pills on team channels (default: false) */
580
+ showTopicPills?: boolean;
453
581
  };
454
582
 
455
583
  /* ----------------------------------------------------------
@@ -464,6 +592,15 @@ export type AttachmentProps = {
464
592
  export type MessageRendererProps = {
465
593
  message: FormatMessageResponse;
466
594
  isOwnMessage: boolean;
595
+ systemMessageTranslations?: SystemMessageTranslations;
596
+ signalMessageTranslations?: SignalMessageTranslations;
597
+ onMentionClick?: (userId: string) => void;
598
+ /** I18n Label for encrypted messages (default: 'Encrypted message') */
599
+ encryptedMessageLabel?: string;
600
+ /** I18n Label for encrypted messages that failed to decrypt (default: 'Encrypted message could not be decrypted') */
601
+ encryptedMessageFailedLabel?: string;
602
+ /** I18n Label for encrypted messages being decrypted (default: 'Decrypting encrypted message...') */
603
+ encryptedMessageDecryptingLabel?: string;
467
604
  };
468
605
 
469
606
  export type MessageBubbleProps = {
@@ -485,9 +622,14 @@ export type JumpToLatestProps = {
485
622
  ---------------------------------------------------------- */
486
623
  export type MediaLightboxItem = {
487
624
  type: 'image' | 'video';
488
- src: string;
625
+ src?: string;
489
626
  alt?: string;
490
627
  posterSrc?: string;
628
+ loading?: boolean;
629
+ progressLabel?: string;
630
+ download?: () => Promise<void> | void;
631
+ onPlaybackError?: (context?: { currentTime?: number }) => Promise<void> | void;
632
+ onDispose?: () => Promise<void> | void;
491
633
  };
492
634
 
493
635
  export type MediaLightboxProps = {
@@ -503,6 +645,12 @@ export type MediaLightboxProps = {
503
645
  export type MessageListProps = {
504
646
  /** Fully custom render for each message */
505
647
  renderMessage?: (message: FormatMessageResponse, isOwnMessage: boolean) => React.ReactNode;
648
+ /** Handler when a mention is clicked */
649
+ onMentionClick?: (userId: string) => void;
650
+ /** Handler when a sender's username is clicked in the message list */
651
+ onUserNameClick?: (userId: string) => void;
652
+ /** Handler when clicking to add a custom reaction */
653
+ onAddReactionClick?: (e: React.MouseEvent, messageId: string) => void;
506
654
  /** Additional CSS class name */
507
655
  className?: string;
508
656
  /** Custom empty state component */
@@ -517,6 +665,8 @@ export type MessageListProps = {
517
665
  loadMoreLimit?: number;
518
666
  /** Custom date separator component */
519
667
  DateSeparatorComponent?: React.ComponentType<DateSeparatorProps>;
668
+ /** Locale string for date separator labels (e.g. 'vi', 'en-US'). Falls back to browser default. */
669
+ dateLocale?: string;
520
670
  /** Custom message item component (replaces the entire row) */
521
671
  MessageItemComponent?: React.ComponentType<MessageItemProps>;
522
672
  /** Custom system message item component */
@@ -572,9 +722,42 @@ export type MessageListProps = {
572
722
  closedTopicReopenLabel?: string;
573
723
 
574
724
  /** Custom component for pending invitee notification in direct channels */
575
- PendingInviteeNotificationComponent?: React.ComponentType<{ inviteeName?: string, label?: string }>;
725
+ PendingInviteeNotificationComponent?: React.ComponentType<{ inviteeName?: string; label?: string }>;
576
726
  /** I18n Label for pending invitee notification */
577
727
  pendingInviteeLabel?: string | ((inviteeName?: string) => string);
728
+
729
+ /** I18n Label for pinned messages header */
730
+ pinnedMessagesLabel?: string | ((count: number) => string);
731
+ /** I18n Label for seeing all pinned messages */
732
+ seeAllLabel?: string;
733
+ /** I18n Label for collapsing pinned messages */
734
+ collapseLabel?: string;
735
+ /** I18n Label for unpinning a message */
736
+ unpinLabel?: string;
737
+ /** I18n Label for sticker message preview */
738
+ stickerLabel?: string;
739
+ /** I18n Label for typing indicator */
740
+ typingIndicatorLabel?: (users: Array<{ id: string; name?: string }>) => string;
741
+ /** I18n Label for deleted display messages (display_type === 'deleted') */
742
+ deletedMessageLabel?: string;
743
+ /** I18n Label for attachment-only previews */
744
+ attachmentLabel?: string;
745
+ /** I18n Label for messages whose contents are unavailable */
746
+ unavailableMessageLabel?: string;
747
+ /** I18n Label for encrypted messages (default: 'Encrypted message') */
748
+ encryptedMessageLabel?: string;
749
+ /** I18n Label for encrypted messages that failed to decrypt (default: 'Encrypted message could not be decrypted') */
750
+ encryptedMessageFailedLabel?: string;
751
+ /** I18n Label for encrypted messages being decrypted (default: 'Decrypting encrypted message...') */
752
+ encryptedMessageDecryptingLabel?: string;
753
+ /** I18n Label for encrypted messages unavailable in sidebar preview (default: 'Encrypted message unavailable') */
754
+ encryptedMessageUnavailableLabel?: string;
755
+ /** Custom translation templates for system messages */
756
+ systemMessageTranslations?: SystemMessageTranslations;
757
+ /** Custom translation templates for signal (call) messages */
758
+ signalMessageTranslations?: SignalMessageTranslations;
759
+ /** Whether to include hidden (deleted) messages in the initial channel query. Defaults to true. */
760
+ includeHiddenMessages?: boolean;
578
761
  };
579
762
 
580
763
  /* ----------------------------------------------------------
@@ -604,6 +787,8 @@ export type MessageReactionsProps = {
604
787
  onClickReaction?: (type: string) => void;
605
788
  /** Whether interactions are disabled */
606
789
  disabled?: boolean;
790
+ /** Whether the message is from the current user */
791
+ isOwnMessage?: boolean;
607
792
  };
608
793
 
609
794
  /* ----------------------------------------------------------
@@ -667,16 +852,44 @@ export type MessageItemProps = {
667
852
  forwardedLabel?: string;
668
853
  /** I18n Label for edited state */
669
854
  editedLabel?: string;
855
+ /** I18n Label for deleted display messages (display_type === 'deleted') */
856
+ deletedMessageLabel?: React.ReactNode;
857
+ /** I18n Label for attachment-only previews */
858
+ attachmentLabel?: string;
859
+ /** I18n Label for messages whose contents are unavailable */
860
+ unavailableMessageLabel?: string;
861
+ /** I18n Label for sticker message previews */
862
+ stickerLabel?: string;
863
+ /** I18n Label for encrypted messages (default: 'Encrypted message') */
864
+ encryptedMessageLabel?: string;
865
+ /** I18n Label for encrypted messages that failed to decrypt (default: 'Encrypted message could not be decrypted') */
866
+ encryptedMessageFailedLabel?: string;
867
+ /** I18n Label for encrypted messages being decrypted (default: 'Decrypting encrypted message...') */
868
+ encryptedMessageDecryptingLabel?: string;
869
+ /** Custom translation templates for system messages */
870
+ systemMessageTranslations?: SystemMessageTranslations;
871
+ /** Custom translation templates for signal (call) messages */
872
+ signalMessageTranslations?: SignalMessageTranslations;
873
+ /** Handler when a mention is clicked */
874
+ onMentionClick?: (userId: string) => void;
875
+ /** Handler when a sender's username is clicked in the message list */
876
+ onUserNameClick?: (userId: string) => void;
877
+ /** Handler when clicking to add a custom reaction */
878
+ onAddReactionClick?: (e: React.MouseEvent, messageId: string) => void;
879
+ /** When true, the avatar column is not rendered (handled by group wrapper) */
880
+ hideAvatar?: boolean;
670
881
  };
671
882
 
672
883
  export type SystemMessageItemProps = {
673
884
  message: FormatMessageResponse;
674
885
  isOwnMessage: boolean;
675
886
  SystemRenderer: React.ComponentType<MessageRendererProps>;
887
+ systemMessageTranslations?: SystemMessageTranslations;
676
888
  };
677
889
 
678
890
  export type SendButtonProps = { disabled: boolean; onClick: () => void };
679
891
  export type AttachButtonProps = { disabled: boolean; onClick: () => void };
892
+ export type VoiceRecordButtonProps = { disabled: boolean; onRecordComplete: (file: File) => void };
680
893
 
681
894
  /** Props passed to a consumer-provided emoji picker component */
682
895
  export type EmojiPickerProps = {
@@ -686,6 +899,18 @@ export type EmojiPickerProps = {
686
899
  onClose: () => void;
687
900
  };
688
901
 
902
+ /** Props for the preview overlay when a user has not joined a public channel */
903
+ export type PreviewOverlayProps = {
904
+ /** Title shown in the preview overlay */
905
+ title?: string;
906
+ /** Label for the join button */
907
+ buttonLabel?: string;
908
+ /** Action when the join button is clicked */
909
+ onJoin?: () => void;
910
+ /** Custom class name */
911
+ className?: string;
912
+ };
913
+
689
914
  /** Props passed to the emoji button component */
690
915
  export type EmojiButtonProps = {
691
916
  /** Whether the picker is currently open */
@@ -705,6 +930,8 @@ export type MessageInputProps = {
705
930
  SendButton?: React.ComponentType<SendButtonProps>;
706
931
  /** Custom attach button component */
707
932
  AttachButton?: React.ComponentType<AttachButtonProps>;
933
+ /** Custom voice record button component */
934
+ VoiceRecordButtonComponent?: React.ComponentType<VoiceRecordButtonProps>;
708
935
  /** Custom file preview component */
709
936
  FilesPreviewComponent?: React.ComponentType<FilesPreviewProps>;
710
937
  /** Custom mention suggestions component */
@@ -743,6 +970,32 @@ export type MessageInputProps = {
743
970
  slowModeLabel?: (cooldown: number) => React.ReactNode;
744
971
  /** I18n Label for closed topic */
745
972
  closedTopicLabel?: string;
973
+ /** I18n Label for replying state */
974
+ replyingToLabel?: string;
975
+ /** I18n Label for editing state */
976
+ editingMessageLabel?: string;
977
+ /** I18n Label for Drag and Drop overlay */
978
+ dragAndDropLabel?: string;
979
+ /** Custom component for Drag and Drop overlay */
980
+ DragAndDropOverlayComponent?: React.ComponentType<{ dragAndDropLabel: string }>;
981
+
982
+ /** Custom component for the Preview Overlay (shown instead of input in unjoined public channels) */
983
+ PreviewOverlayComponent?: React.ComponentType<PreviewOverlayProps>;
984
+ /** I18n Title for Preview Overlay */
985
+ previewOverlayTitle?: string;
986
+ /** I18n Label for Join Button in Preview Overlay */
987
+ joinChannelLabel?: string;
988
+
989
+ /** Disable stickers entirely */
990
+ disableStickers?: boolean;
991
+ /** URL for the sticker picker iframe (default: https://sticker.ermis.network) */
992
+ stickerIframeUrl?: string;
993
+ /** Custom sticker picker component */
994
+ StickerPickerComponent?: React.ComponentType<{ stickerIframeUrl: string; onClose: () => void }>;
995
+ /** Custom sticker button component */
996
+ StickerButtonComponent?: React.ComponentType<{ active: boolean; onClick: () => void }>;
997
+ /** I18n Label for maximum characters exceeded error */
998
+ maxCharsLabel?: string;
746
999
  };
747
1000
 
748
1001
  /* ----------------------------------------------------------
@@ -805,6 +1058,10 @@ export type PinnedMessageItemProps = {
805
1058
  onClickMessage?: (messageId: string) => void;
806
1059
  onUnpin?: (messageId: string) => void;
807
1060
  AvatarComponent: React.ComponentType<AvatarProps>;
1061
+ unpinLabel?: string;
1062
+ stickerLabel?: string;
1063
+ attachmentLabel?: string;
1064
+ unavailableMessageLabel?: string;
808
1065
  };
809
1066
 
810
1067
  export type PinnedMessagesProps = {
@@ -818,6 +1075,14 @@ export type PinnedMessagesProps = {
818
1075
  onClickMessage?: (messageId: string) => void;
819
1076
  /** Max messages to show in collapsed state (default: 1) */
820
1077
  maxCollapsed?: number;
1078
+ /** I18n Labels */
1079
+ pinnedMessagesLabel?: string | ((count: number) => string);
1080
+ seeAllLabel?: string;
1081
+ collapseLabel?: string;
1082
+ unpinLabel?: string;
1083
+ stickerLabel?: string;
1084
+ attachmentLabel?: string;
1085
+ unavailableMessageLabel?: string;
821
1086
  };
822
1087
 
823
1088
  /* ----------------------------------------------------------
@@ -829,11 +1094,28 @@ export type QuotedMessagePreviewProps = {
829
1094
  id: string;
830
1095
  text?: string;
831
1096
  user?: { id?: string; name?: string };
1097
+ attachments?: Attachment[];
1098
+ content_type?: string;
1099
+ mls_ciphertext?: unknown;
1100
+ e2ee_status?: string;
1101
+ sticker_url?: string;
1102
+ type?: string;
1103
+ display_type?: string;
1104
+ mentioned_users?: string[];
1105
+ mentioned_all?: boolean;
832
1106
  };
833
1107
  /** Whether the parent message is from the current user */
834
1108
  isOwnMessage: boolean;
835
1109
  /** Callback when the quote box is clicked */
836
1110
  onClick: (messageId: string) => void;
1111
+ /** I18n Label for attachment-only quoted messages */
1112
+ attachmentLabel?: string;
1113
+ /** I18n Label for quoted messages whose contents are unavailable */
1114
+ unavailableMessageLabel?: string;
1115
+ /** I18n Label for sticker quoted messages */
1116
+ stickerLabel?: string;
1117
+ /** I18n Label for deleted messages */
1118
+ deletedMessageLabel?: string;
837
1119
  };
838
1120
 
839
1121
  /* ----------------------------------------------------------
@@ -903,6 +1185,10 @@ export type FilePreviewItem = {
903
1185
  previewUrl?: string;
904
1186
  /** Upload status */
905
1187
  status: 'pending' | 'uploading' | 'done' | 'error';
1188
+ /** E2EE upload phase when the file is handled by MLS attachment flow */
1189
+ e2eePhase?: 'generating_preview' | 'encrypting' | 'uploading' | 'completing' | 'sending' | 'retrying' | 'failed';
1190
+ /** Upload progress percentage (0-100) */
1191
+ progress?: number;
906
1192
  /** Error message if upload failed */
907
1193
  error?: string;
908
1194
  /** URL returned after successful upload */
@@ -921,7 +1207,7 @@ export type FilesPreviewProps = {
921
1207
  };
922
1208
 
923
1209
  /* --------------------------------------------------------------------------
924
- * Modal Components
1210
+ * Primitive Components Props
925
1211
  * -------------------------------------------------------------------------- */
926
1212
 
927
1213
  export interface ModalProps {
@@ -935,6 +1221,38 @@ export interface ModalProps {
935
1221
  closeOnOutsideClick?: boolean;
936
1222
  }
937
1223
 
1224
+ export interface DropdownProps {
1225
+ /** Whether the dropdown is open */
1226
+ isOpen: boolean;
1227
+ /** Rect from getBoundingClientRect() of the anchor element */
1228
+ anchorRect: DOMRect | null;
1229
+ /** Callback when dropdown requests to close (e.g., click outside, scroll, Escape) */
1230
+ onClose: () => void;
1231
+ /** Dropdown menu content */
1232
+ children: React.ReactNode;
1233
+ /** Horizontal alignment relative to the anchor. Default: 'left' */
1234
+ align?: 'left' | 'right';
1235
+ /** Optional custom CSS class for the container */
1236
+ className?: string;
1237
+ /** Optional custom CSS style for the container */
1238
+ style?: React.CSSProperties;
1239
+ }
1240
+
1241
+ export type PanelProps = {
1242
+ /** Whether the panel is visible */
1243
+ isOpen: boolean;
1244
+ /** Called when user clicks the back button */
1245
+ onClose: () => void;
1246
+ /** Panel title shown in the header */
1247
+ title?: string;
1248
+ /** Panel body content */
1249
+ children: React.ReactNode;
1250
+ /** Optional header content (replaces default title + back button) */
1251
+ headerContent?: React.ReactNode;
1252
+ /** Additional CSS class name */
1253
+ className?: string;
1254
+ };
1255
+
938
1256
  /* ----------------------------------------------------------
939
1257
  Channel Info types
940
1258
  ---------------------------------------------------------- */
@@ -960,10 +1278,19 @@ export type AttachmentItem = {
960
1278
  og_scrape_url?: string;
961
1279
  image_url?: string;
962
1280
  text?: string;
1281
+ e2ee_manifest?: E2eeAttachmentManifest;
1282
+ e2ee_manifest_missing?: boolean;
963
1283
  };
964
1284
 
965
1285
  export type MediaTab = 'members' | 'media' | 'links' | 'files';
966
1286
 
1287
+ export type ChannelInfoTabHeaderProps = {
1288
+ activeTab: MediaTab;
1289
+ onTabChange: (tab: MediaTab) => void;
1290
+ availableTabs: MediaTab[];
1291
+ tabCounts: Record<MediaTab, number>;
1292
+ };
1293
+
967
1294
  /* Sub-component prop types for consumer customization */
968
1295
 
969
1296
  export type ChannelInfoMemberItemProps = {
@@ -979,6 +1306,8 @@ export type ChannelInfoMemberItemProps = {
979
1306
  canPromote?: boolean;
980
1307
  onDemote?: (id: string) => void;
981
1308
  canDemote?: boolean;
1309
+ /** Custom labels for member roles (owner, moder, member, pending) */
1310
+ roleLabels?: Record<string, string>;
982
1311
  };
983
1312
 
984
1313
  export type ChannelInfoMediaItemProps = {
@@ -1023,30 +1352,56 @@ export type ChannelInfoCoverProps = {
1023
1352
  isTopic?: boolean;
1024
1353
  /** Whether the channel is a team channel */
1025
1354
  isTeamChannel?: boolean;
1355
+ /** Whether this channel or inherited parent topic is E2EE enabled */
1356
+ isE2ee?: boolean;
1357
+ /** Current encryption epoch, if available */
1358
+ encryptionEpoch?: number;
1026
1359
  };
1027
1360
 
1028
1361
  export type ChannelInfoActionsProps = {
1362
+ channel?: Channel;
1029
1363
  onSearchClick?: () => void;
1030
1364
  onSettingsClick?: () => void;
1031
1365
  onLeaveChannel?: () => void;
1032
1366
  onDeleteChannel?: () => void;
1367
+ onTruncateChannel?: () => void;
1033
1368
  onBlockUser?: () => void;
1034
1369
  onUnblockUser?: () => void;
1370
+ onPin?: () => void;
1371
+ onUnpin?: () => void;
1035
1372
  isTeamChannel?: boolean;
1036
1373
  isTopic?: boolean;
1037
1374
  isClosedTopic?: boolean;
1038
1375
  isBlocked?: boolean;
1376
+ isPinned?: boolean;
1039
1377
  currentUserRole?: string;
1040
1378
  searchLabel?: string;
1041
1379
  settingsLabel?: string;
1042
1380
  deleteLabel?: string;
1381
+ truncateLabel?: string;
1043
1382
  leaveLabel?: string;
1044
1383
  blockLabel?: string;
1045
1384
  unblockLabel?: string;
1385
+ pinLabel?: string;
1386
+ unpinLabel?: string;
1046
1387
  onCloseTopic?: () => void;
1047
1388
  onReopenTopic?: () => void;
1048
1389
  closeTopicLabel?: string;
1049
1390
  reopenTopicLabel?: string;
1391
+ onDeleteTopic?: () => void;
1392
+ deleteTopicLabel?: string;
1393
+ onCreateTopic?: () => void;
1394
+ createTopicLabel?: string;
1395
+ topicsEnabled?: boolean;
1396
+ isE2ee?: boolean;
1397
+ encryptionInitialized?: boolean;
1398
+ encryptionEpoch?: number;
1399
+ onRotateKey?: () => void;
1400
+ rotateKeyLabel?: string;
1401
+ rotateKeyDisabled?: boolean;
1402
+ onEnableE2ee?: () => void;
1403
+ enableE2eeLabel?: string;
1404
+ enableE2eeDisabled?: boolean;
1050
1405
  };
1051
1406
 
1052
1407
  export type ChannelInfoMember = {
@@ -1060,6 +1415,7 @@ export type ChannelInfoMember = {
1060
1415
  export type EditChannelData = {
1061
1416
  name?: string;
1062
1417
  image?: string;
1418
+ banner?: string;
1063
1419
  description?: string;
1064
1420
  public?: boolean;
1065
1421
  };
@@ -1167,6 +1523,7 @@ export type ChannelInfoTabsProps = {
1167
1523
  onUnbanMember?: (id: string) => void;
1168
1524
  onPromoteMember?: (id: string) => void;
1169
1525
  onDemoteMember?: (id: string) => void;
1526
+ isPreviewMode?: boolean;
1170
1527
 
1171
1528
  /** Label for the 'Add Member' button in the Members tab (default: 'Add Member') */
1172
1529
  addMemberButtonLabel?: string;
@@ -1179,7 +1536,14 @@ export type ChannelInfoTabsProps = {
1179
1536
  LinkItemComponent?: React.ComponentType<ChannelInfoLinkItemProps>;
1180
1537
  FileItemComponent?: React.ComponentType<ChannelInfoFileItemProps>;
1181
1538
  EmptyStateComponent?: React.ComponentType<ChannelInfoEmptyStateProps>;
1182
- LoadingComponent?: React.ComponentType;
1539
+ LoadingComponent?: React.ComponentType<{ tab?: string }>;
1540
+ /** Custom component for the tab header buttons */
1541
+ TabHeaderComponent?: React.ComponentType<ChannelInfoTabHeaderProps>;
1542
+ /** Whether the tabs panel is currently visible — controls data fetching (default: true) */
1543
+ isVisible?: boolean;
1544
+ roleLabels?: Record<string, string>;
1545
+ /** Ref or Element of the parent scrollable container — used for virtualization sync (default: undefined) */
1546
+ scrollContainerRef?: React.RefObject<HTMLDivElement | null> | HTMLDivElement | null;
1183
1547
  };
1184
1548
 
1185
1549
  export type ChannelInfoProps = {
@@ -1193,6 +1557,8 @@ export type ChannelInfoProps = {
1193
1557
  onClose?: () => void;
1194
1558
  /** Custom Title String for the banner */
1195
1559
  title?: string;
1560
+ /** Whether the panel is visible — controls data fetching timing (default: true) */
1561
+ isVisible?: boolean;
1196
1562
 
1197
1563
  /** Custom components to replace internal sections */
1198
1564
  HeaderComponent?: React.ComponentType<ChannelInfoHeaderProps>;
@@ -1203,6 +1569,8 @@ export type ChannelInfoProps = {
1203
1569
  AddMemberModalComponent?: React.ComponentType<AddMemberModalProps>;
1204
1570
  /** Custom component replacing the entire EditChannelModal */
1205
1571
  EditChannelModalComponent?: React.ComponentType<EditChannelModalProps>;
1572
+ /** Custom component replacing the entire EditTopicModal */
1573
+ EditTopicModalComponent?: React.ComponentType<TopicModalProps>;
1206
1574
 
1207
1575
  /** Custom sub-component overrides (passed through to TabsComponent) */
1208
1576
  MemberItemComponent?: React.ComponentType<ChannelInfoMemberItemProps>;
@@ -1210,7 +1578,9 @@ export type ChannelInfoProps = {
1210
1578
  LinkItemComponent?: React.ComponentType<ChannelInfoLinkItemProps>;
1211
1579
  FileItemComponent?: React.ComponentType<ChannelInfoFileItemProps>;
1212
1580
  EmptyStateComponent?: React.ComponentType<ChannelInfoEmptyStateProps>;
1213
- LoadingComponent?: React.ComponentType;
1581
+ LoadingComponent?: React.ComponentType<{ tab?: string }>;
1582
+ /** Custom component for the tab header buttons (passed through to TabsComponent) */
1583
+ TabHeaderComponent?: React.ComponentType<ChannelInfoTabHeaderProps>;
1214
1584
 
1215
1585
  /** Add Member customization (passed through to AddMemberModal) */
1216
1586
  addMemberModalTitle?: string;
@@ -1243,15 +1613,27 @@ export type ChannelInfoProps = {
1243
1613
  editChannelMaxImageSizeError?: string;
1244
1614
 
1245
1615
  /** Action Labels */
1616
+ /** Custom component for the search panel */
1617
+ MessageSearchPanelComponent?: React.ComponentType<MessageSearchPanelProps>;
1618
+ /** Custom component for the channel settings panel */
1619
+ ChannelSettingsPanelComponent?: React.ComponentType<ChannelSettingsPanelProps>;
1246
1620
  actionsSearchLabel?: string;
1247
1621
  actionsSettingsLabel?: string;
1248
1622
  actionsDeleteLabel?: string;
1623
+ actionsTruncateLabel?: string;
1249
1624
  actionsLeaveLabel?: string;
1625
+ actionsPinLabel?: string;
1626
+ actionsUnpinLabel?: string;
1627
+ actionsPinTopicLabel?: string;
1628
+ actionsUnpinTopicLabel?: string;
1250
1629
 
1251
1630
  /** Action callbacks */
1252
1631
  onSearchClick?: () => void;
1253
1632
  onLeaveChannel?: () => void;
1254
1633
  onDeleteChannel?: () => void;
1634
+ onTruncateChannel?: (channel: Channel) => void;
1635
+ onPinChannel?: () => void;
1636
+ onUnpinChannel?: () => void;
1255
1637
  onAddMemberClick?: () => void;
1256
1638
  onRemoveMember?: (id: string) => void;
1257
1639
  onBanMember?: (id: string) => void;
@@ -1267,11 +1649,17 @@ export type ChannelInfoProps = {
1267
1649
  actionsUnblockLabel?: string;
1268
1650
  actionsCloseTopicLabel?: string;
1269
1651
  actionsReopenTopicLabel?: string;
1652
+ actionsDeleteTopicLabel?: string;
1653
+ actionsCreateTopicLabel?: string;
1654
+ onDeleteTopic?: (channel: Channel) => void;
1655
+ onCreateTopic?: (channel: Channel) => void;
1270
1656
 
1271
1657
  /** Settings Panel Topics Labels */
1272
1658
  settingsWorkspaceTopicsTitle?: string;
1273
1659
  settingsTopicsFeatureName?: string;
1274
1660
  settingsTopicsFeatureDescription?: string;
1661
+ /** Custom labels for member roles (owner, moder, member, pending) */
1662
+ roleLabels?: Record<string, string>;
1275
1663
  };
1276
1664
 
1277
1665
  /* ----------------------------------------------------------
@@ -1385,20 +1773,88 @@ export type UserPickerProps = {
1385
1773
  emptyText?: string;
1386
1774
  loadingMoreText?: string;
1387
1775
  selectedEmptyLabel?: string;
1776
+ friendsOnly?: boolean;
1388
1777
  };
1389
1778
 
1390
1779
  /* ----------------------------------------------------------
1391
1780
  Create Channel Modal Props
1392
1781
  ---------------------------------------------------------- */
1393
1782
 
1783
+ export type CreateChannelTabsProps = {
1784
+ activeTab: 'messaging' | 'team';
1785
+ onTabChange: (tab: 'messaging' | 'team') => void;
1786
+ disabled?: boolean;
1787
+ directTabLabel?: string;
1788
+ groupTabLabel?: string;
1789
+ };
1790
+
1791
+ export type CreateChannelFooterProps = {
1792
+ tab: 'messaging' | 'team';
1793
+ step: 1 | 2;
1794
+ onCancel: () => void;
1795
+ onNext: () => void;
1796
+ onBack: () => void;
1797
+ onCreate: () => void;
1798
+ isCreating: boolean;
1799
+ isValid: boolean;
1800
+ hasExistingDirectChannel?: boolean;
1801
+ cancelButtonLabel?: string;
1802
+ createButtonLabel?: string;
1803
+ creatingButtonLabel?: string;
1804
+ messageButtonLabel?: string;
1805
+ nextButtonLabel?: string;
1806
+ backButtonLabel?: string;
1807
+ e2eeEnabled?: boolean;
1808
+ };
1809
+
1810
+ export type CreateChannelGroupFieldsProps = {
1811
+ name: string;
1812
+ onNameChange: (name: string) => void;
1813
+ description: string;
1814
+ onDescriptionChange: (desc: string) => void;
1815
+ isPublic: boolean;
1816
+ onPublicChange: (isPublic: boolean) => void;
1817
+ disabled?: boolean;
1818
+ groupNameLabel?: string;
1819
+ groupNamePlaceholder?: string;
1820
+ groupDescriptionLabel?: string;
1821
+ groupDescriptionPlaceholder?: string;
1822
+ groupPublicLabel?: string;
1823
+ e2eeEnabled?: boolean;
1824
+ onE2eeChange?: (enabled: boolean) => void;
1825
+ e2eeLabel?: string;
1826
+ e2eeDescription?: string;
1827
+ e2eeDisabled?: boolean;
1828
+ };
1829
+
1830
+ export type CreateChannelE2eeToggleProps = {
1831
+ enabled: boolean;
1832
+ onChange: (enabled: boolean) => void;
1833
+ disabled?: boolean;
1834
+ label?: string;
1835
+ description?: string;
1836
+ };
1837
+
1394
1838
  export type CreateChannelModalProps = {
1395
1839
  isOpen: boolean;
1396
1840
  onClose: () => void;
1397
1841
  onSuccess?: (channel: any) => void; // Uses 'any' or 'Channel' based on context
1842
+ /** Recovery coverage policy for newly created E2EE channels. Defaults to member_assisted. */
1843
+ e2eeRecoveryPolicy?: E2eeRecoveryPolicy;
1398
1844
 
1399
1845
  /** Override visual components */
1400
1846
  AvatarComponent?: React.ComponentType<AvatarProps>;
1401
1847
  UserItemComponent?: React.ComponentType<UserPickerItemProps>;
1848
+ TabsComponent?: React.ComponentType<CreateChannelTabsProps>;
1849
+ FooterComponent?: React.ComponentType<CreateChannelFooterProps>;
1850
+ GroupFieldsComponent?: React.ComponentType<CreateChannelGroupFieldsProps>;
1851
+ SearchInputComponent?: React.ComponentType<{
1852
+ value: string;
1853
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
1854
+ placeholder: string;
1855
+ }>;
1856
+ SelectedBoxComponent?: React.ComponentType<UserPickerSelectedBoxProps>;
1857
+ E2eeToggleComponent?: React.ComponentType<CreateChannelE2eeToggleProps>;
1402
1858
 
1403
1859
  /** i18n labels */
1404
1860
  title?: string;
@@ -1415,6 +1871,12 @@ export type CreateChannelModalProps = {
1415
1871
  createButtonLabel?: string;
1416
1872
  creatingButtonLabel?: string;
1417
1873
  messageButtonLabel?: string;
1874
+ nextButtonLabel?: string;
1875
+ backButtonLabel?: string;
1876
+ emptyStateLabel?: string;
1877
+ e2eeLabel?: string;
1878
+ e2eeDescription?: string;
1879
+ e2eeUnavailableLabel?: string;
1418
1880
 
1419
1881
  /** File upload configuration for group channel images */
1420
1882
  imageAccept?: string;