|
1 | 1 | import { formatBytes } from "@/utils/utils"; |
2 | 2 | import { DownloadIcon, Eye, MoveRight } from "lucide-react"; |
| 3 | +import { memo } from "react"; |
3 | 4 | import { PhotoView } from "react-photo-view"; |
4 | 5 | import "react-photo-view/dist/react-photo-view.css"; |
5 | 6 | import { Button } from "./ui/button"; |
6 | 7 |
|
7 | | -const ImagePreviewCard = ({ |
8 | | - onSingleFileDownload, |
9 | | - ...props |
10 | | -}: { |
11 | | - onSingleFileDownload: (file: string) => void; |
12 | | - content: string; |
13 | | - fileName: string; |
14 | | - originalImageSize: number; |
15 | | - compressedImageSize: number; |
16 | | - compressionPercentage: string; |
17 | | -}) => { |
18 | | - return ( |
19 | | - <div className="bg-background flex items-center justify-between gap-2 rounded-lg border p-2 pe-3"> |
20 | | - <div className="flex items-center gap-3 overflow-hidden"> |
21 | | - <div className="bg-accent relative aspect-square shrink-0 cursor-pointer rounded-[6px]"> |
22 | | - <PhotoView src={props?.content}> |
23 | | - <div> |
24 | | - <img |
25 | | - src={props?.content} |
26 | | - alt={props?.fileName} |
27 | | - className="size-12 rounded-[6px] object-cover" |
28 | | - /> |
29 | | - <div className="absolute inset-0 flex items-center justify-center rounded-[6px] bg-black/25"> |
30 | | - <Eye className="text-[#fafafa]" /> |
| 8 | +const ImagePreviewCard = memo( |
| 9 | + ({ |
| 10 | + onSingleFileDownload, |
| 11 | + ...props |
| 12 | + }: { |
| 13 | + onSingleFileDownload: (file: string) => void; |
| 14 | + content: string; |
| 15 | + fileName: string; |
| 16 | + originalImageSize: number; |
| 17 | + compressedImageSize: number; |
| 18 | + compressionPercentage: string; |
| 19 | + }) => { |
| 20 | + return ( |
| 21 | + <div className="bg-background flex items-center justify-between gap-2 rounded-lg border p-2 pe-3 will-change-transform"> |
| 22 | + <div className="flex items-center gap-3 overflow-hidden"> |
| 23 | + <div className="bg-accent relative aspect-square shrink-0 cursor-pointer rounded-[6px]"> |
| 24 | + <PhotoView src={props?.content}> |
| 25 | + <div> |
| 26 | + <img |
| 27 | + src={props?.content} |
| 28 | + alt={props?.fileName} |
| 29 | + className="size-12 rounded-[6px] object-cover" |
| 30 | + /> |
| 31 | + <div className="absolute inset-0 flex items-center justify-center rounded-[6px] bg-black/25"> |
| 32 | + <Eye className="text-[#fafafa]" /> |
| 33 | + </div> |
31 | 34 | </div> |
32 | | - </div> |
33 | | - </PhotoView> |
34 | | - </div> |
35 | | - <div className="flex min-w-0 flex-col"> |
36 | | - <p className="truncate text-sm font-medium">{props?.fileName}</p> |
37 | | - <span className="text-muted-foreground flex items-center text-xs"> |
38 | | - <span className="text-destructive"> |
39 | | - {formatBytes(props?.originalImageSize)} |
40 | | - </span> |
41 | | - <MoveRight className="mx-1 h-4 w-4" /> |
42 | | - <span className="text-success"> |
43 | | - {formatBytes(props?.compressedImageSize)}{" "} |
44 | | - <span className="inline-flex"> |
45 | | - ({props?.compressionPercentage}%) |
| 35 | + </PhotoView> |
| 36 | + </div> |
| 37 | + <div className="flex min-w-0 flex-col"> |
| 38 | + <p className="truncate text-sm font-medium">{props?.fileName}</p> |
| 39 | + <span className="text-muted-foreground flex items-center text-xs"> |
| 40 | + <span className="text-destructive"> |
| 41 | + {formatBytes(props?.originalImageSize)} |
| 42 | + </span> |
| 43 | + <MoveRight className="mx-1 h-4 w-4" /> |
| 44 | + <span className="text-success"> |
| 45 | + {formatBytes(props?.compressedImageSize)}{" "} |
| 46 | + <span className="inline-flex"> |
| 47 | + ({props?.compressionPercentage}%) |
| 48 | + </span> |
46 | 49 | </span> |
47 | 50 | </span> |
48 | | - </span> |
| 51 | + </div> |
49 | 52 | </div> |
| 53 | + <Button |
| 54 | + size="icon" |
| 55 | + variant="ghost" |
| 56 | + className="text-muted-foreground/80 hover:text-foreground -me-2 size-8 hover:bg-transparent" |
| 57 | + onClick={() => onSingleFileDownload(props?.content)} |
| 58 | + > |
| 59 | + <DownloadIcon aria-hidden="true" /> |
| 60 | + </Button> |
50 | 61 | </div> |
51 | | - <Button |
52 | | - size="icon" |
53 | | - variant="ghost" |
54 | | - className="text-muted-foreground/80 hover:text-foreground -me-2 size-8 hover:bg-transparent" |
55 | | - onClick={() => onSingleFileDownload(props?.content)} |
56 | | - > |
57 | | - <DownloadIcon aria-hidden="true" /> |
58 | | - </Button> |
59 | | - </div> |
60 | | - ); |
61 | | -}; |
| 62 | + ); |
| 63 | + } |
| 64 | +); |
62 | 65 |
|
63 | 66 | export default ImagePreviewCard; |
0 commit comments