hermes-chat-react 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react.ts","../src/react/hooks/useMessages.ts","../src/react/hooks/useRooms.ts","../src/react/hooks/usePresence.ts","../src/react/hooks/useTyping.ts","../src/react/hooks/useReadReceipts.ts","../src/react/hooks/useReactions.ts","../src/react/hooks/useUpload.ts","../src/react/components/MessageList.tsx","../src/react/components/ChatInput.tsx","../src/react/components/RoomList.tsx","../src/react/components/TypingIndicator.tsx","../src/react/components/OnlineBadge.tsx","../src/react/components/ReactionPicker.tsx","../src/react/components/MediaMessage.tsx"],"sourcesContent":["\nexport * from \"./index\";\n\nexport { useMessages } from \"./react/hooks/useMessages\";\nexport { useRooms } from \"./react/hooks/useRooms\";\nexport { usePresence } from \"./react/hooks/usePresence\";\nexport { useTyping } from \"./react/hooks/useTyping\";\nexport { useReadReceipts } from \"./react/hooks/useReadReceipts\";\nexport { useReactions } from \"./react/hooks/useReactions\";\nexport { useUpload } from \"./react/hooks/useUpload\";\n\nexport { MessageList } from \"./react/components/MessageList\";\nexport { ChatInput } from \"./react/components/ChatInput\";\nexport { RoomList } from \"./react/components/RoomList\";\nexport { TypingIndicator } from \"./react/components/TypingIndicator\";\nexport { OnlineBadge } from \"./react/components/OnlineBadge\";\nexport { ReactionPicker } from \"./react/components/ReactionPicker\";\nexport { MediaMessage } from \"./react/components/MediaMessage\";\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\nimport type { Message, SendMessageInput } from \"../../types/index\";\n\nexport const useMessages = (client: HermesClient, roomId: string | null) => {\n const [messages, setMessages] = useState<Message[]>([]);\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [typingUsers, setTypingUsers] = useState<\n { userId: string; displayName: string }[]\n >([]);\n const oldestMessageId = useRef<string | undefined>(undefined);\n\n useEffect(() => {\n if (!roomId || !client.isConnected) return;\n\n setMessages([]);\n setHasMore(false);\n oldestMessageId.current = undefined;\n setLoading(true);\n setError(null);\n\n client\n .getHistory(roomId)\n .then(({ messages: msgs, hasMore: more }) => {\n setMessages(msgs);\n setHasMore(more);\n if (msgs.length > 0) oldestMessageId.current = msgs[0]._id;\n })\n .catch((err) => setError(err.message))\n .finally(() => setLoading(false));\n }, [roomId, client.isConnected]);\n\n useEffect(() => {\n if (!roomId) return;\n\n const onReceive = (msg: Message) => {\n if (msg.roomId !== roomId) return;\n setMessages((prev) => {\n if (prev.find((m) => m._id === msg._id)) return prev;\n return [...prev, msg];\n });\n };\n\n const onDeleted = ({\n messageId,\n }: {\n messageId: string;\n roomId: string;\n }) => {\n setMessages((prev) =>\n prev.map((m) =>\n m._id === messageId ? { ...m, isDeleted: true, text: undefined } : m,\n ),\n );\n };\n\n const onEdited = (msg: Message) => {\n setMessages((prev) => prev.map((m) => (m._id === msg._id ? msg : m)));\n };\n\n client.on(\"message:receive\", onReceive);\n client.on(\"message:deleted\", onDeleted);\n client.on(\"message:edited\", onEdited);\n\n return () => {\n client.off(\"message:receive\", onReceive);\n client.off(\"message:deleted\", onDeleted);\n client.off(\"message:edited\", onEdited);\n };\n }, [roomId, client]);\n\n useEffect(() => {\n const onReaction = ({ messageId, reactions }: any) => {\n setMessages((prev) =>\n prev.map((m) => (m._id === messageId ? { ...m, reactions } : m)),\n );\n };\n client.on(\"reaction:updated\", onReaction);\n return () => { client.off(\"reaction:updated\", onReaction); };\n }, [client]);\n\n useEffect(() => {\n if (!roomId) return;\n\n const onStarted = ({ userId, displayName, roomId: rid }: any) => {\n if (rid !== roomId) return;\n setTypingUsers((prev) => [\n ...prev.filter((u) => u.userId !== userId),\n { userId, displayName },\n ]);\n };\n\n const onStopped = ({ userId, roomId: rid }: any) => {\n if (rid !== roomId) return;\n setTypingUsers((prev) => prev.filter((u) => u.userId !== userId));\n };\n\n client.on(\"typing:started\", onStarted);\n client.on(\"typing:stopped\", onStopped);\n\n return () => {\n client.off(\"typing:started\", onStarted);\n client.off(\"typing:stopped\", onStopped);\n \n setTypingUsers([]);\n };\n }, [roomId, client]);\n\n const loadMore = useCallback(async () => {\n if (!roomId || loadingMore || !hasMore) return;\n setLoadingMore(true);\n try {\n const { messages: older, hasMore: more } = await client.getHistory(\n roomId,\n oldestMessageId.current,\n );\n setMessages((prev) => [...older, ...prev]);\n setHasMore(more);\n if (older.length > 0) oldestMessageId.current = older[0]._id;\n } catch (err: any) {\n setError(err.message);\n } finally {\n setLoadingMore(false);\n }\n }, [roomId, loadingMore, hasMore, client]);\n\n const sendMessage = useCallback(\n async (input: Omit<SendMessageInput, \"roomId\">) => {\n if (!roomId) throw new Error(\"No room selected\");\n return client.sendMessage({ ...input, roomId });\n },\n [roomId, client],\n );\n\n const editMessage = useCallback(\n async (messageId: string, text: string) => {\n if (!roomId) throw new Error(\"No room selected\");\n return client.editMessage(messageId, roomId, text);\n },\n [roomId, client],\n );\n\n const deleteMessage = useCallback(\n async (messageId: string) => {\n if (!roomId) throw new Error(\"No room selected\");\n return client.deleteMessage(messageId, roomId);\n },\n [roomId, client],\n );\n\n const addReaction = useCallback(\n async (messageId: string, emoji: string) => {\n if (!roomId) throw new Error(\"No room selected\");\n return client.addReaction(messageId, roomId, emoji);\n },\n [roomId, client],\n );\n\n return {\n messages,\n loading,\n loadingMore,\n hasMore,\n error,\n typingUsers,\n sendMessage,\n editMessage,\n deleteMessage,\n addReaction,\n loadMore,\n };\n};\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\nimport type {\n Room,\n CreateDirectRoomInput,\n CreateGroupRoomInput,\n} from \"../../types/index\";\n\nexport const useRooms = (client: HermesClient) => {\n const [rooms, setRooms] = useState<Room[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const fetchedRef = useRef(false);\n\n \n const fetchRooms = useCallback(async () => {\n setLoading(true);\n setError(null);\n\n \n await new Promise<void>((resolve, reject) => {\n if (client.isConnected) return resolve();\n let attempts = 0;\n const interval = setInterval(() => {\n attempts++;\n if (client.isConnected) {\n clearInterval(interval);\n resolve();\n } else if (attempts > 50) {\n clearInterval(interval);\n reject(new Error(\"Connection timeout\"));\n }\n }, 100);\n });\n\n try {\n const data = await client.getRooms();\n console.log(\"[useRooms] fetched:\", data.length, \"rooms\");\n setRooms(data);\n fetchedRef.current = true;\n } catch (err: any) {\n console.error(\"[useRooms] fetch error:\", err.message);\n setError(err.message);\n } finally {\n setLoading(false);\n }\n }, [client]);\n\n \n useEffect(() => {\n fetchRooms();\n const onConnected = () => {\n if (!fetchedRef.current) fetchRooms();\n };\n client.on(\"connected\", onConnected);\n return () => {\n client.off(\"connected\", onConnected);\n };\n }, [fetchRooms, client]);\n\n \n useEffect(() => {\n const onCreated = (room: Room) => {\n setRooms((prev) => {\n if (prev.find((r) => r._id === room._id)) return prev;\n return [{ ...room, unreadCount: 0 }, ...prev];\n });\n };\n\n const onDeleted = ({ roomId }: { roomId: string }) =>\n setRooms((prev) => prev.filter((r) => r._id !== roomId));\n\n const onMemberJoined = ({\n roomId,\n userId,\n }: {\n roomId: string;\n userId: string;\n }) =>\n setRooms((prev) =>\n prev.map((r) =>\n r._id === roomId ? { ...r, members: [...r.members, userId] } : r,\n ),\n );\n\n const onMemberLeft = ({\n roomId,\n userId,\n }: {\n roomId: string;\n userId: string;\n }) =>\n setRooms((prev) =>\n prev.map((r) =>\n r._id === roomId\n ? { ...r, members: r.members.filter((m) => m !== userId) }\n : r,\n ),\n );\n\n const onMessage = (msg: any) =>\n setRooms((prev) => {\n const idx = prev.findIndex((r) => r._id === msg.roomId);\n if (idx === -1) return prev;\n const updated = {\n ...prev[idx],\n lastMessage: msg,\n lastActivity: msg.createdAt,\n };\n return [updated, ...prev.filter((r) => r._id !== msg.roomId)];\n });\n\n client.on(\"room:created\", onCreated);\n client.on(\"room:deleted\", onDeleted);\n client.on(\"room:member:joined\", onMemberJoined);\n client.on(\"room:member:left\", onMemberLeft);\n client.on(\"message:receive\", onMessage);\n\n return () => {\n client.off(\"room:created\", onCreated);\n client.off(\"room:deleted\", onDeleted);\n client.off(\"room:member:joined\", onMemberJoined);\n client.off(\"room:member:left\", onMemberLeft);\n client.off(\"message:receive\", onMessage);\n };\n }, [client]);\n\n \n const createDirect = useCallback(\n async (input: CreateDirectRoomInput) => {\n const room = await client.createDirectRoom(input);\n setRooms((prev) => {\n if (prev.find((r) => r._id === room._id)) return prev;\n return [{ ...room, unreadCount: 0 }, ...prev];\n });\n return room;\n },\n [client],\n );\n\n const createGroup = useCallback(\n async (input: CreateGroupRoomInput) => {\n const room = await client.createGroupRoom(input);\n setRooms((prev) => {\n if (prev.find((r) => r._id === room._id)) return prev;\n return [{ ...room, unreadCount: 0 }, ...prev];\n });\n return room;\n },\n [client],\n );\n\n const deleteRoom = useCallback(\n async (roomId: string) => {\n await client.deleteRoom(roomId);\n setRooms((prev) => prev.filter((r) => r._id !== roomId));\n },\n [client],\n );\n\n const addMember = useCallback(\n (roomId: string, userId: string) => client.addMember(roomId, userId),\n [client],\n );\n\n const removeMember = useCallback(\n (roomId: string, userId: string) => client.removeMember(roomId, userId),\n [client],\n );\n\n return {\n rooms,\n loading,\n error,\n createDirect,\n createGroup,\n deleteRoom,\n addMember,\n removeMember,\n refetch: fetchRooms,\n };\n};\n","import { useState, useEffect, useCallback } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\n\nexport const usePresence = (client: HermesClient) => {\n const [onlineMap, setOnlineMap] = useState<Map<string, boolean>>(new Map());\n\n useEffect(() => {\n const onOnline = ({ userId }: { userId: string }) => {\n setOnlineMap((prev) => new Map(prev).set(userId, true));\n };\n\n const onOffline = ({ userId }: { userId: string }) => {\n setOnlineMap((prev) => new Map(prev).set(userId, false));\n };\n\n client.on(\"user:online\", onOnline);\n client.on(\"user:offline\", onOffline);\n\n return () => {\n client.off(\"user:online\", onOnline);\n client.off(\"user:offline\", onOffline);\n };\n }, [client]);\n\n const isOnline = useCallback(\n (userId: string): boolean => onlineMap.get(userId) ?? false,\n [onlineMap],\n );\n\n const onlineUsers = Array.from(onlineMap.entries())\n .filter(([, online]) => online)\n .map(([userId]) => userId);\n\n return { isOnline, onlineUsers, onlineMap };\n};\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\nimport type { TypingEvent } from \"../../types/index\";\n\nexport const useTyping = (client: HermesClient, roomId: string | null) => {\n \n const [typingUsers, setTypingUsers] = useState<Map<string, string>>(\n new Map(),\n );\n const timeouts = useRef<Map<string, ReturnType<typeof setTimeout>>>(\n new Map(),\n );\n const typingRef = useRef(false);\n const stopTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!roomId) return;\n\n const onStart = (event: TypingEvent) => {\n if (event.roomId !== roomId) return;\n if (event.userId === client.currentUser?.userId) return;\n\n setTypingUsers((prev) =>\n new Map(prev).set(event.userId, event.displayName),\n );\n\n \n const existing = timeouts.current.get(event.userId);\n if (existing) clearTimeout(existing);\n const t = setTimeout(() => {\n setTypingUsers((prev) => {\n const next = new Map(prev);\n next.delete(event.userId);\n return next;\n });\n }, 4000);\n timeouts.current.set(event.userId, t);\n };\n\n const onStop = (event: TypingEvent) => {\n if (event.roomId !== roomId) return;\n setTypingUsers((prev) => {\n const next = new Map(prev);\n next.delete(event.userId);\n return next;\n });\n const existing = timeouts.current.get(event.userId);\n if (existing) clearTimeout(existing);\n timeouts.current.delete(event.userId);\n };\n\n client.on(\"typing:started\", onStart);\n client.on(\"typing:stopped\", onStop);\n\n return () => {\n client.off(\"typing:started\", onStart);\n client.off(\"typing:stopped\", onStop);\n timeouts.current.forEach(clearTimeout);\n timeouts.current.clear();\n };\n }, [roomId, client]);\n\n \n const startTyping = useCallback(() => {\n if (!roomId) return;\n\n if (!typingRef.current) {\n client.startTyping(roomId);\n typingRef.current = true;\n }\n\n \n if (stopTimeout.current) clearTimeout(stopTimeout.current);\n stopTimeout.current = setTimeout(() => {\n client.stopTyping(roomId);\n typingRef.current = false;\n }, 3000);\n }, [roomId, client]);\n\n \n const stopTyping = useCallback(() => {\n if (!roomId) return;\n if (stopTimeout.current) clearTimeout(stopTimeout.current);\n if (typingRef.current) {\n client.stopTyping(roomId);\n typingRef.current = false;\n }\n }, [roomId, client]);\n\n \n const typingText = (() => {\n const names = Array.from(typingUsers.values());\n if (names.length === 0) return null;\n if (names.length === 1) return `${names[0]} is typing...`;\n if (names.length === 2) return `${names[0]} and ${names[1]} are typing...`;\n return `${names[0]} and ${names.length - 1} others are typing...`;\n })();\n\n return {\n typingUsers, \n typingText, \n isAnyoneTyping: typingUsers.size > 0,\n startTyping,\n stopTyping,\n };\n};\n","import { useState, useEffect, useCallback } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\nimport type { ReceiptEvent } from \"../../types/index\";\n\nexport const useReadReceipts = (\n client: HermesClient,\n roomId: string | null,\n) => {\n \n const [receipts, setReceipts] = useState<Map<string, Set<string>>>(new Map());\n\n useEffect(() => {\n if (!roomId) return;\n\n const onReceipt = (event: ReceiptEvent) => {\n if (event.roomId !== roomId) return;\n setReceipts((prev) => {\n const next = new Map(prev);\n const existing = next.get(event.lastMessageId) ?? new Set();\n existing.add(event.userId);\n next.set(event.lastMessageId, existing);\n return next;\n });\n };\n\n client.on(\"receipt:updated\", onReceipt);\n return () => client.off(\"receipt:updated\", onReceipt);\n }, [roomId, client]);\n\n \n const markSeen = useCallback(\n async (lastMessageId: string) => {\n if (!roomId) return;\n await client.markSeen(roomId, lastMessageId);\n },\n [roomId, client],\n );\n\n \n const seenBy = useCallback(\n (messageId: string): string[] => {\n return Array.from(receipts.get(messageId) ?? []);\n },\n [receipts],\n );\n\n return { markSeen, seenBy, receipts };\n};\n","import { useCallback } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\nimport type { Reaction } from \"../../types/index\";\n\nexport const useReactions = (client: HermesClient, roomId: string | null) => {\n \n const react = useCallback(\n async (messageId: string, emoji: string) => {\n if (!roomId) throw new Error(\"No room selected\");\n await client.addReaction(messageId, roomId, emoji);\n },\n [roomId, client],\n );\n\n \n const hasReacted = useCallback(\n (reactions: Reaction[], emoji: string): boolean => {\n const userId = client.currentUser?.userId;\n if (!userId) return false;\n return (\n reactions.find((r) => r.emoji === emoji)?.users.includes(userId) ??\n false\n );\n },\n [client],\n );\n\n \n const getCount = useCallback(\n (reactions: Reaction[], emoji: string): number => {\n return reactions.find((r) => r.emoji === emoji)?.users.length ?? 0;\n },\n [],\n );\n\n \n const getEmojis = useCallback((reactions: Reaction[]): string[] => {\n return reactions.filter((r) => r.users.length > 0).map((r) => r.emoji);\n }, []);\n\n return { react, hasReacted, getCount, getEmojis };\n};\n","import { useState, useCallback } from \"react\";\nimport type { HermesClient } from \"../../core/HermesClient\";\nimport type { UploadResult, Message } from \"../../types/index\";\n\nexport const useUpload = (client: HermesClient) => {\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [lastUpload, setLastUpload] = useState<UploadResult | null>(null);\n\n \n const upload = useCallback(\n async (file: File): Promise<UploadResult | null> => {\n setUploading(true);\n setError(null);\n try {\n const result = await client.uploadFile(file);\n setLastUpload(result);\n return result;\n } catch (err: any) {\n setError(err.message);\n return null;\n } finally {\n setUploading(false);\n }\n },\n [client],\n );\n\n \n const sendFile = useCallback(\n async (\n roomId: string,\n file: File,\n replyTo?: string,\n ): Promise<Message | null> => {\n setUploading(true);\n setError(null);\n try {\n const uploaded = await client.uploadFile(file);\n setLastUpload(uploaded);\n const message = await client.sendMessage({\n roomId,\n type: uploaded.type,\n url: uploaded.url,\n fileName: uploaded.fileName,\n fileSize: uploaded.fileSize,\n mimeType: uploaded.mimeType,\n thumbnail: uploaded.thumbnail,\n replyTo,\n });\n return message;\n } catch (err: any) {\n setError(err.message);\n return null;\n } finally {\n setUploading(false);\n }\n },\n [client],\n );\n\n \n const validate = useCallback((file: File, maxMb = 50): string | null => {\n if (file.size > maxMb * 1024 * 1024) {\n return `File too large. Max size is ${maxMb}MB.`;\n }\n const allowed = [\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n \"video/mp4\",\n \"video/webm\",\n \"audio/mpeg\",\n \"audio/ogg\",\n \"audio/wav\",\n \"application/pdf\",\n \"application/msword\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n \"text/plain\",\n ];\n if (!allowed.includes(file.type)) {\n return `File type not supported: ${file.type}`;\n }\n return null;\n }, []);\n\n return { upload, sendFile, validate, uploading, error, lastUpload };\n};\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { Message, HermesUser, Reaction } from \"../../types/index\";\n\ninterface MessageListProps {\n messages: Message[];\n currentUser: HermesUser;\n loading?: boolean;\n loadingMore?: boolean;\n hasMore?: boolean;\n onLoadMore?: () => void;\n onEdit?: (messageId: string, text: string) => void;\n onDelete?: (messageId: string) => void;\n onReact?: (messageId: string, emoji: string) => void;\n onReply?: (message: Message) => void;\n renderMessage?: (message: Message, isOwn: boolean) => React.ReactNode;\n renderAvatar?: (senderId: string) => React.ReactNode;\n className?: string;\n autoScroll?: boolean;\n \n typingUsers?: { userId: string; displayName: string }[];\n}\n\nconst formatTime = (iso: string) =>\n new Date(iso).toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" });\n\nconst formatFileSize = (bytes?: number) => {\n if (!bytes) return \"\";\n if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n};\n\nconst REACTION_EMOJIS = [\n \"🫠\",\n \"🥹\",\n \"🫡\",\n \"🤌\",\n \"🫶\",\n \"💀\",\n \"🔥\",\n \"✨\",\n \"🫣\",\n \"😮‍💨\",\n \"🪄\",\n \"🥲\",\n \"💅\",\n \"🫦\",\n \"🤯\",\n \"🌚\",\n \"👁️\",\n \"🫀\",\n \"🦋\",\n \"🪐\",\n];\n\nconst EmojiPicker: React.FC<{\n onPick: (emoji: string) => void;\n onClose: () => void;\n isOwn: boolean;\n}> = ({ onPick, onClose, isOwn }) => {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [onClose]);\n\n return (\n <div\n ref={ref}\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 8px)\",\n [isOwn ? \"right\" : \"left\"]: 0,\n zIndex: 100,\n background: \"#1a1a2e\",\n border: \"1px solid rgba(255,255,255,0.1)\",\n borderRadius: 14,\n padding: \"8px 10px\",\n boxShadow: \"0 8px 32px rgba(0,0,0,0.4)\",\n display: \"grid\",\n gridTemplateColumns: \"repeat(5, 1fr)\",\n gap: 4,\n animation: \"hermes-pop 0.15s ease\",\n }}\n >\n {REACTION_EMOJIS.map((emoji) => (\n <button\n key={emoji}\n onClick={() => {\n onPick(emoji);\n onClose();\n }}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 20,\n padding: \"4px\",\n borderRadius: 8,\n lineHeight: 1,\n transition: \"transform 0.1s, background 0.1s\",\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLButtonElement).style.transform =\n \"scale(1.3)\";\n (e.currentTarget as HTMLButtonElement).style.background =\n \"rgba(255,255,255,0.08)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLButtonElement).style.transform = \"scale(1)\";\n (e.currentTarget as HTMLButtonElement).style.background = \"none\";\n }}\n >\n {emoji}\n </button>\n ))}\n </div>\n );\n};\n\nconst TypingIndicator: React.FC<{\n typingUsers: { userId: string; displayName: string }[];\n}> = ({ typingUsers }) => {\n if (!typingUsers.length) return null;\n\n const text =\n typingUsers.length === 1\n ? `${typingUsers[0].displayName} is typing`\n : typingUsers.length === 2\n ? `${typingUsers[0].displayName} and ${typingUsers[1].displayName} are typing`\n : `${typingUsers[0].displayName} and ${typingUsers.length - 1} others are typing`;\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 16px 2px\",\n minHeight: 28,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 3,\n background: \"#f0f0f0\",\n borderRadius: 12,\n padding: \"6px 10px\",\n }}\n >\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: \"#999\",\n display: \"block\",\n animation: `hermes-bounce 1.2s ease-in-out ${i * 0.18}s infinite`,\n }}\n />\n ))}\n </div>\n <span style={{ fontSize: 11, color: \"#999\" }}>{text}</span>\n </div>\n );\n};\n\nconst DefaultMessage: React.FC<{\n message: Message;\n isOwn: boolean;\n onEdit?: (messageId: string, text: string) => void;\n onDelete?: (messageId: string) => void;\n onReact?: (messageId: string, emoji: string) => void;\n onReply?: (message: Message) => void;\n renderAvatar?: (senderId: string) => React.ReactNode;\n}> = ({ message, isOwn, onEdit, onDelete, onReact, onReply, renderAvatar }) => {\n const [hovered, setHovered] = useState(false);\n const [pickerOpen, setPickerOpen] = useState(false);\n\n if (message.isDeleted) {\n return (\n <div\n style={{\n opacity: 0.5,\n fontStyle: \"italic\",\n padding: \"4px 16px\",\n fontSize: 13,\n }}\n >\n This message was deleted.\n </div>\n );\n }\n\n return (\n <div\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => {\n setHovered(false);\n }}\n style={{\n display: \"flex\",\n flexDirection: isOwn ? \"row-reverse\" : \"row\",\n alignItems: \"flex-end\",\n gap: 8,\n marginBottom: 4,\n position: \"relative\",\n }}\n >\n {}\n {!isOwn && (\n <div style={{ flexShrink: 0 }}>\n {renderAvatar ? (\n renderAvatar(message.senderId)\n ) : (\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n background: \"#e0e0e0\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: 12,\n fontWeight: 600,\n }}\n >\n {message.senderId.slice(-2).toUpperCase()}\n </div>\n )}\n </div>\n )}\n\n {}\n <div\n style={{\n maxWidth: \"70%\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: isOwn ? \"flex-end\" : \"flex-start\",\n }}\n >\n {}\n {(onEdit || onDelete || onReact || onReply) && (\n <div\n style={{\n display: \"flex\",\n flexDirection: isOwn ? \"row-reverse\" : \"row\",\n gap: 2,\n marginBottom: 4,\n opacity: hovered ? 1 : 0,\n pointerEvents: hovered ? \"auto\" : \"none\",\n transition: \"opacity 0.15s ease\",\n position: \"relative\",\n }}\n >\n {}\n {onReact && (\n <div style={{ position: \"relative\" }}>\n <ActionBtn\n onClick={() => setPickerOpen((p) => !p)}\n title=\"React\"\n >\n 🫠\n </ActionBtn>\n {pickerOpen && (\n <EmojiPicker\n isOwn={isOwn}\n onPick={(emoji) => onReact(message._id, emoji)}\n onClose={() => setPickerOpen(false)}\n />\n )}\n </div>\n )}\n {onReply && (\n <ActionBtn onClick={() => onReply(message)} title=\"Reply\">\n ↩\n </ActionBtn>\n )}\n {isOwn && onEdit && message.type === \"text\" && (\n <ActionBtn\n onClick={() => {\n const text = window.prompt(\"Edit message:\", message.text);\n if (text) onEdit(message._id, text);\n }}\n title=\"Edit\"\n >\n ✏️\n </ActionBtn>\n )}\n {isOwn && onDelete && (\n <ActionBtn onClick={() => onDelete(message._id)} title=\"Delete\">\n 🗑\n </ActionBtn>\n )}\n </div>\n )}\n\n {}\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: isOwn ? \"16px 16px 4px 16px\" : \"16px 16px 16px 4px\",\n background: isOwn ? \"#0084ff\" : \"#f0f0f0\",\n color: isOwn ? \"#fff\" : \"#000\",\n }}\n >\n {}\n {message.replyTo && (\n <div\n style={{\n borderLeft: \"3px solid rgba(255,255,255,0.4)\",\n paddingLeft: 8,\n marginBottom: 6,\n fontSize: 12,\n opacity: 0.75,\n }}\n >\n Replying to a message\n </div>\n )}\n\n {message.type === \"text\" && (\n <p style={{ margin: 0, wordBreak: \"break-word\" }}>\n {message.text}\n {message.editedAt && (\n <span style={{ fontSize: 10, opacity: 0.6, marginLeft: 6 }}>\n (edited)\n </span>\n )}\n </p>\n )}\n {message.type === \"link\" && (\n <div>\n {message.text && (\n <p style={{ margin: \"0 0 4px\" }}>{message.text}</p>\n )}\n <a\n href={message.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n color: isOwn ? \"#cce4ff\" : \"#0084ff\",\n wordBreak: \"break-all\",\n }}\n >\n {message.url}\n </a>\n </div>\n )}\n {message.type === \"image\" && (\n <img\n src={message.url}\n alt={message.fileName || \"image\"}\n style={{ maxWidth: \"100%\", borderRadius: 8, display: \"block\" }}\n />\n )}\n {message.type === \"video\" && (\n <video\n src={message.url}\n controls\n style={{ maxWidth: \"100%\", borderRadius: 8 }}\n />\n )}\n {message.type === \"audio\" && (\n <audio src={message.url} controls style={{ width: \"100%\" }} />\n )}\n {message.type === \"document\" && (\n <a\n href={message.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n color: isOwn ? \"#fff\" : \"#333\",\n textDecoration: \"none\",\n }}\n >\n <span style={{ fontSize: 24 }}>📄</span>\n <div>\n <div style={{ fontWeight: 600, fontSize: 13 }}>\n {message.fileName}\n </div>\n <div style={{ fontSize: 11, opacity: 0.7 }}>\n {formatFileSize(message.fileSize)}\n </div>\n </div>\n </a>\n )}\n\n {}\n <div\n style={{\n fontSize: 10,\n opacity: 0.6,\n textAlign: \"right\",\n marginTop: 4,\n }}\n >\n {formatTime(message.createdAt)}\n </div>\n </div>\n\n {}\n {message.reactions?.filter((r: Reaction) => r.users.length > 0).length >\n 0 && (\n <div\n style={{ display: \"flex\", gap: 4, flexWrap: \"wrap\", marginTop: 4 }}\n >\n {message.reactions\n .filter((r: Reaction) => r.users.length > 0)\n .map((r: Reaction) => (\n <span\n key={r.emoji}\n onClick={() => onReact?.(message._id, r.emoji)}\n style={{\n background: \"#f0f0f0\",\n border: \"1px solid rgba(0,0,0,0.08)\",\n borderRadius: 20,\n padding: \"2px 8px\",\n fontSize: 13,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n transition: \"transform 0.1s\",\n userSelect: \"none\",\n }}\n onMouseEnter={(e) =>\n (e.currentTarget.style.transform = \"scale(1.1)\")\n }\n onMouseLeave={(e) =>\n (e.currentTarget.style.transform = \"scale(1)\")\n }\n >\n {r.emoji}\n <span\n style={{ fontSize: 11, fontWeight: 600, color: \"#555\" }}\n >\n {r.users.length}\n </span>\n </span>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nconst ActionBtn: React.FC<{\n onClick: () => void;\n title?: string;\n children: React.ReactNode;\n}> = ({ onClick, title, children }) => (\n <button\n onClick={onClick}\n title={title}\n style={{\n background: \"#fff\",\n border: \"1px solid rgba(0,0,0,0.1)\",\n borderRadius: 8,\n cursor: \"pointer\",\n fontSize: 14,\n padding: \"3px 6px\",\n lineHeight: 1,\n boxShadow: \"0 1px 4px rgba(0,0,0,0.1)\",\n transition: \"transform 0.1s\",\n }}\n onMouseEnter={(e) => (e.currentTarget.style.transform = \"scale(1.15)\")}\n onMouseLeave={(e) => (e.currentTarget.style.transform = \"scale(1)\")}\n >\n {children}\n </button>\n);\n\nexport const MessageList: React.FC<MessageListProps> = ({\n messages,\n currentUser,\n loading = false,\n loadingMore = false,\n hasMore = false,\n onLoadMore,\n onEdit,\n onDelete,\n onReact,\n onReply,\n renderMessage,\n renderAvatar,\n className = \"\",\n autoScroll = true,\n typingUsers = [],\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (autoScroll && bottomRef.current) {\n bottomRef.current.scrollIntoView({ behavior: \"smooth\" });\n }\n }, [messages, autoScroll]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !onLoadMore) return;\n const onScroll = () => {\n if (container.scrollTop === 0 && hasMore && !loadingMore) onLoadMore();\n };\n container.addEventListener(\"scroll\", onScroll);\n return () => container.removeEventListener(\"scroll\", onScroll);\n }, [hasMore, loadingMore, onLoadMore]);\n\n if (loading) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n }}\n >\n Loading messages...\n </div>\n );\n }\n\n return (\n <>\n <style>{`\n @keyframes hermes-bounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-5px); }\n }\n @keyframes hermes-pop {\n from { opacity: 0; transform: scale(0.85); }\n to { opacity: 1; transform: scale(1); }\n }\n `}</style>\n\n <div\n ref={containerRef}\n className={`hermes-message-list ${className}`}\n style={{\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n padding: \"16px\",\n }}\n >\n {}\n {hasMore && (\n <div style={{ textAlign: \"center\", marginBottom: 12 }}>\n {loadingMore ? (\n <span style={{ fontSize: 12, opacity: 0.5 }}>\n Loading older messages...\n </span>\n ) : (\n <button\n onClick={onLoadMore}\n style={{\n background: \"none\",\n border: \"1px solid #ddd\",\n borderRadius: 12,\n padding: \"4px 12px\",\n cursor: \"pointer\",\n fontSize: 12,\n }}\n >\n Load older messages\n </button>\n )}\n </div>\n )}\n\n {messages.length === 0 && (\n <div\n style={{\n textAlign: \"center\",\n opacity: 0.4,\n margin: \"auto\",\n fontSize: 14,\n }}\n >\n No messages yet. Say hello! 👋\n </div>\n )}\n\n {messages.map((message) => {\n const isOwn = message.senderId === currentUser.userId;\n return (\n <div key={message._id} style={{ marginBottom: 8 }}>\n {renderMessage ? (\n renderMessage(message, isOwn)\n ) : (\n <DefaultMessage\n message={message}\n isOwn={isOwn}\n onEdit={onEdit}\n onDelete={onDelete}\n onReact={onReact}\n onReply={onReply}\n renderAvatar={renderAvatar}\n />\n )}\n </div>\n );\n })}\n\n {}\n <TypingIndicator typingUsers={typingUsers} />\n\n <div ref={bottomRef} />\n </div>\n </>\n );\n};\n","import React, { useState, useRef, useCallback } from \"react\";\nimport type { Message, UploadResult } from \"../../types/index\";\n\ninterface ChatInputProps {\n onSendText: (text: string) => Promise<void> | void;\n onSendFile?: (file: File) => Promise<void> | void;\n onTypingStart?: () => void;\n onTypingStop?: () => void;\n replyingTo?: Message | null;\n onCancelReply?: () => void;\n disabled?: boolean;\n placeholder?: string;\n maxLength?: number;\n className?: string;\n inputClassName?: string;\n renderAttachIcon?: () => React.ReactNode;\n renderSendIcon?: () => React.ReactNode;\n}\n\nexport const ChatInput: React.FC<ChatInputProps> = ({\n onSendText,\n onSendFile,\n onTypingStart,\n onTypingStop,\n replyingTo,\n onCancelReply,\n disabled = false,\n placeholder = \"Type a message...\",\n maxLength = 4000,\n className = \"\",\n inputClassName = \"\",\n renderAttachIcon,\n renderSendIcon,\n}) => {\n const [text, setText] = useState(\"\");\n const [sending, setSending] = useState(false);\n const fileRef = useRef<HTMLInputElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n \n const resizeTextarea = useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = \"auto\";\n el.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n }, []);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n resizeTextarea();\n onTypingStart?.();\n };\n\n const handleSend = async () => {\n const trimmed = text.trim();\n if (!trimmed || sending || disabled) return;\n\n setSending(true);\n try {\n await onSendText(trimmed);\n setText(\"\");\n if (textareaRef.current) textareaRef.current.style.height = \"auto\";\n onTypingStop?.();\n } finally {\n setSending(false);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file || !onSendFile) return;\n await onSendFile(file);\n \n if (fileRef.current) fileRef.current.value = \"\";\n };\n\n return (\n <div\n className={`hermes-chat-input ${className}`}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n padding: \"8px 12px\",\n borderTop: \"1px solid #e0e0e0\",\n }}\n >\n {}\n {replyingTo && (\n <div\n className=\"hermes-chat-input__reply\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"6px 10px\",\n marginBottom: 6,\n background: \"#f5f5f5\",\n borderRadius: 8,\n borderLeft: \"3px solid #0084ff\",\n fontSize: 12,\n }}\n >\n <div style={{ overflow: \"hidden\" }}>\n <span style={{ fontWeight: 600, marginRight: 4 }}>\n Replying to:\n </span>\n <span style={{ opacity: 0.7 }}>\n {replyingTo.type === \"text\"\n ? replyingTo.text?.slice(0, 60)\n : `[${replyingTo.type}]`}\n </span>\n </div>\n <button\n onClick={onCancelReply}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 16,\n lineHeight: 1,\n }}\n >\n ✕\n </button>\n </div>\n )}\n\n {}\n <div\n className=\"hermes-chat-input__row\"\n style={{ display: \"flex\", alignItems: \"flex-end\", gap: 8 }}\n >\n {}\n {onSendFile && (\n <>\n <button\n onClick={() => fileRef.current?.click()}\n disabled={disabled}\n className=\"hermes-chat-input__attach\"\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 6,\n flexShrink: 0,\n opacity: disabled ? 0.4 : 1,\n }}\n >\n {renderAttachIcon ? (\n renderAttachIcon()\n ) : (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n )}\n </button>\n <input\n ref={fileRef}\n type=\"file\"\n style={{ display: \"none\" }}\n onChange={handleFileChange}\n accept=\"image/*,video/*,audio/*,.pdf,.doc,.docx,.txt\"\n />\n </>\n )}\n\n {}\n <textarea\n ref={textareaRef}\n value={text}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onBlur={() => onTypingStop?.()}\n placeholder={placeholder}\n disabled={disabled}\n maxLength={maxLength}\n rows={1}\n className={`hermes-chat-input__textarea ${inputClassName}`}\n style={{\n flex: 1,\n resize: \"none\",\n border: \"1px solid #e0e0e0\",\n borderRadius: 20,\n padding: \"8px 14px\",\n fontSize: 14,\n lineHeight: 1.5,\n outline: \"none\",\n overflow: \"hidden\",\n background: disabled ? \"#f5f5f5\" : \"#fff\",\n }}\n />\n\n {}\n <button\n onClick={handleSend}\n disabled={!text.trim() || sending || disabled}\n className=\"hermes-chat-input__send\"\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 6,\n flexShrink: 0,\n opacity: !text.trim() || sending || disabled ? 0.4 : 1,\n }}\n >\n {renderSendIcon ? (\n renderSendIcon()\n ) : (\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n )}\n </button>\n </div>\n\n {}\n {text.length > maxLength * 0.8 && (\n <div\n style={{\n fontSize: 10,\n textAlign: \"right\",\n opacity: 0.5,\n marginTop: 2,\n }}\n >\n {text.length}/{maxLength}\n </div>\n )}\n </div>\n );\n};\n","import React from \"react\";\nimport type { Room } from \"../../types/index\";\n\ninterface RoomListProps {\n rooms: Room[];\n activeRoomId?: string | null;\n currentUserId: string;\n loading?: boolean;\n onSelectRoom: (room: Room) => void;\n onCreateDirect?: () => void;\n onCreateGroup?: () => void;\n renderRoomItem?: (room: Room, isActive: boolean) => React.ReactNode;\n renderAvatar?: (room: Room) => React.ReactNode;\n renderEmpty?: () => React.ReactNode;\n className?: string;\n itemClassName?: string;\n}\n\nconst formatLastActivity = (iso: string) => {\n const date = new Date(iso);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n if (diffMins < 1) return \"now\";\n if (diffMins < 60) return `${diffMins}m`;\n if (diffHours < 24) return `${diffHours}h`;\n if (diffDays < 7) return `${diffDays}d`;\n return date.toLocaleDateString();\n};\n\nconst getRoomName = (room: Room, currentUserId: string) => {\n if (room.type === \"group\") return room.name ?? \"Group\";\n const other = room.members.find((m) => m !== currentUserId);\n return other ?? \"Direct Message\";\n};\n\nconst getLastMessagePreview = (room: Room): string => {\n const msg = room.lastMessage as any;\n if (!msg) return \"No messages yet\";\n if (msg.isDeleted) return \"Message deleted\";\n if (msg.type === \"text\") return msg.text?.slice(0, 50) ?? \"\";\n if (msg.type === \"image\") return \"📷 Image\";\n if (msg.type === \"video\") return \"🎥 Video\";\n if (msg.type === \"audio\") return \"🎵 Audio\";\n if (msg.type === \"document\") return `📄 ${msg.fileName ?? \"File\"}`;\n if (msg.type === \"link\") return `🔗 ${msg.url}`;\n return \"\";\n};\n\nconst DefaultRoomItem: React.FC<{\n room: Room;\n isActive: boolean;\n currentUserId: string;\n renderAvatar?: (room: Room) => React.ReactNode;\n itemClassName?: string;\n}> = ({ room, isActive, currentUserId, renderAvatar, itemClassName }) => (\n <div\n className={`hermes-room-item ${isActive ? \"hermes-room-item--active\" : \"\"} ${itemClassName ?? \"\"}`}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"10px 12px\",\n cursor: \"pointer\",\n background: isActive ? \"rgba(0,132,255,0.08)\" : \"transparent\",\n borderLeft: isActive ? \"3px solid #0084ff\" : \"3px solid transparent\",\n }}\n >\n <div style={{ flexShrink: 0 }}>\n {renderAvatar ? (\n renderAvatar(room)\n ) : (\n <div\n style={{\n width: 42,\n height: 42,\n borderRadius: \"50%\",\n background: \"#e0e0e0\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontWeight: 700,\n fontSize: 16,\n }}\n >\n {room.type === \"group\" ? \"G\" : \"D\"}\n </div>\n )}\n </div>\n <div style={{ flex: 1, overflow: \"hidden\" }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"baseline\",\n }}\n >\n <span\n style={{\n fontWeight: 600,\n fontSize: 14,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {getRoomName(room, currentUserId)}\n </span>\n <span\n style={{ fontSize: 11, opacity: 0.5, flexShrink: 0, marginLeft: 4 }}\n >\n {formatLastActivity(room.lastActivity)}\n </span>\n </div>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginTop: 2,\n }}\n >\n <span\n style={{\n fontSize: 13,\n opacity: 0.6,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {getLastMessagePreview(room)}\n </span>\n {room.unreadCount > 0 && (\n <span\n style={{\n background: \"#0084ff\",\n color: \"#fff\",\n borderRadius: 10,\n fontSize: 11,\n fontWeight: 700,\n padding: \"1px 7px\",\n flexShrink: 0,\n marginLeft: 4,\n }}\n >\n {room.unreadCount > 99 ? \"99+\" : room.unreadCount}\n </span>\n )}\n </div>\n </div>\n </div>\n);\n\nexport const RoomList: React.FC<RoomListProps> = ({\n rooms,\n activeRoomId,\n currentUserId,\n loading = false,\n onSelectRoom,\n onCreateDirect,\n onCreateGroup,\n renderRoomItem,\n renderAvatar,\n renderEmpty,\n className = \"\",\n itemClassName = \"\",\n}) => {\n return (\n <div\n className={`hermes-room-list ${className}`}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n overflowY: \"auto\",\n }}\n >\n {}\n {(onCreateDirect || onCreateGroup) && (\n <div\n style={{\n display: \"flex\",\n gap: 8,\n padding: \"10px 12px\",\n borderBottom: \"1px solid #e0e0e0\",\n }}\n >\n {onCreateDirect && (\n <button\n onClick={onCreateDirect}\n style={{\n flex: 1,\n background: \"#0084ff\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: 8,\n padding: \"8px 10px\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n + Direct\n </button>\n )}\n {onCreateGroup && (\n <button\n onClick={onCreateGroup}\n style={{\n flex: 1,\n background: \"none\",\n border: \"1px solid #e0e0e0\",\n borderRadius: 8,\n padding: \"8px 10px\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n + Group\n </button>\n )}\n </div>\n )}\n\n {loading && (\n <div style={{ padding: \"12px 16px\", opacity: 0.5, fontSize: 13 }}>\n Loading rooms...\n </div>\n )}\n\n {!loading && rooms.length === 0 && (\n <div\n style={{\n textAlign: \"center\",\n padding: 24,\n opacity: 0.4,\n fontSize: 13,\n }}\n >\n {renderEmpty ? renderEmpty() : \"No conversations yet.\"}\n </div>\n )}\n\n {!loading &&\n rooms.map((room) => {\n const isActive = room._id === activeRoomId;\n return (\n <div key={room._id} onClick={() => onSelectRoom(room)}>\n {renderRoomItem ? (\n renderRoomItem(room, isActive)\n ) : (\n <DefaultRoomItem\n room={room}\n isActive={isActive}\n currentUserId={currentUserId}\n renderAvatar={renderAvatar}\n itemClassName={itemClassName}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n};\n","import React from \"react\";\n\ninterface TypingIndicatorProps {\n typingText: string | null;\n className?: string;\n}\n\nexport const TypingIndicator: React.FC<TypingIndicatorProps> = ({\n typingText,\n className = \"\",\n}) => {\n if (!typingText) return null;\n\n return (\n <div\n className={`hermes-typing-indicator ${className}`}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"4px 16px\",\n minHeight: 24,\n }}\n >\n <div style={{ display: \"flex\", gap: 3 }}>\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: \"#aaa\",\n display: \"block\",\n animation: `hermes-bounce 1.2s ease-in-out ${i * 0.2}s infinite`,\n }}\n />\n ))}\n </div>\n <span style={{ fontSize: 12, opacity: 0.6 }}>{typingText}</span>\n <style>{`\n @keyframes hermes-bounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-4px); }\n }\n `}</style>\n </div>\n );\n};\n","import React from \"react\";\n\ninterface OnlineBadgeProps {\n isOnline: boolean;\n size?: number;\n className?: string;\n}\n\nexport const OnlineBadge: React.FC<OnlineBadgeProps> = ({\n isOnline,\n size = 10,\n className = \"\",\n}) => (\n <span\n className={`hermes-online-badge ${isOnline ? \"hermes-online-badge--online\" : \"hermes-online-badge--offline\"} ${className}`}\n data-online={isOnline}\n style={{\n display: \"inline-block\",\n width: size,\n height: size,\n borderRadius: \"50%\",\n background: isOnline ? \"#22c55e\" : \"#d1d5db\",\n boxShadow: isOnline ? \"0 0 0 2px #fff\" : \"none\",\n flexShrink: 0,\n }}\n />\n);\n","import React, { useState, useRef, useEffect } from \"react\";\nimport type { Reaction } from \"../../types/index\";\nimport EmojiPicker, { Theme, type EmojiClickData } from \"emoji-picker-react\";\n\ninterface ReactionPickerProps {\n onSelect: (emoji: string) => void;\n currentReactions?: Reaction[];\n currentUserId?: string;\n emojis?: string[];\n className?: string;\n align?: \"left\" | \"right\";\n}\n\nconst DEFAULT_EMOJIS = [\"👍\", \"❤️\", \"😂\", \"😮\", \"😢\", \"🔥\", \"🎉\", \"👏\"];\n\nexport const ReactionPicker: React.FC<ReactionPickerProps> = ({\n onSelect,\n currentReactions = [],\n currentUserId,\n emojis = DEFAULT_EMOJIS,\n className = \"\",\n align = \"left\",\n}) => {\n const [showPicker, setShowPicker] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n \n const hasReacted = (emoji: string) => {\n if (!currentUserId) return false;\n\n return (\n currentReactions\n .find((r) => r.emoji === emoji)\n ?.users.includes(currentUserId) ?? false\n );\n };\n\n const handleEmojiClick = (emojiData: EmojiClickData) => {\n onSelect(emojiData.emoji);\n setShowPicker(false);\n };\n\n \n useEffect(() => {\n const handleOutsideClick = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n const target = e.target as Node;\n\n if (!containerRef.current.contains(target)) {\n setShowPicker(false);\n }\n };\n\n if (showPicker) {\n window.addEventListener(\"click\", handleOutsideClick);\n }\n\n return () => window.removeEventListener(\"click\", handleOutsideClick);\n }, [showPicker]);\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", display: \"inline-block\" }}\n className={className}\n >\n {}\n <div\n style={{\n display: \"flex\",\n gap: 4,\n flexWrap: \"wrap\",\n padding: \"6px 8px\",\n background: \"#111\",\n borderRadius: 12,\n border: \"1px solid rgba(255,255,255,0.08)\",\n }}\n >\n {emojis.map((emoji) => (\n <button\n key={emoji}\n onClick={() => onSelect(emoji)}\n style={{\n background: hasReacted(emoji)\n ? \"rgba(57,255,20,0.12)\"\n : \"transparent\",\n border: hasReacted(emoji)\n ? \"1px solid rgba(57,255,20,0.35)\"\n : \"1px solid transparent\",\n borderRadius: 8,\n padding: \"4px 6px\",\n cursor: \"pointer\",\n fontSize: 18,\n lineHeight: 1,\n transition: \"transform 0.12s ease\",\n }}\n onMouseEnter={(e) =>\n (e.currentTarget.style.transform = \"scale(1.2)\")\n }\n onMouseLeave={(e) => (e.currentTarget.style.transform = \"scale(1)\")}\n >\n {emoji}\n </button>\n ))}\n\n {}\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowPicker((v) => !v);\n }}\n style={{\n borderRadius: 8,\n padding: \"4px 6px\",\n cursor: \"pointer\",\n fontSize: 18,\n border: \"1px solid transparent\",\n background: \"transparent\",\n }}\n >\n ➕\n </button>\n </div>\n\n {}\n {showPicker && (\n <div\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 6px)\",\n [align === \"right\" ? \"right\" : \"left\"]: 0,\n zIndex: 50,\n animation: \"hermes-pop 0.15s ease\",\n }}\n >\n <EmojiPicker\n theme={Theme.DARK}\n onEmojiClick={handleEmojiClick}\n height={440}\n width={360}\n searchPlaceHolder=\"Search emoji...\"\n lazyLoadEmojis\n />\n </div>\n )}\n\n {}\n <style>{`\n @keyframes hermes-pop {\n from {\n opacity: 0;\n transform: scale(0.85);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n `}</style>\n </div>\n );\n};\n","import React from \"react\";\nimport type { Message } from \"../../types/index\";\n\ninterface MediaMessageProps {\n message: Message;\n className?: string;\n maxWidth?: number | string;\n}\n\nconst formatFileSize = (bytes?: number) => {\n if (!bytes) return \"\";\n if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n};\n\nexport const MediaMessage: React.FC<MediaMessageProps> = ({\n message,\n className = \"\",\n maxWidth = 300,\n}) => {\n if (!message.url) return null;\n\n return (\n <div\n className={`hermes-media-message hermes-media-message--${message.type} ${className}`}\n style={{ maxWidth }}\n >\n {message.type === \"image\" && (\n <img\n src={message.url}\n alt={message.fileName ?? \"image\"}\n style={{\n width: \"100%\",\n borderRadius: 10,\n display: \"block\",\n cursor: \"pointer\",\n }}\n onClick={() => window.open(message.url, \"_blank\")}\n />\n )}\n\n {message.type === \"video\" && (\n <video\n src={message.url}\n poster={message.thumbnail}\n controls\n style={{ width: \"100%\", borderRadius: 10 }}\n />\n )}\n\n {message.type === \"audio\" && (\n <div\n style={{ display: \"flex\", alignItems: \"center\", gap: 8, padding: 8 }}\n >\n <span style={{ fontSize: 20 }}>🎵</span>\n <audio src={message.url} controls style={{ flex: 1, height: 36 }} />\n </div>\n )}\n\n {message.type === \"document\" && (\n <a\n href={message.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"10px 12px\",\n borderRadius: 10,\n border: \"1px solid #e0e0e0\",\n textDecoration: \"none\",\n color: \"inherit\",\n }}\n >\n <span style={{ fontSize: 28, flexShrink: 0 }}>📄</span>\n <div style={{ overflow: \"hidden\" }}>\n <div\n style={{\n fontWeight: 600,\n fontSize: 13,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {message.fileName ?? \"Document\"}\n </div>\n <div style={{ fontSize: 11, opacity: 0.6 }}>\n {formatFileSize(message.fileSize)} · Click to download\n </div>\n </div>\n </a>\n )}\n\n {message.type === \"link\" && (\n <a\n href={message.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"8px 12px\",\n borderRadius: 10,\n border: \"1px solid #e0e0e0\",\n textDecoration: \"none\",\n color: \"#0084ff\",\n wordBreak: \"break-all\",\n fontSize: 13,\n }}\n >\n 🔗 {message.url}\n </a>\n )}\n </div>\n );\n};\n"],"mappings":"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","names":["TypingIndicator","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","TypingIndicator","import_jsx_runtime","import_react","import_jsx_runtime","EmojiPicker","import_jsx_runtime","formatFileSize"]}
@@ -0,0 +1,343 @@
1
+ export { ConnectResponse, ConnectionStatus, CreateDirectRoomInput, CreateGroupRoomInput, DeliveryStatus, HermesConfig, HermesEvents, HermesUser, LastSeenEvent, Message, MessageHistoryResult, MessageType, PresenceEvent, Reaction, ReactionEvent, ReceiptEvent, Room, RoomType, SendMessageInput, TypingEvent, UploadResult } from './index.cjs';
2
+ import React from 'react';
3
+
4
+ interface HermesConfig {
5
+ endpoint: string;
6
+ apiKey: string;
7
+ secret: string;
8
+ userId: string;
9
+ }
10
+ interface HermesUser {
11
+ userId: string;
12
+ displayName: string;
13
+ avatar?: string;
14
+ email?: string;
15
+ }
16
+ type RoomType = "direct" | "group";
17
+ interface Room {
18
+ _id: string;
19
+ name?: string;
20
+ type: RoomType;
21
+ createdBy: string;
22
+ members: string[];
23
+ admins: string[];
24
+ avatar?: string;
25
+ description?: string;
26
+ lastMessage?: Message;
27
+ lastActivity: string;
28
+ unreadCount: number;
29
+ isMuted: boolean;
30
+ isPinned: boolean;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ }
34
+ interface CreateDirectRoomInput {
35
+ targetUserId: string;
36
+ }
37
+ interface CreateGroupRoomInput {
38
+ name: string;
39
+ memberIds: string[];
40
+ description?: string;
41
+ avatar?: string;
42
+ }
43
+ type MessageType = "text" | "link" | "image" | "video" | "audio" | "document";
44
+ type DeliveryStatus = "sent" | "delivered" | "seen";
45
+ interface Reaction {
46
+ emoji: string;
47
+ users: string[];
48
+ }
49
+ interface Message {
50
+ _id: string;
51
+ roomId: string;
52
+ senderId: string;
53
+ type: MessageType;
54
+ text?: string;
55
+ url?: string;
56
+ fileName?: string;
57
+ fileSize?: number;
58
+ mimeType?: string;
59
+ thumbnail?: string;
60
+ replyTo?: string;
61
+ reactions: Reaction[];
62
+ deliveryStatus: DeliveryStatus;
63
+ seenBy: string[];
64
+ isDeleted: boolean;
65
+ deletedAt?: string;
66
+ editedAt?: string;
67
+ createdAt: string;
68
+ updatedAt: string;
69
+ }
70
+ interface SendMessageInput {
71
+ roomId: string;
72
+ type: MessageType;
73
+ text?: string;
74
+ url?: string;
75
+ fileName?: string;
76
+ fileSize?: number;
77
+ mimeType?: string;
78
+ thumbnail?: string;
79
+ replyTo?: string;
80
+ }
81
+ interface MessageHistoryResult {
82
+ messages: Message[];
83
+ hasMore: boolean;
84
+ }
85
+ interface PresenceEvent {
86
+ userId: string;
87
+ displayName: string;
88
+ roomId?: string;
89
+ }
90
+ interface LastSeenEvent {
91
+ userId: string;
92
+ lastSeen: string;
93
+ }
94
+ interface TypingEvent {
95
+ userId: string;
96
+ displayName: string;
97
+ roomId: string;
98
+ }
99
+ interface ReceiptEvent {
100
+ roomId: string;
101
+ userId: string;
102
+ lastMessageId: string;
103
+ seenAt: string;
104
+ }
105
+ interface ReactionEvent {
106
+ messageId: string;
107
+ roomId: string;
108
+ reactions: Reaction[];
109
+ }
110
+ interface UploadResult {
111
+ type: MessageType;
112
+ url: string;
113
+ thumbnail?: string;
114
+ fileName: string;
115
+ fileSize: number;
116
+ mimeType: string;
117
+ }
118
+ interface HermesEvents {
119
+ connected: () => void;
120
+ disconnected: (reason: string) => void;
121
+ error: (error: Error) => void;
122
+ "message:receive": (message: Message) => void;
123
+ "message:deleted": (data: {
124
+ messageId: string;
125
+ roomId: string;
126
+ }) => void;
127
+ "message:edited": (message: Message) => void;
128
+ "room:created": (room: Room) => void;
129
+ "room:deleted": (data: {
130
+ roomId: string;
131
+ }) => void;
132
+ "room:member:joined": (data: {
133
+ roomId: string;
134
+ userId: string;
135
+ }) => void;
136
+ "room:member:left": (data: {
137
+ roomId: string;
138
+ userId: string;
139
+ }) => void;
140
+ "user:online": (event: PresenceEvent) => void;
141
+ "user:offline": (event: LastSeenEvent) => void;
142
+ "typing:started": (event: TypingEvent) => void;
143
+ "typing:stopped": (event: TypingEvent) => void;
144
+ "receipt:updated": (event: ReceiptEvent) => void;
145
+ "reaction:updated": (event: ReactionEvent) => void;
146
+ }
147
+ type ConnectionStatus = "idle" | "connecting" | "connected" | "disconnected" | "error";
148
+
149
+ type EventKey = keyof HermesEvents;
150
+ type EventCallback<K extends EventKey> = HermesEvents[K];
151
+ declare class EventEmitter {
152
+ private listeners;
153
+ on<K extends EventKey>(event: K, callback: EventCallback<K>): this;
154
+ off<K extends EventKey>(event: K, callback: EventCallback<K>): void;
155
+ once<K extends EventKey>(event: K, callback: EventCallback<K>): this;
156
+ emit<K extends EventKey>(event: K, ...args: Parameters<EventCallback<K>>): this;
157
+ removeAllListeners<K extends EventKey>(event?: K): this;
158
+ listenerCount<K extends EventKey>(event: K): number;
159
+ }
160
+
161
+ declare class HermesClient extends EventEmitter {
162
+ private config;
163
+ private socket;
164
+ private token;
165
+ user: HermesUser | null;
166
+ status: ConnectionStatus;
167
+ constructor(config: HermesConfig);
168
+ connect(): Promise<HermesUser>;
169
+ private _connectSocket;
170
+ disconnect(): void;
171
+ private _wireSocketEvents;
172
+ _emit<T = any>(event: string, data?: any): Promise<T>;
173
+ sendMessage(input: SendMessageInput): Promise<Message>;
174
+ getHistory(roomId: string, before?: string, limit?: number): Promise<MessageHistoryResult>;
175
+ deleteMessage(messageId: string, roomId: string): Promise<void>;
176
+ editMessage(messageId: string, roomId: string, text: string): Promise<Message>;
177
+ createDirectRoom(input: CreateDirectRoomInput): Promise<Room>;
178
+ createGroupRoom(input: CreateGroupRoomInput): Promise<Room>;
179
+ deleteRoom(roomId: string): Promise<void>;
180
+ getRooms(): Promise<Room[]>;
181
+ addMember(roomId: string, newMemberId: string): Promise<void>;
182
+ removeMember(roomId: string, targetId: string): Promise<void>;
183
+ pingPresence(roomId: string): void;
184
+ startTyping(roomId: string): void;
185
+ stopTyping(roomId: string): void;
186
+ markSeen(roomId: string, lastMessageId: string): Promise<void>;
187
+ addReaction(messageId: string, roomId: string, emoji: string): Promise<void>;
188
+ uploadFile(file: File): Promise<UploadResult>;
189
+ get isConnected(): boolean;
190
+ get currentUser(): HermesUser | null;
191
+ }
192
+
193
+ declare const useMessages: (client: HermesClient, roomId: string | null) => {
194
+ messages: Message[];
195
+ loading: boolean;
196
+ loadingMore: boolean;
197
+ hasMore: boolean;
198
+ error: string | null;
199
+ typingUsers: {
200
+ userId: string;
201
+ displayName: string;
202
+ }[];
203
+ sendMessage: (input: Omit<SendMessageInput, "roomId">) => Promise<Message>;
204
+ editMessage: (messageId: string, text: string) => Promise<Message>;
205
+ deleteMessage: (messageId: string) => Promise<void>;
206
+ addReaction: (messageId: string, emoji: string) => Promise<void>;
207
+ loadMore: () => Promise<void>;
208
+ };
209
+
210
+ declare const useRooms: (client: HermesClient) => {
211
+ rooms: Room[];
212
+ loading: boolean;
213
+ error: string | null;
214
+ createDirect: (input: CreateDirectRoomInput) => Promise<Room>;
215
+ createGroup: (input: CreateGroupRoomInput) => Promise<Room>;
216
+ deleteRoom: (roomId: string) => Promise<void>;
217
+ addMember: (roomId: string, userId: string) => Promise<void>;
218
+ removeMember: (roomId: string, userId: string) => Promise<void>;
219
+ refetch: () => Promise<void>;
220
+ };
221
+
222
+ declare const usePresence: (client: HermesClient) => {
223
+ isOnline: (userId: string) => boolean;
224
+ onlineUsers: string[];
225
+ onlineMap: Map<string, boolean>;
226
+ };
227
+
228
+ declare const useTyping: (client: HermesClient, roomId: string | null) => {
229
+ typingUsers: Map<string, string>;
230
+ typingText: string | null;
231
+ isAnyoneTyping: boolean;
232
+ startTyping: () => void;
233
+ stopTyping: () => void;
234
+ };
235
+
236
+ declare const useReadReceipts: (client: HermesClient, roomId: string | null) => {
237
+ markSeen: (lastMessageId: string) => Promise<void>;
238
+ seenBy: (messageId: string) => string[];
239
+ receipts: Map<string, Set<string>>;
240
+ };
241
+
242
+ declare const useReactions: (client: HermesClient, roomId: string | null) => {
243
+ react: (messageId: string, emoji: string) => Promise<void>;
244
+ hasReacted: (reactions: Reaction[], emoji: string) => boolean;
245
+ getCount: (reactions: Reaction[], emoji: string) => number;
246
+ getEmojis: (reactions: Reaction[]) => string[];
247
+ };
248
+
249
+ declare const useUpload: (client: HermesClient) => {
250
+ upload: (file: File) => Promise<UploadResult | null>;
251
+ sendFile: (roomId: string, file: File, replyTo?: string) => Promise<Message | null>;
252
+ validate: (file: File, maxMb?: number) => string | null;
253
+ uploading: boolean;
254
+ error: string | null;
255
+ lastUpload: UploadResult | null;
256
+ };
257
+
258
+ interface MessageListProps {
259
+ messages: Message[];
260
+ currentUser: HermesUser;
261
+ loading?: boolean;
262
+ loadingMore?: boolean;
263
+ hasMore?: boolean;
264
+ onLoadMore?: () => void;
265
+ onEdit?: (messageId: string, text: string) => void;
266
+ onDelete?: (messageId: string) => void;
267
+ onReact?: (messageId: string, emoji: string) => void;
268
+ onReply?: (message: Message) => void;
269
+ renderMessage?: (message: Message, isOwn: boolean) => React.ReactNode;
270
+ renderAvatar?: (senderId: string) => React.ReactNode;
271
+ className?: string;
272
+ autoScroll?: boolean;
273
+ typingUsers?: {
274
+ userId: string;
275
+ displayName: string;
276
+ }[];
277
+ }
278
+ declare const MessageList: React.FC<MessageListProps>;
279
+
280
+ interface ChatInputProps {
281
+ onSendText: (text: string) => Promise<void> | void;
282
+ onSendFile?: (file: File) => Promise<void> | void;
283
+ onTypingStart?: () => void;
284
+ onTypingStop?: () => void;
285
+ replyingTo?: Message | null;
286
+ onCancelReply?: () => void;
287
+ disabled?: boolean;
288
+ placeholder?: string;
289
+ maxLength?: number;
290
+ className?: string;
291
+ inputClassName?: string;
292
+ renderAttachIcon?: () => React.ReactNode;
293
+ renderSendIcon?: () => React.ReactNode;
294
+ }
295
+ declare const ChatInput: React.FC<ChatInputProps>;
296
+
297
+ interface RoomListProps {
298
+ rooms: Room[];
299
+ activeRoomId?: string | null;
300
+ currentUserId: string;
301
+ loading?: boolean;
302
+ onSelectRoom: (room: Room) => void;
303
+ onCreateDirect?: () => void;
304
+ onCreateGroup?: () => void;
305
+ renderRoomItem?: (room: Room, isActive: boolean) => React.ReactNode;
306
+ renderAvatar?: (room: Room) => React.ReactNode;
307
+ renderEmpty?: () => React.ReactNode;
308
+ className?: string;
309
+ itemClassName?: string;
310
+ }
311
+ declare const RoomList: React.FC<RoomListProps>;
312
+
313
+ interface TypingIndicatorProps {
314
+ typingText: string | null;
315
+ className?: string;
316
+ }
317
+ declare const TypingIndicator: React.FC<TypingIndicatorProps>;
318
+
319
+ interface OnlineBadgeProps {
320
+ isOnline: boolean;
321
+ size?: number;
322
+ className?: string;
323
+ }
324
+ declare const OnlineBadge: React.FC<OnlineBadgeProps>;
325
+
326
+ interface ReactionPickerProps {
327
+ onSelect: (emoji: string) => void;
328
+ currentReactions?: Reaction[];
329
+ currentUserId?: string;
330
+ emojis?: string[];
331
+ className?: string;
332
+ align?: "left" | "right";
333
+ }
334
+ declare const ReactionPicker: React.FC<ReactionPickerProps>;
335
+
336
+ interface MediaMessageProps {
337
+ message: Message;
338
+ className?: string;
339
+ maxWidth?: number | string;
340
+ }
341
+ declare const MediaMessage: React.FC<MediaMessageProps>;
342
+
343
+ export { ChatInput, MediaMessage, MessageList, OnlineBadge, ReactionPicker, RoomList, TypingIndicator, useMessages, usePresence, useReactions, useReadReceipts, useRooms, useTyping, useUpload };