feat: Product Overview template added
This commit is contained in:
parent
9061bf3e6f
commit
604bb95386
18 changed files with 2096 additions and 0 deletions
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"description": "Product pitch layouts for cover, narrative, comparisons, KPIs, pricing, and team slides",
|
||||
"ordered": false,
|
||||
"default": false
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue