diff --git a/src/components/chat/message-input.tsx b/src/components/chat/message-input.tsx index 39a7517..1e66e40 100644 --- a/src/components/chat/message-input.tsx +++ b/src/components/chat/message-input.tsx @@ -29,6 +29,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" +import { ImagePreviewDialog } from "@/components/ui/image-preview-dialog" import { cn, randomUUID } from "@/lib/utils" import { matchShortcutEvent } from "@/lib/keyboard-shortcuts" import { useShortcutSettings } from "@/hooks/use-shortcut-settings" @@ -303,6 +304,9 @@ export function MessageInput({ }) const [attachments, setAttachments] = useState([]) const [isDragActive, setIsDragActive] = useState(false) + const [previewAttachmentId, setPreviewAttachmentId] = useState( + null + ) const containerRef = useRef(null) const textareaRef = useRef(null) const lastDomDropAtRef = useRef(0) @@ -394,6 +398,13 @@ export function MessageInput({ ), [attachments] ) + const previewAttachment = useMemo( + () => + previewAttachmentId + ? (imageAttachments.find((a) => a.id === previewAttachmentId) ?? null) + : null, + [previewAttachmentId, imageAttachments] + ) const resourceAttachments = useMemo( () => attachments.filter( @@ -1275,14 +1286,20 @@ export function MessageInput({ key={attachment.id} className="relative shrink-0 overflow-hidden rounded-md border border-border/70 bg-muted/30" > - {attachment.name} + ))} + { + if (!open) setPreviewIndex(null) + }} + /> ) } diff --git a/src/components/ui/image-preview-dialog.tsx b/src/components/ui/image-preview-dialog.tsx new file mode 100644 index 0000000..307876e --- /dev/null +++ b/src/components/ui/image-preview-dialog.tsx @@ -0,0 +1,58 @@ +"use client" + +import { Dialog as DialogPrimitive } from "radix-ui" +import { X } from "lucide-react" +import { cn } from "@/lib/utils" + +interface ImagePreviewDialogProps { + src: string + alt: string + open: boolean + onOpenChange: (open: boolean) => void +} + +function ImagePreviewDialog({ + src, + alt, + open, + onOpenChange, +}: ImagePreviewDialogProps) { + return ( + + + + onOpenChange(false)} + > + + {alt} + + + {/* eslint-disable-next-line @next/next/no-img-element */} + {alt} e.stopPropagation()} + className="max-h-[90vh] max-w-[90vw] rounded-lg object-contain" + /> + + + + ) +} + +export { ImagePreviewDialog }