2026-04-21 07:53:05 +04:00

110 lines
3.5 KiB
TypeScript

/**
* DescriptionElement Component
*
* Description element with icon or styled text content.
* Renders with unified wrapper styling + content.
*/
import React, { useMemo } from 'react';
import type { CSSProperties } from 'react';
import type { CanvasElement } from '../../../types/constructor';
import { resolveAssetPlaybackUrl } from '../../../lib/assetUrl';
import { getFontByKey, getFontStyle } from '../../../lib/fonts';
import { normalizePixelValue } from '../../../lib/elementStyles';
interface DescriptionElementProps {
element: CanvasElement;
resolveUrl?: (url: string | undefined) => string;
className: string;
style: CSSProperties;
}
const DescriptionElement: React.FC<DescriptionElementProps> = ({
element,
resolveUrl,
className,
style,
}) => {
const resolve = resolveUrl ?? resolveAssetPlaybackUrl;
// Resolve font keys to full CSS styles (including fontStretch for condensed variants)
const titleFontStyle = useMemo(() => {
const fontKey = element.descriptionTitleFontFamily;
if (!fontKey) return {};
const font = getFontByKey(fontKey);
return font ? getFontStyle(font) : { fontFamily: fontKey };
}, [element.descriptionTitleFontFamily]);
const textFontStyle = useMemo(() => {
const fontKey = element.descriptionTextFontFamily;
if (!fontKey) return {};
const font = getFontByKey(fontKey);
return font ? getFontStyle(font) : { fontFamily: fontKey };
}, [element.descriptionTextFontFamily]);
// With icon: render image
if (element.iconUrl) {
const imgStyle: CSSProperties = {
width: element.width ? '100%' : 'auto',
height: element.height ? '100%' : 'auto',
objectFit: 'contain',
// Override Tailwind preflight's max-width: 100% which causes shrinking near canvas edges
maxWidth: 'none',
};
return (
<div className={className} style={style}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={resolve(element.iconUrl)}
alt='Description'
style={imgStyle}
draggable={false}
/>
</div>
);
}
// Without icon: render styled text description
// Background color is controlled via CSS Styles tab (backgroundColor property)
// Inheritable styles (color, fontSize, fontWeight) cascade from General Element Styles
// when section-specific values are not set
// Build title style - only set properties if explicitly configured
// fontWeight cascades from General Element Styles via CSS inheritance
const titleStyle: CSSProperties = {
...titleFontStyle,
};
if (element.descriptionTitleFontSize) {
titleStyle.fontSize = normalizePixelValue(element.descriptionTitleFontSize);
}
if (element.descriptionTitleColor) {
titleStyle.color = element.descriptionTitleColor;
}
// Build text style - only set properties if explicitly configured
// fontWeight cascades from General Element Styles via CSS inheritance
const textStyle: CSSProperties = {
...textFontStyle,
};
if (element.descriptionTextFontSize) {
textStyle.fontSize = normalizePixelValue(element.descriptionTextFontSize);
}
if (element.descriptionTextColor) {
textStyle.color = element.descriptionTextColor;
}
return (
<div className={className} style={style}>
<div className='p-4'>
<p style={titleStyle}>{element.descriptionTitle || ''}</p>
{element.descriptionText && (
<p style={textStyle}>{element.descriptionText}</p>
)}
</div>
</div>
);
};
export default DescriptionElement;