// Carousel slide renderer + thumbnail. Used in dashboard, posts list, preview.
// Slides are 1080×1350 portrait Instagram. We render them at any size via aspect-ratio + scale.
// Export to window.Carousel.
function pickFont(brand, role) {
// role: 'display' uses first font, 'body' uses second (or first if only one)
if (!brand || !brand.fonts || brand.fonts.length === 0) return 'Manrope';
if (role === 'display') return brand.fonts[0];
return brand.fonts[brand.fonts.length > 1 ? 1 : 0];
}
function isSerif(name = '') {
return /Serif|Playfair|Instrument|DM Serif/i.test(name);
}
function SlideFrame({ slide, brand, scale = 1, interactive = false }) {
const { fg, bg, accent, label, kind } = slide;
const display = pickFont(brand, 'display');
const body = pickFont(brand, 'body');
const W = 540, H = 675; // 4:5 portrait base
const wrap = {
width: W * scale, height: H * scale,
background: bg, color: fg,
fontFamily: body,
transition: 'background 240ms ease, color 240ms ease',
overflow: 'hidden',
};
const inner = (children) => (
{/* top label */}
{label}
OMNEEE
{children}
{/* bottom accent line */}
);
const fontDisplay = { fontFamily: display, fontWeight: isSerif(display) ? 600 : 700, letterSpacing: isSerif(display) ? -0.5 : -1 };
const fontBody = { fontFamily: body, fontWeight: 400 };
if (kind === 'cover') {
return (
{inner(
{slide.title}
{slide.subtitle &&
{slide.subtitle}
}
)}
);
}
if (kind === 'header') {
return (
{inner(
раздел
{slide.title}
{slide.body &&
{slide.body}
}
)}
);
}
if (kind === 'number') {
return (
{inner(
{slide.number || '3×'}
{slide.body}
)}
);
}
if (kind === 'quote') {
return (
{inner(
"
{slide.body}
{slide.author &&
{slide.author}
}
)}
);
}
if (kind === 'body') {
return (
{inner(
{slide.title}
{(slide.items || []).map((t, i) => (
-
{t}
))}
)}
);
}
return ;
}
// Cover-only mini renderer for thumbnails (no chrome, very compact)
function SlideThumb({ cover, brand, w = 120, h = 150 }) {
const { fg, bg, accent, kind, label } = cover;
const display = pickFont(brand || { fonts: ['Manrope', 'Manrope'] }, 'display');
const isCover = kind === 'cover';
const isQuote = kind === 'quote';
const isNumber = kind === 'number';
const isHeader = kind === 'header';
return (
{label}
OMNEEE
{isCover && (
{cover.title || 'Заголовок'}
)}
{isQuote && (
"
{cover.title || 'Цитата дня'}
)}
{isNumber && (
3×
)}
{isHeader && (
{cover.title || 'Раздел'}
)}
);
}
window.Carousel = { SlideFrame, SlideThumb, pickFont };