feat: Product Overview template added

This commit is contained in:
shiva raj badu 2026-04-07 12:40:39 +05:45
parent 9061bf3e6f
commit 604bb95386
No known key found for this signature in database
18 changed files with 2096 additions and 0 deletions

View file

@ -0,0 +1,133 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-business-challenges-cards-slide";
export const slideLayoutName = "Product Overview Business Challenges Cards Slide";
export const slideLayoutDescription =
"A business challenges slide with headline and tagline on the left, a large supporting image in the top-right area, and three vertical detail cards across the lower center-right section.";
const CardSchema = z.object({
heading: z.string().min(4).max(12).meta({
description: "Card heading for one challenge column.",
}),
body: z.string().min(30).max(60).meta({
description: "Card body copy for one challenge column.",
}),
dark: z.boolean().default(false).meta({
description: "Controls whether the card uses a dark emphasis style.",
}),
});
export const Schema = z.object({
title: z.string().min(8).max(24).default("Business Challenges").meta({
description: "Main slide title.",
}),
taglineLabel: z.string().min(3).max(10).default("TAGLINE").meta({
description: "Short label above the left-side paragraph.",
}),
taglineBody: z.string().min(40).max(100).default(
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea."
).meta({
description: "Supporting paragraph on the left side.",
}),
heroImage: z.object({
__image_url__: z.string().url().default("https://images.unsplash.com/photo-1552664730-d307ca884978?auto=format&fit=crop&w=1400&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Team meeting and stressed analyst"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1552664730-d307ca884978?auto=format&fit=crop&w=1400&q=80",
__image_prompt__: "Team meeting and stressed analyst",
}).meta({
description: "Primary image shown in the upper right area.",
}),
cards: z
.array(CardSchema)
.min(3)
.max(3)
.default([
{
heading: "HEADING 1",
body: "Lorem ipsum dolor sit amet, consectetur elit.",
dark: false,
},
{
heading: "HEADING 2",
body: "Lorem ipsum dolor sit amet, consectetur elit.",
dark: false,
},
{
heading: "HEADING 3",
body: "Lorem ipsum dolor sit amet, consectetur elit.",
dark: true,
},
])
.meta({
description: "Three vertical challenge cards rendered under the image.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const BusinessChallengesCardsSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, taglineLabel, taglineBody, heroImage, cards } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className=" pl-[66px] pt-[60px] pb-[28px]">
<h2
className="text-[80px] max-w-[406px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<div className="mt-[72px] w-[360px]">
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: "#15342D" }}
>
{taglineLabel}
</p>
<p className="mt-[16px] text-[24px] font-normal text-[#15342DCC]">{taglineBody}</p>
</div>
</div>
{heroImage?.__image_url__ && (
<img
src={heroImage.__image_url__}
alt={heroImage.__image_prompt__}
className="absolute right-0 top-[72px] h-[350px] w-[770px] object-cover bg-white"
/>
)}
<div className="absolute bottom-[72px] right-[40px] flex items-start gap-[16px]">
{cards?.map((card, index) => (
<div
key={index}
className=" w-[248px] px-[34px] py-[34px]"
style={{ backgroundColor: card.dark ? "#15342D" : "#ebebee" }}
>
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: card.dark ? "#edf2f1" : "#15342D" }}
>
{card.heading}
</p>
<p
className="mt-[18px] text-[28px] font-normal text-white"
style={{ color: card.dark ? "#edf2f1" : "#15342D" }}
>
{card.body}
</p>
</div>
))}
</div>
</div>
);
};
export default BusinessChallengesCardsSlide;

View file

