68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import React from 'react'
|
|
import { cn } from '../lib/utils'
|
|
import { Plus, X } from 'lucide-react'
|
|
|
|
interface ImageUploaderProps {
|
|
images: { uri?: string }[]
|
|
onAddImage: () => void
|
|
onRemoveImage: (uri: string) => void
|
|
existingImageUrls?: string[]
|
|
onRemoveExistingImage?: (url: string) => void
|
|
allowMultiple?: boolean
|
|
}
|
|
|
|
export function ImageUploader({
|
|
images,
|
|
existingImageUrls = [],
|
|
onAddImage,
|
|
onRemoveImage,
|
|
onRemoveExistingImage,
|
|
allowMultiple = true,
|
|
}: ImageUploaderProps) {
|
|
const totalCount = images.length + existingImageUrls.length
|
|
|
|
return (
|
|
<div className="mb-4">
|
|
<div className="flex flex-wrap gap-2">
|
|
{existingImageUrls.map((url, index) => (
|
|
<div key={`existing-${index}`} className="relative w-1/3 aspect-square">
|
|
<img
|
|
src={url}
|
|
alt={`Existing ${index + 1}`}
|
|
className="h-full w-full rounded object-cover"
|
|
/>
|
|
<button
|
|
onClick={() => onRemoveExistingImage?.(url)}
|
|
className="absolute right-1 top-1 rounded-full bg-red-500 p-1 text-white"
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</button>
|
|
</div>
|
|
))}
|
|
{images.map((image, index) => (
|
|
<div key={`new-${index}`} className="relative w-1/3 aspect-square">
|
|
<img
|
|
src={image.uri}
|
|
alt={`Upload ${index + 1}`}
|
|
className="h-full w-full rounded object-cover"
|
|
/>
|
|
<button
|
|
onClick={() => image.uri && onRemoveImage(image.uri)}
|
|
className="absolute right-1 top-1 rounded-full bg-red-500 p-1 text-white"
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</button>
|
|
</div>
|
|
))}
|
|
{(!allowMultiple || totalCount < 1) && (
|
|
<button
|
|
onClick={onAddImage}
|
|
className="flex aspect-square w-1/3 items-center justify-center rounded bg-gray-200 opacity-75 hover:opacity-100"
|
|
>
|
|
<Plus className="h-8 w-8 text-gray-600" />
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|