84 lines
2.2 KiB
TypeScript
84 lines
2.2 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useRef, useCallback, KeyboardEvent } from 'react'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Textarea } from '@/components/ui/textarea'
|
|
import { Send, Loader2 } from 'lucide-react'
|
|
|
|
interface ChatInputProps {
|
|
onSend: (message: string) => void
|
|
disabled?: boolean
|
|
isLoading?: boolean
|
|
placeholder?: string
|
|
}
|
|
|
|
export function ChatInput({
|
|
onSend,
|
|
disabled = false,
|
|
isLoading = false,
|
|
placeholder = 'Skriv ett meddelande...',
|
|
}: ChatInputProps) {
|
|
const [message, setMessage] = useState('')
|
|
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
|
|
|
const handleSend = useCallback(() => {
|
|
const trimmed = message.trim()
|
|
if (trimmed && !disabled && !isLoading) {
|
|
onSend(trimmed)
|
|
setMessage('')
|
|
// Reset textarea height
|
|
if (textareaRef.current) {
|
|
textareaRef.current.style.height = 'auto'
|
|
}
|
|
}
|
|
}, [message, disabled, isLoading, onSend])
|
|
|
|
const handleKeyDown = useCallback(
|
|
(e: KeyboardEvent<HTMLTextAreaElement>) => {
|
|
// Send on Enter (without Shift)
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault()
|
|
handleSend()
|
|
}
|
|
},
|
|
[handleSend]
|
|
)
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
setMessage(e.target.value)
|
|
// Auto-resize textarea
|
|
const textarea = e.target
|
|
textarea.style.height = 'auto'
|
|
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`
|
|
}
|
|
|
|
const isDisabled = disabled || isLoading || !message.trim()
|
|
|
|
return (
|
|
<div className="flex gap-2 items-end p-4 border-t bg-background">
|
|
<Textarea
|
|
ref={textareaRef}
|
|
value={message}
|
|
onChange={handleChange}
|
|
onKeyDown={handleKeyDown}
|
|
placeholder={placeholder}
|
|
disabled={disabled || isLoading}
|
|
className="min-h-[44px] max-h-[200px] resize-none py-3"
|
|
rows={1}
|
|
/>
|
|
<Button
|
|
onClick={handleSend}
|
|
disabled={isDisabled}
|
|
size="icon"
|
|
className="flex-shrink-0 h-[44px] w-[44px]"
|
|
>
|
|
{isLoading ? (
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
) : (
|
|
<Send className="h-4 w-4" />
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|