@ -0,0 +1,84 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-business-challenges-grid-slide";
export const slideLayoutName = "Product Overview Business Challenges Grid Slide";
export const slideLayoutDescription =
"A slide with a light title band on top and a dark content section below containing four challenge blocks in a two-by-two grid.";
const ChallengeSchema = z.object({
heading: z.string().min(4).max(12).meta({
description: "Short heading for a single challenge block.",
}),
body: z.string().min(40).max(96).meta({
description: "Description text for a single challenge block.",
}),
});
export const Schema = z.object({
title: z.string().min(8).max(24).default("Business Challenges").meta({
description: "Main title shown in the top band.",
}),
challenges: z
.array(ChallengeSchema)
.min(2)
.max(4)
.default([
{
heading: "HEADING 1",
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.",
},
{
heading: "HEADING 2",
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.",
},
{
heading: "HEADING 1",
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.",
},
{
heading: "HEADING 2",
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.",
},
])
.meta({
description: "Four challenge blocks rendered in a 2x2 arrangement.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const BusinessChallengesGridSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, challenges } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className=" px-[60px] pt-[60px] pb-[28px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
</div>
<div
className="grid h-[540px] grid-cols-2 justify-between items-center gap-y-[63px] px-[84px] py-[70px] gap-x-[63px]"
style={{ backgroundColor: "#15342D" }}
>
{challenges?.map((challenge, index) => (
<div key={index} className="">
<p className="text-[20px] font-semibold tracking-[2.074px] text-white">
{challenge.heading}
</p>
<p className="mt-[24px] text-[28px] font-normal text-white">{challenge.body}</p>
</div>
))}
</div>
</div>
);
};
export default BusinessChallengesGridSlide;

View file

@ -0,0 +1,187 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-comparison-chart-slide";
export const slideLayoutName = "Product Overview Comparison Chart Slide";
export const slideLayoutDescription =
"A comparison table slide with a headline, short description, four column headers, and three data rows using check, cross, or empty cells.";
const CellStatusSchema = z.enum(["check", "cross", "empty"]);
const RowSchema = z.object({
label: z.string().min(4).max(18).meta({
description: "Row heading shown in the first column.",
}),
cell1: CellStatusSchema.default("check"),
cell2: CellStatusSchema.default("empty"),
cell3: CellStatusSchema.default("check"),
cell4: CellStatusSchema.default("empty"),
});
export const Schema = z.object({
title: z.string().min(8).max(32).default("Comparison Chart").meta({
description: "Main heading shown above the table.",
}),
subtitle: z.string().min(30).max(140).default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt."
).meta({
description: "Short subtitle shown under the main heading.",
}),
columns: z
.array(z.string().min(4).max(18))
.min(4)
.max(4)
.default(["HEADING 1", "HEADING 1", "HEADING 2", "HEADING 3"])
.meta({
description: "Four table column headings.",
}),
rows: z
.array(RowSchema)
.min(3)
.max(3)
.default([
{
label: "HEADING 1",
cell1: "check",
cell2: "cross",
cell3: "check",
cell4: "cross",
},
{
label: "HEADING 1",
cell1: "check",
cell2: "empty",
cell3: "check",
cell4: "empty",
},
{
label: "HEADING 2",
cell1: "check",
cell2: "check",
cell3: "check",
cell4: "check",
},
])
.meta({
description: "Three table rows with status indicators.",
}),
checkIcon: z.object({
__icon_url__: z.string(),
__icon_query__: z.string(),
}).default({
__icon_url__:
"https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "check icon",
}).meta({
description: "Icon used for positive comparison status.",
}),
crossIcon: z.object({
__icon_url__: z.string(),
__icon_query__: z.string(),
}).default({
__icon_url__:
"https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "cross icon",
}).meta({
description: "Icon used for negative comparison status.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
function StatusIcon({
status,
checkIconUrl,
checkIconAlt,
crossIconUrl,
crossIconAlt,
}: {
status: "check" | "cross" | "empty";
checkIconUrl: string | undefined;
checkIconAlt: string | undefined;
crossIconUrl: string | undefined;
crossIconAlt: string | undefined;
}) {
if (status === "empty") {
return <span className="h-[26px] w-[26px]" />;
}
if (status === "cross") {
return <img src={crossIconUrl} alt={crossIconAlt} className="h-[26px] w-[26px] object-contain" />;
}
return <img src={checkIconUrl} alt={checkIconAlt} className="h-[26px] w-[26px] object-contain" />;
}
const ComparisonChartSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, subtitle, columns, rows, checkIcon, crossIcon } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="px-[56px] pt-[74px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<p className="mt-[20px] w-[740px] text-[24px] font-normal text-[#15342DCC]">{subtitle}</p>
</div>
<div className="absolute left-[54px] top-[268px] w-[1058px] ">
<div className="grid grid-cols-[220px_repeat(4,1fr)] border-b border-[#c5cccb]">
<div className="h-[94px] " />
{columns?.map((column, index) => (
<div
key={index}
className="flex h-[94px] items-center justify-center border-r border-[#c5cccb] text-[20px] font-semibold uppercase tracking-[0.2em]"
style={{ backgroundColor: index === 3 ? "#15342D" : "#ffffff", color: index === 3 ? "#edf2f1" : "#15342D" }}
>
{column}
</div>
))}
</div>
{rows?.map((row, index) => {
const cells: ("check" | "cross" | "empty")[] = [
row.cell1,
row.cell2,
row.cell3,
row.cell4,
];
return (
<div
key={index}
className={`grid grid-cols-[220px_repeat(4,1fr)] ${index < rows.length - 1 ? "border-b border-[#c5cccb]" : ""}`}
>
<div className="flex h-[94px] bg-[#ffffff] items-center border-r border-[#c5cccb] pl-[34px] text-[20px] font-semibold uppercase tracking-[0.2em]" style={{ color: "#15342D" }}>
{row.label}
</div>
{cells?.map((status, cellIndex) => (
<div
key={cellIndex}
className={`flex h-[94px] items-center justify-center border-r bg-[#ffffff] border-[#c5cccb]`}
>
<StatusIcon
status={status}
checkIconUrl={checkIcon?.__icon_url__}
checkIconAlt={checkIcon?.__icon_query__}
crossIconUrl={crossIcon?.__icon_url__}
crossIconAlt={crossIcon?.__icon_query__}
/>
</div>
))}
</div>
);
})}
</div>
</div>
);
};
export default ComparisonChartSlide;

View file

@ -0,0 +1,138 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-comparison-table-with-text-slide";
export const slideLayoutName = "Product Overview Comparison Table With Text Slide";
export const slideLayoutDescription =
"A comparison table slide with a title, a subtitle, four headers, and three text rows.";
const RowSchema = z.object({
cell1: z.string().min(8).max(24).meta({
description: "First column cell text.",
}),
cell2: z.string().min(8).max(24).meta({
description: "Second column cell text.",
}),
cell3: z.string().min(8).max(24).meta({
description: "Third column cell text.",
}),
cell4: z.string().min(8).max(24).meta({
description: "Fourth column cell text.",
}),
});
export const Schema = z.object({
title: z.string().min(8).max(32).default("Comparison Chart").meta({
description: "Main heading shown above the table.",
}),
subtitle: z
.string()
.min(30)
.max(100)
.default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt."
)
.meta({
description: "Short subtitle shown under the main heading.",
}),
columns: z
.array(z.string().min(4).max(18))
.min(4)
.max(4)
.default(["HEADING 1", "HEADING 1", "HEADING 2", "HEADING 3"])
.meta({
description: "Four table column headings.",
}),
highlightedHeaderIndex: z.number().int().min(1).max(4).default(4).meta({
description: "1-based column index for the dark highlighted table header.",
}),
rows: z
.array(RowSchema)
.min(3)
.max(3)
.default([
{
cell1: "Lorem ipsum dolor sit.",
cell2: "Lorem ipsum dolor sit.",
cell3: "Lorem ipsum dolor sit.",
cell4: "Lorem ipsum dolor sit.",
},
{
cell1: "Lorem ipsum dolor sit.",
cell2: "Lorem ipsum dolor sit.",
cell3: "Lorem ipsum dolor sit.",
cell4: "Lorem ipsum dolor sit.",
},
{
cell1: "Lorem ipsum dolor sit.",
cell2: "Lorem ipsum dolor sit.",
cell3: "Lorem ipsum dolor sit.",
cell4: "Lorem ipsum dolor sit.",
},
])
.meta({
description: "Three table rows of text content.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const ComparisonTableWithTextSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, subtitle, columns, highlightedHeaderIndex, rows } = data;
return (
<div className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px] bg-[#c3cccc]">
<div className="px-[44px] pt-[46px]">
<h2 className="text-[80px] font-semibold leading-[1.02] tracking-[-0.03em] text-[#0a443b]">
{title}
</h2>
<p className="mt-[22px] max-w-[700px] text-[24px] leading-[1.22] text-[#2d5d56]">
{subtitle}
</p>
</div>
<div className="mx-[44px] mt-[30px] overflow-hidden border border-[#bcc3c3]">
<table className="w-full table-fixed border-collapse bg-[#ffffff]">
<thead>
<tr>
{columns?.map((column, index) => {
const isHighlighted = index + 1 === highlightedHeaderIndex;
return (
<th
key={`${column}-${index}`}
className=" border-r border-[#bcc3c3] p-[33px] text-left text-[20px] font-semibold uppercase tracking-[0.16em] last:border-r-0"
style={{
backgroundColor: isHighlighted ? "#05443a" : "#ffffff",
color: isHighlighted ? "#eef2f0" : "#123f38",
}}
>
{column}
</th>
);
})}
</tr>
</thead>
<tbody>
{rows?.map((row, rowIndex) => {
const cells = [row.cell1, row.cell2, row.cell3, row.cell4];
return (
<tr key={`row-${rowIndex}`}>
{cells?.map((cell, cellIndex) => (
<td
key={`cell-${rowIndex}-${cellIndex}`}
className=" border-r border-t bg-white border-[#bcc3c3] p-[33px] text-left text-[18px] leading-[1.2] text-[#183f38] last:border-r-0"
>
{cell}
</td>
))}
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
};
export default ComparisonTableWithTextSlide;

View file

@ -0,0 +1,94 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-cover-slide";
export const slideLayoutName = "Product Overview Cover Slide";
export const slideLayoutDescription =
"A cover slide with a compact logo in the top-left, a date in the top-right, a two-line centered title, and a city/building image anchored to the bottom with a soft fade into the background.";
export const Schema = z.object({
logoImage: z.object({
__image_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg"),
__image_prompt__: z.string().min(10).max(100).default("Professional logo of the company"),
}).default({
__image_url__:
"https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg",
__image_prompt__: "Professional logo of the company",
}),
label: z.string().min(3).max(16).default("MARCH 2026").meta({
description: "Date label shown at the top-right corner.",
}),
titleLine1: z.string().min(3).max(18).default("Social Media").meta({
description: "First line of the cover title.",
}),
titleLine2: z.string().min(3).max(20).default("Marketing Report").meta({
description: "Second line of the cover title.",
}),
backgroundImage: z.object({
__image_url__: z.string().url().default("https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&w=1920&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Tall glass buildings from street view"),
}).default({
__image_url__: "https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&w=1920&q=80",
__image_prompt__: "Tall glass buildings from street view",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const CoverSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { logoImage, label, titleLine1, titleLine2, backgroundImage } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="relative z-20 flex h-full flex-col px-[36px] pt-[62px] text-[#15342D]">
<div className="flex items-center justify-between">
<img
src={logoImage?.__image_url__ ?? ''}
alt={logoImage?.__image_prompt__ || ''}
className="h-[42px] w-[171px] object-cover"
/>
<p className="text-[18px] font-normal leading-[18.991px] text-[#15342D]">
{label}
</p>
</div>
<div className="flex flex-1 items-center justify-center pb-[80px]">
<h1
className="text-center text-[100px] font-semibold leading-[108.4%] tracking-[-3.024px]"
>
{titleLine1}
<br />
{titleLine2}
</h1>
</div>
</div>
{backgroundImage?.__image_url__ && (
<img
src={backgroundImage.__image_url__ || ''}
alt={backgroundImage.__image_prompt__ || ''}
className="absolute bottom-0 left-0 z-0 h-[360px] w-full object-cover"
/>
)}
<div
className="pointer-events-none absolute bottom-0 left-0 w-full z-10"
style={{
height: "365px",
background:
"linear-gradient(0deg, rgba(218, 225, 222, 0.00) 0%, #DAE1DE 80.33%)",
}}
/>
</div>
);
};
export default CoverSlide;

View file

@ -0,0 +1,139 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-image-gallery-slide";
export const slideLayoutName = "Product Overview Image Gallery Slide";
export const slideLayoutDescription =
"A gallery slide with a title and paragraph on the left and a five-image collage on the right and bottom.";
export const Schema = z.object({
title: z.string().min(5).max(16).default("Image Gallery").meta({
description: "Main gallery heading.",
}),
description: z.string().min(50).max(130).default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore."
).meta({
description: "Supporting paragraph shown under the title.",
}),
topCenterImage: z.object({
__image_url__:
z.string().default("https://images.unsplash.com/photo-1521737711867-e3b97375f902?auto=format&fit=crop&w=800&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Design team discussing project board"),
}).default({
__image_url__: "https://images.unsplash.com/photo-1521737711867-e3b97375f902?auto=format&fit=crop&w=800&q=80",
__image_prompt__: "Design team discussing project board",
}).meta({
description: "Top-middle gallery image.",
}),
topRightImage: z.object({
__image_url__:
z.string().default("https://images.unsplash.com/photo-1455390582262-044cdead277a?auto=format&fit=crop&w=800&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Creative desk with notebook and photos"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1455390582262-044cdead277a?auto=format&fit=crop&w=800&q=80",
__image_prompt__: "Creative desk with notebook and photos",
}).meta({
description: "Top-right gallery image.",
}),
bottomWideImage: z.object({
__image_url__:
z.string().default("https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?auto=format&fit=crop&w=1300&q=80"),
__image_prompt__: z.string().min(10).max(100).default("City skyline seen from office window"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?auto=format&fit=crop&w=1300&q=80",
__image_prompt__: "City skyline seen from office window",
}).meta({
description: "Bottom-left wide gallery image.",
}),
bottomCenterImage: z.object({
__image_url__:
z.string().default("https://images.unsplash.com/photo-1517048676732-d65bc937f952?auto=format&fit=crop&w=900&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Art gallery wall with framed photos"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1517048676732-d65bc937f952?auto=format&fit=crop&w=900&q=80",
__image_prompt__: "Art gallery wall with framed photos",
}).meta({
description: "Bottom-center gallery image.",
}),
bottomRightImage: z.object({
__image_url__:
z.string().default("https://images.unsplash.com/photo-1521791136064-7986c2920216?auto=format&fit=crop&w=900&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Office workshop with presentation board"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1521791136064-7986c2920216?auto=format&fit=crop&w=900&q=80",
__image_prompt__: "Office workshop with presentation board",
}).meta({
description: "Bottom-right gallery image.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const ImageGallerySlide = ({ data }: { data: Partial<SchemaType> }) => {
const {
title,
description,
topCenterImage,
topRightImage,
bottomWideImage,
bottomCenterImage,
bottomRightImage,
} = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px] p-[56px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="flex items-center justify-between gap-1 ">
<div className=" ">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<p className="mt-[24px] w-[620px] text-[24px] font-normal text-[#15342DCC]">{description}</p>
</div>
<div className="flex items-center gap-[22px]">
<img
src={topCenterImage?.__image_url__ ?? ''}
alt={topCenterImage?.__image_prompt__ ?? ''}
className="h-[294px] w-[270px] object-cover"
/>
<img
src={topRightImage?.__image_url__}
alt={topRightImage?.__image_prompt__ ?? ''}
className="h-[294px] w-[270px] object-cover"
/>
</div>
</div>
<div className="absolute bottom-[56px] w-full left-[58px] flex gap-[22px]">
<img
src={bottomWideImage?.__image_url__}
alt={bottomWideImage?.__image_prompt__}
className="h-[290px] w-[584px] object-cover"
/>
<img
src={bottomCenterImage?.__image_url__}
alt={bottomCenterImage?.__image_prompt__}
className="h-[290px] w-[270px] object-cover"
/>
<img
src={bottomRightImage?.__image_url__}
alt={bottomRightImage?.__image_prompt__}
className="h-[290px] w-[270px] object-cover"
/>
</div>
</div>
);
};
export default ImageGallerySlide;

View file

@ -0,0 +1,101 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-introduction-slide";
export const slideLayoutName = "Product Overview Introduction Slide";
export const slideLayoutDescription =
"A split slide with a large portrait image on the left and a structured introduction column on the right containing a main title and two labeled body paragraphs.";
const IntroBlockSchema = z.object({
label: z.string().min(3).max(12).meta({
description: "Uppercase mini-heading shown above each intro paragraph.",
}),
body: z.string().min(40).max(96).meta({
description: "Supporting paragraph content for the intro block.",
}),
});
export const Schema = z.object({
title: z.string().min(4).max(16).default("Introduction").meta({
description: "Primary title in the right column.",
}),
portraitImage: z.object({
__image_url__: z.string().url().default("https://images.unsplash.com/photo-1521119989659-a83eee488004?auto=format&fit=crop&w=1200&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Two business professionals in office"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1521119989659-a83eee488004?auto=format&fit=crop&w=1200&q=80",
__image_prompt__: "Two business professionals in office",
}).meta({
description: "Main portrait image shown on the left half.",
}),
blocks: z
.array(IntroBlockSchema)
.min(2)
.max(2)
.default([
{
label: "TAGLINE",
body: "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea.",
},
{
label: "TAGLINE",
body: "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea.",
},
])
.meta({
description: "Two short intro content blocks shown in the text column.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const IntroductionSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, portraitImage, blocks } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="grid h-full gap-[54px] items-center grid-cols-2">
<div className="h-full w-full overflow-hidden bg-[#15342D]">
{portraitImage?.__image_url__ && (
<img
src={portraitImage.__image_url__}
alt={portraitImage.__image_prompt__}
className="h-full w-full object-cover"
/>
)}
</div>
<div className="">
<h2
className="text-[80px] font-bold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
>
{title}
</h2>
<div className="mt-[53px] space-y-[53px] pr-[33px]">
{blocks?.map((block, index) => (
<div key={`${block.label}-${index}`}>
<p
className="text-[20px] font-semibold tracking-[2.074px] text-[#15342D]"
>
{block.label}
</p>
<p className="mt-[14px] text-[24px] leading-[26.667px] text-[#15342DCC]">
{block.body}
</p>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default IntroductionSlide;

View file

@ -0,0 +1,114 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-kpi-cards-slide";
export const slideLayoutName = "Product Overview KPI Cards Slide";
export const slideLayoutDescription =
"A KPI overview slide with a dark-tinted background image, large title, and a two-row grid of six white KPI cards.";
const KpiSchema = z.object({
value: z.string().min(1).max(8).meta({
description: "Primary KPI value shown in a card.",
}),
body: z.string().min(10).max(28).meta({
description: "Short KPI supporting text.",
}),
});
export const Schema = z.object({
title: z.string().min(3).max(10).default("KPIs").meta({
description: "Main title shown in the top-left corner.",
}),
kpiIcon: z.object({
__icon_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg"),
__icon_query__: z.string().min(3).max(30).default("pulse icon"),
}).default({
__icon_url__:
"https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "pulse icon",
}).meta({
description: "Icon shown in each KPI card badge.",
}),
backgroundImage: z.object({
__image_url__: z.string().url().default("https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1600&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Business team using laptop in meeting"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1600&q=80",
__image_prompt__: "Business team using laptop in meeting",
}).meta({
description: "Background image behind the KPI cards.",
}),
items: z
.array(KpiSchema)
.min(3)
.max(6)
.default([
{ value: "X 5", body: "Lorem ipsum dolor sit." },
{ value: "X 5", body: "Lorem ipsum dolor sit." },
{ value: "X 5", body: "Lorem ipsum dolor sit." },
{ value: "X 5", body: "Lorem ipsum dolor sit." },
{ value: "X 5", body: "Lorem ipsum dolor sit." },
{ value: "X 5", body: "Lorem ipsum dolor sit." },
])
.meta({
description: "Six KPI cards displayed in a 3x2 grid.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const KpiCardsSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, kpiIcon, backgroundImage, items } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
{backgroundImage?.__image_url__ && (
<img
src={backgroundImage?.__image_url__}
alt={backgroundImage?.__image_prompt__}
className="absolute inset-0 h-full w-full object-cover"
/>
)}
<div className="absolute inset-0 bg-[#15342D]/80" />
<div className="relative z-10 px-[66px] pt-[72px] mb-[33px]">
<h2 className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#FEFEFF]"
>
{title}
</h2>
</div>
<div className="relative z-10 grid grid-cols-3 gap-x-[30px] gap-y-[19px] px-[66px]">
{items?.map((item, index) => (
<div key={index} className=" bg-[#FEFEFF] p-[33px]">
<div className="flex h-[55px] w-[55px] items-center justify-center rounded-full bg-[#15342D]">
<img
src={kpiIcon?.__icon_url__}
alt={kpiIcon?.__icon_query__}
className="h-[25px] w-[25px] object-contain"
style={{ filter: "brightness(0) invert(1)" }}
/>
</div>
<p
className="mt-[18px] text-[42px] font-semibold leading-none"
style={{ color: "#15342D" }}
>
{item.value}
</p>
<p className="mt-[18px] text-[28px] font-normal text-[#15342DCC]" style={{ color: "#15342D" }}>
{item.body}
</p>
</div>
))}
</div>
</div>
);
};
export default KpiCardsSlide;

View file

@ -0,0 +1,108 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-market-opportunity-slide";
export const slideLayoutName = "Product Overview Market Opportunity Slide";
export const slideLayoutDescription =
"A market opportunity slide with title and intro text on the left, four bullet lines extending toward the right, and concentric value circles as the visual focal point.";
const BulletSchema = z.object({
text: z.string().min(12).max(46).meta({
description: "Bullet text shown on the left side of a line.",
}),
});
export const Schema = z.object({
title: z.string().min(8).max(22).default("Market Opportunity").meta({
description: "Main heading shown at the top-left.",
}),
subtitle: z.string().min(40).max(110).default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt."
).meta({
description: "Supporting text under the main heading.",
}),
bullets: z
.array(BulletSchema)
.min(4)
.max(4)
.default([
{ text: "Ut enim ad minim veniam, quis" },
{ text: "Ut enim ad minim veniam, quis" },
{ text: "Ut enim ad minim veniam, quis" },
{ text: "Ut enim ad minim veniam, quis" },
])
.meta({
description: "Four bullet-line entries shown on the left.",
}),
values: z
.array(z.string().min(2).max(6))
.min(4)
.max(4)
.default(["$33", "$20", "$120", "$200"])
.meta({
description: "Four values shown from outer to inner circles.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const COLORS = [
"#5f7f79",
"#1f5a4f",
"#0d4f43",
"#06463d",
];
const MarketOpportunitySlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, subtitle, bullets, values } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="px-[56px] pt-[72px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<p className="mt-[20px] w-[730px] text-[24px] font-normal text-[#15342DCC]">{subtitle}</p>
</div>
<div className="absolute left-[56px] top-[368px] space-y-[42px]">
{bullets?.map((bullet, index) => (
<div key={index} className="relative flex items-center">
<span className="mr-[14px] h-[14px] w-[14px] rounded-full bg-[#0a4a3f]" />
<p className="w-[640px] text-[24px] font-normal text-[#15342DCC]">{bullet.text}</p>
<span className="ml-[8px] h-[2px] w-[80px] bg-[#8ea8a5]" />
<span className="h-[6px] w-[6px] rounded-full bg-[#edf2f1]" />
</div>
))}
</div>
<div className="absolute bottom-[58px] right-[48px] h-[474px] w-[474px]">
{values?.map((value, index) => (
<div
key={index}
className="absolute rounded-full"
style={{
width: 237 + (index * 50),
height: 237 + (index * 50),
bottom: 0,
right: 0,
backgroundColor: COLORS[index],
}}
>
<p className="pt-[24px] text-center text-[24px] font-normal text-white" >
{value}
</p>
</div>
))}
</div>
</div>
);
};
export default MarketOpportunitySlide;

View file

@ -0,0 +1,150 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-meet-team-slide";
export const slideLayoutName = "Product Overview Meet Team Slide";
export const slideLayoutDescription =
"A team introduction slide with a title and intro text on top, followed by four profile cards where one card can be highlighted with a dark footer style.";
const MemberSchema = z.object({
title: z.string().min(2).max(12).meta({
description: "Member role or short heading.",
}),
name: z.string().min(2).max(16).meta({
description: "Member name shown in the card footer.",
}),
image: z.object({
__image_url__: z.string().url().default("https://i.pravatar.cc/600?img=12"),
__image_prompt__: z.string().min(10).max(100).default("Professional male portrait with suit"),
}).default({
__image_url__: "https://i.pravatar.cc/600?img=12",
__image_prompt__: "Professional male portrait with suit",
}).meta({
description: "Portrait image for a team member card.",
}),
highlighted: z.boolean().default(false).meta({
description: "Whether this card uses the dark highlight footer.",
}),
});
export const Schema = z.object({
title: z.string().min(8).max(18).default("Meet Our Team").meta({
description: "Main title at the top-left.",
}),
taglineLabel: z.string().min(3).max(10).default("TAGLINE").meta({
description: "Small heading above team description.",
}),
taglineBody: z.string().min(50).max(100).default(
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea."
).meta({
description: "Short descriptive paragraph at top-right.",
}),
members: z
.array(MemberSchema)
.min(4)
.max(4)
.default([
{
title: "CEO",
name: "Lanny LA",
image: {
__image_url__: "https://i.pravatar.cc/600?img=12",
__image_prompt__: "Professional male portrait with suit",
},
highlighted: false,
},
{
title: "HEADING 2",
name: "Lanny LA",
image: {
__image_url__: "https://i.pravatar.cc/600?img=13",
__image_prompt__: "Professional male portrait with tie",
},
highlighted: false,
},
{
title: "HEADING 3",
name: "Lanny LA",
image: {
__image_url__: "https://i.pravatar.cc/600?img=14",
__image_prompt__: "Professional male portrait smiling",
},
highlighted: true,
},
{
title: "HEADING 2",
name: "Lanny LA",
image: {
__image_url__: "https://i.pravatar.cc/600?img=15",
__image_prompt__: "Professional male portrait office",
},
highlighted: false,
},
])
.meta({
description: "Four team member cards shown in one row.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const MeetTeamSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, taglineLabel, taglineBody, members } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="flex items-start justify-between px-[64px] pt-[76px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<div className="w-[520px]">
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: "#15342D" }}
>
{taglineLabel}
</p>
<p className="mt-[14px] text-[24px] font-normal text-[#15342DCC]">{taglineBody}</p>
</div>
</div>
<div className="absolute bottom-[58px] left-[64px] grid grid-cols-4 gap-[22px]">
{members?.map((member, index) => (
<div key={index} className="w-[252px] overflow-hidden">
<img
src={member.image.__image_url__}
alt={member.image.__image_prompt__}
className="h-[244px] w-full object-cover"
/>
<div
className="h-[154px] p-[33px]"
style={{ backgroundColor: member.highlighted ? "#15342D" : "#FEFEFF" }}
>
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: member.highlighted ? "#edf2f1" : "#15342D" }}
>
{member.title}
</p>
<p
className="mt-[20px] text-[28px] font-normal text-white"
style={{ color: member.highlighted ? "#edf2f1" : "#15342D" }}
>
{member.name}
</p>
</div>
</div>
))}
</div>
</div>
);
};
export default MeetTeamSlide;

View file

@ -0,0 +1,88 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-mission-vision-slide";
export const slideLayoutName = "Product Overview Mission and Vision Slide";
export const slideLayoutDescription =
"A quadrant layout with a large title in the top-left block, mission text in the top-right dark block, vision text in the bottom-left dark block, and an image in the bottom-right block.";
export const Schema = z.object({
title: z.string().min(8).max(20).default("Mission & Vision").meta({
description: "Primary heading shown in the top-left tile.",
}),
missionLabel: z.string().min(3).max(10).default("MISSION").meta({
description: "Mission section label.",
}),
missionBody: z.string().min(40).max(98).default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore."
).meta({
description: "Mission paragraph content.",
}),
visionLabel: z.string().min(3).max(10).default("VISION").meta({
description: "Vision section label.",
}),
visionBody: z.string().min(40).max(98).default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore."
).meta({
description: "Vision paragraph content.",
}),
image: z.object({
__image_url__: z.string(),
__image_prompt__: z.string(),
}).optional().meta({
description: "Bottom-right supporting image. Optional.",
}).default({
__image_url__: "https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?auto=format&fit=crop&w=1400&q=80",
__image_prompt__: "Business silhouette at window skyline",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const MissionVisionSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, missionLabel, missionBody, visionLabel, visionBody, image } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="grid h-full grid-cols-2 grid-rows-2">
<div className="px-[74px] pt-[76px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
>
{title}
</h2>
</div>
<div className="pl-[60px] pt-[76px]" style={{ backgroundColor: "#15342D" }}>
<p className="text-[20px] font-semibold tracking-[2.074px] text-white">
{missionLabel}
</p>
<p className="mt-[26px] text-[28px] font-normal text-white">{missionBody}</p>
</div>
<div className="pl-[53px] py-[53px]" style={{ backgroundColor: "#15342D" }}>
<p className="text-[20px] font-semibold tracking-[2.074px] text-white">
{visionLabel}
</p>
<p className="mt-[24px] text-[28px] font-normal text-white">{visionBody}</p>
</div>
<div className="h-full w-full overflow-hidden bg-white">
{image?.__image_url__ && (
<img
src={image.__image_url__}
alt={image.__image_prompt__}
className="h-full w-full object-cover"
/>
)}
</div>
</div>
</div>
);
};
export default MissionVisionSlide;

View file

@ -0,0 +1,127 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-our-services-slide";
export const slideLayoutName = "Product Overview Our Services Slide";
export const slideLayoutDescription =
"A services slide with title and intro copy on the left, a large image below, and a two-by-two service card matrix on the right.";
const ServiceSchema = z.object({
heading: z.string().min(4).max(12).meta({
description: "Service card heading.",
}),
body: z.string().min(20).max(44).meta({
description: "Service card short description.",
}),
dark: z.boolean().default(false).meta({
description: "Whether this service card uses the dark style.",
}),
});
export const Schema = z.object({
title: z.string().min(6).max(18).default("Our Services").meta({
description: "Main heading shown at the top-left.",
}),
taglineLabel: z.string().min(3).max(10).default("TAGLINE").meta({
description: "Small label above left paragraph.",
}),
taglineBody: z.string().min(40).max(100).default(
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea."
).meta({
description: "Supporting text shown beneath the tagline label.",
}),
featureImage: z.object({
__image_url__: z.string().url().default("https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Customer support team in office"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80",
__image_prompt__: "Customer support team in office",
}).meta({
description: "Main image shown at the lower left side.",
}),
services: z
.array(ServiceSchema)
.min(4)
.max(4)
.default([
{ heading: "HEADING 1", body: "Lorem ipsum dolor sit amet, consectetur", dark: false },
{ heading: "HEADING 2", body: "Lorem ipsum dolor sit amet, consectetur", dark: true },
{ heading: "HEADING 3", body: "Lorem ipsum dolor sit amet, consectetur", dark: false },
{ heading: "HEADING 4", body: "Lorem ipsum dolor sit amet, consectetur", dark: false },
])
.meta({
description: "Four service cards rendered on the right side.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const OurServicesSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, taglineLabel, taglineBody, featureImage, services } = data;
return (
<div
className="relative h-[720px] w-[1280px] flex items-end pb-[56px] justify-between overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className=" pt-[74px]">
<div className="px-[68px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<div className="mt-[26px] w-[560px]">
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: "#15342D" }}
>
{taglineLabel}
</p>
<p className="mt-[14px] text-[24px] font-normal text-[#15342DCC]">{taglineBody}</p>
</div>
</div>
<div className="mt-[35px] h-[326px] w-[650px] bg-[#15342D]">
{featureImage?.__image_url__ && (
<img
src={featureImage?.__image_url__}
alt={featureImage?.__image_prompt__}
className="h-[326px] w-[650px] object-cover"
/>
)}
</div>
</div>
<div className="grid grid-cols-2 gap-[22px] pr-[76px]">
{services?.map((service, index) => (
<div
key={index}
className=" p-[33px]"
style={{ backgroundColor: service.dark ? "#15342D" : "#ececee" }}
>
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: service.dark ? "#edf2f1" : "#15342D" }}
>
{service.heading}
</p>
<p
className={`${service.dark ? "text-white" : "text-[#15342DCC]"} mt-[20px] text-[28px] font-normal`}
>
{service.body}
</p>
</div>
))}
</div>
</div>
);
};
export default OurServicesSlide;

View file

@ -0,0 +1,153 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-pricing-plan-slide";
export const slideLayoutName = "Product Overview Pricing Plan Slide";
export const slideLayoutDescription =
"A three-column pricing slide with one emphasized center plan and feature bullet lists for each plan.";
const PlanSchema = z.object({
price: z.string().min(4).max(12).meta({
description: "Plan price label shown at the top of each card.",
}),
description: z.string().min(18).max(26).meta({
description: "Short statement describing the plan.",
}),
features: z
.array(z.string().min(10).max(24))
.min(4)
.max(4)
.meta({
description: "Four bullet features shown in the pricing card.",
}),
highlighted: z.boolean().default(false).meta({
description: "Whether this card uses the highlighted dark style.",
}),
});
export const Schema = z.object({
title: z.string().min(6).max(18).default("Pricing Plan").meta({
description: "Main slide title.",
}),
featureIcon: z.object({
__icon_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg"),
__icon_query__: z.string().min(3).max(30).default("check icon"),
}).default({
__icon_url__:
"https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "check icon",
}).meta({
description: "Icon used for each feature bullet in plan cards.",
}),
plans: z
.array(PlanSchema)
.min(3)
.max(3)
.default([
{
price: "$80/MONTH",
description: "Lorem ipsum dolor sit.",
features: [
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
],
highlighted: false,
},
{
price: "$80/MONTH",
description: "Lorem ipsum dolor sit.",
features: [
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
],
highlighted: true,
},
{
price: "$80/MONTH",
description: "Lorem ipsum dolor sit.",
features: [
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
"Lorem ipsum dolor sit.",
],
highlighted: false,
},
])
.meta({
description: "Three pricing cards displayed across the slide.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const PricingPlanSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, featureIcon, plans } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="px-[68px] pt-[76px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
</div>
<div className="absolute left-[86px] right-[86px] top-[252px] grid grid-cols-3 items-start">
{plans?.map((plan, index) => {
const active = plan.highlighted;
return (
<div
key={index}
className={` px-[20px] ${active ? "-mt-[30px] py-[60px]" : "py-[33px]"}`}
style={{ backgroundColor: active ? "#15342D" : "#ececee" }}
>
<p
className="text-[20px] font-semibold tracking-[2.074px] text-white"
style={{ color: active ? "#edf2f1" : "#15342D" }}
>
{plan.price}
</p>
<p
className="mt-[18px] text-[28px] font-normal text-[#15342DCC]"
style={{ color: active ? "#edf2f1" : "#15342D" }}
>
{plan.description}
</p>
<div className="mt-[18px] space-y-[6px]">
{plan.features.map((feature, featureIndex) => (
<div key={featureIndex} className="flex items-center gap-[10px]">
<img
src={featureIcon?.__icon_url__}
alt={featureIcon?.__icon_query__}
className="h-[28px] w-[28px] object-contain"
style={{ filter: active ? "brightness(0) invert(1)" : "none" }}
/>
<p
className="text-[28px] font-normal text-[#15342DCC]"
style={{ color: active ? "#edf2f1" : "#15342D" }}
>
{feature}
</p>
</div>
))}
</div>
</div>
);
})}
</div>
</div>
);
};
export default PricingPlanSlide;

View file

@ -0,0 +1,173 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-process-slide";
export const slideLayoutName = "Product Overview Process Slide";
export const slideLayoutDescription =
"A process diagram slide with five connected hexagon steps and alternating caption blocks above and below the flow.";
const StepSchema = z.object({
label: z.string().min(3).max(10).meta({
description: "Short uppercase label for a process step.",
}),
body: z.string().max(20).meta({
description: "Brief explanatory text for the process step.",
}),
icon: z.object({
__icon_url__: z.string(),
__icon_query__: z.string(),
}).default({
__icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "pulse icon",
}),
highlighted: z.boolean().default(false).meta({
description: "Whether the hexagon is emphasized with dark fill.",
}),
});
export const Schema = z.object({
title: z.string().min(5).max(14).default("PROCESS").meta({
description: "Main title shown in the top-left corner.",
}),
steps: z
.array(StepSchema)
.min(5)
.max(5)
.default([
{
label: "TAGLINE", body: "Ut enim ad minim.", icon: {
__icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "pulse icon",
}, highlighted: false
},
{
label: "TAGLINE", body: "Ut enim ad minim.", icon: {
__icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "upload icon",
}, highlighted: false
},
{
label: "TAGLINE", body: "Ut enim ad minim.", icon: {
__icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "pulse icon",
}, highlighted: false
},
{
label: "TAGLINE", body: "Ut enim ad minim.", icon: {
__icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "upload icon",
}, highlighted: false
},
{
label: "TAGLINE", body: "Ut enim ad minim.", icon: {
__icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "pulse icon",
}, highlighted: true
},
])
.meta({
description: "Five process steps rendered from left to right.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const ProcessSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, steps } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: "#DAE1DE" }}
>
<div className="px-[66px] pt-[73px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
</div>
<div className="flex justify-center w-full px-[66px] mt-[110px] ">
{steps?.map((step, index) => {
if (index % 2 === 0) {
return (
<div key={index} className="relative w-[230px] "
style={{
marginLeft: index === 0 ? '0' : '-10px',
}}
>
<div className="relative flex justify-center items-center h-[276px]">
<div className="relative">
<img src={step.icon.__icon_url__} alt={step.icon.__icon_query__} className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-[42px] w-[42px] object-contain"
style={{
filter: step.highlighted ? "invert(1)" : "invert(0)",
}}
/>
<svg xmlns="http://www.w3.org/2000/svg" width="162" height="187" viewBox="0 0 162 187" fill="none">
<path d="M80.8291 0L161.658 46.6667V140L80.8291 186.667L2.28882e-05 140V46.6667L80.8291 0Z" fill={step.highlighted ? "#15342D" : "#FEFEFF"} />
</svg>
</div>
<div className="absolute bottom-1 right-0">
<svg xmlns="http://www.w3.org/2000/svg" width="231" height="134" viewBox="0 0 231 134" fill="none">
<path d="M230.94 66.667L115.47 133.334L0 66.667V0H11.5469V60L115.47 120L219.393 60V0H230.94V66.667Z" fill="#FEFEFF" />
</svg>
</div>
</div>
<div className=" absolute bottom-[-110px] left-0 text-center mt-[60px]">
<p
className="text-[20px] font-semibold tracking-[2.074px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{step.label}
</p>
<p className="mt-[6px] text-[24px] leading-[1.2] text-[#315f58]">{step.body}</p>
</div>
</div>
)
}
else {
return (
<div key={index} className="relative w-[230px]"
style={{
marginLeft: index === 0 ? '0' : '-10px',
}}
>
<div className=" absolute top-[-100px] left-0 w-[224px] text-center">
<p
className="text-[20px] font-semibold tracking-[2.074px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{step.label}
</p>
<p className="mt-[6px] text-[24px] leading-[1.2] text-[#315f58]">{step.body}</p>
</div>
<div className="relative w-[230px] flex justify-center items-center h-[276px]">
<div className="relative">
<svg xmlns="http://www.w3.org/2000/svg" width="162" height="187" viewBox="0 0 162 187" fill="none">
<path d="M80.8291 0L161.658 46.6667V140L80.8291 186.667L2.28882e-05 140V46.6667L80.8291 0Z" fill={step.highlighted ? "#15342D" : "#FEFEFF"} />
</svg>
<img src={step.icon.__icon_url__} alt={step.icon.__icon_query__} className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-[42px] w-[42px] object-contain" />
</div>
<div className="absolute top-1 right-0">
<svg xmlns="http://www.w3.org/2000/svg" width="231" height="134" viewBox="0 0 231 134" fill="none">
<path d="M230.94 66.667L115.47 0L0 66.667V133.333H11.5469V73.333L115.47 13.333L219.394 73.333V133.333H230.94V66.667Z" fill="#FEFEFF" />
</svg>
</div>
</div>
</div>
)
}
})}
</div>
</div>
);
};
export default ProcessSlide;

View file

@ -0,0 +1,162 @@
import * as z from "zod";
export const slideLayoutId = "product-overview-report-snapshot-slide";
export const slideLayoutName = "Product Overview Report Snapshot Slide";
export const slideLayoutDescription =
"A report summary slide with a left-edge photo strip, title and intro copy, a compact bar chart card, and a KPI callout card on the right.";
const BarSchema = z.object({
value: z.number().min(10).max(100).meta({
description: "Relative bar value used in the spending mini chart.",
}),
});
export const Schema = z.object({
title: z.string().min(4).max(12).default("Report").meta({
description: "Slide heading text.",
}),
taglineLabel: z.string().min(3).max(10).default("TAGLINE").meta({
description: "Small label above intro paragraph.",
}),
taglineBody: z.string().min(40).max(100).default(
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea."
).meta({
description: "Intro paragraph shown beneath the heading.",
}),
sideImage: z.object({
__image_url__: z.string().url().default("https://images.unsplash.com/photo-1520607162513-77705c0f0d4a?auto=format&fit=crop&w=700&q=80"),
__image_prompt__: z.string().min(10).max(100).default("Team members reviewing charts together"),
}).default({
__image_url__:
"https://images.unsplash.com/photo-1520607162513-77705c0f0d4a?auto=format&fit=crop&w=700&q=80",
__image_prompt__: "Team members reviewing charts together",
}).meta({
description: "Left-side vertical image strip.",
}),
chartTitle: z.string().min(3).max(20).default("Sandro Tavares").meta({
description: "Name displayed in the chart card.",
}),
bars: z
.array(BarSchema)
.min(8)
.max(8)
.default([
{ value: 52 },
{ value: 24 },
{ value: 35 },
{ value: 48 },
{ value: 26 },
{ value: 72 },
{ value: 47 },
{ value: 55 },
])
.meta({
description: "Eight bars used in the spending card chart.",
}),
metricValue: z.string().min(1).max(8).default("X 5").meta({
description: "KPI value in the callout card.",
}),
metricBody: z.string().min(10).max(18).default("Lorem ipsum.").meta({
description: "KPI short text in the callout card.",
}),
metricIcon: z.object({
__icon_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg"),
__icon_query__: z.string().min(3).max(30).default("pulse icon"),
}).default({
__icon_url__:
"https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/placeholder.svg",
__icon_query__: "pulse icon",
}).meta({
description: "Icon shown in the KPI callout card.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const ReportSnapshotSlide = ({ data }: { data: Partial<SchemaType> }) => {
const {
title,
taglineLabel,
taglineBody,
sideImage,
chartTitle,
bars,
metricValue,
metricBody,
metricIcon,
} = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px] flex gap-[44px]"
style={{ backgroundColor: "#DAE1DE" }}
>
{sideImage?.__image_url__ && (
<img
src={sideImage?.__image_url__}
alt={sideImage?.__image_prompt__}
className=" h-full w-[232px] object-cover"
/>
)}
<div className=" pt-[74px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<div className="mt-[17px] w-[560px]">
<p
className="text-[20px] font-semibold tracking-[2.074px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{taglineLabel}
</p>
<p className="mt-[13px] text-[24px] font-normal text-[#15342DCC]">{taglineBody}</p>
</div>
</div>
<div className="absolute bottom-[56px] left-[268px] w-[574px] bg-[#ececee] px-[24px] py-[20px]">
<p className="text-[20px] text-[#6a6a6a]">Spendings</p>
<p className="mt-[14px] text-[28px] font-normal text-[#15342DCC]" style={{ color: "#15342D" }}>
{chartTitle}
</p>
<div className="mt-[24px] flex h-[124px] items-end gap-[22px] border-b border-[#d8dcdb] pb-[10px]">
{bars?.map((bar, index) => (
<div key={index} className="w-[24px] rounded-[4px] bg-[#0b4b40]" style={{ height: `${bar.value}%` }} />
))}
</div>
<div className="mt-[10px] flex justify-between text-[22px] text-[#6a6a6a]">
<p>Current margin: April Spendings</p>
<p style={{ color: "#15342D" }}>$350.00 / $640.00</p>
</div>
</div>
<div className="absolute right-[42px] top-[380px] h-[148px] w-[360px] bg-[#ececee] px-[34px] py-[22px]">
<div className="flex items-center gap-[14px]">
<div className="flex h-[48px] w-[48px] items-center justify-center rounded-full bg-[#0a3f73]">
<img
src={metricIcon?.__icon_url__}
alt={metricIcon?.__icon_query__}
className="h-[22px] w-[22px] object-contain"
style={{ filter: "brightness(0) invert(1)" }}
/>
</div>
<p className="text-[28px] font-normal text-[#15342DCC]" style={{ color: "#15342D" }}>
{metricValue}
</p>
</div>
<p className="mt-[16px] text-[28px] font-normal text-[#15342DCC]" style={{ color: "#15342D" }}>
{metricBody}
</p>
</div>
</div>
);
};
export default ReportSnapshotSlide;

View file

@ -0,0 +1,94 @@
import * as z from "zod";
const PRODUCT_BG = "#d7dddd";
const PRODUCT_DARK = "#05463d";
export const slideLayoutId = "product-overview-table-of-content-slide";
export const slideLayoutName = "Product Overview Table of Content Slide";
export const slideLayoutDescription =
"A two-column table-of-content slide with section titles and numbers on a dark left panel and a large title plus description paragraph on the right panel.";
const SectionSchema = z.object({
title: z.string().min(4).max(14).meta({
description: "Section label shown in the left navigation column.",
}),
number: z.string().min(2).max(3).meta({
description: "Section number shown beside the section label.",
}),
description: z.string().min(4).max(22).optional().meta({
description: "Section description shown in the right column.",
}),
});
export const Schema = z.object({
title: z.string().min(6).max(18).default("Table Of Content").meta({
description: "Heading in the right-side content area.",
}),
description: z.string().min(50).max(120).default(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore."
).meta({
description: "Supporting descriptive paragraph under the heading.",
}),
sections: z
.array(SectionSchema)
.min(6)
.max(6)
.default([
{ title: "SECTION TITLE", number: "01", description: "Lorem ipsum dolor sit." },
{ title: "SECTION TITLE", number: "02", description: "Lorem ipsum dolor sit." },
{ title: "SECTION TITLE", number: "03", description: "Lorem ipsum dolor sit." },
{ title: "SECTION TITLE", number: "04", description: "Lorem ipsum dolor sit." },
{ title: "SECTION TITLE", number: "05", description: "Lorem ipsum dolor sit." },
{ title: "SECTION TITLE", number: "06", description: "Lorem ipsum dolor sit." },
])
.meta({
description: "Six rows listed in the table of contents panel.",
}),
});
export type SchemaType = z.infer<typeof Schema>;
const TableOfContentSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, description, sections } = data;
return (
<div
className="relative h-[720px] w-[1280px] overflow-hidden rounded-[24px]"
style={{ backgroundColor: PRODUCT_BG }}
>
<div className="grid h-full grid-cols-[1fr_1fr]">
<div className="px-[128px] pt-[69px]" style={{ backgroundColor: PRODUCT_DARK }}>
<div className="space-y-[52px]">
{sections?.map((section, index) => (
<div key={index} className="flex items-center justify-between">
<div>
<p className="text-[20px] font-semibold tracking-[0.2em] text-[#ecf2f1]">
{section.title}
</p>
<p className="mt-[6px] text-[18px] leading-[1.2] text-[#ecf2f1]">{section.description}</p>
</div>
<p className="text-[22px] font-medium text-[#ecf2f1]">{section.number}</p>
</div>
))}
</div>
</div>
<div className="px-[42px] pt-[118px]">
<h2
className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]"
style={{ color: "#15342D" }}
>
{title}
</h2>
<p className="mt-[28px] w-[560px] text-[24px] font-normal text-[#15342DCC]">
{description}
</p>
</div>
</div>
</div>
);
};
export default TableOfContentSlide;

View file

@ -0,0 +1,5 @@
{
"description": "Product pitch layouts for cover, narrative, comparisons, KPIs, pricing, and team slides",
"ordered": false,
"default": false
}

View file

@ -27,6 +27,24 @@ import EducationServicesSplitSlide, { Schema as EduServicesSplitSchema, slideLay
import EducationStatisticsGridSlide, { Schema as EduStatisticsGridSchema, slideLayoutId as EduStatisticsGridId, slideLayoutName as EduStatisticsGridName, slideLayoutDescription as EduStatisticsGridDesc } from "./Education/EducationStatisticsGridSlide";
import EducationTimelineSlide, { Schema as EduTimelineSchema, slideLayoutId as EduTimelineId, slideLayoutName as EduTimelineName, slideLayoutDescription as EduTimelineDesc } from "./Education/EducationTimelineSlide";
// Product Overview templates
import BusinessChallengesCardsSlide, { Schema as PoBizChallengesCardsSchema, slideLayoutId as PoBizChallengesCardsId, slideLayoutName as PoBizChallengesCardsName, slideLayoutDescription as PoBizChallengesCardsDesc } from "./ProductOverview/BusinessChallengesCardsSlide";
import BusinessChallengesGridSlide, { Schema as PoBizChallengesGridSchema, slideLayoutId as PoBizChallengesGridId, slideLayoutName as PoBizChallengesGridName, slideLayoutDescription as PoBizChallengesGridDesc } from "./ProductOverview/BusinessChallengesGridSlide";
import ComparisonChartSlide, { Schema as PoComparisonChartSchema, slideLayoutId as PoComparisonChartId, slideLayoutName as PoComparisonChartName, slideLayoutDescription as PoComparisonChartDesc } from "./ProductOverview/ComparisonChartSlide";
import ComparisonTableWithTextSlide, { Schema as PoComparisonTableSchema, slideLayoutId as PoComparisonTableId, slideLayoutName as PoComparisonTableName, slideLayoutDescription as PoComparisonTableDesc } from "./ProductOverview/ComparisonTableWithTextSlide";
import CoverSlide, { Schema as PoCoverSchema, slideLayoutId as PoCoverId, slideLayoutName as PoCoverName, slideLayoutDescription as PoCoverDesc } from "./ProductOverview/CoverSlide";
import ImageGallerySlide, { Schema as PoImageGallerySchema, slideLayoutId as PoImageGalleryId, slideLayoutName as PoImageGalleryName, slideLayoutDescription as PoImageGalleryDesc } from "./ProductOverview/ImageGallerySlide";
import IntroductionSlide, { Schema as PoIntroductionSchema, slideLayoutId as PoIntroductionId, slideLayoutName as PoIntroductionName, slideLayoutDescription as PoIntroductionDesc } from "./ProductOverview/IntroductionSlide";
import KpiCardsSlide, { Schema as PoKpiCardsSchema, slideLayoutId as PoKpiCardsId, slideLayoutName as PoKpiCardsName, slideLayoutDescription as PoKpiCardsDesc } from "./ProductOverview/KpiCardsSlide";
import MarketOpportunitySlide, { Schema as PoMarketOpportunitySchema, slideLayoutId as PoMarketOpportunityId, slideLayoutName as PoMarketOpportunityName, slideLayoutDescription as PoMarketOpportunityDesc } from "./ProductOverview/MarketOpportunitySlide";
import MeetTeamSlide, { Schema as PoMeetTeamSchema, slideLayoutId as PoMeetTeamId, slideLayoutName as PoMeetTeamName, slideLayoutDescription as PoMeetTeamDesc } from "./ProductOverview/MeetTeamSlide";
import MissionVisionSlide, { Schema as PoMissionVisionSchema, slideLayoutId as PoMissionVisionId, slideLayoutName as PoMissionVisionName, slideLayoutDescription as PoMissionVisionDesc } from "./ProductOverview/MissionVisionSlide";
import OurServicesSlide, { Schema as PoOurServicesSchema, slideLayoutId as PoOurServicesId, slideLayoutName as PoOurServicesName, slideLayoutDescription as PoOurServicesDesc } from "./ProductOverview/OurServicesSlide";
import PricingPlanSlide, { Schema as PoPricingPlanSchema, slideLayoutId as PoPricingPlanId, slideLayoutName as PoPricingPlanName, slideLayoutDescription as PoPricingPlanDesc } from "./ProductOverview/PricingPlanSlide";
import ProcessSlide, { Schema as PoProcessSchema, slideLayoutId as PoProcessId, slideLayoutName as PoProcessName, slideLayoutDescription as PoProcessDesc } from "./ProductOverview/ProcessSlide";
import ReportSnapshotSlide, { Schema as PoReportSnapshotSchema, slideLayoutId as PoReportSnapshotId, slideLayoutName as PoReportSnapshotName, slideLayoutDescription as PoReportSnapshotDesc } from "./ProductOverview/ReportSnapshotSlide";
import TableOfContentSlide, { Schema as PoTableOfContentSchema, slideLayoutId as PoTableOfContentId, slideLayoutName as PoTableOfContentName, slideLayoutDescription as PoTableOfContentDesc } from "./ProductOverview/TableOfContentSlide";
// General templates
import GeneralIntroSlideLayout, { Schema as GeneralIntroSchema, layoutId as GeneralIntroId, layoutName as GeneralIntroName, layoutDescription as GeneralIntroDesc } from "./general/IntroSlideLayout";
import BasicInfoSlideLayout, { Schema as BasicInfoSchema, layoutId as BasicInfoId, layoutName as BasicInfoName, layoutDescription as BasicInfoDesc } from "./general/BasicInfoSlideLayout";
@ -201,6 +219,7 @@ import neoModernSettings from "./neo-modern/settings.json";
import neoSwiftSettings from "./neo-swift/settings.json";
import codeSettings from "./Code/settings.json";
import educationSettings from "./Education/settings.json";
import productOverviewSettings from "./ProductOverview/settings.json";
// Helper to create template entry
@ -234,6 +253,25 @@ export const educationTemplates: TemplateWithData[] = [
createTemplateEntry(EducationTimelineSlide, EduTimelineSchema, EduTimelineId, EduTimelineName, EduTimelineDesc, "education", "EducationTimelineSlide"),
];
export const productOverviewTemplates: TemplateWithData[] = [
createTemplateEntry(CoverSlide, PoCoverSchema, PoCoverId, PoCoverName, PoCoverDesc, "product-overview", "CoverSlide"),
createTemplateEntry(TableOfContentSlide, PoTableOfContentSchema, PoTableOfContentId, PoTableOfContentName, PoTableOfContentDesc, "product-overview", "TableOfContentSlide"),
createTemplateEntry(IntroductionSlide, PoIntroductionSchema, PoIntroductionId, PoIntroductionName, PoIntroductionDesc, "product-overview", "IntroductionSlide"),
createTemplateEntry(MissionVisionSlide, PoMissionVisionSchema, PoMissionVisionId, PoMissionVisionName, PoMissionVisionDesc, "product-overview", "MissionVisionSlide"),
createTemplateEntry(MarketOpportunitySlide, PoMarketOpportunitySchema, PoMarketOpportunityId, PoMarketOpportunityName, PoMarketOpportunityDesc, "product-overview", "MarketOpportunitySlide"),
createTemplateEntry(BusinessChallengesGridSlide, PoBizChallengesGridSchema, PoBizChallengesGridId, PoBizChallengesGridName, PoBizChallengesGridDesc, "product-overview", "BusinessChallengesGridSlide"),
createTemplateEntry(BusinessChallengesCardsSlide, PoBizChallengesCardsSchema, PoBizChallengesCardsId, PoBizChallengesCardsName, PoBizChallengesCardsDesc, "product-overview", "BusinessChallengesCardsSlide"),
createTemplateEntry(OurServicesSlide, PoOurServicesSchema, PoOurServicesId, PoOurServicesName, PoOurServicesDesc, "product-overview", "OurServicesSlide"),
createTemplateEntry(ProcessSlide, PoProcessSchema, PoProcessId, PoProcessName, PoProcessDesc, "product-overview", "ProcessSlide"),
createTemplateEntry(ComparisonChartSlide, PoComparisonChartSchema, PoComparisonChartId, PoComparisonChartName, PoComparisonChartDesc, "product-overview", "ComparisonChartSlide"),
createTemplateEntry(ComparisonTableWithTextSlide, PoComparisonTableSchema, PoComparisonTableId, PoComparisonTableName, PoComparisonTableDesc, "product-overview", "ComparisonTableWithTextSlide"),
createTemplateEntry(KpiCardsSlide, PoKpiCardsSchema, PoKpiCardsId, PoKpiCardsName, PoKpiCardsDesc, "product-overview", "KpiCardsSlide"),
createTemplateEntry(ReportSnapshotSlide, PoReportSnapshotSchema, PoReportSnapshotId, PoReportSnapshotName, PoReportSnapshotDesc, "product-overview", "ReportSnapshotSlide"),
createTemplateEntry(PricingPlanSlide, PoPricingPlanSchema, PoPricingPlanId, PoPricingPlanName, PoPricingPlanDesc, "product-overview", "PricingPlanSlide"),
createTemplateEntry(MeetTeamSlide, PoMeetTeamSchema, PoMeetTeamId, PoMeetTeamName, PoMeetTeamDesc, "product-overview", "MeetTeamSlide"),
createTemplateEntry(ImageGallerySlide, PoImageGallerySchema, PoImageGalleryId, PoImageGalleryName, PoImageGalleryDesc, "product-overview", "ImageGallerySlide"),
];
export const neoGeneralTemplates: TemplateWithData[] = [
createTemplateEntry(TextSplitWithEmphasisBlockLayout, TextSplitWithEmphasisBlockSchema, TextSplitWithEmphasisBlockId, TextSplitWithEmphasisBlockName, TextSplitWithEmphasisBlockDesc, 'neo-general', 'TextSplitWithEmphasisBlock'),
@ -406,6 +444,7 @@ export const allLayouts: TemplateWithData[] = [
...swiftTemplates,
...codeTemplates,
...educationTemplates,
...productOverviewTemplates,
];
@ -482,6 +521,13 @@ export const templates: TemplateLayoutsWithSettings[] = [
settings: educationSettings as TemplateGroupSettings,
layouts: educationTemplates,
},
{
id: "product-overview",
name: "Product Overview",
description: productOverviewSettings.description,
settings: productOverviewSettings as TemplateGroupSettings,
layouts: productOverviewTemplates,
},
];
// Helper to get templates by group ID