164 lines
5.9 KiB
TypeScript
164 lines
5.9 KiB
TypeScript
import React, { FC } from 'react'
|
|
import { SocialType, SocialNetworkType, SocialIconSize, SocialIconStyle, ElementType, PersonalityDataType, HorizontalAlignment, VerticalAlignment } from '../types/Types'
|
|
import { usePersonalityStore } from '../store/Store'
|
|
import { getSocialIconPath, hasPngIcon, getSocialColor as getSocialColorFromUtils, getSocialSvgIcon } from '../utils/socialIcons'
|
|
|
|
interface SocialRendererProps {
|
|
socials: SocialType[]
|
|
itemId: string
|
|
sectionKey: keyof PersonalityDataType
|
|
}
|
|
|
|
const SocialRenderer: FC<SocialRendererProps> = ({ socials, itemId, sectionKey }) => {
|
|
const { selectedElement, setSelectedElement } = usePersonalityStore()
|
|
|
|
if (!socials || socials.length === 0) return null
|
|
|
|
const handleSocialClick = (e: React.MouseEvent, socialId: string) => {
|
|
// جلوگیری از propagation به parent handlers
|
|
e.stopPropagation()
|
|
e.preventDefault()
|
|
setSelectedElement({
|
|
type: ElementType.SOCIAL,
|
|
elementId: socialId,
|
|
itemId,
|
|
sectionKey,
|
|
})
|
|
}
|
|
|
|
const getSocialIcon = (networkType: SocialNetworkType) => {
|
|
// Check if PNG icon is available, if so use it
|
|
if (hasPngIcon(networkType)) {
|
|
const iconPath = getSocialIconPath(networkType)
|
|
return (
|
|
<img
|
|
src={iconPath}
|
|
alt={`${networkType} icon`}
|
|
style={{
|
|
width: '100%',
|
|
height: '100%',
|
|
objectFit: 'contain',
|
|
display: 'block'
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
|
|
// Use shared SVG function
|
|
return getSocialSvgIcon(networkType, true) as React.ReactElement
|
|
}
|
|
|
|
const getSocialColor = getSocialColorFromUtils
|
|
|
|
const getIconSize = (size: SocialIconSize) => {
|
|
switch (size) {
|
|
case SocialIconSize.SMALL:
|
|
return { width: '24px', height: '24px', fontSize: '16px' }
|
|
case SocialIconSize.MEDIUM:
|
|
return { width: '32px', height: '32px', fontSize: '20px' }
|
|
case SocialIconSize.LARGE:
|
|
return { width: '40px', height: '40px', fontSize: '24px' }
|
|
default:
|
|
return { width: '32px', height: '32px', fontSize: '20px' }
|
|
}
|
|
}
|
|
|
|
const getIconStyle = (social: SocialType) => {
|
|
const size = getIconSize(social.size)
|
|
const baseStyle = {
|
|
...size,
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
textDecoration: 'none',
|
|
color: social.color || getSocialColor(social.networkType),
|
|
transition: 'all 0.2s ease',
|
|
margin: '2px',
|
|
cursor: 'pointer',
|
|
pointerEvents: 'none' as const,
|
|
}
|
|
|
|
switch (social.style) {
|
|
case SocialIconStyle.CIRCLE:
|
|
return {
|
|
...baseStyle,
|
|
borderRadius: '50%',
|
|
}
|
|
case SocialIconStyle.SQUARE:
|
|
return {
|
|
...baseStyle,
|
|
borderRadius: '0',
|
|
}
|
|
case SocialIconStyle.ROUNDED:
|
|
return {
|
|
...baseStyle,
|
|
borderRadius: '8px',
|
|
}
|
|
default:
|
|
return baseStyle
|
|
}
|
|
}
|
|
|
|
const getHorizontalAlign = (alignment?: HorizontalAlignment) => {
|
|
switch (alignment) {
|
|
case HorizontalAlignment.LEFT:
|
|
return 'left'
|
|
case HorizontalAlignment.RIGHT:
|
|
return 'right'
|
|
case HorizontalAlignment.CENTER:
|
|
default:
|
|
return 'center'
|
|
}
|
|
}
|
|
|
|
const getVerticalAlign = (verticalAlignment?: VerticalAlignment) => {
|
|
switch (verticalAlignment) {
|
|
case VerticalAlignment.TOP:
|
|
return 'top'
|
|
case VerticalAlignment.BOTTOM:
|
|
return 'bottom'
|
|
case VerticalAlignment.MIDDLE:
|
|
default:
|
|
return 'middle'
|
|
}
|
|
}
|
|
|
|
return (
|
|
<table width="100%" cellPadding="0" cellSpacing="0" border={0}>
|
|
<tbody>
|
|
<tr>
|
|
<td
|
|
align={getHorizontalAlign(socials[0]?.alignment)}
|
|
valign={getVerticalAlign(socials[0]?.verticalAlignment)}
|
|
style={{ padding: '4px 0' }}
|
|
>
|
|
<div style={{ textAlign: getHorizontalAlign(socials[0]?.alignment) }}>
|
|
{socials.map((social) => (
|
|
<div
|
|
key={social.id}
|
|
data-element-type="social"
|
|
onClick={(e) => handleSocialClick(e, social.id)}
|
|
style={{
|
|
cursor: 'pointer',
|
|
outline: selectedElement?.elementId === social.id ? '2px dashed #0038FF' : 'none',
|
|
outlineOffset: '2px',
|
|
borderRadius: '4px',
|
|
padding: '2px',
|
|
display: 'inline-block',
|
|
margin: '2px'
|
|
}}
|
|
>
|
|
<div style={getIconStyle(social)}>
|
|
{getSocialIcon(social.networkType)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
)
|
|
}
|
|
|
|
export default SocialRenderer
|