65 行
1.3 KiB
TypeScript
65 行
1.3 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
|
|
import { cn } from '@/lib/utils'
|
|
|
|
import type { FC } from 'react'
|
|
|
|
type Props = {
|
|
url: string
|
|
file?: File
|
|
alt?: string
|
|
className?: string
|
|
referrerPolicy?: 'no-referrer' }
|
|
|
|
|
|
const PostThumbnailPreview: FC<Props> = (
|
|
{ url,
|
|
file,
|
|
alt = 'サムネール',
|
|
className = 'h-16 w-16',
|
|
referrerPolicy },
|
|
) => {
|
|
const [failed, setFailed] = useState (false)
|
|
const [fileUrl, setFileUrl] = useState<string | null> (null)
|
|
|
|
useEffect (() => {
|
|
setFailed (false)
|
|
}, [file, url])
|
|
|
|
useEffect (() => {
|
|
if (file == null)
|
|
{
|
|
setFileUrl (null)
|
|
return
|
|
}
|
|
|
|
const nextUrl = URL.createObjectURL (file)
|
|
setFileUrl (nextUrl)
|
|
|
|
return () => {
|
|
URL.revokeObjectURL (nextUrl)
|
|
}
|
|
}, [file])
|
|
|
|
const resolvedUrl = url.trim () !== '' ? url : (fileUrl ?? '')
|
|
|
|
if (resolvedUrl === '' || failed)
|
|
{
|
|
return (
|
|
<div
|
|
className={cn (
|
|
className,
|
|
'rounded border border-border bg-muted')}/>)
|
|
}
|
|
|
|
return (
|
|
<img
|
|
src={resolvedUrl}
|
|
alt={alt}
|
|
referrerPolicy={referrerPolicy}
|
|
className={cn (className, 'rounded border border-border object-cover')}
|
|
onError={() => setFailed (true)}/>)
|
|
}
|
|
|
|
export default PostThumbnailPreview
|