| import { useState, useRef } from "react"; | |
| import { Send, Paperclip, Smile, X } from "lucide-react"; | |
| interface MessageInputProps { | |
| value: string; | |
| onChange: (val: string) => void; | |
| onSend: () => void; | |
| onFileSelect: (e: React.ChangeEvent<HTMLInputElement>) => void; | |
| onTyping: () => void; | |
| selectedFiles: File[]; | |
| clearFiles: () => void; | |
| } | |
| export function MessageInput({ | |
| value, | |
| onChange, | |
| onSend, | |
| onFileSelect, | |
| onTyping, | |
| selectedFiles, | |
| clearFiles, | |
| }: MessageInputProps) { | |
| const fileInputRef = useRef<HTMLInputElement>(null); | |
| const handleKeyDown = (e: React.KeyboardEvent) => { | |
| if (e.key === "Enter" && !e.shiftKey) { | |
| e.preventDefault(); | |
| onSend(); | |
| } | |
| }; | |
| return ( | |
| <div className="bg-white dark:bg-gray-800 p-3 border-t border-gray-200 dark:border-gray-700"> | |
| {selectedFiles.length > 0 && ( | |
| <div className="mb-2 flex gap-2 overflow-x-auto pb-1"> | |
| {selectedFiles.map((file, idx) => ( | |
| <div key={idx} className="relative shrink-0"> | |
| <img | |
| src={URL.createObjectURL(file)} | |
| alt={file.name} | |
| className="h-16 w-16 object-cover rounded-lg" | |
| /> | |
| <button | |
| onClick={() => { | |
| const newFiles = selectedFiles.filter((_, i) => i !== idx); | |
| // Update parent with new files (parent should handle state) | |
| clearFiles(); // For simplicity, we clear all; better to modify array | |
| }} | |
| className="absolute -top-1 -right-1 bg-red-500 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs" | |
| > | |
| <X className="w-3 h-3" /> | |
| </button> | |
| </div> | |
| ))} | |
| </div> | |
| )} | |
| <div className="flex items-end gap-2"> | |
| <button | |
| onClick={() => fileInputRef.current?.click()} | |
| className="p-2 text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition" | |
| > | |
| <Paperclip className="w-5 h-5" /> | |
| </button> | |
| <input | |
| ref={fileInputRef} | |
| type="file" | |
| multiple | |
| accept="image/*,video/*,application/pdf" | |
| className="hidden" | |
| onChange={onFileSelect} | |
| /> | |
| <div className="flex-1 relative"> | |
| <input | |
| type="text" | |
| value={value} | |
| onChange={(e) => onChange(e.target.value)} | |
| onKeyDown={handleKeyDown} | |
| onInput={onTyping} | |
| placeholder="Type a message..." | |
| className="w-full pl-4 pr-10 py-2.5 bg-gray-100 dark:bg-gray-700 rounded-full focus:outline-none focus:ring-2 focus:ring-primary text-gray-800 dark:text-gray-100" | |
| /> | |
| <button | |
| className="absolute right-2 top-1/2 -translate-y-1/2 p-1 text-gray-400 hover:text-gray-600" | |
| title="Emoji" | |
| > | |
| <Smile className="w-5 h-5" /> | |
| </button> | |
| </div> | |
| <button | |
| onClick={onSend} | |
| disabled={!value.trim() && selectedFiles.length === 0} | |
| className="p-2.5 bg-primary text-white rounded-full hover:bg-primary-dark disabled:opacity-50 transition shadow" | |
| > | |
| <Send className="w-5 h-5" /> | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| } | |
Xet Storage Details
- Size:
- 3.32 kB
- Xet hash:
- 7d6583fa2bab4b3e60450efc5dd1d206b18991a1cde185e06912ff9033022958
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.