Files
test1/components/ui/image-preview.tsx
2026-03-20 07:33:46 +00:00

69 lines
1.7 KiB
TypeScript

import * as React from 'react'
import { Dialog, DialogContent } from './dialog'
import { cn } from '@/utils/cn'
export interface ImagePreviewProps {
/** 图片 URL */
src: string
/** 图片描述 */
alt?: string
/** 是否打开 */
open?: boolean
/** 打开/关闭回调 */
onOpenChange?: (open: boolean) => void
/** 子元素(通常是 Image 组件) */
children?: React.ReactNode
/** 自定义类名 */
className?: string
}
/**
* ImagePreview 组件 - 图片预览对话框
*/
export function ImagePreview({
src,
alt = '图片预览',
open: controlledOpen,
onOpenChange,
children,
className,
}: ImagePreviewProps) {
const [internalOpen, setInternalOpen] = React.useState(false)
const open = controlledOpen ?? internalOpen
const setOpen = React.useCallback(
(value: boolean) => {
if (controlledOpen === undefined) {
setInternalOpen(value)
}
onOpenChange?.(value)
},
[controlledOpen, onOpenChange]
)
const handleChildClick = React.useCallback(() => {
setOpen(true)
}, [setOpen])
return (
<>
{children ? (
<div onClick={handleChildClick} className={cn('cursor-pointer', className)}>
{children}
</div>
) : null}
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="max-w-[90vw] max-h-[90vh] p-0 bg-transparent border-0 shadow-none z-50">
<div className="relative flex items-center justify-center w-full h-full">
<img
src={src}
alt={alt}
className="max-w-full max-h-[90vh] object-contain rounded-lg"
/>
</div>
</DialogContent>
</Dialog>
</>
)
}