import {
ChatInput,
ChatMessage,
ChatMessages,
ChatSection,
useChatUI,
useFile,
} from '@llamaindex/chat-ui'
import { useChat } from '@ai-sdk/react'
import { motion, AnimatePresence } from 'framer-motion'
export function CustomChat() {
const handler = useChat()
const { image, uploadFile, reset, getAttachments } = useFile({
uploadAPI: '/chat/upload',
})
const handleUpload = async (file: File) => {
try {
await uploadFile(file)
} catch (error) {
console.error(error)
}
}
const attachments = getAttachments()
return (
<ChatSection
handler={handler}
className="h-screen overflow-hidden p-0 md:p-5"
>
<CustomChatMessages />
<ChatInput
attachments={attachments}
resetUploadedFiles={reset}
>
<div>
{image ? (
<img
className="max-h-[100px] object-contain"
src={image.url}
alt="uploaded"
/>
) : null}
</div>
<ChatInput.Form>
<ChatInput.Field />
<ChatInput.Upload
allowedExtensions={['jpg', 'png', 'jpeg']}
onUpload={handleUpload}
/>
<ChatInput.Submit />
</ChatInput.Form>
</ChatInput>
</ChatSection>
)
}
function CustomChatMessages() {
const { messages } = useChatUI()
return (
<ChatMessages>
<ChatMessages.List className="px-0 md:px-16">
<AnimatePresence>
{messages.map((message, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, delay: index * 0.1 }}
>
<ChatMessage
message={message}
isLast={index === messages.length - 1}
className="items-start"
>
<ChatMessage.Avatar>
<img
className="border-1 rounded-full border-[#e711dd]"
alt="LlamaIndex"
src="/llama.png"
/>
</ChatMessage.Avatar>
<ChatMessage.Content>
<ChatMessage.Part.File />
<ChatMessage.Part.Markdown />
</ChatMessage.Content>
<ChatMessage.Actions />
</ChatMessage>
</motion.div>
))}
</AnimatePresence>
</ChatMessages.List>
</ChatMessages>
)
}