'use client' import * as React from 'react' import { cn } from '@/lib/utils' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' // Icons const SendIcon = () => ( ) const EmojiIcon = () => ( ) const AttachIcon = () => ( ) // Typing indicator dots function TypingIndicator({ className }: { className?: string }) { return (
{[0, 1, 2].map((i) => ( ))}
) } // Single message bubble interface MessageProps { content: string sender: { name: string avatar?: string initials: string } timestamp?: string isOwn?: boolean status?: 'sent' | 'delivered' | 'read' reactions?: { emoji: string; count: number }[] className?: string } function Message({ content, sender, timestamp, isOwn = false, status, reactions, className, }: MessageProps) { return (
{!isOwn && ( {sender.avatar ? ( ) : null} {sender.initials} )}
{!isOwn && ( {sender.name} )}
{content}
{reactions && reactions.length > 0 && (
{reactions.map((reaction, i) => ( {reaction.emoji} {reaction.count > 1 && reaction.count} ))}
)} {(timestamp || status) && (
{timestamp && {timestamp}} {isOwn && status && ( {status === 'sent' && '✓'} {status === 'delivered' && '✓✓'} {status === 'read' && '✓✓'} )}
)}
) } // Chat container interface ChatProps { title?: string subtitle?: string messages?: MessageProps[] className?: string onSend?: (message: string) => void showTyping?: boolean } function Chat({ title = 'Chat', subtitle, messages = [], className, onSend, showTyping = false, }: ChatProps) { const [inputValue, setInputValue] = React.useState('') const messagesEndRef = React.useRef(null) const handleSend = () => { if (inputValue.trim() && onSend) { onSend(inputValue.trim()) setInputValue('') } } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault() handleSend() } } return (
{/* Header */}
💬

{title}

{subtitle && (

{subtitle}

)}
{/* Messages area */}
{messages.map((message, i) => ( ))} {showTyping && }
{/* Input area */}
setInputValue(e.target.value)} onKeyDown={handleKeyDown} className="flex-1 h-9 bg-background" />
) } // Presence indicator interface PresenceProps { status: 'online' | 'away' | 'busy' | 'offline' label?: boolean className?: string } function Presence({ status, label = false, className }: PresenceProps) { const statusConfig = { online: { color: 'bg-success shadow-[0_0_8px_oklch(0.72_0.19_145_/_0.6)]', text: 'Online', }, away: { color: 'bg-warning', text: 'Away', }, busy: { color: 'bg-destructive', text: 'Do not disturb', }, offline: { color: 'bg-muted-foreground', text: 'Offline', }, } const config = statusConfig[status] return (
{label && ( {config.text} )}
) } export { Chat, Message, TypingIndicator, Presence }