@ermis-network/ermis-chat-react 1.0.2 → 1.0.4
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.
- package/dist/index.cjs +2112 -1279
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +880 -165
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +219 -2
- package/dist/index.d.ts +219 -2
- package/dist/index.mjs +2023 -1194
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/ChannelHeader.tsx +50 -9
- package/src/components/ChannelList.tsx +4 -3
- package/src/components/ErmisCallProvider.tsx +279 -0
- package/src/components/ErmisCallUI.tsx +634 -0
- package/src/components/MessageRenderers.tsx +37 -10
- package/src/components/Modal.tsx +2 -1
- package/src/context/ChatProvider.tsx +49 -1
- package/src/context/ErmisCallContext.tsx +37 -0
- package/src/hooks/useCallContext.ts +10 -0
- package/src/index.ts +16 -0
- package/src/styles/_add-member-modal.css +12 -29
- package/src/styles/_call-ui.css +743 -0
- package/src/styles/_channel-info.css +34 -34
- package/src/styles/_channel-list.css +7 -7
- package/src/styles/_create-channel-modal.css +15 -15
- package/src/styles/_message-bubble.css +108 -16
- package/src/styles/_message-input.css +4 -4
- package/src/styles/_message-list.css +11 -11
- package/src/styles/_modal.css +23 -36
- package/src/styles/_panel.css +1 -1
- package/src/styles/_search-panel.css +9 -9
- package/src/styles/_tokens.css +42 -0
- package/src/styles/_typing-indicator.css +15 -2
- package/src/styles/_user-picker.css +16 -16
- package/src/styles/index.css +1 -1
- package/src/types.ts +193 -1
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FormatMessageResponse, MessageLabel, Attachment, Channel, ChannelFilters, ChannelSort, ChannelQueryOptions } from '@ermis-network/ermis-chat-sdk';
|
|
1
|
+
import type { FormatMessageResponse, MessageLabel, Attachment, Channel, ChannelFilters, ChannelSort, ChannelQueryOptions, UserCallInfo } from '@ermis-network/ermis-chat-sdk';
|
|
2
2
|
import type { ErmisChat } from '@ermis-network/ermis-chat-sdk';
|
|
3
3
|
|
|
4
4
|
/* ----------------------------------------------------------
|
|
@@ -43,6 +43,8 @@ export type ChatContextValue = {
|
|
|
43
43
|
/** Message ID to jump/scroll to (set by search, cleared after scroll) */
|
|
44
44
|
jumpToMessageId: string | null;
|
|
45
45
|
setJumpToMessageId: (id: string | null) => void;
|
|
46
|
+
/** Indicates whether the direct call feature is enabled */
|
|
47
|
+
enableCall?: boolean;
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
export type ChatProviderProps = {
|
|
@@ -50,6 +52,185 @@ export type ChatProviderProps = {
|
|
|
50
52
|
children: React.ReactNode;
|
|
51
53
|
/** Initial theme, defaults to 'dark' */
|
|
52
54
|
initialTheme?: Theme;
|
|
55
|
+
/** Enable direct call feature (Audio/Video). If enabled, configures internal CallProvider */
|
|
56
|
+
enableCall?: boolean;
|
|
57
|
+
/** Provide session ID to be used for call nodes */
|
|
58
|
+
callSessionId?: string;
|
|
59
|
+
/** Override the WebAssembly module path for Call Nodes */
|
|
60
|
+
callWasmPath?: string;
|
|
61
|
+
/** Override the relay URL for Call Nodes */
|
|
62
|
+
callRelayUrl?: string;
|
|
63
|
+
/** Custom Component to completely replace the default Call UI */
|
|
64
|
+
CallUIComponent?: React.ComponentType;
|
|
65
|
+
/** Path to the mp3 file for incoming call ringing */
|
|
66
|
+
incomingCallAudioPath?: string;
|
|
67
|
+
/** Path to the mp3 file for outgoing call ringing */
|
|
68
|
+
outgoingCallAudioPath?: string;
|
|
69
|
+
/** Called when a call is initiated by the local user */
|
|
70
|
+
onCallStart?: (callType: 'audio' | 'video', cid: string) => void;
|
|
71
|
+
/** Called when a call ends (includes duration in seconds) */
|
|
72
|
+
onCallEnd?: (duration: number) => void;
|
|
73
|
+
/** Called when a call error occurs */
|
|
74
|
+
onCallError?: (error: string) => void;
|
|
75
|
+
/** Called when an incoming call is received */
|
|
76
|
+
onIncomingCall?: (callerInfo: UserCallInfo) => void;
|
|
77
|
+
/** Called when the local user accepts an incoming call */
|
|
78
|
+
onCallAccepted?: () => void;
|
|
79
|
+
/** Called when the local user rejects an incoming call */
|
|
80
|
+
onCallRejected?: () => void;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/* ----------------------------------------------------------
|
|
84
|
+
Call Provider types
|
|
85
|
+
---------------------------------------------------------- */
|
|
86
|
+
export interface ErmisCallProviderProps {
|
|
87
|
+
children: React.ReactNode;
|
|
88
|
+
client: ErmisChat;
|
|
89
|
+
sessionId: string;
|
|
90
|
+
wasmPath?: string;
|
|
91
|
+
relayUrl?: string;
|
|
92
|
+
/** Called when a call is initiated by the local user */
|
|
93
|
+
onCallStart?: (callType: 'audio' | 'video', cid: string) => void;
|
|
94
|
+
/** Called when a call ends (includes duration in seconds) */
|
|
95
|
+
onCallEnd?: (duration: number) => void;
|
|
96
|
+
/** Called when a call error occurs */
|
|
97
|
+
onCallError?: (error: string) => void;
|
|
98
|
+
/** Called when an incoming call is received */
|
|
99
|
+
onIncomingCall?: (callerInfo: UserCallInfo) => void;
|
|
100
|
+
/** Called when the local user accepts an incoming call */
|
|
101
|
+
onCallAccepted?: () => void;
|
|
102
|
+
/** Called when the local user rejects an incoming call */
|
|
103
|
+
onCallRejected?: () => void;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* ----------------------------------------------------------
|
|
107
|
+
Call UI types
|
|
108
|
+
---------------------------------------------------------- */
|
|
109
|
+
export type ErmisCallUIProps = {
|
|
110
|
+
/** Additional CSS class name */
|
|
111
|
+
className?: string;
|
|
112
|
+
incomingCallTitle?: (callType: string) => string;
|
|
113
|
+
outgoingCallTitle?: (callType: string) => string;
|
|
114
|
+
ongoingCallTitle?: (callType: string) => string;
|
|
115
|
+
isCallingYouLabel?: string;
|
|
116
|
+
ringingLabel?: string;
|
|
117
|
+
rejectCallLabel?: string;
|
|
118
|
+
acceptCallLabel?: string;
|
|
119
|
+
endCallLabel?: string;
|
|
120
|
+
cancelLabel?: string;
|
|
121
|
+
toggleMicTitle?: string;
|
|
122
|
+
toggleVideoTitle?: string;
|
|
123
|
+
shareScreenTitle?: string;
|
|
124
|
+
stopScreenShareTitle?: string;
|
|
125
|
+
/** Label shown during an active call (default: "Connected") */
|
|
126
|
+
connectedLabel?: string;
|
|
127
|
+
/** Label for the audio call type badge (default: "Audio Call") */
|
|
128
|
+
audioCallBadgeLabel?: string;
|
|
129
|
+
/** Label for the video call type badge (default: "Video Call") */
|
|
130
|
+
videoCallBadgeLabel?: string;
|
|
131
|
+
/** Tooltip for the fullscreen button (default: "Fullscreen") */
|
|
132
|
+
fullscreenTitle?: string;
|
|
133
|
+
/** Tooltip for the exit fullscreen button (default: "Exit Fullscreen") */
|
|
134
|
+
exitFullscreenTitle?: string;
|
|
135
|
+
/** Tooltip for the upgrade call button (default: "Request Video Upgrade") */
|
|
136
|
+
upgradeCallTitle?: string;
|
|
137
|
+
/** If true, suppress incoming call UI — useful for "Do Not Disturb" mode */
|
|
138
|
+
suppressIncomingCalls?: boolean;
|
|
139
|
+
/** Called on each second tick of the call duration timer */
|
|
140
|
+
onCallDurationChange?: (seconds: number) => void;
|
|
141
|
+
AvatarComponent?: React.ComponentType<AvatarProps>;
|
|
142
|
+
MicIcon?: React.ComponentType;
|
|
143
|
+
MicOffIcon?: React.ComponentType;
|
|
144
|
+
VideoIcon?: React.ComponentType;
|
|
145
|
+
VideoOffIcon?: React.ComponentType;
|
|
146
|
+
PhoneIcon?: React.ComponentType;
|
|
147
|
+
ScreenShareIcon?: React.ComponentType;
|
|
148
|
+
ScreenShareOffIcon?: React.ComponentType;
|
|
149
|
+
FullscreenIcon?: React.ComponentType;
|
|
150
|
+
ExitFullscreenIcon?: React.ComponentType;
|
|
151
|
+
/** Custom icon for the upgrade call button (audio → video) */
|
|
152
|
+
UpgradeCallIcon?: React.ComponentType;
|
|
153
|
+
incomingCallAudioPath?: string;
|
|
154
|
+
outgoingCallAudioPath?: string;
|
|
155
|
+
/** Replace the entire Ringing state view */
|
|
156
|
+
RingingComponent?: React.ComponentType<ErmisCallRingingProps>;
|
|
157
|
+
/** Replace the entire Connected Audio state view */
|
|
158
|
+
ConnectedAudioComponent?: React.ComponentType<ErmisCallConnectedAudioProps>;
|
|
159
|
+
/** Replace the entire Connected Video state view */
|
|
160
|
+
ConnectedVideoComponent?: React.ComponentType<ErmisCallConnectedVideoProps>;
|
|
161
|
+
/** Replace the entire Error state view */
|
|
162
|
+
ErrorComponent?: React.ComponentType<ErmisCallErrorProps>;
|
|
163
|
+
/** Replace the controls bar */
|
|
164
|
+
ControlsBarComponent?: React.ComponentType<ErmisCallControlsBarProps>;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/* ----------------------------------------------------------
|
|
168
|
+
Call sub-component prop types (for component slots)
|
|
169
|
+
---------------------------------------------------------- */
|
|
170
|
+
|
|
171
|
+
/** Props for the Ringing state view */
|
|
172
|
+
export type ErmisCallRingingProps = {
|
|
173
|
+
peerInfo?: UserCallInfo;
|
|
174
|
+
callType: string;
|
|
175
|
+
isIncoming: boolean;
|
|
176
|
+
acceptCall: () => Promise<void>;
|
|
177
|
+
rejectCall: () => Promise<void>;
|
|
178
|
+
endCall: () => Promise<void>;
|
|
179
|
+
AvatarComponent: React.ComponentType<AvatarProps>;
|
|
180
|
+
isCallingYouLabel: string;
|
|
181
|
+
ringingLabel: string;
|
|
182
|
+
rejectCallLabel: string;
|
|
183
|
+
acceptCallLabel: string;
|
|
184
|
+
endCallLabel: string;
|
|
185
|
+
audioCallBadgeLabel: string;
|
|
186
|
+
videoCallBadgeLabel: string;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/** Props for the Connected Audio state view */
|
|
190
|
+
export type ErmisCallConnectedAudioProps = {
|
|
191
|
+
peerInfo?: UserCallInfo;
|
|
192
|
+
callDuration: number;
|
|
193
|
+
isRemoteMicMuted: boolean;
|
|
194
|
+
AvatarComponent: React.ComponentType<AvatarProps>;
|
|
195
|
+
connectedLabel: string;
|
|
196
|
+
renderControls: () => React.ReactNode;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/** Props for the Connected Video state view */
|
|
200
|
+
export type ErmisCallConnectedVideoProps = {
|
|
201
|
+
localVideoRef: React.RefObject<HTMLVideoElement | null>;
|
|
202
|
+
remoteVideoRef: React.RefObject<HTMLVideoElement | null>;
|
|
203
|
+
isRemoteMicMuted: boolean;
|
|
204
|
+
renderControls: () => React.ReactNode;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** Props for the Error state view */
|
|
208
|
+
export type ErmisCallErrorProps = {
|
|
209
|
+
errorMessage: string;
|
|
210
|
+
clearError: () => void;
|
|
211
|
+
cancelLabel: string;
|
|
212
|
+
PhoneIcon: React.ComponentType;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/** Props for the Controls bar */
|
|
216
|
+
export type ErmisCallControlsBarProps = {
|
|
217
|
+
callType: string;
|
|
218
|
+
toggleMic: () => void;
|
|
219
|
+
toggleVideo: () => void;
|
|
220
|
+
toggleScreenShare: () => Promise<void>;
|
|
221
|
+
toggleFullscreen: () => void;
|
|
222
|
+
upgradeCall: () => Promise<void>;
|
|
223
|
+
endCall: () => Promise<void>;
|
|
224
|
+
isMicMuted: boolean;
|
|
225
|
+
isVideoMuted: boolean;
|
|
226
|
+
isScreenSharing: boolean;
|
|
227
|
+
isFullscreen: boolean;
|
|
228
|
+
audioDevices: MediaDeviceInfo[];
|
|
229
|
+
videoDevices: MediaDeviceInfo[];
|
|
230
|
+
selectedAudioDeviceId: string;
|
|
231
|
+
selectedVideoDeviceId: string;
|
|
232
|
+
switchAudioDevice: (id: string) => Promise<void>;
|
|
233
|
+
switchVideoDevice: (id: string) => Promise<void>;
|
|
53
234
|
};
|
|
54
235
|
|
|
55
236
|
/* ----------------------------------------------------------
|
|
@@ -96,6 +277,16 @@ export type ChannelHeaderProps = {
|
|
|
96
277
|
renderRight?: (channel: Channel, actionDisabled?: boolean) => React.ReactNode;
|
|
97
278
|
/** Override default title rendering */
|
|
98
279
|
renderTitle?: (channel: Channel) => React.ReactNode;
|
|
280
|
+
/** Custom renderer for Audio Call button */
|
|
281
|
+
renderAudioCallButton?: (onClick: () => void, disabled: boolean) => React.ReactNode;
|
|
282
|
+
/** Custom renderer for Video Call button */
|
|
283
|
+
renderVideoCallButton?: (onClick: () => void, disabled: boolean) => React.ReactNode;
|
|
284
|
+
/** I18n label for the audio call button tooltip (default: "Audio Call") */
|
|
285
|
+
audioCallTitle?: string;
|
|
286
|
+
/** I18n label for the video call button tooltip (default: "Video Call") */
|
|
287
|
+
videoCallTitle?: string;
|
|
288
|
+
/** Custom component to show when a call is active (e.g. "Call in progress" badge) */
|
|
289
|
+
CallBadgeComponent?: React.ComponentType<{ callType: string }>;
|
|
99
290
|
};
|
|
100
291
|
|
|
101
292
|
/** Data passed to a fully custom HeaderComponent */
|
|
@@ -591,6 +782,7 @@ export interface ModalProps {
|
|
|
591
782
|
footer?: React.ReactNode;
|
|
592
783
|
maxWidth?: string;
|
|
593
784
|
hideCloseButton?: boolean;
|
|
785
|
+
closeOnOutsideClick?: boolean;
|
|
594
786
|
}
|
|
595
787
|
|
|
596
788
|
/* ----------------------------------------------------------
|