Files
site-builder/craft/src/components/basic/Logo.tsx
T

130 lines
3.2 KiB
TypeScript
Raw Normal View History

import React, { CSSProperties } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { useSiteDesign } from '../../state/SiteDesignContext';
import { escapeHtml, escapeAttr, safeUrl } from '../../utils/escape';
/* ---------- Types ---------- */
interface LogoProps {
type?: 'text' | 'image';
text?: string;
imageSrc?: string;
imageWidth?: string;
href?: string;
fontFamily?: string;
fontSize?: string;
fontWeight?: string;
color?: string;
style?: CSSProperties;
}
/* ---------- Component ---------- */
export const Logo: UserComponent<LogoProps> = ({
type = 'text',
text = 'MySite',
imageSrc = '',
imageWidth = '120px',
href = '/',
fontFamily = 'Inter, sans-serif',
fontSize = '20px',
fontWeight = '700',
color,
style = {},
}) => {
const {
connectors: { connect, drag },
} = useNode();
const { design } = useSiteDesign();
const resolvedColor = color || design.textColor;
return (
<a
ref={(ref: HTMLElement | null): void => { if (ref) connect(drag(ref)); }}
href={href}
onClick={(e) => e.preventDefault()}
style={{
textDecoration: 'none',
display: 'inline-flex',
alignItems: 'center',
flexShrink: 0,
...style,
}}
>
{type === 'image' && imageSrc ? (
<img
src={imageSrc}
alt={text || 'Logo'}
style={{ width: imageWidth, height: 'auto', display: 'block' }}
/>
) : (
<span style={{
fontWeight,
fontSize,
fontFamily,
color: resolvedColor,
}}>
{text}
</span>
)}
</a>
);
};
/* ---------- Craft config ---------- */
Logo.craft = {
displayName: 'Logo',
props: {
type: 'text',
text: 'MySite',
imageSrc: '',
imageWidth: '120px',
href: '/',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '700',
color: undefined,
style: {},
} as LogoProps,
rules: {
canDrag: () => true,
canMoveIn: () => false,
canMoveOut: () => true,
},
};
/* ---------- HTML export ---------- */
(Logo as any).toHtml = (props: LogoProps, _childrenHtml: string) => {
const href = props.href || '/';
let innerHtml: string;
if (props.type === 'image' && props.imageSrc) {
const imgStyle = cssPropsToString({ width: props.imageWidth || '120px', height: 'auto', display: 'block' });
innerHtml = `<img src="${escapeAttr(safeUrl(props.imageSrc))}" alt="${escapeAttr(props.text || 'Logo')}"${imgStyle ? ` style="${imgStyle}"` : ''} />`;
} else {
const spanStyle = cssPropsToString({
fontWeight: props.fontWeight || '700',
fontSize: props.fontSize || '20px',
fontFamily: props.fontFamily || 'Inter, sans-serif',
color: props.color || '#1f2937',
});
innerHtml = `<span${spanStyle ? ` style="${spanStyle}"` : ''}>${escapeHtml(props.text || 'MySite')}</span>`;
}
const aStyle = cssPropsToString({
textDecoration: 'none',
display: 'inline-flex',
alignItems: 'center',
flexShrink: '0',
...props.style,
});
return {
html: `<a href="${escapeAttr(safeUrl(href))}"${aStyle ? ` style="${aStyle}"` : ''}>${innerHtml}</a>`,
};
};