a3152ee84f
- CharacterStory: refined flat-illustration character (gradient-shaded sweater,
modern hair, calm minimal face), muted editorial palette (coral/teal/sand/navy),
abstract environment (soft depth blobs, ground "stage", sparse particles,
vignette + grain), scene-number kicker. Verified in 16:9/1:1/9:16 and all poses.
- seed: 13 editable scene cards (c1..c13, keys s{N}_title/s{N}_text) via new
MULTISCENE path; per-aspect previews; muted defaults.
- assets: 3 thumbnails + 4 preview MP4s vendored into public/template-media.
- fix: load BrandedVideoPlayer (plyr-react) client-only via next/dynamic
(ssr:false) — plyr touches `document` at import, which was 500-ing every
template detail page during SSR.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
265 lines
12 KiB
TypeScript
265 lines
12 KiB
TypeScript
/**
|
|
* Registry of FlatRender branded templates. Each entry is rendered into the
|
|
* three supported aspects (16:9 / 1:1 / 9:16) by Root.tsx, producing composition
|
|
* ids like "LogoMotion-16x9". Every template uses Persian text presets + the
|
|
* shared colour props so the studio can offer one consistent edit experience.
|
|
*/
|
|
import React from "react";
|
|
import type { AnyZodObject } from "zod";
|
|
import { BRAND } from "./lib/branding";
|
|
|
|
import { LogoMotion, logoMotionSchema } from "./compositions/LogoMotion";
|
|
import { Opener, openerSchema } from "./compositions/Opener";
|
|
import { InstaPromo, instaPromoSchema } from "./compositions/InstaPromo";
|
|
import { YouTubeIntro, youTubeIntroSchema } from "./compositions/YouTubeIntro";
|
|
import { Slideshow, slideshowSchema } from "./compositions/Slideshow";
|
|
import { HappyBirthday, happyBirthdaySchema } from "./compositions/HappyBirthday";
|
|
import { SalePromo, salePromoSchema } from "./compositions/SalePromo";
|
|
import { QuoteCard, quoteCardSchema } from "./compositions/QuoteCard";
|
|
import { EventInvite, eventInviteSchema } from "./compositions/EventInvite";
|
|
import { Countdown, countdownSchema } from "./compositions/Countdown";
|
|
import { GlitterReveal, glitterRevealSchema } from "./compositions/GlitterReveal";
|
|
import { NowruzGreeting, nowruzGreetingSchema } from "./compositions/NowruzGreeting";
|
|
import { Hero3D, hero3DSchema } from "./compositions/Hero3D";
|
|
import { Nowruz3D, nowruz3DSchema } from "./compositions/Nowruz3D";
|
|
import { Birthday3D, birthday3DSchema } from "./compositions/Birthday3D";
|
|
import { Promo3D, promo3DSchema } from "./compositions/Promo3D";
|
|
import { AppShowcase3D, appShowcase3DSchema } from "./compositions/AppShowcase3D";
|
|
import { CharacterStory, characterStorySchema, characterStoryDefaults } from "./compositions/CharacterStory";
|
|
|
|
export interface TemplateDef {
|
|
/** Base id; the registered composition ids are `${id}-${aspect}`. */
|
|
id: string;
|
|
/** Persian display name (used when seeding the site catalog). */
|
|
name: string;
|
|
/** Short Persian description for the catalog. */
|
|
description: string;
|
|
/** Default/shared component — used for any aspect without an override below. */
|
|
component: React.FC<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
/**
|
|
* Optional per-aspect component overrides, keyed by aspect id
|
|
* ("16x9" | "1x1" | "9x16"). Provide one when a design must differ
|
|
* STRUCTURALLY between aspects (a different layout/scene, not just
|
|
* repositioning — repositioning should be done responsively inside the shared
|
|
* `component` via useLayout). Aspects you omit fall back to `component`.
|
|
*/
|
|
componentsByAspect?: Partial<Record<string, React.FC<any>>>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
schema: AnyZodObject;
|
|
durationSec: number;
|
|
defaultProps: Record<string, unknown>;
|
|
}
|
|
|
|
const c = (accent: string, secondary: string, bg: string) => ({
|
|
accentColor: accent,
|
|
secondaryColor: secondary,
|
|
backgroundColor: bg,
|
|
textColor: BRAND.white,
|
|
});
|
|
|
|
export const TEMPLATES: TemplateDef[] = [
|
|
{
|
|
id: "LogoMotion",
|
|
name: "موشن لوگو",
|
|
description: "نمایش حرفهای لوگو و نام برند با درخشش و حرکت",
|
|
component: LogoMotion,
|
|
schema: logoMotionSchema,
|
|
durationSec: 5,
|
|
defaultProps: { brandText: "فلترندر", tagline: "موشن، ساده و حرفهای", ...c(BRAND.blue, BRAND.purple, "#04060f") },
|
|
},
|
|
{
|
|
id: "Opener",
|
|
name: "تیتراژ آغازین",
|
|
description: "شروع سینمایی برای ویدیو با عنوان و زیرعنوان",
|
|
component: Opener,
|
|
schema: openerSchema,
|
|
durationSec: 5,
|
|
defaultProps: { kicker: "تقدیم میکند", title: "یک شروع تازه", subtitle: "داستان شما از همینجا آغاز میشود", ...c(BRAND.cyan, "#6366f1", "#0a0a12") },
|
|
},
|
|
{
|
|
id: "InstaPromo",
|
|
name: "تبلیغ پیج اینستاگرام",
|
|
description: "معرفی و تبلیغ صفحهٔ اینستاگرام با دعوت به فالو",
|
|
component: InstaPromo,
|
|
schema: instaPromoSchema,
|
|
durationSec: 5,
|
|
defaultProps: { handle: "@flatrender", headline: "پیج ما را دنبال کنید", subtext: "هر روز محتوای تازه و الهامبخش", cta: "فالو کنید", ...c(BRAND.pink, BRAND.amber, "#140a12") },
|
|
},
|
|
{
|
|
id: "YouTubeIntro",
|
|
name: "اینترو کانال یوتیوب",
|
|
description: "اینترو حرفهای کانال یوتیوب با دکمهٔ سابسکرایب",
|
|
component: YouTubeIntro,
|
|
schema: youTubeIntroSchema,
|
|
durationSec: 5,
|
|
defaultProps: { channelName: "کانال فلترندر", subtitle: "آموزش، ترفند و انگیزه", cta: "سابسکرایب کنید", ...c("#ff4d4d", BRAND.purple, "#0c0810") },
|
|
},
|
|
{
|
|
id: "Slideshow",
|
|
name: "اسلایدشو",
|
|
description: "نمایش پشتسرهم چند پیام یا ویژگی بهصورت اسلاید",
|
|
component: Slideshow,
|
|
schema: slideshowSchema,
|
|
durationSec: 9,
|
|
defaultProps: { title: "چرا فلترندر؟", slide1: "ساخت ویدیو در چند دقیقه", slide2: "بدون نیاز به دانش فنی", slide3: "خروجی با کیفیت حرفهای", ...c(BRAND.green, "#3b82f6", "#060b0a") },
|
|
},
|
|
{
|
|
id: "HappyBirthday",
|
|
name: "تولدت مبارک",
|
|
description: "کارت تبریک تولد با کاغذرنگی و نام شخص",
|
|
component: HappyBirthday,
|
|
schema: happyBirthdaySchema,
|
|
durationSec: 6,
|
|
defaultProps: { greeting: "تولدت مبارک", name: "سارا", message: "بهترینها را برایت آرزومندیم 🎉", ...c(BRAND.pink, "#fde047", "#140a18") },
|
|
},
|
|
{
|
|
id: "SalePromo",
|
|
name: "فروش ویژه",
|
|
description: "بنر تبلیغاتی فروش و تخفیف با دعوت به خرید",
|
|
component: SalePromo,
|
|
schema: salePromoSchema,
|
|
durationSec: 5,
|
|
defaultProps: { badge: "۵۰٪ تخفیف", headline: "فروش ویژهٔ پایان فصل", subtext: "فقط تا پایان همین هفته", cta: "همین حالا خرید کنید", ...c(BRAND.amber, BRAND.pink, "#120a08") },
|
|
},
|
|
{
|
|
id: "QuoteCard",
|
|
name: "کارت نقلقول",
|
|
description: "نمایش جملهٔ انگیزشی یا نقلقول با نام گوینده",
|
|
component: QuoteCard,
|
|
schema: quoteCardSchema,
|
|
durationSec: 6,
|
|
defaultProps: { quote: "موفقیت، مجموع تلاشهای کوچکِ هر روز است.", author: "فلترندر", ...c(BRAND.cyan, "#6366f1", "#0a0a12") },
|
|
},
|
|
{
|
|
id: "EventInvite",
|
|
name: "دعوتنامهٔ رویداد",
|
|
description: "دعوتنامهٔ شیک برای رویداد با تاریخ و مکان",
|
|
component: EventInvite,
|
|
schema: eventInviteSchema,
|
|
durationSec: 6,
|
|
defaultProps: { kicker: "دعوتنامه", eventTitle: "همایش سالانهٔ نوآوری", date: "۱۵ مهر ۱۴۰۳", location: "تهران، سالن همایشها", cta: "ثبتنام کنید", ...c(BRAND.purple, BRAND.blue, "#0a0814") },
|
|
},
|
|
{
|
|
id: "Countdown",
|
|
name: "شمارش معکوس",
|
|
description: "شمارش معکوس هیجانانگیز برای شروع یک رویداد",
|
|
component: Countdown,
|
|
schema: countdownSchema,
|
|
durationSec: 8,
|
|
defaultProps: { title: "شروع رویداد تا", startNumber: 5, goText: "شروع!", subtitle: "آمادهاید؟", ...c(BRAND.blue, BRAND.cyan, "#04060f") },
|
|
},
|
|
{
|
|
id: "GlitterReveal",
|
|
name: "نمایش لوگو با غبار درخشان",
|
|
description: "نمایش جادویی لوگو با ذرات درخشان؛ لوگو و متن قابل ویرایش",
|
|
component: GlitterReveal,
|
|
schema: glitterRevealSchema,
|
|
durationSec: 6,
|
|
defaultProps: { brandText: "فلترندر", tagline: "موشن، ساده و حرفهای", logoUrl: "", ...c(BRAND.blue, BRAND.purple, "#05040e") },
|
|
},
|
|
{
|
|
id: "NowruzGreeting",
|
|
name: "تبریک نوروز",
|
|
description: "صحنهٔ بهاری نوروز با شخصیتهای متحرک؛ حاجیفیروز، ماهی قرمز و سبزه",
|
|
component: NowruzGreeting,
|
|
schema: nowruzGreetingSchema,
|
|
durationSec: 7.5,
|
|
defaultProps: {
|
|
greeting: "نوروز مبارک",
|
|
subtitle: "سال نو پیروز و شادمان",
|
|
message: "۱۴۰۶",
|
|
accentColor: "#f5b942",
|
|
secondaryColor: "#e23b3b",
|
|
backgroundColor: "#1fb6b0",
|
|
textColor: "#fdf6e3",
|
|
},
|
|
},
|
|
{
|
|
id: "Hero3D",
|
|
name: "نمایش سهبعدی برند",
|
|
description: "نمایش حرفهای و سهبعدی لوگو و برند با نورپردازی و جلوههای واقعی",
|
|
component: Hero3D,
|
|
schema: hero3DSchema,
|
|
durationSec: 6,
|
|
defaultProps: { brandText: "فلترندر", tagline: "موشن، ساده و حرفهای", ...c(BRAND.blue, BRAND.purple, "#04060f") },
|
|
},
|
|
{
|
|
id: "Nowruz3D",
|
|
name: "تبریک نوروز سهبعدی",
|
|
description: "صحنهٔ سهبعدی نوروز با حاجیفیروز، سفرهٔ هفتسین و نورپردازی سینمایی",
|
|
component: Nowruz3D,
|
|
schema: nowruz3DSchema,
|
|
durationSec: 7,
|
|
defaultProps: {
|
|
greeting: "نوروز مبارک",
|
|
subtitle: "سال نو پیروز و شادمان",
|
|
message: "۱۴۰۶",
|
|
accentColor: "#f5c542",
|
|
secondaryColor: "#e23b3b",
|
|
backgroundColor: "#1a1228",
|
|
textColor: "#fdf6e3",
|
|
},
|
|
},
|
|
{
|
|
id: "Birthday3D",
|
|
name: "تولد سهبعدی",
|
|
description: "صحنهٔ سهبعدی تولد با کیک و شمعهای روشن، بادکنک و کاغذرنگی",
|
|
component: Birthday3D,
|
|
schema: birthday3DSchema,
|
|
durationSec: 6,
|
|
defaultProps: {
|
|
greeting: "تولدت مبارک",
|
|
name: "سارا",
|
|
message: "بهترینها را برایت آرزومندیم 🎉",
|
|
accentColor: "#fb7185",
|
|
secondaryColor: "#a855f7",
|
|
backgroundColor: "#1a1226",
|
|
textColor: "#fdf6e3",
|
|
},
|
|
},
|
|
{
|
|
id: "Promo3D",
|
|
name: "فروش ویژه سهبعدی",
|
|
description: "تبلیغ سهبعدی فروش و تخفیف با جعبههای هدیه و نورپردازی سینمایی",
|
|
component: Promo3D,
|
|
schema: promo3DSchema,
|
|
durationSec: 6,
|
|
defaultProps: {
|
|
badge: "۵۰٪ تخفیف",
|
|
headline: "فروش ویژهٔ پایان فصل",
|
|
subtext: "فقط تا پایان همین هفته",
|
|
cta: "همین حالا خرید کنید",
|
|
accentColor: "#f59e0b",
|
|
secondaryColor: "#fb7185",
|
|
backgroundColor: "#140e1f",
|
|
textColor: "#ffffff",
|
|
},
|
|
},
|
|
{
|
|
id: "AppShowcase3D",
|
|
name: "معرفی اپلیکیشن سهبعدی",
|
|
description: "نمایش سهبعدی و حرفهای اپلیکیشن روی گوشی پرچمدار با نورپردازی استودیویی",
|
|
component: AppShowcase3D,
|
|
schema: appShowcase3DSchema,
|
|
durationSec: 6,
|
|
defaultProps: {
|
|
appName: "اپلیکیشن شما",
|
|
tagline: "تجربهای روان، سریع و زیبا",
|
|
cta: "همین حالا دانلود کنید",
|
|
screenUrl: "",
|
|
accentColor: "#3b82f6",
|
|
secondaryColor: "#8b5cf6",
|
|
backgroundColor: "#f4f5f7",
|
|
textColor: "#0f172a",
|
|
},
|
|
},
|
|
{
|
|
id: "CharacterStory",
|
|
name: "داستان شخصیتی (۱۳ صحنه)",
|
|
description: "قالب داستانگویی منعطف با شخصیت متحرک؛ تا ۱۳ صحنهٔ قابلویرایش (صحنههای خالی نمایش داده نمیشوند)",
|
|
component: CharacterStory,
|
|
schema: characterStorySchema,
|
|
durationSec: 39,
|
|
defaultProps: characterStoryDefaults,
|
|
},
|
|
];
|