auto select and edit
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import { FC, useState } from 'react'
|
||||
import { ImageBlock as ImageBlockType } from '../../types/blocks'
|
||||
import Input from '@/components/Input'
|
||||
import UploadBoxDraggble from '@/components/UploadBoxDraggble'
|
||||
|
||||
interface ImageBlockProps {
|
||||
block: ImageBlockType
|
||||
isSelected?: boolean
|
||||
onUpdate: (updates: Partial<ImageBlockType>) => void
|
||||
onSelect: () => void
|
||||
isEditing?: boolean
|
||||
}
|
||||
|
||||
const ImageBlock: FC<ImageBlockProps> = ({
|
||||
block,
|
||||
isSelected,
|
||||
onUpdate,
|
||||
onSelect,
|
||||
isEditing = false
|
||||
}) => {
|
||||
const [localSrc, setLocalSrc] = useState(block.data.src)
|
||||
const [localAlt, setLocalAlt] = useState(block.data.alt)
|
||||
const [localUrl, setLocalUrl] = useState(block.data.url || '')
|
||||
|
||||
const handleSrcChange = (src: string) => {
|
||||
setLocalSrc(src)
|
||||
onUpdate({
|
||||
data: {
|
||||
...block.data,
|
||||
src
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleAltChange = (alt: string) => {
|
||||
setLocalAlt(alt)
|
||||
onUpdate({
|
||||
data: {
|
||||
...block.data,
|
||||
alt
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleUrlChange = (url: string) => {
|
||||
setLocalUrl(url)
|
||||
onUpdate({
|
||||
data: {
|
||||
...block.data,
|
||||
url
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleImageUpload = (files: File[]) => {
|
||||
if (files.length > 0) {
|
||||
const file = files[0]
|
||||
const imageUrl = URL.createObjectURL(file)
|
||||
handleSrcChange(imageUrl)
|
||||
}
|
||||
}
|
||||
|
||||
const imageStyle = {
|
||||
width: typeof block.style.width === 'number' ? `${block.style.width}px` : block.style.width,
|
||||
height: typeof block.style.height === 'number' ? `${block.style.height}px` : block.style.height,
|
||||
objectFit: block.style.objectFit as 'cover' | 'contain' | 'fill',
|
||||
borderRadius: block.style.borderRadius ? `${block.style.borderRadius}px` : '0',
|
||||
maxWidth: '100%',
|
||||
display: 'block',
|
||||
margin: block.style.margin ?
|
||||
`${block.style.margin.top}px ${block.style.margin.right}px ${block.style.margin.bottom}px ${block.style.margin.left}px` :
|
||||
'8px 0'
|
||||
}
|
||||
|
||||
const containerStyle = {
|
||||
border: isSelected ? '2px dashed #0038FF' : '2px dashed transparent',
|
||||
borderRadius: '8px',
|
||||
padding: '4px',
|
||||
textAlign: block.style.textAlign as 'left' | 'center' | 'right',
|
||||
position: 'relative' as const,
|
||||
display: 'inline-block',
|
||||
minHeight: '60px',
|
||||
minWidth: '80px'
|
||||
}
|
||||
|
||||
// Process variables in src for preview
|
||||
const processVariables = (content: string) => {
|
||||
return content.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
||||
const sampleData: Record<string, string> = {
|
||||
userImage: 'https://via.placeholder.com/150x150?text=تصویر+کاربر',
|
||||
companyLogo: 'https://via.placeholder.com/200x80?text=لوگو+شرکت',
|
||||
productImage: 'https://via.placeholder.com/300x200?text=تصویر+محصول'
|
||||
}
|
||||
return sampleData[key] || match
|
||||
})
|
||||
}
|
||||
|
||||
const processedSrc = processVariables(localSrc)
|
||||
|
||||
return (
|
||||
<div
|
||||
style={containerStyle}
|
||||
onClick={onSelect}
|
||||
className="image-block-wrapper"
|
||||
>
|
||||
{isEditing ? (
|
||||
<div className="space-y-3 p-2 bg-gray-50 rounded">
|
||||
<UploadBoxDraggble
|
||||
label="آپلود تصویر"
|
||||
onChange={handleImageUpload}
|
||||
/>
|
||||
<Input
|
||||
label="آدرس تصویر"
|
||||
value={localSrc}
|
||||
onChange={(e) => handleSrcChange(e.target.value)}
|
||||
placeholder="https://example.com/image.jpg"
|
||||
/>
|
||||
<Input
|
||||
label="متن جایگزین (Alt Text)"
|
||||
value={localAlt}
|
||||
onChange={(e) => handleAltChange(e.target.value)}
|
||||
placeholder="توضیح تصویر"
|
||||
/>
|
||||
<Input
|
||||
label="لینک تصویر (اختیاری)"
|
||||
value={localUrl}
|
||||
onChange={(e) => handleUrlChange(e.target.value)}
|
||||
placeholder="https://example.com"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
{localUrl ? (
|
||||
<a
|
||||
href={localUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<img
|
||||
src={processedSrc}
|
||||
alt={localAlt}
|
||||
style={imageStyle}
|
||||
onError={(e) => {
|
||||
const target = e.target as HTMLImageElement
|
||||
target.src = 'https://via.placeholder.com/400x200?text=تصویر+یافت+نشد'
|
||||
}}
|
||||
/>
|
||||
</a>
|
||||
) : (
|
||||
<img
|
||||
src={processedSrc}
|
||||
alt={localAlt}
|
||||
style={imageStyle}
|
||||
onError={(e) => {
|
||||
const target = e.target as HTMLImageElement
|
||||
target.src = 'https://via.placeholder.com/400x200?text=تصویر+یافت+نشد'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Block type indicator */}
|
||||
{isSelected && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '-8px',
|
||||
right: '8px',
|
||||
backgroundColor: '#0038FF',
|
||||
color: 'white',
|
||||
padding: '2px 6px',
|
||||
fontSize: '10px',
|
||||
borderRadius: '4px',
|
||||
fontWeight: 'bold',
|
||||
zIndex: 10
|
||||
}}
|
||||
>
|
||||
تصویر
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ImageBlock
|
||||
Reference in New Issue
Block a user