From d3209e4b9f78cecefa96751c296476d88f09fd12 Mon Sep 17 00:00:00 2001 From: Suraj Jha Date: Thu, 4 Sep 2025 16:35:24 +0545 Subject: [PATCH 1/5] delete: remove chalss and classic-dark theme --- .../classic-dark/1-TitleSlide.tsx | 87 ------ .../classic-dark/2-ChartAndMetrics.tsx | 154 ---------- .../classic-dark/3-BarGraph.tsx | 146 ---------- .../classic-dark/4-Comparison.tsx | 120 -------- .../classic-dark/5-Metrics.tsx | 141 --------- .../6-BulletPointWithDescription.tsx | 103 ------- .../classic-dark/settings.json | 5 - .../classic/Type10SlideLayout.tsx | 269 ------------------ .../classic/Type1SlideLayout.tsx | 65 ----- .../classic/Type2NumberedSlideLayout.tsx | 124 -------- .../classic/Type2SlideLayout.tsx | 111 -------- .../classic/Type2TimelineSlideLayout.tsx | 101 ------- .../classic/Type3SlideLayout.tsx | 119 -------- .../classic/Type4SlideLayout.tsx | 209 -------------- .../classic/Type5SlideLayout.tsx | 101 ------- .../classic/Type6SlideLayout.tsx | 161 ----------- .../classic/Type7SlideLayout.tsx | 173 ----------- .../classic/Type8SlideLayout.tsx | 167 ----------- .../classic/Type9SlideLayout.tsx | 253 ---------------- .../classic/TypeMermaidSlideLayout.tsx | 136 --------- .../classic/settings.json | 5 - 21 files changed, 2750 deletions(-) delete mode 100644 servers/nextjs/presentation-templates/classic-dark/1-TitleSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/classic-dark/2-ChartAndMetrics.tsx delete mode 100644 servers/nextjs/presentation-templates/classic-dark/3-BarGraph.tsx delete mode 100644 servers/nextjs/presentation-templates/classic-dark/4-Comparison.tsx delete mode 100644 servers/nextjs/presentation-templates/classic-dark/5-Metrics.tsx delete mode 100644 servers/nextjs/presentation-templates/classic-dark/6-BulletPointWithDescription.tsx delete mode 100644 servers/nextjs/presentation-templates/classic-dark/settings.json delete mode 100644 servers/nextjs/presentation-templates/classic/Type10SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type1SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type2NumberedSlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type2SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type2TimelineSlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type3SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type4SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type5SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type6SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type7SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type8SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/Type9SlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/TypeMermaidSlideLayout.tsx delete mode 100644 servers/nextjs/presentation-templates/classic/settings.json diff --git a/servers/nextjs/presentation-templates/classic-dark/1-TitleSlide.tsx b/servers/nextjs/presentation-templates/classic-dark/1-TitleSlide.tsx deleted file mode 100644 index 6f7846db..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/1-TitleSlide.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ImageSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'classic-dark-title-slide' -export const layoutName = 'Classic Dark Title Slide' -export const layoutDescription = 'A modern title slide with dark gradient background, gradient text, and geographical elements.' - -const titleSlideSchema = z.object({ - title: z.string().min(3).max(100).default('Nepal\'s Imports and\nExports: A Data-Driven\nOverview').meta({ - description: "Main title of the slide", - }), - subtitle: z.string().min(3).max(100).default('Key Trade Statistics and Trends (2022–2025)').meta({ - description: "Subtitle text", - }), - presenter: z.string().min(3).max(50).default('[Your Name]').meta({ - description: "Presenter name", - }), - date: z.string().min(3).max(50).default('April 13, 2025').meta({ - description: "Presentation date", - }), - image: ImageSchema.default({ - __image_url__: 'https://images.pexels.com/photos/9669089/pexels-photo-9669089.jpeg', - __image_prompt__: 'Map of Nepal with gradient coloring from orange to red-brown' - }).meta({ - description: "Image of the title slide of the presentation", - }), -}) - -export const Schema = titleSlideSchema - -export type TitleSlideData = z.infer - -interface TitleSlideLayoutProps { - data: Partial -} - -const TitleSlideLayout: React.FC = ({ data: slideData }) => { - const { title, subtitle, presenter, date, image } = slideData; - - return ( -
- -
- {/* Left side - Text content */} -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Subtitle */} - {subtitle && ( -

- {subtitle} -

- )} - - {/* Presenter and date */} -
- Presenter: {presenter} | {date} -
-
- - {/* Right side - Visual elements */} -
- {image && ( -
- {image.__image_prompt__} -
- )} -
-
-
- ) -} - -export default TitleSlideLayout diff --git a/servers/nextjs/presentation-templates/classic-dark/2-ChartAndMetrics.tsx b/servers/nextjs/presentation-templates/classic-dark/2-ChartAndMetrics.tsx deleted file mode 100644 index c266bbe3..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/2-ChartAndMetrics.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import { PieChart, Pie, Cell } from "recharts"; - -export const layoutId = 'classic-dark-piechart-and-metrics' -export const layoutName = 'Classic Dark Pie Chart and Metrics' -export const layoutDescription = 'A modern slide with dark background, metrics on the left, and pie chart visualization on the right.' - -const chartDataSchema = z.object({ - name: z.string().min(2).max(30).meta({ description: "Data point name" }), - value: z.number().meta({ description: "Data point value" }), -}); - -const pieChartAndMetricsSchema = z.object({ - title: z.string().min(3).max(80).default('Introduction to Nepal\'s Trade').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(100).default('Nepal\'s landlocked geography heavily influences its trade, fostering reliance on India and China.').meta({ - description: "Description text", - }), - metrics: z.array(z.object({ - label: z.string().meta({ description: "Metric label" }), - value: z.string().meta({ description: "Metric value" }), - percentage: z.string().optional().meta({ description: "Optional percentage" }), - })).min(2).max(4).default([ - { label: 'Exports (2023)', value: '$2.85 billion', percentage: '6.76% of GDP' }, - { label: 'Imports (2023)', value: '$17.39 billion', percentage: '42.64% of GDP' }, - { label: 'GDP (2022)', value: '$40.83 billion' }, - { label: 'Trade Deficit (2022)', value: '-$12.44 billion' }, - ]).meta({ - description: "List of key metrics", - }), - chartData: z.array(chartDataSchema).min(2).max(4).default([ - { name: 'Imports', value: 42.64 }, - { name: 'Exports', value: 6.76 }, - { name: 'Other GDP', value: 50.6 }, - ]).meta({ - description: "Pie chart data", - }) -}) - -const chartConfig = { - value: { - label: "Value", - }, - name: { - label: "Name", - }, -}; - -const CHART_COLORS = [ - '#8b5cf6', - '#3b82f6', - '#a855f7', -]; - -export const Schema = pieChartAndMetricsSchema - -export type PieChartAndMetricsData = z.infer - -interface PieChartAndMetricsLayoutProps { - data: Partial -} - -const PieChartAndMetricsLayout: React.FC = ({ data: slideData }) => { - const { title, description, metrics, chartData } = slideData; - - const CustomLegend = () => ( -
- {chartData?.map((entry, index) => ( -
-
- {entry.name} -
- ))} -
- ); - - const renderPieChart = () => { - return ( - - } /> - `${name} ${(percent * 100).toFixed(0)}%`} - labelLine={false} - fontSize={18} - > - {chartData?.map((entry, index) => ( - - ))} - - - ); - }; - - return ( -
- -
- {/* Left side - Text content and metrics */} -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Description */} - {description && ( -

- {description} -

- )} - - {/* Metrics */} - {metrics && metrics.length > 0 && ( -
- {metrics.map((metric, index) => ( -
- • {metric.label}: - {metric.value} - {metric.percentage && ( - ({metric.percentage}) - )} -
- ))} -
- )} -
- - {/* Right side - Chart */} -
-
- - {renderPieChart()} - - -
-
-
-
- ) -} - -export default PieChartAndMetricsLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic-dark/3-BarGraph.tsx b/servers/nextjs/presentation-templates/classic-dark/3-BarGraph.tsx deleted file mode 100644 index 2e77ee86..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/3-BarGraph.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Cell } from "recharts"; - -export const layoutId = 'classic-dark-bar-graph' -export const layoutName = 'Classic Dark Bar Graph' -export const layoutDescription = 'A modern slide with dark background, gradient title, bar chart visualization, and footer text.' - -const barDataSchema = z.object({ - name: z.string().min(2).max(30).meta({ description: "Product name" }), - value: z.number().meta({ description: "Export value in millions" }), -}); - -const barGraphSchema = z.object({ - title: z.string().min(3).max(80).default('Export Overview: Key Products').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(120).default('Nepal\'s total exports were $1.3 billion in 2022, a 21% decrease from 2021, but showed a 47.5% YoY increase by Nov 2024.').meta({ - description: "Description text", - }), - chartData: z.array(barDataSchema).min(2).max(6).default([ - { name: 'Soybean Oil (non-crude)', value: 180 }, - { name: 'Palm Oil (non-crude)', value: 180 }, - { name: 'Carpets/Textile Floor...', value: 80 }, - { name: 'Cardamom', value: 50 }, - { name: 'Felt Products', value: 40 }, - ]).meta({ - description: "Bar chart data", - }), -}) - -const chartConfig = { - value: { - label: "Value ($M)", - }, - name: { - label: "Product", - }, -}; - -const BAR_COLORS = [ - '#8b5cf6', // Dark purple for top products - '#8b5cf6', // Dark purple for top products - '#a855f7', // Light purple for other products - '#a855f7', // Light purple for other products - '#a855f7', // Light purple for other products -]; - -export const Schema = barGraphSchema - -export type BarGraphData = z.infer - -interface BarGraphLayoutProps { - data: Partial -} - -const BarGraphLayout: React.FC = ({ data: slideData }) => { - const { title, description, chartData } = slideData; - - const CustomLegend = () => ( -
- {chartData?.map((entry, index) => ( -
-
- {entry.name} -
- ))} -
- ); - - const renderBarChart = () => { - return ( - - - { - if (value.length > 15) { - return value.substring(0, 15) + '...'; - } - return value; - }} - /> - value.toFixed(0)} - /> - } /> - - {chartData?.map((entry, index) => ( - - ))} - - - ); - }; - - return ( -
- -
- {/* Header section */} -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Description */} - {description && ( -

- {description} -

- )} -
- - {/* Chart section */} -
-
- - {renderBarChart()} - - -
-
-
-
- ) -} - -export default BarGraphLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic-dark/4-Comparison.tsx b/servers/nextjs/presentation-templates/classic-dark/4-Comparison.tsx deleted file mode 100644 index fa928f69..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/4-Comparison.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ImageSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'classic-dark-comparison' -export const layoutName = 'Classic Dark Comparison' -export const layoutDescription = 'A modern slide with dark background, image on the left (2/5), and comparison content on the right (3/5).' - -const comparisonItemSchema = z.object({ - name: z.string().min(3).max(30).meta({ description: "Commodity name" }), - value: z.string().min(3).max(30).meta({ description: "Value" }), - when: z.string().min(3).max(30).meta({ description: "When the value was recorded" }), - details: z.string().min(3).max(50).optional().meta({ description: "Additional details" }), -}); - -const comparisonSectionSchema = z.object({ - title: z.string().min(3).max(50).meta({ description: "Section title" }), - items: z.array(comparisonItemSchema).min(1).max(3).meta({ description: "List of items in the section" }), -}); - -const comparisonSchema = z.object({ - title: z.string().min(3).max(80).default('Key Commodities in Focus').meta({ - description: "Main title of the slide", - }), - comparisonSections: z.array(comparisonSectionSchema).min(2).max(2).default([ - { - title: 'Exports', - items: [ - { name: 'Soybean Oil', value: '$186.91 million', when: '2022' }, - { name: 'Cardamom', value: '$46.64 million', when: '2022', details: 'primarily to India' }, - ] - }, - { - title: 'Imports', - items: [ - { name: 'Crude Soybean Oil', value: '$347.77 million', when: '2022' }, - { name: 'Petroleum Products', value: '$3.15 billion', when: '2022', details: '22% of total imports' }, - { name: 'Vehicles/Parts', value: '$526 million', when: '2022', details: 'down 45% from 2021' }, - ] - } - ]).meta({ - description: "Comparison sections with title and data items", - }), - image: ImageSchema.default({ - __image_url__: 'https://images.pexels.com/photos/9669089/pexels-photo-9669089.jpeg', - __image_prompt__: 'Map of South Asia showing Nepal and neighboring countries with trade routes highlighted' - }).meta({ - description: "Comparison visualization image", - }), -}) - -export const Schema = comparisonSchema - -export type ComparisonData = z.infer - -interface ComparisonLayoutProps { - data: Partial -} - -const ComparisonLayout: React.FC = ({ data: slideData }) => { - const { title, comparisonSections, image } = slideData; - - return ( -
- -
- {/* Left side - Image (2/5) */} -
- {image && ( -
- {image.__image_prompt__} -
- )} -
- - {/* Right side - Content (3/5) */} -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Comparison Sections */} -
- {comparisonSections && comparisonSections.map((section, sectionIndex) => ( -
-

- {section.title} -

- {section.items && section.items.length > 0 && ( -
- {section.items.map((item, index) => ( -
- {item.name}: {item.value} ({item.when}) - {item.details && ( - , {item.details} - )} -
- ))} -
- )} -
- ))} -
-
-
-
- ) -} - -export default ComparisonLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic-dark/5-Metrics.tsx b/servers/nextjs/presentation-templates/classic-dark/5-Metrics.tsx deleted file mode 100644 index 397eef25..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/5-Metrics.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { IconSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'classic-dark-metrics' -export const layoutName = 'Classic Dark Metrics' -export const layoutDescription = 'A modern slide with dark background, metric cards arranged in a grid with icons and data.' - -const metricItemSchema = z.object({ - title: z.string().min(3).max(50).meta({ description: "Metric title" }), - value: z.string().min(3).max(30).meta({ description: "Metric value" }), - percentage: z.string().min(3).max(30).meta({ description: "Percentage value" }), - icon: IconSchema.meta({ description: "Icon for the metric" }), -}); - -const metricsSchema = z.object({ - title: z.string().min(3).max(80).default('Top Export Destinations').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(120).default('Nepal exports 760 products to 132 countries, with a strong focus on regional trade.').meta({ - description: "Description text", - }), - metrics: z.array(metricItemSchema).min(2).max(6).default([ - { - title: 'India', - value: '$935 million', - percentage: '71.93%', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'star rating' - } - }, - { - title: 'United States', - value: '$147 million', - percentage: '11.32%', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'flag country' - } - }, - { - title: 'Germany', - value: '$33 million', - percentage: '2.51%', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'user person' - } - }, - { - title: 'Turkey', - value: '$26 million', - percentage: '2.01%', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'pen tool' - } - }, - { - title: 'United Kingdom', - value: '$24 million', - percentage: '1.83%', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'message chat' - } - }, - ]).meta({ - description: "Metric cards data", - }), -}) - -export const Schema = metricsSchema - -export type MetricsData = z.infer - -interface MetricsLayoutProps { - data: Partial -} - -const MetricsLayout: React.FC = ({ data: slideData }) => { - const { title, description, metrics } = slideData; - - return ( -
- -
- {/* Header section */} -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Description */} - {description && ( -

- {description} -

- )} -
- - {/* Metrics Cards Grid */} -
-
- {metrics && metrics.map((metric, index) => ( -
- {/* Metric Card with overlapping icon */} -
- {/* Icon overlapping the top */} -
- {metric.icon.__icon_query__} -
- - {/* Content with top padding for icon space */} -
-

- {metric.title} -

-

- {metric.value} ({metric.percentage}) -

-
-
-
- ))} -
-
-
-
- ) -} - -export default MetricsLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic-dark/6-BulletPointWithDescription.tsx b/servers/nextjs/presentation-templates/classic-dark/6-BulletPointWithDescription.tsx deleted file mode 100644 index 64b9f292..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/6-BulletPointWithDescription.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ImageSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'classic-dark-bullet-point-with-description' -export const layoutName = 'Classic Dark Bullet Point with Description' -export const layoutDescription = 'A modern slide with dark background, image on the left (2/5), and bullet points with descriptions in boxes on the right (3/5).' - -const bulletPointSchema = z.object({ - title: z.string().min(3).max(60).meta({ description: "Bullet point title" }), - content: z.string().min(10).max(120).meta({ description: "Bullet point content (max 150 characters)" }), -}); - -const bulletPointWithDescriptionSchema = z.object({ - title: z.string().min(3).max(80).default('Trade Policies and Challenges').meta({ - description: "Main title of the slide", - }), - bulletPoints: z.array(bulletPointSchema).min(2).max(3).default([ - { - title: 'Tariffs', - content: 'Effectively Applied Tariff (2022): 11.59%. Most Favored Nation Tariff (2022): 12.87%. Duty-free imports: $412.11 million.' - }, - { - title: 'Forex Reserves', - content: '$8.18 billion in 2019, covering 8 months of imports.' - }, - { - title: 'Import Ban Impact', - content: 'Luxury goods ban (Apr-Dec 2022) cut deficit by 15.45% but reduced export earnings by 21.44%.' - } - ]).meta({ - description: "Bullet points with descriptions (max 3 items)", - }), - image: ImageSchema.default({ - __image_url__: 'https://images.pexels.com/photos/9669089/pexels-photo-9669089.jpeg', - __image_prompt__: 'Stylized mountainous landscape with trade arrows and network connections, dark gradient background with orange sun and purple mountains' - }).meta({ - description: "Visual representation image", - }), -}) - -export const Schema = bulletPointWithDescriptionSchema - -export type BulletPointWithDescriptionData = z.infer - -interface BulletPointWithDescriptionLayoutProps { - data: Partial -} - -const BulletPointWithDescriptionLayout: React.FC = ({ data: slideData }) => { - const { title, bulletPoints, image } = slideData; - - return ( -
- -
- {/* Left side - Image (2/5) */} -
- {image && ( -
- {image.__image_prompt__} -
- )} -
- - {/* Right side - Content (3/5) */} -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Bullet Points */} - {bulletPoints && bulletPoints.length > 0 && ( -
- {bulletPoints.map((point, index) => ( -
-

- {point.title} -

-

- {point.content} -

-
- ))} -
- )} -
-
-
- ) -} - -export default BulletPointWithDescriptionLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic-dark/settings.json b/servers/nextjs/presentation-templates/classic-dark/settings.json deleted file mode 100644 index 2e888eab..00000000 --- a/servers/nextjs/presentation-templates/classic-dark/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "description": "Classic dark layout for presentations", - "ordered": false, - "default": false -} \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type10SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type10SlideLayout.tsx deleted file mode 100644 index 5acad87d..00000000 --- a/servers/nextjs/presentation-templates/classic/Type10SlideLayout.tsx +++ /dev/null @@ -1,269 +0,0 @@ -import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import React from 'react' -import { BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Cell, ResponsiveContainer } from "recharts"; -import * as z from "zod"; -import { IconSchema } from '../defaultSchemes'; - -export const layoutId = 'type4-slide' -export const layoutName = 'Type4 Slide' -export const layoutDescription = 'A chart-focused layout with title, chart visualization, and description text.' - -const chartDataSchema = z.object({ - name: z.string().meta({ description: "Data point name" }), - value: z.number().meta({ description: "Data point value" }), - category: z.string().optional().meta({ description: "Category for grouping" }), - x: z.number().optional().meta({ description: "X coordinate for scatter plots" }), - y: z.number().optional().meta({ description: "Y coordinate for scatter plots" }), -}); - - -const type10SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Chart Analysis').meta({ - description: "Main title of the slide", - }), - description: z.string().min(8).max(40).default('This is a description of the chart analysis').meta({ - description: " Short description of the chart analysis", - }), - items: z.array(z.object({ - icon: IconSchema.meta({ - description: "Item icon", - }), - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }) - })).min(2).max(3).default(() => [ - { - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'A beautiful road in the mountains' - }, - heading: 'First Key Point', - description: 'Detailed explanation of the first important point that supports the main topic' - }, - { - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'A beautiful road in the mountains' - }, - heading: 'Second Key Point', - description: 'Detailed explanation of the second important point with relevant information' - } - ]).meta({ - description: "List of numbered items (2-3 items)", - }), - chartData: z.any().optional().meta({ - description: "Chart data object", - }), - isFullSizeChart: z.boolean().default(false).meta({ - description: "Whether to display chart in full size mode", - }), - chartType: z.enum(['bar', 'line', 'pie', 'area', 'scatter']).default('line').meta({ - description: "Type of chart to display", - }), - data: z.array(chartDataSchema).min(2).max(10).default([ - { name: '2021', value: 5 }, - { name: '2022', value: 12 }, - { name: '2023', value: 18 }, - { name: '2024', value: 23 }, - { name: '2025', value: 26 }, - ]).meta({ - description: "Chart data points", - }), - dataKey: z.string().default('value').meta({ - description: "Key field for chart values", - }), - categoryKey: z.string().default('name').meta({ - description: "Key field for chart categories", - }), - color: z.string().default('#3b82f6').meta({ - description: "Primary color for chart elements", - }), - showLegend: z.boolean().default(false).meta({ - description: "Whether to show chart legend", - }), - showTooltip: z.boolean().default(true).meta({ - description: "Whether to show chart tooltip", - }), -}) - - -const chartConfig = { - value: { - label: "Value", - }, - name: { - label: "Name", - }, -}; -const CHART_COLORS = [ - '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6', - '#06b6d4', '#84cc16', '#f97316', '#ec4899', '#6366f1' -]; - -export const Schema = type10SlideSchema - -export type Type10SlideData = z.infer - -interface Type10SlideLayoutProps { - data: Partial -} - -const Type10SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items, data, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; - const chartData = data || []; - const renderChart = () => { - const commonProps = { - data: chartData, - margin: { top: 10, right: 20, left: 0, bottom: 30 }, - }; - - switch (chartType) { - case 'bar': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'line': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'area': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'pie': - return ( - - {showTooltip && } />} - {showLegend && } />} - `${name} ${(percent * 100).toFixed(0)}%`} - > - {chartData.map((entry: any, index: number) => ( - - ))} - - - ); - - case 'scatter': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - default: - return
Unsupported chart type
; - } - }; - - return ( -
-
- - {title &&

- {title || 'Chart Analysis'} -

} - -
-
-
-
- - {renderChart()} - -
-
-
-
- {items && items.map((item, index) => ( -
-
-
-
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__} -
-
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
-
- ))} -
-
-
-
- ) -} - -export default Type10SlideLayout - diff --git a/servers/nextjs/presentation-templates/classic/Type1SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type1SlideLayout.tsx deleted file mode 100644 index cbbaaa0c..00000000 --- a/servers/nextjs/presentation-templates/classic/Type1SlideLayout.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ImageSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'type1-slide' -export const layoutName = 'Type1 Slide' -export const layoutDescription = 'A clean two-column layout with title and description on the left and a featured image on the right.' - -const type1SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Hot NOT Reload Working!').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(130).default('This is a test of the hot reload system! If you can see this text, hot reload is working perfectly. Changes should appear instantly without page refresh.').meta({ - description: "Main description text", - }), - image: ImageSchema.default({ - __image_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', - __image_prompt__: 'A beautiful road in the mountains' - }).meta({ - description: "Main slide image", - }) -}) - -export const Schema = type1SlideSchema - -export type Type1SlideData = z.infer - -interface Type1SlideLayoutProps { - data: Partial -} - -const Type1SlideLayout: React.FC = ({ data: slideData }) => { - const { title, description, image } = slideData; - return ( -
-
-
- {/* Title */} - {title &&

- {title} -

} - - {/* Description */} - {description &&

- {description} -

} -
- - {/* Image */} -
- {image && {image?.__image_prompt__} -
-
-
- ) -} - -export default Type1SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type2NumberedSlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type2NumberedSlideLayout.tsx deleted file mode 100644 index 76457ca6..00000000 --- a/servers/nextjs/presentation-templates/classic/Type2NumberedSlideLayout.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import React from 'react' -import * as z from "zod"; - -export const layoutId = 'type2-numbered-slide' -export const layoutName = 'Type2 Numbered Slide' -export const layoutDescription = 'A content layout with title and numbered content items with large numerals and shadow boxes.' - -const type2NumberedSlideSchema = z.object({ - title: z.string().min(3).max(50).default('Main Title').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(100).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }) - })).min(2).max(3).default([ - { - heading: 'First Point', - description: 'Description for the first key point that explains important details' - }, - { - heading: 'Second Point', - description: 'Description for the second key point with relevant information' - }, - { - heading: 'Third Point', - description: 'Description for the third key point highlighting crucial aspects' - } - ]).meta({ - description: "List of content items (2-4 items)", - }) -}) - -export const Schema = type2NumberedSlideSchema - -export type Type2NumberedSlideData = z.infer - -interface Type2NumberedSlideLayoutProps { - data: Partial -} - -const Type2NumberedSlideLayout: React.FC = ({ data: slideData }) => { - const { title, items } = slideData; - const isGridLayout = items?.length && items?.length >= 4 - const numberTranslations: string[] = ['01', '02', '03', '04', '05', '06'] - - const renderGridContent = () => { - return ( -
- {items?.map((item, index) => ( -
-
-
- {numberTranslations[index] || `0${index + 1}`} -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
-
- ))} -
- ) - } - - const renderHorizontalContent = () => { - return ( -
- {items?.map((item, index) => ( -
-
- {numberTranslations[index] || `0${index + 1}`} -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
- ) - } - - return ( -
-
- {title &&

- {title} -

} -
- - {isGridLayout ? renderGridContent() : renderHorizontalContent()} -
- ) -} - -export default Type2NumberedSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type2SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type2SlideLayout.tsx deleted file mode 100644 index 275a6fe7..00000000 --- a/servers/nextjs/presentation-templates/classic/Type2SlideLayout.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import React from 'react' -import * as z from "zod"; - -export const layoutId = 'type2-slide' -export const layoutName = 'Type2 Slide' -export const layoutDescription = 'A flexible content layout with title and multiple content items in default presentation style.' - -const type2SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Main Title').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }) - })).min(2).max(3).default([ - { - heading: 'First Point', - description: 'Description for the first key point that explains important details' - }, - { - heading: 'Second Point', - description: 'Description for the second key point with relevant information' - }, - { - heading: 'Third Point', - description: 'Description for the third key point highlighting crucial aspects' - } - ]).meta({ - description: "List of content items (2-4 items)", - }) -}) - -export const Schema = type2SlideSchema - -export type Type2SlideData = z.infer - -interface Type2SlideLayoutProps { - data: Partial -} - -const Type2SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items } = slideData; - const isGridLayout = items?.length && items?.length >= 4 - - const renderGridContent = () => { - return ( -
- {items?.map((item, index) => ( -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
- ) - } - - const renderHorizontalContent = () => { - return ( -
- {items?.map((item, index) => ( -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
- ) - } - - return ( -
-
- {title &&

- {title} -

} -
- - {isGridLayout ? renderGridContent() : renderHorizontalContent()} -
- ) -} - -export default Type2SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type2TimelineSlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type2TimelineSlideLayout.tsx deleted file mode 100644 index 0a62e82a..00000000 --- a/servers/nextjs/presentation-templates/classic/Type2TimelineSlideLayout.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React from 'react' -import * as z from "zod"; - -export const layoutId = 'type2-timeline-slide' -export const layoutName = 'Type2 Timeline Slide' -export const layoutDescription = 'A timeline layout with title and content items arranged horizontally with numbered circles and connecting line.' - -const type2TimelineSlideSchema = z.object({ - title: z.string().min(3).max(50).default('Main Title').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }) - })).min(2).max(3).default([ - { - heading: 'First Point', - description: 'Description for the first key point that explains important details' - }, - { - heading: 'Second Point', - description: 'Description for the second key point with relevant information' - }, - { - heading: 'Third Point', - description: 'Description for the third key point highlighting crucial aspects' - } - ]).meta({ - description: "List of content items (2-4 items)", - }) -}) - -export const Schema = type2TimelineSlideSchema - -export type Type2TimelineSlideData = z.infer - -interface Type2TimelineSlideLayoutProps { - data: Partial -} - -const Type2TimelineSlideLayout: React.FC = ({ data: slideData }) => { - const { title, items } = slideData; - - const renderTimelineContent = () => { - return ( -
- {/* Timeline Header with Numbers and Line */} -
- {/* Horizontal Line */} -
- - {/* Timeline Numbers */} - {items && items.map((_, index) => ( -
- {index + 1} -
- ))} -
- - {/* Timeline Content */} -
- {items && items.map((item, index) => ( -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
-
- ) - } - - return ( -
-
- {title &&

- {title} -

} -
- - {renderTimelineContent()} -
- ) -} - -export default Type2TimelineSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type3SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type3SlideLayout.tsx deleted file mode 100644 index af26d279..00000000 --- a/servers/nextjs/presentation-templates/classic/Type3SlideLayout.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { ImageSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'type3-slide' -export const layoutName = 'Type3 Slide' -export const layoutDescription = 'A centered title with a grid of image cards, each containing a heading and description.' - -const type3SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Featured Content').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }), - image: ImageSchema.meta({ - description: "Item image", - }) - })).min(2).max(3).default([ - { - heading: 'First Feature', - description: 'Description for the first featured item with detailed information', - image: { - __image_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', - __image_prompt__: 'A beautiful road in the mountains' - } - }, - { - heading: 'Second Feature', - description: 'Description for the second featured item with relevant details', - image: { - __image_url__: 'https://cdn.pixabay.com/photo/2016/02/19/11/19/office-1209640_1280.jpg', - __image_prompt__: 'Modern office workspace' - } - }, - { - heading: 'Third Feature', - description: 'Description for the third featured item with important points', - image: { - __image_url__: 'https://cdn.pixabay.com/photo/2017/08/10/08/47/laptop-2619235_1280.jpg', - __image_prompt__: 'Laptop with code on screen' - } - } - ]).meta({ - description: "List of featured items (2-4 items)", - }) -}) - -export const Schema = type3SlideSchema - -export type Type3SlideData = z.infer - -interface Type3SlideLayoutProps { - data: Partial -} - -const Type3SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items } = slideData; - - const getGridCols = (length: number) => { - switch (length) { - case 1: return 'lg:grid-cols-1'; - case 2: return 'lg:grid-cols-2'; - case 3: return 'lg:grid-cols-3'; - case 4: return 'lg:grid-cols-4'; - default: return 'lg:grid-cols-1'; - } - } - - return ( -
-
- {title &&

- {title} -

} -
- -
- {items && items.map((item, index) => ( -
- {/* Image */} -
- {item.image?.__image_prompt__ -
- - {/* Content */} -
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
-
- ) -} - -export default Type3SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type4SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type4SlideLayout.tsx deleted file mode 100644 index da9ac603..00000000 --- a/servers/nextjs/presentation-templates/classic/Type4SlideLayout.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import React from 'react' -import { BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Cell } from "recharts"; -import * as z from "zod"; - -export const layoutId = 'type4-slide' -export const layoutName = 'Type4 Slide' -export const layoutDescription = 'A chart-focused layout with title, chart visualization, and description text.' - -const chartDataSchema = z.object({ - name: z.string().meta({ description: "Data point name" }), - value: z.number().meta({ description: "Data point value" }), - category: z.string().optional().meta({ description: "Category for grouping" }), - x: z.number().optional().meta({ description: "X coordinate for scatter plots" }), - y: z.number().optional().meta({ description: "Y coordinate for scatter plots" }), -}); - - -const type4SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Chart Analysis').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(130).default('This chart shows important data trends and insights that help understand the current situation and make informed decisions.').meta({ - description: "Description text for the chart", - }), - chartData: z.any().optional().meta({ - description: "Chart data object", - }), - isFullSizeChart: z.boolean().default(false).meta({ - description: "Whether to display chart in full size mode", - }), - chartType: z.enum(['bar', 'line', 'pie', 'area', 'scatter']).default('bar').meta({ - description: "Type of chart to display", - }), - data: z.array(chartDataSchema).min(2).max(10).default([ - { name: '2021', value: 5 }, - { name: '2022', value: 12 }, - { name: '2023', value: 18 }, - { name: '2024', value: 23 }, - { name: '2025', value: 26 }, - ]).meta({ - description: "Chart data points", - }), - dataKey: z.string().default('value').meta({ - description: "Key field for chart values", - }), - categoryKey: z.string().default('name').meta({ - description: "Key field for chart categories", - }), - color: z.string().default('#3b82f6').meta({ - description: "Primary color for chart elements", - }), - showLegend: z.boolean().default(false).meta({ - description: "Whether to show chart legend", - }), - showTooltip: z.boolean().default(true).meta({ - description: "Whether to show chart tooltip", - }), -}) - - -const chartConfig = { - value: { - label: "Value", - }, - name: { - label: "Name", - }, -}; -const CHART_COLORS = [ - '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6', - '#06b6d4', '#84cc16', '#f97316', '#ec4899', '#6366f1' -]; - -export const Schema = type4SlideSchema - -export type Type4SlideData = z.infer - -interface Type4SlideLayoutProps { - data: Partial -} - -const Type4SlideLayout: React.FC = ({ data: slideData }) => { - - const { title, description, data, dataKey, categoryKey, color, showLegend = false, showTooltip = true, chartType = 'bar' } = slideData; - - const chartData = data || []; - const renderChart = () => { - const commonProps = { - data: chartData, - margin: { top: 10, right: 20, left: 0, bottom: 30 }, - }; - - switch (chartType) { - case 'bar': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'line': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'area': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'pie': - return ( - - {showTooltip && } />} - {showLegend && } />} - `${name} ${(percent * 100).toFixed(0)}%`} - > - {chartData.map((entry, index) => ( - - ))} - - - ); - - case 'scatter': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - default: - return
Unsupported chart type
; - } - }; - - return ( -
- {title &&

- {title} -

} - -
-
-
- - {renderChart()} - -
-
-
- {description &&

- {description} -

} -
-
-
- ) -} - -export default Type4SlideLayout - diff --git a/servers/nextjs/presentation-templates/classic/Type5SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type5SlideLayout.tsx deleted file mode 100644 index 75fc2daa..00000000 --- a/servers/nextjs/presentation-templates/classic/Type5SlideLayout.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React from 'react' -import * as z from "zod"; - -export const layoutId = 'type5-slide' -export const layoutName = 'Type5 Slide' -export const layoutDescription = 'A two-column layout with title and description on the left, and numbered items with large numerals on the right.' - -const type5SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Key Points').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(130).default('Here is the main description that provides context and introduction to the numbered points on the right side.').meta({ - description: "Main description text", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }) - })).min(2).max(3).default([ - { - heading: 'First Key Point', - description: 'Detailed explanation of the first important point that supports the main topic' - }, - { - heading: 'Second Key Point', - description: 'Detailed explanation of the second important point with relevant information' - }, - { - heading: 'Third Key Point', - description: 'Detailed explanation of the third important point that concludes the discussion' - } - ]).meta({ - description: "List of numbered items (2-3 items)", - }) -}) - -export const Schema = type5SlideSchema - -export type Type5SlideData = z.infer - -interface Type5SlideLayoutProps { - data: Partial -} - -const Type5SlideLayout: React.FC = ({ data: slideData }) => { - - const { title, description, items } = slideData; - return ( -
-
- {/* Left section - Title and Description */} -
- {title &&

- {title} -

} - - {description &&

- {description} -

} -
- - {/* Right section - Numbered items */} -
-
- {slideData?.items?.map((item, index) => ( -
-
-
- {`0${index + 1}`} -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
-
- ))} -
-
-
-
- ) -} - -export default Type5SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type6SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type6SlideLayout.tsx deleted file mode 100644 index c35e0042..00000000 --- a/servers/nextjs/presentation-templates/classic/Type6SlideLayout.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { IconSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'type6-slide' -export const layoutName = 'Type6 Slide' -export const layoutDescription = 'A centered title with a flexible grid of icon-based content items, adapting layout based on item count.' - -const type6SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Our Services').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }), - icon: IconSchema, - })).min(2).max(6).default([ - { - heading: 'Professional Service', - description: 'High-quality professional services tailored to your specific needs and requirements', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Professional Service' - } - }, - { - heading: 'Expert Consultation', - description: 'Expert advice and consultation from experienced professionals in the field', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Expert Consultation' - } - }, - { - heading: 'Quality Assurance', - description: 'Comprehensive quality assurance processes to ensure excellent results', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Quality Assurance' - } - }, - { - heading: 'Customer Support', - description: 'Dedicated customer support available to assist you throughout the process', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Customer Support' - } - } - ]).meta({ - description: "List of service items (2-6 items)", - }) -}) - -export const Schema = type6SlideSchema - -export type Type6SlideData = z.infer - -interface Type6SlideLayoutProps { - data: Partial -} - -const Type6SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items } = slideData; - const isGridLayout = items && items.length >= 4 - - const getGridCols = (length: number) => { - switch (length) { - case 1: return 'lg:grid-cols-1'; - case 2: return 'lg:grid-cols-2'; - case 3: return 'lg:grid-cols-3'; - case 4: return 'lg:grid-cols-4'; - case 5: return 'lg:grid-cols-5'; - case 6: return 'lg:grid-cols-6'; - default: return 'lg:grid-cols-1'; - } - } - - const renderGridContent = () => { - return ( -
4 ? 'md:grid-cols-3' : 'md:grid-cols-2'} gap-4 sm:gap-6 lg:gap-8 mt-4 lg:mt-12 w-full`}> - {items && items.map((item, index) => ( -
-
-
-
- {item.icon.__icon_query__} -
-
-
-

- {item.heading} -

-

- {item.description} -

-
-
-
- ))} -
- ) - } - - const renderHorizontalContent = () => { - return ( -
- {items && items.map((item, index) => ( -
-
-
- {item.icon.__icon_query__} -
-
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
- ) - } - - return ( -
-
- {title &&

- {title} -

} -
- - {isGridLayout ? renderGridContent() : renderHorizontalContent()} -
- ) -} - -export default Type6SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type7SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type7SlideLayout.tsx deleted file mode 100644 index 95c87df3..00000000 --- a/servers/nextjs/presentation-templates/classic/Type7SlideLayout.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { IconSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'type7-slide' -export const layoutName = 'Type7 Slide' -export const layoutDescription = 'A centered title with a flexible grid of icon-based content items, adapting layout based on item count.' - -const type7SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Our Services').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }), - icon: IconSchema.default({ - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Default icon' - }).meta({ - description: "Icon for the item", - }) - })).min(2).max(6).default([ - { - heading: 'Professional Service', - description: 'High-quality professional services tailored to your specific needs and requirements', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Professional service icon' - } - }, - { - heading: 'Expert Consultation', - description: 'Expert advice and consultation from experienced professionals in the field', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Expert consultation icon' - } - }, - { - heading: 'Quality Assurance', - description: 'Comprehensive quality assurance processes to ensure excellent results', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Quality assurance icon' - } - }, - { - heading: 'Customer Support', - description: 'Dedicated customer support available to assist you throughout the process', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Customer support icon' - } - } - ]).meta({ - description: "List of service items (2-6 items)", - }) -}) - -export const Schema = type7SlideSchema - -export type Type7SlideData = z.infer - -interface Type7SlideLayoutProps { - data: Partial -} - -const Type7SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items } = slideData; - const isGridLayout = items && items.length >= 4 - - const getGridCols = (length: number) => { - switch (length) { - case 1: return 'lg:grid-cols-1'; - case 2: return 'lg:grid-cols-2'; - case 3: return 'lg:grid-cols-3'; - case 4: return 'lg:grid-cols-4'; - case 5: return 'lg:grid-cols-5'; - case 6: return 'lg:grid-cols-6'; - default: return 'lg:grid-cols-1'; - } - } - - const renderGridContent = () => { - return ( -
4 ? 'md:grid-cols-3' : 'md:grid-cols-2'} gap-4 sm:gap-6 lg:gap-8 mt-4 lg:mt-12 w-full`}> - {items && items.map((item, index) => ( -
-
-
-
- {item.icon?.__icon_query__ -
-
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
-
- ))} -
- ) - } - - const renderHorizontalContent = () => { - return ( -
- {items && items.map((item, index) => ( -
-
-
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__} -
-
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
- ) - } - - return ( -
-
- {title &&

- {title} -

} -
- - {isGridLayout ? renderGridContent() : renderHorizontalContent()} -
- ) -} - -export default Type7SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type8SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type8SlideLayout.tsx deleted file mode 100644 index c6f7453d..00000000 --- a/servers/nextjs/presentation-templates/classic/Type8SlideLayout.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import React from 'react' -import * as z from "zod"; -import { IconSchema } from '@/presentation-templates/defaultSchemes'; - -export const layoutId = 'type8-slide' -export const layoutName = 'Type8 Slide' -export const layoutDescription = 'A two-column layout with title and description on the left, and icon-based items on the right.' - -const type8SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Key Features').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(130).default('Here is the main description that provides context and introduces the key features outlined on the right side.').meta({ - description: "Main description text", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }), - icon: IconSchema.default({ - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Default icon' - }).meta({ - description: "Icon for the item", - }) - })).min(2).max(3).default([ - { - heading: 'Advanced Features', - description: 'Cutting-edge functionality designed to enhance productivity and user experience', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Advanced features icon' - } - }, - { - heading: 'Reliable Performance', - description: 'Consistent and dependable performance across all platforms and devices', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Reliable performance icon' - } - }, - { - heading: 'Secure Environment', - description: 'Enterprise-grade security measures to protect your data and privacy', - icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Secure environment icon' - } - } - ]).meta({ - description: "List of featured items (2-3 items)", - }) -}) - -export const Schema = type8SlideSchema - -export type Type8SlideData = z.infer - -interface Type8SlideLayoutProps { - data: Partial -} - -const Type8SlideLayout: React.FC = ({ data: slideData }) => { - const { title, description, items } = slideData; - - const renderItems = () => { - if (items && items.length === 2) { - // Vertical stacked layout for 2 items - return ( -
- {items && items.map((item, index) => ( -
-
-
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__} -
-
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
- ))} -
- ) - } else { - // Horizontal layout with side icons for 3+ items - return ( -
- {items && items.map((item, index) => ( -
-
-
-
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__} -
-
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
-
- ))} -
- ) - } - } - - return ( -
-
- {/* Left section - Title and Description */} -
- {title &&

- {title} -

} - - {description &&

- {description} -

} -
- - {/* Right section - Items */} -
- {renderItems()} -
-
-
- ) -} - -export default Type8SlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/Type9SlideLayout.tsx b/servers/nextjs/presentation-templates/classic/Type9SlideLayout.tsx deleted file mode 100644 index bdb8e29a..00000000 --- a/servers/nextjs/presentation-templates/classic/Type9SlideLayout.tsx +++ /dev/null @@ -1,253 +0,0 @@ -import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import React from 'react' -import { BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Cell, ResponsiveContainer } from "recharts"; -import * as z from "zod"; - -export const layoutId = 'type4-slide' -export const layoutName = 'Type4 Slide' -export const layoutDescription = 'A chart-focused layout with title, chart visualization, and description text.' - -const chartDataSchema = z.object({ - name: z.string().meta({ description: "Data point name" }), - value: z.number().meta({ description: "Data point value" }), - category: z.string().optional().meta({ description: "Category for grouping" }), - x: z.number().optional().meta({ description: "X coordinate for scatter plots" }), - y: z.number().optional().meta({ description: "Y coordinate for scatter plots" }), -}); - - -const type9SlideSchema = z.object({ - title: z.string().min(3).max(50).default('Chart Analysis').meta({ - description: "Main title of the slide", - }), - items: z.array(z.object({ - heading: z.string().min(2).max(50).meta({ - description: "Item heading", - }), - description: z.string().min(10).max(130).meta({ - description: "Item description", - }) - })).min(2).max(3).default([ - { - heading: 'First Key Point', - description: 'Detailed explanation of the first important point that supports the main topic' - }, - { - heading: 'Second Key Point', - description: 'Detailed explanation of the second important point with relevant information' - }, - { - heading: 'Third Key Point', - description: 'Detailed explanation of the third important point that concludes the discussion' - } - ]).meta({ - description: "List of numbered items (2-3 items)", - }), - chartData: z.any().optional().meta({ - description: "Chart data object", - }), - isFullSizeChart: z.boolean().default(false).meta({ - description: "Whether to display chart in full size mode", - }), - chartType: z.enum(['bar', 'line', 'pie', 'area', 'scatter']).default('pie').meta({ - description: "Type of chart to display", - }), - data: z.array(chartDataSchema).min(2).max(10).default([ - { name: '2021', value: 5 }, - { name: '2022', value: 12 }, - { name: '2023', value: 18 }, - { name: '2024', value: 23 }, - { name: '2025', value: 26 }, - ]).meta({ - description: "Chart data points", - }), - dataKey: z.string().default('value').meta({ - description: "Key field for chart values", - }), - categoryKey: z.string().default('name').meta({ - description: "Key field for chart categories", - }), - color: z.string().default('#3b82f6').meta({ - description: "Primary color for chart elements", - }), - showLegend: z.boolean().default(false).meta({ - description: "Whether to show chart legend", - }), - showTooltip: z.boolean().default(true).meta({ - description: "Whether to show chart tooltip", - }), -}) - - -const chartConfig = { - value: { - label: "Value", - }, - name: { - label: "Name", - }, -}; -const CHART_COLORS = [ - '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6', - '#06b6d4', '#84cc16', '#f97316', '#ec4899', '#6366f1' -]; - -export const Schema = type9SlideSchema - -export type Type9SlideData = z.infer - -interface Type9SlideLayoutProps { - data: Partial -} - -const Type9SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items, data, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; - const chartData = data || []; - const renderChart = () => { - const commonProps = { - data: chartData, - margin: { top: 10, right: 20, left: 0, bottom: 30 }, - }; - - switch (chartType) { - case 'bar': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'line': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'area': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - case 'pie': - return ( - - - {showTooltip && } />} - {showLegend && } />} - `${name} ${(percent * 100).toFixed(0)}%`} - > - {chartData && chartData.map((entry: any, index: number) => ( - - ))} - - - - ); - - case 'scatter': - return ( - - - - - {showTooltip && } />} - {showLegend && } />} - - - ); - - default: - return
Unsupported chart type
; - } - }; - - return ( -
- {title &&

- {title} -

} - -
-
-
- - {renderChart()} - -
-
-
-
- {items && items.map((item, index) => ( -
-
-
- {`0${index + 1}`} -
-
- {item.heading &&

- {item.heading} -

} - {item.description &&

- {item.description} -

} -
-
-
- ))} -
-
-
-
- ) -} - -export default Type9SlideLayout - diff --git a/servers/nextjs/presentation-templates/classic/TypeMermaidSlideLayout.tsx b/servers/nextjs/presentation-templates/classic/TypeMermaidSlideLayout.tsx deleted file mode 100644 index 7f97809a..00000000 --- a/servers/nextjs/presentation-templates/classic/TypeMermaidSlideLayout.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React, { useEffect, useRef } from 'react' -import * as z from "zod"; - -export const layoutId = 'type-mermaid-slide' -export const layoutName = 'Mermaid Chart Slide' -export const layoutDescription = 'A clean layout for displaying Mermaid diagrams with title and optional description.' - -const typeMermaidSlideSchema = z.object({ - title: z.string().min(3).max(50).default('Process Flow').meta({ - description: "Main title of the slide", - }), - description: z.string().min(10).max(200).optional().meta({ - description: "Optional description text to provide context for the diagram", - }), - mermaidCode: z.string().min(10).default(`graph LR - A[Start] --> B{Is it working?} - B -->|Yes| C[Great!] - B -->|No| D[Fix it] - D --> B - C --> E[End]`).meta({ - description: "Mermaid diagram code, and it must be a graph LR", - }), - theme: z.enum(['default', 'dark', 'forest', 'neutral']).default('default').meta({ - description: "Mermaid theme to use", - }) -}) - -export const Schema = typeMermaidSlideSchema - -export type TypeMermaidSlideData = z.infer - -interface TypeMermaidSlideLayoutProps { - data: Partial -} - -const TypeMermaidSlideLayout: React.FC = ({ data: slideData }) => { - const { title, description, mermaidCode, theme } = slideData; - const mermaidRef = useRef(null); - - useEffect(() => { - const loadMermaid = async () => { - try { - // Dynamically import mermaid - const mermaid = (await import('mermaid')).default; - - // Initialize mermaid with the selected theme - mermaid.initialize({ - startOnLoad: true, - theme: theme || 'default', - themeVariables: { - primaryColor: '#3b82f6', - primaryTextColor: '#1f2937', - primaryBorderColor: '#e5e7eb', - lineColor: '#6b7280', - secondaryColor: '#f3f4f6', - tertiaryColor: '#ffffff' - }, - flowchart: { - useMaxWidth: true, - htmlLabels: true, - curve: 'basis' - } - }); - - if (mermaidRef.current && mermaidCode) { - // Clear previous content - mermaidRef.current.innerHTML = ''; - - // Create a unique ID for this diagram - const diagramId = `mermaid-${Date.now()}`; - - // Render the diagram - const { svg } = await mermaid.render(diagramId, mermaidCode); - mermaidRef.current.innerHTML = svg; - } - } catch (error) { - console.error('Error loading or rendering mermaid:', error); - if (mermaidRef.current) { - mermaidRef.current.innerHTML = ` -
-
-

Error rendering diagram

-

Please check your Mermaid syntax

-
-
- `; - } - } - }; - - loadMermaid(); - }, [mermaidCode, theme]); - - return ( -
- {/* Title */} - {title && ( -

- {title} -

- )} - - {/* Description */} - {description && ( -

- {description} -

- )} - - {/* Mermaid Diagram Container */} -
-
-
- - {/* Fallback content if no mermaid code is provided */} - {!mermaidCode && ( -
-
-

No diagram to display

-

Please provide Mermaid diagram code

-
-
- )} -
- ) -} - -export default TypeMermaidSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/classic/settings.json b/servers/nextjs/presentation-templates/classic/settings.json deleted file mode 100644 index af6e3e7d..00000000 --- a/servers/nextjs/presentation-templates/classic/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "description": "Default layout for presentations", - "ordered": false, - "default": false -} \ No newline at end of file From a1b7dfd51b82129d876c26ab02101b997abeede2 Mon Sep 17 00:00:00 2001 From: Suraj Jha Date: Tue, 9 Sep 2025 03:53:31 +0545 Subject: [PATCH 2/5] add: swift template --- .../BulletsWithIconsTitleDescription.tsx | 242 +++++++++++++++ .../swift/IconBulletListDescription.tsx | 200 +++++++++++++ .../swift/ImageListDescription.tsx | 171 +++++++++++ .../swift/IntroSlideLayout.tsx | 177 +++++++++++ .../swift/MetricsNumbers.tsx | 178 +++++++++++ .../swift/SimpleBulletPointsLayout.tsx | 129 ++++++++ .../swift/TableOfContents.tsx | 144 +++++++++ .../swift/TableorChart.tsx | 279 ++++++++++++++++++ .../presentation-templates/swift/Timeline.tsx | 170 +++++++++++ .../swift/settings.json | 6 + 10 files changed, 1696 insertions(+) create mode 100644 servers/nextjs/presentation-templates/swift/BulletsWithIconsTitleDescription.tsx create mode 100644 servers/nextjs/presentation-templates/swift/IconBulletListDescription.tsx create mode 100644 servers/nextjs/presentation-templates/swift/ImageListDescription.tsx create mode 100644 servers/nextjs/presentation-templates/swift/IntroSlideLayout.tsx create mode 100644 servers/nextjs/presentation-templates/swift/MetricsNumbers.tsx create mode 100644 servers/nextjs/presentation-templates/swift/SimpleBulletPointsLayout.tsx create mode 100644 servers/nextjs/presentation-templates/swift/TableOfContents.tsx create mode 100644 servers/nextjs/presentation-templates/swift/TableorChart.tsx create mode 100644 servers/nextjs/presentation-templates/swift/Timeline.tsx create mode 100644 servers/nextjs/presentation-templates/swift/settings.json diff --git a/servers/nextjs/presentation-templates/swift/BulletsWithIconsTitleDescription.tsx b/servers/nextjs/presentation-templates/swift/BulletsWithIconsTitleDescription.tsx new file mode 100644 index 00000000..39c7548f --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/BulletsWithIconsTitleDescription.tsx @@ -0,0 +1,242 @@ +import React from "react" +import * as z from "zod" + +import { IconSchema, ImageSchema } from '@/presentation-templates/defaultSchemes'; +import { RemoteSvgIcon } from "@/app/hooks/useRemoteSvgIcon"; + +const layoutId = "bullet-with-icons-title-description" +const layoutName = "Bullet With Icons Title Description" +const layoutDescription = "Bullet with icons with title and description and title and description for whole" + +const ItemSchema = z + .object({ + icon: IconSchema, + title: z.string().min(3).max(40).default("Lorem ipsum dolor"), + description: z + .string() + .min(0) + .max(160) + .default( + "Short supporting description that fits under the icon title." + ), + }) + .default({ + icon: { + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/graduation-cap-bold.svg", + __icon_query__: "feature icon", + }, + title: "Lorem ipsum dolor", + description: "Short supporting description that fits under the icon title.", + }) + +const Schema = z + .object({ + title: z + .string() + .min(3) + .max(60) + .default("Our Infographic"), + sideHeading: z.string().min(0).max(60).default("Lorem ipsum dolor sit amet,"), + sideParagraph: z + .string() + .min(0) + .max(300) + .default( + "Concise paragraph describing context. Keep it short and readable across one or two lines." + ), + items: z + .array(ItemSchema) + .min(3) + .max(4) + .default([ + { + icon: { + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/graduation-cap-bold.svg", + __icon_query__: "feature icon", + }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the first icon explaining the point.", + }, + { + icon: { + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/user-bold.svg", + __icon_query__: "feature icon", + }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the second icon explaining the point.", + }, + { + icon: { + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/calendar-blank-bold.svg", + __icon_query__: "feature icon", + }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the third icon explaining the point.", + }, + { + icon: { + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/x-bold.svg", + __icon_query__: "feature icon", + }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the fourth icon explaining the point.", + }, + ]), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + title: "Our Infographic", + sideHeading: "Lorem ipsum dolor sit amet,", + sideParagraph: + "Concise paragraph describing context. Keep it short and readable across one or two lines.", + items: [ + { + icon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/graduation-cap-bold.svg", __icon_query__: "feature icon" }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the first icon explaining the point.", + }, + { + icon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/user-bold.svg", __icon_query__: "feature icon" }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the second icon explaining the point.", + }, + { + icon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/calendar-blank-bold.svg", __icon_query__: "feature icon" }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the third icon explaining the point.", + }, + { + icon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/x-bold.svg", __icon_query__: "feature icon" }, + title: "Lorem ipsum dolor", + description: + "Concise supporting text under the fourth icon explaining the point.", + }, + ], + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const InfographicFourIcons: React.FC = ({ data }) => { + const slideData = data || {} + const items = slideData.items || [] + + const renderTitle = (title?: string) => { + if (!title) return null + const parts = title.split("\n") + return ( + <> + {parts.map((p, i) => ( +
{p}
+ ))} + + ) + } + + return ( + <> + + +
+ {/* Header */} +
+
+
+
+ {(slideData as any )?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+
+ + {/* Title + right paragraph */} +
+
+
+ {renderTitle(slideData.title)} +
+
+ {slideData.sideHeading && ( +
+ {slideData.sideHeading} +
+ )} + {slideData.sideParagraph && ( +
+ {slideData.sideParagraph} +
+ )} +
+
+
+ + {/* Icons row */} +
+
+ {items.slice(0, 4).map((item, idx) => ( +
+
+
+ {/* Icon */} + +
+
+
+ {item.title} +
+
+ {item.description} +
+
+ ))} +
+
+ + {/* Footer (standardized like IntroSlideLayout) */} +
+ {slideData.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default InfographicFourIcons + + diff --git a/servers/nextjs/presentation-templates/swift/IconBulletListDescription.tsx b/servers/nextjs/presentation-templates/swift/IconBulletListDescription.tsx new file mode 100644 index 00000000..7a2e393d --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/IconBulletListDescription.tsx @@ -0,0 +1,200 @@ +import React from "react" +import * as z from "zod" +import { RemoteSvgIcon } from "@/app/hooks/useRemoteSvgIcon"; + +const layoutId = "icon-bullet-list-description-slide" +const layoutName = "Icon Bullet List Description" +const layoutDescription = "Bullet list with title, description, and icon" + +const IconSchema = z + .object({ + __icon_url__: z + .string() + .default( + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/file-text-bold.svg" + ), + __icon_query__: z.string().min(0).max(80).default("feature icon"), + }) + .default({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/file-text-bold.svg", + __icon_query__: "feature icon", + }) + +const FeatureSchema = z + .object({ + title: z.string().min(4).max(28).default("Customizable Workflows"), + body: z + .string() + .min(20) + .max(140) + .default("Lorem ipsum dolor sit amet, dolor sit amet."), + icon: IconSchema, + }) + .default({ + title: "Customizable Workflows", + body: "Lorem ipsum dolor sit amet, dolor sit amet.", + icon: IconSchema.parse({}), + }) + +const Schema = z + .object({ + + title: z + .string() + .min(8) + .max(48) + .default("Key Product Features"), + description: z + .string() + .min(30) + .max(200) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor." + ), + features: z + .array(FeatureSchema) + .min(3) + .max(4) + .default([ + FeatureSchema.parse({}), + { + title: "Multi-Device Access", + body: "Lorem ipsum dolor sit amet.", + icon: IconSchema.parse({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/devices-bold.svg", + }), + }, + { + title: "Scalable Architecture", + body: "Lorem ipsum dolor sit amet.", + icon: IconSchema.parse({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/chart-line-up-bold.svg", + }), + }, + { + title: "Detailed Reports", + body: "Lorem ipsum dolor sit amet.", + icon: IconSchema.parse({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/checks-bold.svg", + }), + }, + ]), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + + title: "Key Product Features", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor.", + features: [ + FeatureSchema.parse({}), + { + title: "Multi-Device Access", + body: "Lorem ipsum dolor sit amet.", + icon: IconSchema.parse({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/devices-bold.svg", + }), + }, + { + title: "Scalable Architecture", + body: "Lorem ipsum dolor sit amet.", + icon: IconSchema.parse({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/chart-line-up-bold.svg", + }), + }, + { + title: "Detailed Reports", + body: "Lorem ipsum dolor sit amet.", + icon: IconSchema.parse({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/checks-bold.svg", + }), + }, + ], + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const FeatureCards: React.FC = ({ data: slideData }) => { + const features = slideData?.features || [] + return ( + <> + + +
+ {/* Header */} +
+
+
+ {(slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+ + {/* Decorative right image area removed to keep imagery-driven design */} + +
+

{slideData?.title}

+

{slideData?.description}

+
+ + {/* Cyan band */} +
+ + {/* Feature cards */} +
+
+ {features.slice(0,4).map((f, i) => ( +
+
+
+ +
+
{f.title}
+

{f.body}

+
+
+ ))} +
+
+ + {/* Footer (standardized like IntroSlideLayout) */} +
+ {slideData?.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default FeatureCards + + diff --git a/servers/nextjs/presentation-templates/swift/ImageListDescription.tsx b/servers/nextjs/presentation-templates/swift/ImageListDescription.tsx new file mode 100644 index 00000000..1ef23463 --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/ImageListDescription.tsx @@ -0,0 +1,171 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "image-list-description-slide" +const layoutName = "Image List Description" +const layoutDescription = "List of Images with subtitle and description with one description for the entire page" + +const ImageSchema = z + .object({ + __image_url__: z + .string() + .url() + .default( + "https://images.unsplash.com/photo-1522199710521-72d69614c702?w=1200&q=80&auto=format&fit=crop" + ), + __image_prompt__: z + .string() + .min(0) + .max(120) + .default("abstract gradient background"), + }) + .default({ + __image_url__: + "https://images.unsplash.com/photo-1522199710521-72d69614c702?w=1200&q=80&auto=format&fit=crop", + __image_prompt__: "abstract gradient background", + }) + +const ItemSchema = z + .object({ + title: z.string().min(2).max(40).default("Sample Title"), + description: z + .string() + .min(10) + .max(140) + .default("Short description for the image or item."), + image: ImageSchema, + }) + .default({ + title: "Sample Title", + description: "Short description for the image or item.", + image: ImageSchema.parse({}), + }) + +const Schema = z + .object({ + titleLine1: z.string().min(3).max(24).default("Meet Our"), + titleLine2: z.string().min(3).max(24).default("Team"), + description: z + .string() + .min(20) + .max(200) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + ), + items: z + .array(ItemSchema) + .min(3) + .max(6) + .default([ + ItemSchema.parse({}), + ItemSchema.parse({ title: "Another Item", description: "Concise supporting text.", image: ImageSchema.parse({}) }), + ItemSchema.parse({ title: "Third Item", description: "Concise supporting text.", image: ImageSchema.parse({}) }), + ]), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + + titleLine1: "Meet Our", + titleLine2: "Team", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + items: [ + ItemSchema.parse({}), + ItemSchema.parse({ title: "Another Item", description: "Concise supporting text.", image: ImageSchema.parse({}) }), + ItemSchema.parse({ title: "Third Item", description: "Concise supporting text.", image: ImageSchema.parse({}) }), + ], + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const TeamMembers: React.FC = ({ data: slideData }) => { + const items = slideData?.items || [] + return ( + <> + + +
+ {/* Header: diamond + business name */} +
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__} + } +
+
+ +
+ {/* Left text stack */} +
+
+ {slideData?.titleLine1} +
+ {slideData?.titleLine2} +
+

+ {slideData?.description} +

+
+ + {/* Right generic image cards */} +
+ {items.slice(0, 3).map((it, i) => ( +
+ {/* Photo block uses provided image */} +
+ {it.image.__image_prompt__} +
+ {/* Cyan details panel */} +
+
{it.title}
+

{it.description}

+
+
+ ))} +
+
+ + {/* Footer line with website and end diamond */} +
+ {slideData?.website} +
+
+ + {/* Big bottom-right diamond */} +
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default TeamMembers + + diff --git a/servers/nextjs/presentation-templates/swift/IntroSlideLayout.tsx b/servers/nextjs/presentation-templates/swift/IntroSlideLayout.tsx new file mode 100644 index 00000000..cd7b587b --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/IntroSlideLayout.tsx @@ -0,0 +1,177 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "IntroSlideLayout" +const layoutName = "Intro Slide Layout" +const layoutDescription = "Intro slide with header, title, subtitle, body, image. If used for last slide, then intro card should be disabled." + +const ImageSchema = z + .object({ + __image_url__: z.string().url().default("https://images.unsplash.com/photo-1522199710521-72d69614c702?w=1200&q=80&auto=format&fit=crop"), + __image_prompt__: z.string().min(0).max(120).default("abstract gradient background"), + }) + .default({ + __image_url__: + "https://images.unsplash.com/photo-1522199710521-72d69614c702?w=1200&q=80&auto=format&fit=crop", + __image_prompt__: "abstract gradient background", + }) + +const Schema = z + .object({ + + title: z + .string() + .min(12) + .max(68) + .default("Pitch Deck") + .meta({ description: "Main slide title" }), + + subtitlePrefix: z.string().min(3).max(40).default("Presentation"), + subtitleAccent: z.string().min(3).max(40).default("Template"), + + paragraph: z + .string() + .min(40) + .max(200) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + ), + + website: z + .string() + .min(6) + .max(60) + .default("www.yourwebsite.com"), + + introCard: z + .object({ + enabled: z.boolean().default(false), + name: z.string().min(3).max(40).default("John Doe"), + date: z.string().min(4).max(40).default("Jan 1, 2025"), + }) + .default({ enabled: true, name: "John Doe", date: "Jan 1, 2025" }), + + media: z + .object({ + type: z.literal("image").default("image"), + image: ImageSchema, + }) + .default({ type: "image", image: ImageSchema.parse({}) }), + }) + .default({ + title: "Pitch Deck", + subtitlePrefix: "Presentation", + subtitleAccent: "Template", + paragraph: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + website: "www.yourwebsite.com", + introCard: { enabled: true, name: "John Doe", date: "Jan 1, 2025" }, + media: { type: "image", image: ImageSchema.parse({}) }, + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const IntroSlideLayout: React.FC = ({ data: slideData }) => { + return ( + <> + + +
+ {/* Header: diamond + business name */} +
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__} + } +
+
+ + {/* Right panel image (replaces dark gradient box) */} +
+ {slideData?.media?.image?.__image_prompt__} +
+ + {/* Vertical diamond decorations */} +
+
+
+
+
+ +
+
+

+ {slideData?.title} +

+

{slideData?.paragraph}

+ + {slideData?.introCard?.enabled && ( +
+
+
+ + {slideData?.introCard?.name} + + + {slideData?.introCard?.date} + +
+
+ )} +
+
+
+ + {/* Footer line with website and end diamond */} +
+ {slideData?.website} +
+
+ + {/* Big bottom-right diamond */} +
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default IntroSlideLayout + + diff --git a/servers/nextjs/presentation-templates/swift/MetricsNumbers.tsx b/servers/nextjs/presentation-templates/swift/MetricsNumbers.tsx new file mode 100644 index 00000000..433bb6fc --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/MetricsNumbers.tsx @@ -0,0 +1,178 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "MetricsNumbers" +const layoutName = "Metrics Numbers" +const layoutDescription = "Swift: Our Impact in Numbers with three stacked metric cards" + +const MetricSchema = z + .object({ + value: z.string().min(1).max(8).default("10K+"), + line1: z.string().min(2).max(22).default("Total"), + line2: z.string().min(0).max(22).default("Users"), + description: z + .string() + .min(10) + .max(140) + .default("active users across multiple industries"), + }) + .default({ + value: "10K+", + line1: "Total", + line2: "Users", + description: "active users across multiple industries", + }) + +const Schema = z + .object({ + title: z + .string() + .min(8) + .max(60) + .default("Our Impact in Numbers"), + leftTitle: z + .string() + .min(6) + .max(40) + .default("Proven Results\nThrough Data"), + leftBody: z + .string() + .min(30) + .max(220) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + ), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + metrics: z + .array(MetricSchema) + .min(1) + .max(4) + .default([ + MetricSchema.parse({ + value: "10K+", + line1: "Total", + line2: "Users", + description: "active users across multiple industries", + }), + MetricSchema.parse({ + value: "150%", + line1: "Revenue", + line2: "Growth", + description: "year-over-year revenue growth", + }), + MetricSchema.parse({ + value: "95%", + line1: "Customer", + line2: "Satisfaction", + description: "retention rate with an average rating of 4.8/5", + }), + ]), + }) + .default({ + title: "Our Impact in Numbers", + leftTitle: "Proven Results\nThrough Data", + leftBody: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + website: "www.yourwebsite.com", + metrics: [ + MetricSchema.parse({ + value: "10K+", + line1: "Total", + line2: "Users", + description: "active users across multiple industries", + }), + MetricSchema.parse({ + value: "150%", + line1: "Revenue", + line2: "Growth", + description: "year-over-year revenue growth", + }), + MetricSchema.parse({ + value: "95%", + line1: "Customer", + line2: "Satisfaction", + description: "retention rate with an average rating of 4.8/5", + }), + ], + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const MetricsNumbers: React.FC = ({ data: slideData }) => { + const metrics = slideData?.metrics || [] + return ( + <> + + +
+ {/* Header */} +
+
+
+ { (slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+ + {/* Separator line like the reference */} +
+ +
+ {/* Left content */} +
+

{slideData?.title}

+
+
+
+
{slideData?.leftTitle}
+
+
+

{slideData?.leftBody}

+
+ + {/* Right stacked metric cards */} +
+ {/* decorative circle on the right */} +
+ +
+ {metrics.slice(0,3).map((m, i) => ( +
+
{m.value}
+
+
{m.line1}
+ {m.line2 &&
{m.line2}
} +

{m.description}

+
+
+ ))} +
+
+
+ + {/* Footer (standardized like IntroSlideLayout) */} +
+ {slideData?.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default MetricsNumbers + + diff --git a/servers/nextjs/presentation-templates/swift/SimpleBulletPointsLayout.tsx b/servers/nextjs/presentation-templates/swift/SimpleBulletPointsLayout.tsx new file mode 100644 index 00000000..bee2833c --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/SimpleBulletPointsLayout.tsx @@ -0,0 +1,129 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "simple-bullet-points-layout" +const layoutName = "Simple Bullet Points" +const layoutDescription = "Bullet Points with title and description" + +const PointSchema = z + .object({ + title: z.string().min(6).max(60).default("Your Title Here"), + body: z + .string() + .min(30) + .max(220) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." + ), + }) + .default({ title: "Your Title Here", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." }) + +const Schema = z + .object({ + title: z.string().min(4).max(36).default("Our Commitment"), + statement: z + .string() + .min(20) + .max(260) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + ), + points: z + .array(PointSchema) + .min(1) + .max(4) + .default([PointSchema.parse({}), PointSchema.parse({}), PointSchema.parse({}), PointSchema.parse({ title: "Your Title Here", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." })]), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + title: "Our Commitment to Innovation", + statement: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + points: [ + { title: "Your Title Here", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." }, + { title: "Your Title Here", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." }, + { title: "Your Title Here", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." }, + { title: "Your Title Here", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." }, + + ], + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const CommitmentTwoPoints: React.FC = ({ data: slideData }) => { + const points = slideData?.points || [] + return ( + <> + + +
+ {/* Header */} +
+
+
+ { (slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+ + {/* Subtle background motif */} +
+ + {/* Content grid */} +
+ {/* Left heading and statement */} +
+
+ {slideData?.title} +
+ +

+ {slideData?.statement} +

+
+ + {/* Right numbered points (up to 4) */} +
+ {points.slice(0, 4).map((p, i) => ( +
+
{p.title}
+

{p.body}

+
+ ))} +
+
+ + {/* Footer (align with other Swift layouts) */} +
+ {slideData?.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default CommitmentTwoPoints + + diff --git a/servers/nextjs/presentation-templates/swift/TableOfContents.tsx b/servers/nextjs/presentation-templates/swift/TableOfContents.tsx new file mode 100644 index 00000000..85094861 --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/TableOfContents.tsx @@ -0,0 +1,144 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "SwiftTableOfContents" +const layoutName = "Table Of Contents" +const layoutDescription = "Swift: Table of contents with up to 10 items (title + description)" + +const ToCItemSchema = z + .object({ + title: z.string().min(3).max(40).default("Introduction"), + description: z + .string() + .min(0) + .max(60) + .default("A brief overview of the section."), + }) + .default({ title: "Introduction", description: "A brief overview of the section." }) + +const Schema = z + .object({ + title: z + .string() + .min(3) + .max(60) + .default("Table of Contents"), + items: z + .array(ToCItemSchema) + .min(1) + .max(10) + .default([ + { title: "Introduction", description: "A brief description of our company and goals." }, + { title: "Our Team", description: "Leadership and core contributors." }, + { title: "Timeline", description: "High-level execution plan and milestones." }, + { title: "Recommendations", description: "Key suggestions based on initial requirements." }, + { title: "Solution", description: "What we propose and why it works." }, + { title: "Market", description: "Audience, segments, and opportunity size." }, + { title: "Business Model", description: "How we create and capture value." }, + { title: "Conclusion", description: "Closing notes and next steps." }, + { title: "Business Model", description: "How we create and capture value." }, + { title: "Conclusion", description: "Closing notes and next steps." }, + ]), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + title: "Table of Contents", + items: [ + { title: "Introduction", description: "A brief description of our company and goals." }, + { title: "Our Team", description: "Leadership and core contributors." }, + { title: "Timeline", description: "High-level execution plan and milestones." }, + { title: "Recommendations", description: "Key suggestions based on initial requirements." }, + { title: "Solution", description: "What we propose and why it works." }, + { title: "Market", description: "Audience, segments, and opportunity size." }, + { title: "Business Model", description: "How we create and capture value." }, + { title: "Conclusion", description: "Closing notes and next steps." }, + { title: "Business Model", description: "How we create and capture value." }, + { title: "Conclusion", description: "Closing notes and next steps." }, + + ], + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const TableOfContents: React.FC = ({ data: slideData }) => { + const items = slideData?.items || [] + return ( + <> + + +
+ {/* Header */} +
+
+
+ { (slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+ +
+

{slideData?.title}

+
+ + {/* List */} +
+
+ {items.slice(0, 10).map((item, idx) => ( +
+
+
+
+ {String(idx + 1).padStart(2, "0")} +
+
+
+
+ {item.title} +
+ {item.description && ( +
+ {item.description} +
+ )} +
+
+
+
+ ))} +
+
+ + {/* Footer (standardized like IntroSlideLayout) */} +
+ {slideData?.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default TableOfContents + + diff --git a/servers/nextjs/presentation-templates/swift/TableorChart.tsx b/servers/nextjs/presentation-templates/swift/TableorChart.tsx new file mode 100644 index 00000000..da36a7a7 --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/TableorChart.tsx @@ -0,0 +1,279 @@ +import React from "react" +import * as z from "zod" +import { + ResponsiveContainer, + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + LineChart, + Line, + PieChart, + Pie, + Cell, +} from "recharts" + +const layoutId = "tableorChart" +const layoutName = "Table Or Chart" +const layoutDescription = "Swift: Generic data table with option to render a chart (bar, horizontalBar, line, pie)" + +const ChartDatumSchema = z.object({ + label: z.string().min(1).max(12).default("A"), + value: z.number().min(0).max(1000000).default(60), +}) + +const TableRowSchema = z.object({ + cells: z + .array(z.string().min(0).max(200)) + .min(2) + .max(10) + .default(["Row 1", "Value", "Value"]) + .meta({ description: "Row cells; count should match columns length" }), +}) + +const Schema = z + .object({ + title: z.string().min(6).max(60).default("Data Table or Chart"), + description: z + .string() + .min(20) + .max(220) + .default( + "Present structured information in a flexible table or visualize it with a chart." + ), + + mode: z.enum(["table", "chart"]).default("table"), + + // Table configuration (generic) + columns: z + .array(z.string().min(1).max(40)) + .min(2) + .max(10) + .default(["Column 1", "Column 2", "Column 3"]), + rows: z + .array(TableRowSchema) + .min(1) + .max(30) + .default([ + { cells: ["Row A", "✓", "-"] }, + { cells: ["Row B", "Text", "123"] }, + { cells: ["Row C", "More text", "456"] }, + ]), + + // Chart configuration (parity with @standard ChartLeftTextRightLayout) + chart: z + .object({ + type: z.enum(["bar", "horizontalBar", "line", "pie"]).default("line"), + data: z.array(ChartDatumSchema).min(3).max(12).default([ + { label: "A", value: 60 }, + { label: "B", value: 42 }, + { label: "C", value: 75 }, + { label: "D", value: 30 }, + ]), + primaryColor: z.string().default("var(--text-heading-color, #111827)"), + gridColor: z.string().default("var(--primary-accent-color, #BFF4FF)"), + pieColors: z + .array(z.string()) + .min(1) + .max(10) + .default(["var(--text-heading-color, #111827)", "#3b82f6", "#f59e0b", "#10b981", "#ef4444"]), + showLabels: z.boolean().default(true), + }) + .default({ + type: "line", + data: [ + { label: "A", value: 60 }, + { label: "B", value: 42 }, + { label: "C", value: 75 }, + { label: "D", value: 30 }, + ], + primaryColor: "#1B8C2D", + gridColor: "#E5E7EB", + pieColors: ["#1B8C2D", "#3b82f6", "#f59e0b", "#10b981", "#ef4444"], + showLabels: true, + }), + + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + title: "Data Table or Chart", + description: + "Present structured information in a flexible table or visualize it with a chart.", + mode: "table", + columns: ["Column 1", "Column 2", "Column 3"], + rows: [ + { cells: ["Row A", "✓", "-"] }, + { cells: ["Row B", "Text", "123"] }, + { cells: ["Row C", "More text", "456"] }, + ], + chart: { + type: "line", + data: [ + { label: "A", value: 60 }, + { label: "B", value: 42 }, + { label: "C", value: 75 }, + { label: "D", value: 30 }, + ], + primaryColor: "#1B8C2D", + gridColor: "#E5E7EB", + pieColors: ["#1B8C2D", "#3b82f6", "#f59e0b", "#10b981", "#ef4444"], + showLabels: true, + }, + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const TableOrChart: React.FC = ({ data: slideData }) => { + const mode = slideData?.mode || "table" + const columns = slideData?.columns || [] + const rows = slideData?.rows || [] + + const cData = slideData?.chart?.data || [] + const type = slideData?.chart?.type || "bar" + const primaryColor = slideData?.chart?.primaryColor || "var(--text-heading-color, #111827)" + const gridColor = slideData?.chart?.gridColor || "var(--primary-accent-color, #BFF4FF)" + const pieColors = slideData?.chart?.pieColors || ["var(--text-heading-color, #111827)"] + const showLabels = slideData?.chart?.showLabels !== false + + return ( + <> + + +
+ {/* Header */} +
+
+
+ {(slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+ + {/* Title and description */} +
+

{slideData?.title}

+

{slideData?.description}

+
+ + {/* Content area: Table or Chart */} +
+ {mode === "table" ? ( +
+
+ + + + {columns.map((col, idx) => ( + + ))} + + + + {rows.map((row, rIdx) => ( + + {columns.map((_, cIdx) => ( + + ))} + + ))} + +
+ {col} +
+ {row.cells[cIdx] || ''} +
+
+
+ ) : ( +
+ + {type === 'bar' ? ( + + + + + + + + + ) : type === 'horizontalBar' ? ( + + + + + + + + + ) : type === 'line' ? ( + + + + + + + + + ) : ( + + + + + {cData.map((_, i) => ( + + ))} + + + )} + +
+ )} +
+ + {/* Footer (standardized like IntroSlideLayout) */} +
+ {slideData?.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default TableOrChart + + diff --git a/servers/nextjs/presentation-templates/swift/Timeline.tsx b/servers/nextjs/presentation-templates/swift/Timeline.tsx new file mode 100644 index 00000000..2fdf9516 --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/Timeline.tsx @@ -0,0 +1,170 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "Timeline" +const layoutName = "Timeline" +const layoutDescription = "Timeline of cards with title, subtitle banner" + +const IconSchema = z + .object({ + __icon_url__: z + .string() + .default( + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/clipboard-text-bold.svg" + ), + __icon_query__: z.string().min(0).max(80).default("timeline icon"), + }) + .default({ + __icon_url__: + "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/clipboard-text-bold.svg", + __icon_query__: "timeline icon", + }) + +const ItemSchema = z + .object({ + year: z.string().min(3).max(6).default("2018"), + heading: z.string().min(3).max(28).default("Founded in 2020"), + body: z + .string() + .min(10) + .max(160) + .default("Lorem ipsum dolor"), + icon: IconSchema, + }) + .default({ year: "2018", heading: "Founded in 2020", body: "Lorem ipsum dolor", icon: IconSchema.parse({}) }) + +const Schema = z + .object({ + title: z + .string() + .min(8) + .max(60) + .default("Our Journey at a Glance"), + subtitle: z + .string() + .min(20) + .max(200) + .default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa." + ), + items: z + .array(ItemSchema) + .min(1) + .max(4) + .default([ + ItemSchema.parse({ year: "2018", heading: "Founded in 2020", body: "Lorem ipsum dolor" }), + ItemSchema.parse({ year: "2019", heading: "First Product in 2021", body: "Lorem ipsum dolor" }), + ItemSchema.parse({ year: "2020", heading: "Key Milestone in 2022", body: "Lorem ipsum dolor" }), + ItemSchema.parse({ year: "2021", heading: "Global Expansion in 2024", body: "Lorem ipsum dolor" }), + ]), + website: z.string().min(6).max(60).default("www.yourwebsite.com"), + }) + .default({ + title: "Our Journey at a Glance", + subtitle: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.", + items: [ + ItemSchema.parse({ year: "2018", heading: "Founded in 2020", body: "Lorem ipsum dolor" }), + ItemSchema.parse({ year: "2019", heading: "First Product in 2021", body: "Lorem ipsum dolor" }), + ItemSchema.parse({ year: "2020", heading: "Key Milestone in 2022", body: "Lorem ipsum dolor" }), + ItemSchema.parse({ year: "2021", heading: "Global Expansion in 2024", body: "Lorem ipsum dolor" }), + ], + website: "www.yourwebsite.com", + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const Timeline: React.FC = ({ data: slideData }) => { + const items = slideData?.items || [] + return ( + <> + + +
+ {/* Keep white background to match Swift layouts */} + + {/* Header: diamond + business name */} +
+
+
+ {(slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__}} +
+
+ + {/* Right vertical diamonds */} +
+
+
+
+
+ + {/* Title */} +
+

{slideData?.title}

+ {/* Subtitle banner */} +
+ {slideData?.subtitle} +
+
+ + {/* Horizontal timeline */} +
+ {/* center line */} +
+ +
+ {items.slice(0, 4).map((it, idx) => ( +
+ {/* year badge - placed close to the card */} +
{it.year}
+ + {/* connector dot */} +
+ + {/* card container */} +
+
+
+ {it.icon.__icon_query__} +
+
{it.heading}
+

{it.body}

+
+
+
+ ))} +
+
+ + {/* Footer (standardized like IntroSlideLayout) */} +
+ {slideData?.website} +
+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default Timeline + + diff --git a/servers/nextjs/presentation-templates/swift/settings.json b/servers/nextjs/presentation-templates/swift/settings.json new file mode 100644 index 00000000..e1a89369 --- /dev/null +++ b/servers/nextjs/presentation-templates/swift/settings.json @@ -0,0 +1,6 @@ +{ + "description": "Swift layouts for presentations", + "ordered": false, + "default": false +} + From d6adc556027f98abf399fb50d1507f62c953ae9f Mon Sep 17 00:00:00 2001 From: Suraj Jha Date: Tue, 9 Sep 2025 03:54:26 +0545 Subject: [PATCH 3/5] add: standard template --- .../standard/ChartLeftTextRightLayout.tsx | 177 +++++++++++++++ .../standard/ContactLayout.tsx | 204 ++++++++++++++++++ .../HeadingBulletImageDescriptionLayout.tsx | 137 ++++++++++++ .../standard/IconBulletDescriptionLayout.tsx | 170 +++++++++++++++ .../standard/IconImageDescriptionLayout.tsx | 183 ++++++++++++++++ .../ImageListWithDescriptionLayout.tsx | 148 +++++++++++++ .../standard/IntroSlideLayout.tsx | 160 ++++++++++++++ .../standard/MetricsDescriptionLayout.tsx | 179 +++++++++++++++ .../NumberedBulletSingleImageLayout.tsx | 176 +++++++++++++++ .../standard/TableOfContentsLayout.tsx | 180 ++++++++++++++++ .../standard/VisualMetricsSlideLayout.tsx | 191 ++++++++++++++++ .../standard/settings.json | 5 + 12 files changed, 1910 insertions(+) create mode 100644 servers/nextjs/presentation-templates/standard/ChartLeftTextRightLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/ContactLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/HeadingBulletImageDescriptionLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/IconBulletDescriptionLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/IconImageDescriptionLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/ImageListWithDescriptionLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/IntroSlideLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/MetricsDescriptionLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/NumberedBulletSingleImageLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/TableOfContentsLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/VisualMetricsSlideLayout.tsx create mode 100644 servers/nextjs/presentation-templates/standard/settings.json diff --git a/servers/nextjs/presentation-templates/standard/ChartLeftTextRightLayout.tsx b/servers/nextjs/presentation-templates/standard/ChartLeftTextRightLayout.tsx new file mode 100644 index 00000000..abed05a3 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/ChartLeftTextRightLayout.tsx @@ -0,0 +1,177 @@ +import React from 'react' +import * as z from 'zod' +import { + ResponsiveContainer, + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + LineChart, + Line, + PieChart, + Pie, + Cell, +} from 'recharts' + +const layoutId = 'chart-left-text-right-layout' +const layoutName = 'Chart Left Text Right' +const layoutDescription = 'A slide with header label, a left-side inline bar chart, and right-side title with paragraph.' + +const ChartDatumSchema = z.object({ + label: z.string().min(1).max(12).default('A').meta({ description: 'Category label' }), + value: z.number().min(0).max(100).default(60).meta({ description: 'Value 0–100' }), +}) + +const Schema = z.object({ + + title: z + .string() + .min(16) + .max(64) + .default('Insights At A Glance') + .meta({ description: 'Main heading (max ~7 words)' }), + paragraph: z + .string() + .min(50) + .max(200) + .default( + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' + ) + .meta({ description: 'Supporting description' }), + chart: z + .object({ + type: z.enum(['bar', 'horizontalBar', 'line', 'pie']).default('line'), + data: z.array(ChartDatumSchema).min(3).max(8).default([ + { label: 'A', value: 60 }, + { label: 'B', value: 42 }, + { label: 'C', value: 75 }, + { label: 'D', value: 30 }, + ]), + primaryColor: z.string().default('#1B8C2D'), + gridColor: z.string().default('#E5E7EB'), + pieColors: z.array(z.string()).min(1).max(10).default(['#1B8C2D', '#3b82f6', '#f59e0b', '#10b981', '#ef4444']), + showLabels: z.boolean().default(true), + }) + .default({ + type: 'line', + data: [ + { label: 'A', value: 60 }, + { label: 'B', value: 42 }, + { label: 'C', value: 75 }, + { label: 'D', value: 30 }, + ], + primaryColor: '#1B8C2D', + gridColor: '#E5E7EB', + pieColors: ['#1B8C2D', '#3b82f6', '#f59e0b', '#10b981', '#ef4444'], + showLabels: true, + }), +}) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const data = slideData?.chart?.data || [] + const type = slideData?.chart?.type || 'bar' + const primaryColor = slideData?.chart?.primaryColor || '#1B8C2D' + const gridColor = slideData?.chart?.gridColor || '#E5E7EB' + const pieColors = slideData?.chart?.pieColors || ['#1B8C2D'] + const showLabels = slideData?.chart?.showLabels !== false + + return ( + <> + +
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__ || 'Pitchdeck'} + } + + + +
+ {/* page number intentionally omitted */} +
+ +
+ {/* Left: Recharts visualization */} +
+
+
+ + {type === 'bar' ? ( + + + + + + + + + ) : type === 'horizontalBar' ? ( + + + + + + + + + ) : type === 'line' ? ( + + + + + + + + + ) : ( + + + + + {data.map((_, i) => ( + + ))} + + + )} + +
+
+
+ + {/* Right: Text */} +
+

+ {slideData?.title || 'Insights At A Glance'} +

+

+ {slideData?.paragraph || + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'} +

+
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default dynamicSlideLayout + + diff --git a/servers/nextjs/presentation-templates/standard/ContactLayout.tsx b/servers/nextjs/presentation-templates/standard/ContactLayout.tsx new file mode 100644 index 00000000..da1975c9 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/ContactLayout.tsx @@ -0,0 +1,204 @@ +import React from 'react' +import * as z from "zod"; + + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(120).default("Muted cover background image with subtle subject suitable for contact slide").meta({ + description: "Prompt used to generate the image. Max 24 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().default("data:svg+xml,placeholder").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(3).max(24).default("photo placeholder").meta({ + description: "Query used to search the icon. Max 5 words", + }), + }) + + const layoutId = "header-left-media-contact-info-slide" + const layoutName = "ContactLayout" + const layoutDescription = "A slide with a top bar, left media with overlay and bottom bar, and right content with header and text blocks. This should only be used for contact information." + + const Schema = z.object({ + metaMaxWords: z.number().default(24).meta({ + description: "Maximum number of words in any single text field", + }), + + topBar: z.object({ + + pageNumber: z.string().min(1).max(3).default("9").meta({ + description: "Top-right number text. Max 1 word", + }), + }).default({ + + pageNumber: "9", + }), + + leftPanel: z.object({ + backgroundImage: ImageSchema.default({ + __image_url__: "https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg", + __image_prompt__: "Muted cover background image with subtle subject suitable for contact slide", + }), + centerIcon: IconSchema.default({ + __icon_url__: "data:svg+xml,placeholder", + __icon_query__: "photo placeholder", + }), + websiteBar: z.object({ + websiteText: z.string().min(12).max(30).default("www.yourwebsite.com").meta({ + description: "Website text in bottom green bar. Max 4 words", + }), + actionIcon: IconSchema.default({ + __icon_url__: "data:svg+xml,plus-arrow", + __icon_query__: "plus arrow", + }), + }).default({ + websiteText: "www.yourwebsite.com", + actionIcon: { + __icon_url__: "data:svg+xml,plus-arrow", + __icon_query__: "plus arrow", + }, + }), + }).default({ + backgroundImage: { + __image_url__: "https://images.pexels.com/photos/326576/pexels-photo-326576.jpeg", + __image_prompt__: "Muted cover background image with subtle subject suitable for contact slide", + }, + centerIcon: { + __icon_url__: "data:svg+xml,placeholder", + __icon_query__: "photo placeholder", + }, + websiteBar: { + websiteText: "www.yourwebsite.com", + actionIcon: { + __icon_url__: "data:svg+xml,plus-arrow", + __icon_query__: "plus arrow", + }, + }, + }), + + rightContent: z.object({ + title: z.string().min(18).max(40).default("Let’s Get in\nTouch with Us").meta({ + description: "Main heading. Max 6 words", + }), + sections: z.array(z.object({ + label: z.string().min(4).max(10).default("Label").meta({ + description: "Section label text. Max 2 words", + }), + value: z.string().min(8).max(50).default("Value text").meta({ + description: "Section value text. Max 100 characters", + }), + showDivider: z.boolean().default(true).meta({ + description: "Whether to show bottom divider", + }), + })).min(1).max(3).default([ + { + label: "Address", + value: "Boston, Downtown Main Street 233, New York, US", + showDivider: true, + }, + { + label: "Phone", + value: "+1234 2345 1234", + showDivider: true, + }, + { + label: "E-mail:", + value: "mail@company.com", + showDivider: false, + }, + ]).meta({ + description: "List of content sections", + }), + }).default({ + title: "Let’s Get in\nTouch with Us", + sections: [ + { + label: "Address", + value: "Boston, Downtown Main Street 233, New York, US", + showDivider: true, + }, + { + label: "Phone", + value: "+1234 2345 1234", + showDivider: true, + }, + { + label: "E-mail:", + value: "mail@company.com", + showDivider: false, + }, + ], + }), + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const sections = slideData?.rightContent?.sections || [] + + return ( + <> + +
+
+
+ {(slideData as any)?.__companyName__ &&
+ {(slideData as any)?.__companyName__ || "Pitchdeck"} +
} +
+
+ {/* page number removed */} +
+ +
+
+
+ {slideData?.leftPanel?.backgroundImage?.__image_prompt__ +
+ +
+

+ {slideData?.rightContent?.title || "Let’s Get in\nTouch with Us"} +

+ +
+ {sections.map((sec, idx) => ( +
+
+ {sec.label} +
+
+ {sec.value} +
+ {sec.showDivider ?
: null} +
+ ))} +
+ +
+
+
+
+
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/HeadingBulletImageDescriptionLayout.tsx b/servers/nextjs/presentation-templates/standard/HeadingBulletImageDescriptionLayout.tsx new file mode 100644 index 00000000..0d862297 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/HeadingBulletImageDescriptionLayout.tsx @@ -0,0 +1,137 @@ +import React from 'react' +// charts removed +import * as z from "zod"; + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(150).default("Small decorative photo partially behind the card showing a business theme").meta({ + description: "Prompt used to generate the image. Max 30 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().default("").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(3).max(30).default("").meta({ + description: "Query used to search the icon. Max 5 words", + }), + }) + + const layoutId = "split-left-strip-header-title-subtitle-cards-slide" + const layoutName = "Heading Bullet Image Description" + const layoutDescription = "A slide with a left strip, top label with rule, right header, right description, floating small image, and a centered card with ...cards." + + const Schema = z.object({ + metaMaxWords: z.number().default(200).meta({ + description: "Maximum number of words the text areas can handle collectively.", + }), + pageNumber: z.string().min(1).max(3).default("7").meta({ + description: "Top-right page number text. Max 3 chars", + }), + + heading: z.string().min(16).max(38).default("A Blueprint for\nSuccess").meta({ + description: "Main heading across up to 2 lines. Max 7 words", + }), + subheading: z.string().min(60).max(200).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna").meta({ + description: "Supporting paragraph under the heading. Max 35 words", + }), + smallImage: ImageSchema.default({ + __image_url__: "https://images.pexels.com/photos/327533/pexels-photo-327533.jpeg", + __image_prompt__: "A small landscape image suitable for a business slide" + }).meta({ + description: "Small image partially behind the main card", + }), + cards: z.array(z.object({ + title: z.string().min(8).max(16).default("Strategy 01").meta({ + description: "Card ribbon title. Max 3 words", + }), + body: z.string().min(60).max(160).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor").meta({ + description: "Card body text. Max 28 words", + }), + })).min(1).max(4).default([ + { title: "Strategy 01", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" }, + { title: "Strategy 02", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" }, + { title: "Strategy 03", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" }, + { title: "Strategy 04", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" }, + ]).meta({ + description: "Array of strategy cards", + }), + + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const cards = slideData?.cards || [] + + return ( + <> + +
+ {/* page number removed */} + +
+
+ {slideData?.smallImage?.__image_url__ ? ( + <> + {slideData.smallImage.__image_prompt__ + {/* overlay removed */} + + ) : null} +
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__ || "Pitchdeck"} + } +
+
+
+
+
+ +
+

+ {slideData?.heading || "A Blueprint for\nSuccess"} +

+ +
+
+
+
+
+
+ {cards.map((card, idx) => ( +
+
+ {card.title} +
+

+ {card.body} +

+
+ ))} +
+
+
+
+
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/IconBulletDescriptionLayout.tsx b/servers/nextjs/presentation-templates/standard/IconBulletDescriptionLayout.tsx new file mode 100644 index 00000000..99516cea --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/IconBulletDescriptionLayout.tsx @@ -0,0 +1,170 @@ +import { RemoteSvgIcon } from '@/app/hooks/useRemoteSvgIcon'; +import React from 'react' +// charts removed +import * as z from "zod"; + + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(180).default("Decorative abstract office scene photo placed at lower right on the band").meta({ + description: "Prompt used to generate the image. Max 30 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/fediverse-logo-bold.svg").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(2).max(20).default("info icon").meta({ + description: "Query used to search the icon. Max 3 words", + }), + }) + + const layoutId = "header-bullets-title-description-image-slide" + const layoutName = "Icon Bullet Description" + const layoutDescription = "A slide with a small header label and number, a left card of ...cards with round symbols and titles with descriptions, a large heading with supporting text, and a decorative image on a mid-page band" + + const Schema = z.object({ + metaMaxWords: z.number().default(240).meta({ + description: "Maximum number of words any single text field can handle in this layout", + }), + + + headerNumber: z.string().min(1).max(3).default("6").meta({ + description: "Small header number text. Max 3 characters", + }), + rightTitle: z.string().min(24).max(72).default("Disrupting the\nIndustry").meta({ + description: "Large heading on the right. Max 8 words", + }), + rightDescription: z.string().min(120).max(240).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna").meta({ + description: "Supporting paragraph under the large heading. Max 40 words", + }), + // decorative image removed + cards: z.array(z.object({ + symbolText: z.string().min(1).max(1).default("i").meta({ + description: "Single-character symbol inside the round badge", + }), + symbolIcon: IconSchema.default({ + __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/fediverse-logo-bold.png", + __icon_query__: "info icon", + }).meta({ + description: "Optional icon representation for the round symbol", + }), + title: z.string().min(16).max(38).default("Visionary Leadership").meta({ + description: "Title for the card item. Max 4 words", + }), + description: z.string().min(50).max(100).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor").meta({ + description: "Description for the card item. Max 15 words.", + }), + })).min(1).max(4).default([ + { + symbolText: "i", + symbolIcon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/fediverse-logo-bold.svg", __icon_query__: "info icon" }, + title: "Visionary Leadership", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", + }, + { + symbolText: "i", + symbolIcon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/video-bold.png", __icon_query__: "info icon" }, + title: "Innovation at the Core", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", + }, + { + symbolText: "i", + symbolIcon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/receipt-x-bold.png", __icon_query__: "info icon" }, + title: "Customer-Centric Disruption", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", + }, + { + symbolText: "i", + symbolIcon: { __icon_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/users-four-bold.png", __icon_query__: "info icon" }, + title: "Customer-Centric Disruption", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", + } + ]).meta({ + description: "Array of ...cards with a round symbol, title and description. Max 6 items", + }), + // chart and diagram removed + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const cards = slideData?.cards || [] + // charts removed + + return ( + <> + +
+ +
+
+ { (slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__ || "Pitchdeck"}} + +
+ {/* page number removed */} +
+ +
+
+
+
    + {cards.map((item, idx) => ( +
  • +
    + {item.symbolIcon?.__icon_url__ ? ( + + ) : ( + {item.symbolText} + )} +
    +
    +

    {item.title}

    +

    {item.description}

    +
    +
  • + ))} +
+
+
+ +
+

") }}>

+
+

+ {slideData?.rightDescription || "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna"} +

+
+ + {/* charts removed */} + + {/* flowchart removed */} +
+
+ + {/* decorative image removed */} +
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/IconImageDescriptionLayout.tsx b/servers/nextjs/presentation-templates/standard/IconImageDescriptionLayout.tsx new file mode 100644 index 00000000..6d267f2e --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/IconImageDescriptionLayout.tsx @@ -0,0 +1,183 @@ +import { RemoteSvgIcon } from '@/app/hooks/useRemoteSvgIcon'; +import React from 'react' +// Charts removed +import * as z from "zod"; + + + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://via.placeholder.com/900x500").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(200).default("Wide landscape placeholder representing a slide image area").meta({ + description: "Prompt used to generate the image. Max 30 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().default("https://via.placeholder.com/60").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(3).max(30).default("camera landscape placeholder").meta({ + description: "Query used to search the icon. Max 3 words", + }), + }) + + const layoutId = "header-title-card-slide" + const layoutName = "Icon Image Description" + const layoutDescription = "A slide with a top bar, centered title, placeholder icon area, and a colored card with circular icon, heading, and paragraph" + + const Schema = z.object({ + meta: z.object({ + maxWords: z.number().default(56), + }).default({ maxWords: 56 }), + topBar: z.object({ + + pageNumber: z.string().min(1).max(3).default("3").meta({ + description: "Page number text. Max 1 word", + }), + }).default({ + + pageNumber: "3", + }), + title: z.string().min(24).max(56).default("Transforming Ideas into\nReality").meta({ + description: "Main title split across up to two lines. Max 10 words", + }), + backgroundImage: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1650831432942-aa352df4e9b4?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + __image_prompt__: "Background image covering the entire section behind the card", + }).meta({ + description: "Full-bleed background image behind card area", + }), + card: z.object({ + circleIcon: IconSchema.default({ + __icon_url__: "data:image/svg+xml;utf8,", + __icon_query__: "badge document icon", + }), + heading: z.string().min(22).max(70).default("Idea Generation and Validation").meta({ + description: "Card heading text. Max 10 words", + }), + body: z.string().min(140).max(450).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.").meta({ + description: "Card body paragraph. Max 80 words", + }), + image: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/1200x600", + __image_prompt__: "Optional supporting image inside card area", + }).meta({ + description: "Optional supporting image for the card. Max 30 words", + }), + }).default({ + circleIcon: { + __icon_url__: "data:image/svg+xml;utf8,", + __icon_query__: "badge document icon", + }, + heading: "Idea Generation and Validation", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", + image: { + __image_url__: "https://via.placeholder.com/1200x600", + __image_prompt__: "Optional supporting image inside card area", + }, + }), + // charts removed + // diagram removed + }).default({ + meta: { maxWords: 56 }, + topBar: { pageNumber: "3" }, + title: "Transforming Ideas into\nReality", + backgroundImage: { + __image_url__: "https://images.unsplash.com/photo-1650831432942-aa352df4e9b4?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + __image_prompt__: "Background image covering the entire section behind the card", + }, + card: { + circleIcon: { + __icon_url__: "data:image/svg+xml;utf8,", + __icon_query__: "badge document icon", + }, + heading: "Idea Generation and Validation", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", + image: { __image_url__: "https://via.placeholder.com/1200x600", __image_prompt__: "Optional supporting image inside card area" }, + }, + // charts removed + // diagram removed + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + + return ( + <> + +
+
+
+ { (slideData as any)?.__companyName__ &&
{(slideData as any)?.__companyName__ || "Pitchdeck"}
} +
+
+ {/* page number removed */} +
+ +
+

+ {(slideData?.title || "").split("\n").map((line, idx) => ( + + {line} + {idx === 0 ?
: null} +
+ ))} +

+
+ +
+ {slideData?.backgroundImage?.__image_prompt__ +
+
+
+
+
+ {slideData?.card?.circleIcon?.__icon_url__ ? ( + + ) : null} +
+
+ +
+
+ {slideData?.card?.heading} +
+

+ {slideData?.card?.body} +

+ + {/* Chart section removed */} + + {/* Diagram removed */} + +
+
+
+
+
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/ImageListWithDescriptionLayout.tsx b/servers/nextjs/presentation-templates/standard/ImageListWithDescriptionLayout.tsx new file mode 100644 index 00000000..a1a62518 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/ImageListWithDescriptionLayout.tsx @@ -0,0 +1,148 @@ +import React from 'react' +import * as z from "zod"; + + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(160).default("Portrait of a professional team member with subtle background, soft light, business attire").meta({ + description: "Prompt used to generate the image. Max 30 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().url().default("https://static.thenounproject.com/png/1137401-200.png").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(3).max(30).default("photo image placeholder").meta({ + description: "Query used to search the icon. Max 5 words", + }), + }) + + const layoutId = "header-smallbar-title-team-cards-slide" + const layoutName = "Image List With Description" + const layoutDescription = "A slide with a top utility bar, centered title, and a grid of cards with names, roles, and background images." + + const Schema = z.object({ + utilityBar: z.object({ + + pageNumber: z.string().min(1).max(2).default("8").meta({ + description: "Page number text. 1-2 digits", + }), + decorativeLine: IconSchema.default({ + __icon_url__: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='2'%3E%3Crect width='220' height='2' fill='%231FA34A'/%3E%3C/svg%3E", + __icon_query__: "green line separator", + }).meta({ + description: "Decorative line representation.", + }), + }).default({ + + pageNumber: "8", + decorativeLine: { + __icon_url__: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='2'%3E%3Crect width='220' height='2' fill='%231FA34A'/%3E%3C/svg%3E", + __icon_query__: "green line separator", + }, + }), + title: z.string().min(10).max(50).default("Our Professional Team").meta({ + description: "Centered main title. Max 5 words", + }), + cards: z.array(z.object({ + name: z.string().min(3).max(30).default("Sam Rawlings").meta({ + description: "Member name. Up to 3 words.", + }), + role: z.string().min(20).max(50).default("Marketing specialist with brand and growth experience").meta({ + description: "Short description under name. Up to 10 words", + }), + photo: ImageSchema, + })).min(1).max(4).default([ + { + name: "Sam Rawlings", + role: "Marketing specialist with brand and growth experience", + photo: { + __image_url__: "https://images.pexels.com/photos/1181695/pexels-photo-1181695.jpeg", + __image_prompt__: "Portrait of a professional team member with subtle background, soft light, business attire", + }, + }, + { + name: "Sam Rawlings", + role: "Marketing specialist with brand and growth experience", + photo: { + __image_url__: "https://images.pexels.com/photos/450214/pexels-photo-450214.jpeg", + __image_prompt__: "Portrait of a professional team member with subtle background, soft light, business attire", + }, + }, + { + name: "Sam Rawlings", + role: "Marketing specialist with brand and growth experience", + photo: { + __image_url__: "https://images.pexels.com/photos/756484/pexels-photo-756484.jpeg", + __image_prompt__: "Portrait of a professional team member with subtle background, soft light, business attire", + }, + }, + + ]).meta({ + description: "Grid of member cards with name, role, and image. Up to 4 items", + }), + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const cards = slideData?.cards || [] + + return ( + <> + +
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__ || "Pitchdeck"} + } + + + +
+ {/* page number removed */} +
+ +

+ {slideData?.title || "Our Professional Team"} +

+ +
+
+
+ {cards.map((card, idx) => ( +
+
+
+ {card.name} +
+
+ {card.role} +
+
+
+ {card.photo.__image_prompt__} +
+
+ ))} +
+
+
+
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/IntroSlideLayout.tsx b/servers/nextjs/presentation-templates/standard/IntroSlideLayout.tsx new file mode 100644 index 00000000..3073ef93 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/IntroSlideLayout.tsx @@ -0,0 +1,160 @@ +import React from 'react' +import * as z from "zod"; + +const ImageSchema = z.object({ +__image_url__: z.string().url().default("https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg").meta({ + description: "URL to image", +}), +__image_prompt__: z.string().min(10).max(150).default("High-quality illustrative image for the left panel of a pitch deck cover").meta({ + description: "Prompt used to generate the image. Max 30 words", +}), +}) + +const IconSchema = z.object({ +__icon_url__: z.string().default("https://static.thenounproject.com/png/5563447-200.png").meta({ + description: "URL to icon", +}), +__icon_query__: z.string().min(3).max(40).default("image placeholder icon").meta({ + description: "Query used to search the icon. Max 3 words", +}), +}) + +const layoutId = "header-counter-two-column-image-text-slide" +const layoutName = "Intro Slide" +const layoutDescription = "A slide with a header row containing label, separator, and counter, followed by a two-column layout with a media area and stacked text blocks. If used as the endig slide then it shoudn't have the intro card." + +const Schema = z.object({ +header: z.object({ + + separatorIcon: IconSchema.default({ + __icon_url__: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='230' height='2' viewBox='0 0 230 2'%3E%3Crect width='230' height='2' fill='%2322863A'/%3E%3C/svg%3E", + __icon_query__: "green line", + }).meta({ + description: "Graphic separator element", + }), + counter: z.string().min(1).max(3).default("1").meta({ + description: "Small counter text. Max 1 word", + }), +}).default({ + + separatorIcon: { + __icon_url__: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='230' height='2' viewBox='0 0 230 2'%3E%3Crect width='230' height='2' fill='%2322863A'/%3E%3C/svg%3E", + __icon_query__: "green line", + }, + counter: "1", +}), + +media: z.object({ + type: z.enum(["image"]).default("image").meta({ + description: "Choose media type for left panel", + }), + image: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1557426272-fc759fdf7a8d?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + __image_prompt__: "Abstract gradient image suitable for a presentation left panel", + }), +}).default({ + type: "image", + image: { + __image_url__: "https://images.unsplash.com/photo-1557426272-fc759fdf7a8d?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + __image_prompt__: "Abstract gradient image suitable for a presentation left panel", + }, +}), + +title: z.string().min(12).max(30).default("Introduction Our Pitchdeck").meta({ + description: "Main title, supports a line break. Max 6 words", +}), +titleBreakAfter: z.number().min(1).max(25).default(12).meta({ + description: "Character index to insert a line break in title", +}), + +paragraph: z.string().min(50).max(200).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris").meta({ + description: "Paragraph text block. Max 20 words", +}), + +introCard: z.object({ + enabled: z.boolean().default(false).meta({ description: "Show intro card with name and date" }), + initials: z.string().min(2).max(3).default("PDT").meta({ description: "Initials inside the circle" }), + name: z.string().min(3).max(40).default("Pitch Deck Team").meta({ description: "Display name" }), + date: z.string().min(6).max(40).default("December 22, 2025").meta({ description: "Display date string" }), +}).default({ + enabled: true, + initials: "PDT", + name: "Pitch Deck Team", + date: "December 22, 2025", +}), +}).meta({ +maxWords: 460, +}) + +type SlideData = z.infer + +interface LayoutProps { +data?: Partial +} + +const dynamicSlideLayout: React.FC = ({ data: slideData }) => { +const title = slideData?.title || "Introduction Our Pitchdeck" +const brIndex = typeof slideData?.titleBreakAfter === "number" ? slideData?.titleBreakAfter as number : 12 +const titleFirst = title.slice(0, brIndex) +const titleSecond = title.slice(brIndex) +return ( + <> + +
+
+
+ { (slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__ || "Pitchdeck"}} + + + +
+ {/* page number removed */} +
+ +
+
+ {slideData?.media?.type === "image" ? ( + {slideData?.media?.image?.__image_prompt__ + ) : null } +
+ +
+
+

+ {titleFirst} +
+ {titleSecond} +

+ +

+ {slideData?.paragraph || "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"} +

+ + {slideData?.introCard?.enabled ? ( +
+
+ {slideData?.introCard?.initials} +
+
+
{slideData?.introCard?.name}
+
{slideData?.introCard?.date}
+
+
+ ) : null} +
+
+
+
+ +) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/MetricsDescriptionLayout.tsx b/servers/nextjs/presentation-templates/standard/MetricsDescriptionLayout.tsx new file mode 100644 index 00000000..37761f89 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/MetricsDescriptionLayout.tsx @@ -0,0 +1,179 @@ +import React from 'react' +// charts removed +import * as z from "zod"; + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://images.unsplash.com/photo-1503264116251-35a269479413?q=80&w=1200&auto=format&fit=crop").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(200).default("Elegant abstract green themed background for a presentation slide, minimal shapes, soft lighting").meta({ + description: "Prompt used to generate the image. Max 40 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().default("https://static.thenounproject.com/png/1783767-200.png").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(3).max(40).default("leaf growth").meta({ + description: "Query used to search the icon. Max 6 words", + }), + }) + + const layoutId = "header-tagline-cards-grid-slide" + const layoutName = "Metrics Description" + const layoutDescription = "A slide with a top utility row, a header, a tagline, and a grid of cards each with a number block and text" + + const CardSchema = z.object({ + number: z.string().min(1).max(5).default("45").meta({ + description: "Main number text inside number block. 1 to 3 digits", + }), + numberSymbol: z.string().min(0).max(3).default("%").meta({ + description: "Optional symbol next to the number. Single character", + }), + subtitle: z.string().min(8).max(28).default("Subtitle Here").meta({ + description: "Card subtitle. Max 5 words", + }), + body: z.string().min(20).max(100).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do.").meta({ + description: "Card body text. Max 100 characters", + }), + icon: IconSchema.default({ + __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", + __icon_query__: "progress indicator", + }).meta({ + description: "Optional icon for the card header area", + }), + }) + + const Schema = z.object({ + + title: z.string().min(12).max(70).default("Scaling New Heights Together").meta({ + description: "Main title. Single line up to ~34 chars or two lines up to ~70 chars. Max 9 words", + }), + tagline: z.string().min(40).max(120).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna").meta({ + description: "Subtitle/tagline under title. Max 20 words", + }), + decorativeLine: ImageSchema.default({ + __image_url__: "data:image/svg+xml;utf8,", + __image_prompt__: "Thin green horizontal line divider, 220x2, rounded ends", + }).meta({ + description: "SVG decorative line asset", + }), + cards: z.array(CardSchema).min(1).max(6).default([ + { + number: "87", + numberSymbol: "%", + subtitle: "Customer Satisfaction", + body: "Our customers consistently rate their experience with our products and services as excellent.", + icon: { __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", __icon_query__: "happy customer icon" }, + }, + { + number: "2.5", + numberSymbol: "M", + subtitle: "Active Users Monthly", + body: "Growing user base actively engaging with our platform across multiple regions worldwide.", + icon: { __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", __icon_query__: "users group icon" }, + }, + { + number: "99", + numberSymbol: "%", + subtitle: "System Uptime", + body: "Maintaining exceptional reliability with industry-leading system availability and performance.", + icon: { __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", __icon_query__: "server uptime icon" }, + }, + { + number: "142", + numberSymbol: "+", + subtitle: "Global Partners", + body: "Strategic partnerships driving innovation and market expansion across key industry sectors.", + icon: { __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", __icon_query__: "handshake deal icon" }, + }, + { + number: "32", + numberSymbol: "x", + subtitle: "Revenue Growth", + body: "Year-over-year growth demonstrating strong market position and business model scalability.", + icon: { __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", __icon_query__: "growth chart icon" }, + }, + { + number: "500", + numberSymbol: "K", + subtitle: "Carbon Offset", + body: "Committed to sustainability through significant carbon reduction and environmental initiatives.", + icon: { __icon_url__: "https://static.thenounproject.com/png/1783767-200.png", __icon_query__: "leaf sustainability icon" }, + }, + ]).meta({ + description: "Grid of cards with number block, subtitle, and body (<=100 chars)", + }), + // chart and diagram removed + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const cards = slideData?.cards || [] + + return ( + <> + +
+
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__ || "Pitchdeck"} + } +
+
+ {/* page number removed */} +
+ +

+ {slideData?.title || "Scaling New Heights Together"} +

+ +

+ {slideData?.tagline || "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna"} +

+ +
+ {cards.map((card, idx) => ( +
+
+
+ + {card.number} + + + {card.numberSymbol} + +
+
+

+ {card.subtitle} +

+

+ {card.body} +

+
+
+
+ ))} +
+ + {/* chart and flowchart removed */} +
+
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/NumberedBulletSingleImageLayout.tsx b/servers/nextjs/presentation-templates/standard/NumberedBulletSingleImageLayout.tsx new file mode 100644 index 00000000..d1c2166f --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/NumberedBulletSingleImageLayout.tsx @@ -0,0 +1,176 @@ +import React from 'react' +// charts removed +import * as z from "zod"; + +const ImageSchema = z.object({ + __image_url__: z.string().url().default("https://images.pexels.com/photos/31527637/pexels-photo-31527637.jpeg").meta({ + description: "URL to image", + }), + __image_prompt__: z.string().min(10).max(90).default("Professional business meeting scene for roadmap presentation image").meta({ + description: "Prompt used to generate the image. Max 18 words", + }), + }) + + const IconSchema = z.object({ + __icon_url__: z.string().default("").meta({ + description: "URL to icon", + }), + __icon_query__: z.string().min(3).max(30).default("").meta({ + description: "Query used to search the icon. Max 6 words", + }), + }) + + const layoutId = "header-bullets-image-split-slide" + const layoutName = "Numbered Bullet Single Image" + const layoutDescription = "A slide with a top bar, left column with numbered bullets, middle image panel, and right stacked heading with paragraph" + + const Schema = z.object({ + metaMaxWords: z.number().default(18).meta({ + description: "Maximum number of words allowed in any prompt/description metadata fields.", + }), + topBar: z.object({ + + lineIcon: IconSchema.default({ + __icon_url__: "", + __icon_query__: "thin green line", + }).meta({ + description: "Decorative line representation with query only", + }), + }).default({ + + lineIcon: { + __icon_url__: "", + __icon_query__: "thin green line", + }, + }), + leftBullets: z.array( + z.object({ + numberText: z.string().min(2).max(2).default("01").meta({ + description: "Two-digit bullet number. Max 2 chars", + }), + title: z.string().min(10).max(36).default("Strategic Execution").meta({ + description: "Bullet title text. Designed for 24px. Max ~36 chars", + }), + body: z.string().min(60).max(100).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.").meta({ + description: "Bullet body text. Max ~100 chars", + }), + }) + ).min(1).max(4).default([ + { + numberText: "01", + title: "Strategic Execution", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.", + }, + { + numberText: "02", + title: "Building a Strong Team", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.", + }, + { + numberText: "03", + title: "Market Expansion Strategy", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.", + }, + { + numberText: "04", + title: "Innovation Pipeline", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.", + } + ]).meta({ + description: "List of numbered bullets. Max 5 items", + }), + middleImage: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1515623959088-7617915baa1e?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + __image_prompt__: "Professional business meeting scene for roadmap presentation image", + }).meta({ + description: "Image displayed in the middle column", + }), + rightHeader: z.object({ + heading: z.string().min(6).max(30).default("Our Journey").meta({ + description: "Right column heading. Max ~30 chars", + }), + paragraph: z.string().min(80).max(200).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.").meta({ + description: "Right paragraph text. Max 200 chars", + }), + }).default({ + heading: "Our Journey", + paragraph: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.", + }), + }) + + type SlideData = z.infer + + interface SlideLayoutProps { + data?: Partial + } + + const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const bullets = slideData?.leftBullets || [] + + return ( + <> + +
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__ || "Pitchdeck"} + } + + + +
+ {/* page number removed */} +
+ +
+
+
    + {bullets.map((b, i) => ( +
  • +
    +

    + {b.title} +

    +

    + {b.body} +

    +
    +
    + {b.numberText} +
    +
  • + ))} +
+
+ +
+ {slideData?.middleImage?.__image_prompt__ + {/* overlay removed */} +
+ +
+
+

+ {slideData?.rightHeader?.heading || "Our Journey"} +

+

+ {slideData?.rightHeader?.paragraph || "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore."} +

+
+
+
+
+ + ) + } + + export { Schema, layoutId, layoutName, layoutDescription } + export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/TableOfContentsLayout.tsx b/servers/nextjs/presentation-templates/standard/TableOfContentsLayout.tsx new file mode 100644 index 00000000..6b6e286d --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/TableOfContentsLayout.tsx @@ -0,0 +1,180 @@ +import React from "react" +import * as z from "zod" + +const layoutId = "table-of-contents-layout" +const layoutName = "Table Of Contents" +const layoutDescription = "Header with brand marker, title, optional description, and a two-column table of contents list" + +const ToCItemSchema = z + .object({ + title: z.string().min(4).max(50).default("Introduction").meta({ + description: "Section title. Max 50 characters", + }), + }) + .default({ + title: "Introduction", + }) + +const Schema = z + .object({ + topBar: z + .object({ + + marker: z.string().min(1).max(3).default("2").meta({ + description: "Numeric marker on the top bar. Up to 3 digits", + }), + }) + .default({ marker: "2" }), + + title: z + .string() + .min(12) + .max(68) + .default("Table Of Contents") + .meta({ description: "Main slide title. Max 10 words" }), + + description: z + .string() + .min(0) + .max(200) + .default( + "Use this as a quick guide to navigate the presentation sections." + ) + .meta({ description: "Lead paragraph. Optional. Max 35 words" }), + + items: z + .array(ToCItemSchema) + .min(3) + .max(10) + .default([ + { title: "Introduction" }, + { title: "Problem Statement" }, + { title: "Solution" }, + { title: "Market" }, + { title: "Business Model" }, + { title: "Roadmap" }, + { title: "Team" }, + { title: "Go-To-Market" }, + { title: "Financials" }, + { title: "Ask" }, + ]) + .meta({ description: "List of contents (3-10)" }), + }) + .default({ + topBar: { marker: "2" }, + title: "Table Of Contents", + description: + "Use this as a quick guide to navigate the presentation sections.", + items: [ + { title: "Introduction" }, + { title: "Problem Statement" }, + { title: "Solution" }, + { title: "Market" }, + { title: "Business Model" }, + { title: "Roadmap" }, + { title: "Team" }, + { title: "Go-To-Market" }, + { title: "Financials" }, + { title: "Ask" }, + ], + }) + +type SlideData = z.infer + +interface SlideLayoutProps { + data?: Partial +} + +const dynamicSlideLayout: React.FC = ({ data: slideData }) => { + const items = slideData?.items || [] + + return ( + <> + + +
+
+
+
+ { (slideData as any)?.__companyName__ && + {(slideData as any)?.__companyName__ || "Pitchdeck"} + } +
+
+ {/* page number intentionally omitted */} +
+
+ +
+

+ {slideData?.title} +

+ {slideData?.description && ( +

+ {slideData?.description} +

+ )} +
+ +
+
+ {items.map((item, idx) => ( +
+
+ {idx + 1} +
+
+
+ {item.title} +
+
+
+ ))} +
+
+
+ + ) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default dynamicSlideLayout + + diff --git a/servers/nextjs/presentation-templates/standard/VisualMetricsSlideLayout.tsx b/servers/nextjs/presentation-templates/standard/VisualMetricsSlideLayout.tsx new file mode 100644 index 00000000..e168da71 --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/VisualMetricsSlideLayout.tsx @@ -0,0 +1,191 @@ +import React from 'react' +// charts trimmed to donut only (inline SVG) +import * as z from "zod"; + + +const ImageSchema = z.object({ +__image_url__: z.string().url().default("https://images.unsplash.com/photo-1522199755839-a2bacb67c546?q=80&w=1200&auto=format&fit=crop").meta({ + description: "URL to image", +}), +__image_prompt__: z.string().min(10).max(150).default("Abstract light background for slide header area").meta({ + description: "Prompt used to generate the image. Max 30 words", +}), +}) + +const IconSchema = z.object({ +__icon_url__: z.string().url().default("https://cdn.jsdelivr.net/gh/tabler/tabler-icons/icons/placeholder.svg").meta({ + description: "URL to icon", +}), +__icon_query__: z.string().min(3).max(30).default("progress ring placeholder").meta({ + description: "Query used to search the icon. Max 3 words", +}), +}) + +const layoutId = "visual-metrics" +const layoutName = "Visual Metrics" +const layoutDescription = "A slide with a header bar, numeric marker, title, description, and grid of cards with headings, circular metrics, and texts" + +const CardSchema = z.object({ +title: z.string().min(6).max(18).default("Research").meta({ + description: "Card heading. Max 3 words", +}), +value: z.number().min(0).max(9999).default(67).meta({ + description: "Numeric value to display", +}), +unit: z.string().min(0).max(2).default("K").meta({ + description: "Unit for the value, e.g., %, K, M", +}), +description: z.string().min(1).max(50).default("Lorem ipsum dolor sit amet, consectetur").meta({ + description: "Card supporting text. Max 50 characters", +}), +}).default({ +title: "Research", +value: 67, +unit: "K", +description: "Lorem ipsum dolor sit amet, consectetur", +}) + +const Schema = z.object({ +topBar: z.object({ + + marker: z.string().min(1).max(3).default("2").meta({ + description: "Numeric marker on the top bar. Up to 3 digits", + }), +}).default({ + + marker: "2", +}), +title: z.string().min(20).max(68).default("Our Vision And Strategy For Excellence").meta({ + description: "Main slide title. Max 10 words", +}), +description: z.string().min(70).max(200).default("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation").meta({ + description: "Lead paragraph. Max 35 words", +}), +cards: z.array(CardSchema).min(1).max(4).default([ + { + title: "Research", + value: 6700, + unit: "K", + description: "Lorem ipsum dolor sit amet, consectetur", + + }, + { + title: "Development", + value: 80, + unit: "K", + description: "Lorem ipsum dolor sit amet, consectetur", + + }, + { + title: "Research", + value: 67, + unit: "%", + description: "Lorem ipsum dolor sit amet, consectetur", + + }, + { title: "Development", value: 80, unit: "K", description: "Lorem ipsum dolor sit amet, consectetur" }, +]).meta({ + description: "Grid of cards with heading, circular metric, and text", +}), +chartPalette: z.array(z.string().min(4).max(20)).min(2).max(6).default(["var(--primary-accent-color, #1B8C2D)", "var(--tertiary-accent-color, #E5E7EB)", "#f59e0b", "#3b82f6"]).meta({ + description: "Palette for charts", +}), +}).default({ +topBar: { marker: "2" }, +title: "Our Vision And Strategy For Excellence", +description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation", +cards: [ + { title: "Research", value: 67, unit: "K", description: "Lorem ipsum dolor sit amet, consectetur" }, + { title: "Ops", value: 42, unit: "M", description: "Lorem ipsum dolor sit amet, consectetur" }, + { title: "Efficiency", value: 67, unit: "%", description: "Lorem ipsum dolor sit amet, consectetur" }, + { title: "Development", value: 80, unit: "K", description: "Lorem ipsum dolor sit amet, consectetur" }, +], +chartPalette: ["var(--primary-accent-color, #1B8C2D)", "var(--tertiary-accent-color, #E5E7EB)", "#f59e0b", "#3b82f6"], +}) + +type SlideData = z.infer + +interface SlideLayoutProps { +data?: Partial +} + +// removed external chart components; using inline SVG ring only + +const dynamicSlideLayout: React.FC = ({ data: slideData }) => { +const cards = slideData?.cards || [] +return ( + <> + +
+
+
+
+ { (slideData as any)?.__companyName__ && {(slideData as any)?.__companyName__ || "Pitchdeck"}} +
+
+ {/* page number removed */} +
+
+ +
+

+ {slideData?.title} +

+

+ {slideData?.description} +

+
+ +
+
+ {cards.map((card, idx) => { + const radius = 80 + const circumference = 2 * Math.PI * radius + const dasharray = circumference + return ( +
+
+

{card.title}

+
+ {/* donut ring retained */} + + + + + +
+ {card.value}{card.unit} +
+
+

+ {card.description} +

+
+
+ ) + })} +
+
+ + {/* mermaid removed */} +
+ +) +} + +export { Schema, layoutId, layoutName, layoutDescription } +export default dynamicSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-templates/standard/settings.json b/servers/nextjs/presentation-templates/standard/settings.json new file mode 100644 index 00000000..847af67b --- /dev/null +++ b/servers/nextjs/presentation-templates/standard/settings.json @@ -0,0 +1,5 @@ +{ + "description": "Standard layouts for presentations", + "ordered": false, + "default": false +} \ No newline at end of file From 2e015451e1a9eb4a3da5f1032b2b8b8de67c10f0 Mon Sep 17 00:00:00 2001 From: Suraj Jha Date: Tue, 9 Sep 2025 03:55:36 +0545 Subject: [PATCH 4/5] update: professional template --- .../professional/AboutUsSlide.tsx | 168 -------- .../professional/BusinessModelSlide.tsx | 212 ---------- .../professional/MarketSizeSlide.tsx | 174 --------- .../professional/OurServiceSlide.tsx | 147 ------- .../professional/ProblemsSlide.tsx | 172 --------- .../professional/SolutionsSlide.tsx | 208 ---------- .../professional/StatisticCircularSlide.tsx | 268 ------------- .../professional/StatisticDualChartSlide.tsx | 361 ------------------ .../professional/StatisticSlide.tsx | 301 --------------- .../professional/TableOfContentsSlide.tsx | 197 ---------- .../professional/TestimonialSlide.tsx | 221 ----------- .../professional/ThankYouSlide.tsx | 229 ----------- .../professional/TitleSlide.tsx | 217 ----------- .../professional/WhatWeBelieveSlide.tsx | 179 --------- .../professional/settings.json | 5 - 15 files changed, 3059 deletions(-) delete mode 100644 servers/nextjs/presentation-templates/professional/AboutUsSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/BusinessModelSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/MarketSizeSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/OurServiceSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/ProblemsSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/SolutionsSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/StatisticCircularSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/StatisticDualChartSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/StatisticSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/TableOfContentsSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/TestimonialSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/ThankYouSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/TitleSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/WhatWeBelieveSlide.tsx delete mode 100644 servers/nextjs/presentation-templates/professional/settings.json diff --git a/servers/nextjs/presentation-templates/professional/AboutUsSlide.tsx b/servers/nextjs/presentation-templates/professional/AboutUsSlide.tsx deleted file mode 100644 index 9688c8d2..00000000 --- a/servers/nextjs/presentation-templates/professional/AboutUsSlide.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "About Us Slide"; -export const layoutId = "about-us-slide"; -export const layoutDescription = - "A slide with an introduction to the organization"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(25).default("ABOUT US").meta({ - description: - "Main section heading - can be used for any organizational introduction", - }), - - sectionSubtitle: z - .string() - .min(5) - .max(40) - .default("GET TO KNOW US BETTER") - .meta({ - description: - "Supporting subtitle that invites audience engagement and builds connection", - }), - - organizationDescription: z - .string() - .min(50) - .max(300) - .default( - "We believe in the transformative power of innovation, strategic thinking, and cutting-edge solutions. Our mission is simple: to empower organizations with comprehensive strategies that not only elevate performance but also drive tangible growth and success." - ) - .meta({ - description: - "Primary description of the organization's mission, values, and approach", - }), - - additionalContext: z - .string() - .min(30) - .max(150) - .default( - "What sets us apart is not just our expertise but our commitment to understanding the unique needs of each client." - ) - .meta({ - description: - "Additional context or differentiating statement about the organization", - }), - - featuredImage: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Professional business team analyzing data and working collaboratively", - }).meta({ - description: - "Primary visual that represents the organization's work or environment", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), - - showColorBlocks: z.boolean().default(true).meta({ - description: - "Whether to show colored background blocks for visual hierarchy", - }), - - showAccentSquare: z.boolean().default(true).meta({ - description: "Whether to display the accent square decoration element", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definitionz -const AboutUsSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - organizationDescription, - additionalContext, - featuredImage, - showVisualAccents, - showColorBlocks, - showAccentSquare, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} - - {/* Decorative gray line */} -
-
- - {/* Description Text */} - {organizationDescription && ( -

- {organizationDescription} -

- )} - - {/* Additional Text */} - {additionalContext && ( -
-

- {additionalContext} -

-
- )} -
- - {/* Right Side - Image and Decorative Elements */} -
- {/* Yellow Square - Top Right */} - {showAccentSquare && ( -
- )} - - {/* Decorative Circle - On Yellow Square */} - {showVisualAccents && ( -
- )} - - {/* Business Image - Left positioned */} - {featuredImage?.__image_url__ && ( -
- {featuredImage.__image_prompt__} -
- )} - - {/* Teal Accent Areas */} - {showColorBlocks && ( - <> - {/* Vertical Teal Strip - Center */} -
- - )} -
-
-
- ); -}; - -export default AboutUsSlide; diff --git a/servers/nextjs/presentation-templates/professional/BusinessModelSlide.tsx b/servers/nextjs/presentation-templates/professional/BusinessModelSlide.tsx deleted file mode 100644 index 9b1fa1d5..00000000 --- a/servers/nextjs/presentation-templates/professional/BusinessModelSlide.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import React from "react"; -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; -import { - ChartContainer, - ChartLegend, - ChartLegendContent, - ChartTooltip, - ChartTooltipContent, -} from "@/components/ui/chart"; -import { BarChart, Bar, XAxis, YAxis, CartesianGrid } from "recharts"; - -export const layoutName = "Business Model Slide"; -export const layoutId = "business-model-slide"; -export const layoutDescription = "A slide with a business model"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("BUSINESS MODEL").meta({ - description: - "Main section heading - adapt to presentation topic (e.g., 'Revenue Strategy', 'Funding Model', 'Implementation Plan', 'Solution Framework')", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(60) - .default("SUSTAINABLE REVENUE AND VALUE CREATION") - .meta({ - description: - "Supporting subtitle that describes the approach - adapt to topic (e.g., 'Carbon Reduction Strategy', 'Healthcare Delivery Model', 'Educational Framework')", - }), - - modelDescription: z - .string() - .min(50) - .max(300) - .default( - "Our business model focuses on creating sustainable value through multiple revenue streams, strategic partnerships, and customer-centric solutions. We prioritize long-term relationships and scalable growth opportunities." - ) - .meta({ - description: - "IMPORTANT: Provide topic-specific description of the model/approach. For global warming: describe carbon reduction strategies, renewable energy adoption, sustainability metrics. For healthcare: treatment protocols, patient care models. For education: learning methodologies, curriculum design. Always provide concrete, relevant details for the presentation topic.", - }), - - headerVisual: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Business strategy meeting with charts, graphs and team collaboration", - }).meta({ - description: - "Header visual representing the topic area - ADAPT the image prompt to match presentation topic (e.g., 'Climate scientists analyzing global warming data', 'Medical team reviewing patient care protocols', 'Teachers planning educational curriculum')", - }), - - chartData: z - .array( - z.object({ - category: z.string().min(3).max(25), - value: z.number().min(0).max(100), - color: z.string().min(3).max(20).optional(), - }) - ) - .min(2) - .max(6) - .default([ - { category: "Product Sales", value: 45, color: "#22C55E" }, - { category: "Services", value: 30, color: "#0891B2" }, - { category: "Partnerships", value: 15, color: "#FDE047" }, - { category: "Licensing", value: 10, color: "#F97316" }, - ]) - .meta({ - description: - "CRITICAL: Provide actual data relevant to the presentation topic. For global warming: CO2 emission sources (Transport 29%, Energy 25%, Industry 21%, Agriculture 24%), temperature rise by decade, renewable energy adoption rates. For healthcare: treatment success rates, patient demographics, cost breakdowns. For education: student performance metrics, learning outcomes, resource allocation. Always use REAL topic-specific data with appropriate categories and realistic values.", - }), - - showChart: z.boolean().default(true).meta({ - description: - "Whether to display the data visualization - typically keep true for data-driven presentations", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), -}); - -// Chart configuration -const chartConfig = { - series1: { - label: "Series 1", - color: "#1D9A8A", - }, - series2: { - label: "Series 2", - color: "#E8F4B8", - }, - series3: { - label: "Series 3", - color: "#A8C97F", - }, -}; - -// Type inference -type SchemaType = z.infer; - -// Component definition -const BusinessModelSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - modelDescription, - headerVisual, - chartData, - showChart, - showVisualAccents, - } = data; - - return ( -
- {/* Header Image Section */} - {headerVisual?.__image_url__ && ( -
- {headerVisual.__image_prompt__} -
-
- )} - - {/* Main Content Area */} -
- {/* Left Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} -
- - {/* Model Description */} - {modelDescription && ( -
-

- {modelDescription} -

-
- )} - - {/* Visual Accents */} - {showVisualAccents && ( - <> -
-
- - )} -
- - {/* Right Side - Chart */} -
- {showChart && chartData && chartData.length > 0 && ( -
- - - - - - } /> - - - -
- )} -
-
- - {/* Bottom accent strip */} -
-
- ); -}; - -export default BusinessModelSlide; diff --git a/servers/nextjs/presentation-templates/professional/MarketSizeSlide.tsx b/servers/nextjs/presentation-templates/professional/MarketSizeSlide.tsx deleted file mode 100644 index 0ac39595..00000000 --- a/servers/nextjs/presentation-templates/professional/MarketSizeSlide.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Market Size Slide"; -export const layoutId = "market-size-slide"; -export const layoutDescription = "A slide with a market size analysis"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("MARKET ANALYSIS").meta({ - description: - "Main section heading - can be 'Market Size', 'Market Opportunity', 'Industry Overview', or similar", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(60) - .default("UNDERSTANDING THE OPPORTUNITY LANDSCAPE") - .meta({ - description: - "Supporting subtitle that frames the market discussion and opportunity scope", - }), - - marketDefinitions: z - .array( - z.object({ - marketType: z.string().min(3).max(30), - marketDescription: z.string().min(20).max(150), - marketValue: z.string().min(3).max(25).optional(), - }) - ) - .min(2) - .max(3) - .default([ - { - marketType: "Total Addressable Market (TAM)", - marketDescription: - "The overall revenue opportunity available if we achieved 100% market share across all segments and geographies.", - marketValue: "$50B", - }, - { - marketType: "Serviceable Addressable Market (SAM)", - marketDescription: - "The portion of TAM targeted by our products and services within our geographic reach.", - marketValue: "$15B", - }, - { - marketType: "Serviceable Obtainable Market (SOM)", - marketDescription: - "The portion of SAM that we can realistically capture based on our resources and market conditions.", - marketValue: "$3B", - }, - ]) - .meta({ - description: - "List of market definitions and opportunities with descriptions and potential values", - }), - - visualRepresentation: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1597149962419-0d900ac2b46c?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "World map showing global market reach and geographic distribution", - }).meta({ - description: - "Visual that represents market scope - could be a world map, chart, or geographic visualization", - }), - - showYellowUnderline: z.boolean().default(true).meta({ - description: "Whether to display the decorative yellow underline accent", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const MarketSizeSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - marketDefinitions, - visualRepresentation, - showYellowUnderline, - showVisualAccents, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} - - {/* Yellow Decorative Underline */} - {showYellowUnderline && ( -
- )} -
- - {/* Market Definitions List */} - {marketDefinitions && marketDefinitions.length > 0 && ( -
- {marketDefinitions.map((market, index) => ( -
-
-

- {market.marketType} -

- {market.marketValue && ( - - {market.marketValue} - - )} -
-

- {market.marketDescription} -

-
- ))} -
- )} -
- - {/* Right Side - Visual Representation */} -
- {/* Visual Accents */} - {showVisualAccents && ( - <> - {/* Decorative circles */} -
-
- - )} - - {/* Visual Representation */} - {visualRepresentation?.__image_url__ && ( -
- {visualRepresentation.__image_prompt__} -
- )} -
-
- - {/* Bottom accent strip */} -
-
- ); -}; - -export default MarketSizeSlide; diff --git a/servers/nextjs/presentation-templates/professional/OurServiceSlide.tsx b/servers/nextjs/presentation-templates/professional/OurServiceSlide.tsx deleted file mode 100644 index 64a23020..00000000 --- a/servers/nextjs/presentation-templates/professional/OurServiceSlide.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Our Service Slide"; -export const layoutId = "our-service-slide"; -export const layoutDescription = "A slide with a list of services"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("OUR SERVICES").meta({ - description: - "Main section heading - can be 'Our Services', 'What We Offer', 'Service Portfolio', or similar", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(60) - .default("COMPREHENSIVE SOLUTIONS TAILORED FOR SUCCESS") - .meta({ - description: - "Supporting subtitle that describes the service approach or value proposition", - }), - - bulletPoints: z - .array(z.string().min(10).max(40)) - .min(4) - .max(6) - .default([ - "Customized solutions for your business", - "Expert guidance and support", - "Innovative technology solutions", - "Comprehensive service portfolio", - ]) - .meta({ - description: "Bullet points to describe the services offered", - }), - - serviceHighlight: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1556761175-b413da4baf72?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Professional service delivery or team working on client solutions", - }).meta({ - description: - "Visual that represents service delivery, expertise, or client collaboration", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), - - showColorBlocks: z.boolean().default(true).meta({ - description: - "Whether to show colored background sections for visual hierarchy", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const OurServiceSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - serviceHighlight, - showVisualAccents, - showColorBlocks, - bulletPoints, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left - Title */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} - -
- {bulletPoints && - bulletPoints.map((point, index) => ( -
-
-
-

- {point} -

-
-
- ))} -
- - {/* Visual Accents */} - {showVisualAccents && ( - <> - {/* Decorative elements */} -
-
- - )} -
- - {/* Right - Service Highlight */} -
- {/* Service Highlight Image */} - {serviceHighlight?.__image_url__ && ( -
- {serviceHighlight.__image_prompt__} -
- )} - - {/* Color overlay if enabled */} - {showColorBlocks && ( -
- )} -
-
- - {/* Bottom accent strip */} - {showColorBlocks && ( -
- )} -
- ); -}; - -export default OurServiceSlide; diff --git a/servers/nextjs/presentation-templates/professional/ProblemsSlide.tsx b/servers/nextjs/presentation-templates/professional/ProblemsSlide.tsx deleted file mode 100644 index 5e82b403..00000000 --- a/servers/nextjs/presentation-templates/professional/ProblemsSlide.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Problems Slide"; -export const layoutId = "problems-slide"; -export const layoutDescription = "A slide with a list of problems"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(25).default("CHALLENGES").meta({ - description: - "Main section heading - can be 'Problems', 'Challenges', 'Issues', or similar", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(50) - .default("KEY CHALLENGES TO ADDRESS") - .meta({ - description: "Supporting subtitle that frames the problem discussion", - }), - - challengeItems: z - .array( - z.object({ - itemNumber: z.string().min(1).max(3), - challengeTitle: z.string().min(5).max(40), - challengeDescription: z.string().min(20).max(200), - }) - ) - .min(2) - .max(3) - .default([ - { - itemNumber: "01", - challengeTitle: "Inefficient Processes", - challengeDescription: - "Current workflows and systems lack optimization, leading to wasted resources and reduced productivity across all operational areas.", - }, - { - itemNumber: "02", - challengeTitle: "Limited Scalability", - challengeDescription: - "Existing infrastructure and methodologies cannot accommodate growth, creating bottlenecks that hinder expansion and progress.", - }, - { - itemNumber: "03", - challengeTitle: "Resource Constraints", - challengeDescription: - "Limited availability of key resources including time, budget, and skilled personnel creates barriers to achieving desired outcomes.", - }, - ]) - .meta({ - description: - "List of key challenges or problems with numbered identification and detailed descriptions", - }), - - supportingVisual: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1542744173-8e7e53415bb0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Professional workspace showing analysis and problem-solving activities", - }).meta({ - description: - "Visual that supports the problem discussion - could show analysis, challenges, or work environment", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), - - showColorBlocks: z.boolean().default(true).meta({ - description: "Whether to show colored accent blocks for visual hierarchy", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const ProblemsSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - challengeItems, - supportingVisual, - showVisualAccents, - showColorBlocks, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} -
- - {/* Challenge Items List */} - {challengeItems && challengeItems.length > 0 && ( -
- {challengeItems.map((item, index) => ( -
- {/* Number Circle */} -
- - {item.itemNumber} - -
- - {/* Content */} -
-

- {item.challengeTitle} -

-

- {item.challengeDescription} -

-
-
- ))} -
- )} -
- - {/* Right Side - Image and Decorative Elements */} -
- {/* Decorative Circle */} - {showVisualAccents && ( -
- )} - - {/* Supporting Visual */} - {supportingVisual?.__image_url__ && ( -
- {supportingVisual.__image_prompt__} -
- )} - - {/* Teal Accent Block - Right Edge */} - {showColorBlocks && ( -
- )} -
-
- - {/* Bottom Teal Stripe */} -
-
- ); -}; - -export default ProblemsSlide; diff --git a/servers/nextjs/presentation-templates/professional/SolutionsSlide.tsx b/servers/nextjs/presentation-templates/professional/SolutionsSlide.tsx deleted file mode 100644 index 2b8b731e..00000000 --- a/servers/nextjs/presentation-templates/professional/SolutionsSlide.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Solutions Slide"; -export const layoutId = "solutions-slide"; -export const layoutDescription = "A slide with a list of solutions"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(25).default("OUR SOLUTIONS").meta({ - description: - "Main section heading - can be 'Solutions', 'Our Approach', 'How We Help', or similar", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(50) - .default("COMPREHENSIVE SOLUTIONS FOR YOUR NEEDS") - .meta({ - description: "Supporting subtitle that frames the solution discussion", - }), - - solutionItems: z - .array( - z.object({ - itemNumber: z.string().min(1).max(3), - solutionTitle: z.string().min(5).max(40), - solutionDescription: z.string().min(20).max(200), - }) - ) - .min(2) - .max(3) - .default([ - { - itemNumber: "01", - solutionTitle: "Process Optimization", - solutionDescription: - "Streamline workflows and implement efficient systems that reduce waste, improve productivity, and maximize resource utilization across all operational areas.", - }, - { - itemNumber: "02", - solutionTitle: "Scalable Infrastructure", - solutionDescription: - "Build robust, flexible systems and methodologies that can grow with your organization, eliminating bottlenecks and supporting expansion efforts.", - }, - { - itemNumber: "03", - solutionTitle: "Resource Management", - solutionDescription: - "Strategic allocation and optimization of available resources including time, budget, and personnel to achieve maximum impact and desired outcomes.", - }, - ]) - .meta({ - description: - "List of key solutions or approaches with numbered identification and detailed descriptions", - }), - - primaryVisual: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Modern workspace with team collaboration and strategic planning", - }).meta({ - description: - "Primary visual representing teamwork, strategy, or solution implementation", - }), - - brandingVisual: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/150x80/22C55E/FFFFFF?text=LOGO", - __image_prompt__: "Organization logo or brand mark", - }).meta({ - description: "Logo or branding element to maintain visual identity", - }), - - showYellowUnderline: z.boolean().default(true).meta({ - description: "Whether to display the decorative yellow underline accent", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), - - showColorBlocks: z.boolean().default(true).meta({ - description: - "Whether to show colored background blocks for visual hierarchy", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const SolutionsSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - solutionItems, - primaryVisual, - brandingVisual, - showYellowUnderline, - showVisualAccents, - showColorBlocks, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Images and Branding */} -
- {/* Top Image Area */} - {primaryVisual?.__image_url__ && ( -
- {primaryVisual.__image_prompt__} -
- )} - - {/* Bottom Branding Area */} -
- {brandingVisual?.__image_url__ && ( - {brandingVisual.__image_prompt__} - )} -
-
- - {/* Right Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} - - {/* Yellow Decorative Underline */} - {showYellowUnderline && ( -
- )} -
- - {/* Solution Items List */} - {solutionItems && solutionItems.length > 0 && ( -
- {solutionItems.map((item, index) => ( -
- {/* Number Circle */} -
- - {item.itemNumber} - -
- - {/* Content */} -
-

- {item.solutionTitle} -

-

- {item.solutionDescription} -

-
-
- ))} -
- )} - - {/* Visual Accents */} - {showVisualAccents && ( - <> - {/* Decorative circles */} -
-
- - )} -
-
- - {/* Color blocks for visual hierarchy */} - {showColorBlocks && ( - <> - {/* Bottom accent strip */} -
- {/* Side accent */} -
- - )} -
- ); -}; - -export default SolutionsSlide; diff --git a/servers/nextjs/presentation-templates/professional/StatisticCircularSlide.tsx b/servers/nextjs/presentation-templates/professional/StatisticCircularSlide.tsx deleted file mode 100644 index e4178caa..00000000 --- a/servers/nextjs/presentation-templates/professional/StatisticCircularSlide.tsx +++ /dev/null @@ -1,268 +0,0 @@ -import * as z from "zod"; -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Statistic Circular Slide"; -export const layoutId = "statistic-circular-slide"; -export const layoutDescription = "A slide with a circular statistic"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(20).default("CLIENT SATISFACTION").meta({ - description: - "Main section heading - adapt to presentation topic (e.g., 'Climate Progress', 'Treatment Success', 'Learning Achievement', 'Project Completion')", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(35) - .default("MEASURING OUR IMPACT AND SUCCESS") - .meta({ - description: - "Supporting subtitle that provides context - adapt to topic (e.g., 'Tracking Climate Action Progress', 'Monitoring Patient Recovery Rates', 'Assessing Educational Outcomes')", - }), - - description: z - .string() - .min(2) - .max(230) - .default( - "At the heart of our success lies the unwavering satisfaction of our clients. We take pride in fostering lasting partnerships, consistently exceeding expectations, and delivering results that not only meet but surpass the unique objectives of each client we serve." - ) - .meta({ - description: "Name of the organization or entity being measured", - }), - - brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: - "Professional organization logo - clean and modern design", - }).meta({ - description: "Logo or brand mark representing the organization", - }), - - satisfactionRate: z - .object({ - value: z.number().min(0).max(100), - label: z.string().min(5).max(30), - percentage: z.string().min(2).max(5), - }) - .default({ - value: 90, - label: "CLIENT'S REPEAT ORDER", - percentage: "90%", - }) - .meta({ - description: - "CRITICAL: Provide topic-specific circular progress metric. For global warming: {value: 33, label: 'CO2 REDUCTION ACHIEVED', percentage: '33%'} or {value: 78, label: 'RENEWABLE ENERGY ADOPTION', percentage: '78%'}. For healthcare: {value: 95, label: 'PATIENT RECOVERY RATE', percentage: '95%'} or {value: 87, label: 'TREATMENT SUCCESS RATE', percentage: '87%'}. For education: {value: 92, label: 'GRADUATION SUCCESS RATE', percentage: '92%'}. Use realistic percentages and meaningful labels.", - }), - - statisticBlocks: z - .array( - z.object({ - percentage: z.string().min(2).max(5), - description: z.string().min(20).max(150), - backgroundColor: z.enum(["teal", "beige"]), - }) - ) - .min(2) - .max(2) - .default([ - { - percentage: "90%", - description: - "Our client loyalty speaks volumes as evidenced by a robust repeat order rate", - backgroundColor: "teal", - }, - { - percentage: "99%", - description: - "Our paramount focus on client satisfaction is the bedrock of our agency's success.", - backgroundColor: "beige", - }, - ]) - .meta({ - description: - "ESSENTIAL: Provide two topic-relevant supporting statistics. For global warming: [{percentage: '1.1°C', description: 'Global temperature increase since pre-industrial times represents urgent need for climate action', backgroundColor: 'teal'}, {percentage: '410ppm', description: 'Current atmospheric CO2 levels are the highest in human history requiring immediate intervention', backgroundColor: 'beige'}]. For healthcare: [{percentage: '85%', description: 'Early detection rates have improved significantly with advanced screening technologies', backgroundColor: 'teal'}, {percentage: '72h', description: 'Average patient response time demonstrates our commitment to rapid care delivery', backgroundColor: 'beige'}]. Always provide factual, impactful statistics.", - }), - - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/FFFFFF/1D9A8A?text=C", - __image_prompt__: "Clean modern company logo icon in white", - }).meta({ - description: "Company logo icon", - }), - - companyName: z.string().min(2).max(25).default("Deskpro").meta({ - description: "Company name for branding", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const StatisticCircularSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - description, - brandLogo, - satisfactionRate, - statisticBlocks, - companyLogo, - companyName, - } = data; - - const getBackgroundClass = (bg: string) => { - switch (bg) { - case "teal": - return "bg-teal-600 text-white"; - case "beige": - return "bg-yellow-200 text-gray-900"; - default: - return "bg-gray-200 text-gray-900"; - } - }; - - // Calculate stroke dash array for circular progress - const radius = 150; - const circumference = 2 * Math.PI * radius; - const strokeDasharray = circumference; - const strokeDashoffset = - circumference - (circumference * (satisfactionRate?.value || 90)) / 100; - - return ( -
- {/* Main Content Area */} -
- {/* Header Section */} -
- {/* Left - Title */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} -
- - {/* Right - Company Branding */} -
-
- {companyLogo?.__image_url__ && ( -
- {companyLogo.__image_prompt__} -
- )} - {companyName && ( - - {companyName} - - )} -
-
-
- - {/* Content Section */} -
- {/* Left Side - Circular Chart */} -
-
- {/* Circular Progress SVG */} - - {/* Background circle */} - - {/* Progress circle */} - - - - {/* Center Content */} -
- {satisfactionRate?.label && ( -

- {satisfactionRate.label} -

- )} - {satisfactionRate?.percentage && ( - - {satisfactionRate.percentage} - - )} -
-
-
- - {/* Right Side - Content and Statistics */} -
- {/* Description */} -
- {description && ( -

- {description} -

- )} -
- - {/* Statistics Blocks */} - {statisticBlocks && statisticBlocks.length > 0 && ( -
- {statisticBlocks.map((block, index) => ( -
- {/* Percentage Block */} -
- - {block.percentage} - -
- - {/* Description Block */} -
-

- {block.description} -

-
-
- ))} -
- )} -
-
-
-
- ); -}; - -export default StatisticCircularSlide; diff --git a/servers/nextjs/presentation-templates/professional/StatisticDualChartSlide.tsx b/servers/nextjs/presentation-templates/professional/StatisticDualChartSlide.tsx deleted file mode 100644 index 3780d301..00000000 --- a/servers/nextjs/presentation-templates/professional/StatisticDualChartSlide.tsx +++ /dev/null @@ -1,361 +0,0 @@ -import React from "react"; -import * as z from "zod"; -import { ImageSchema, IconSchema } from "../defaultSchemes"; -import { - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "@/components/ui/chart"; -import { - BarChart, - Bar, - AreaChart, - Area, - XAxis, - YAxis, - CartesianGrid, -} from "recharts"; - -export const layoutName = "Statistic Dual Chart Slide"; -export const layoutId = "statistic-dual-chart-slide"; -export const layoutDescription = "A slide with a statistic and a chart"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("PERFORMANCE METRICS").meta({ - description: - "Main section heading - adapt to presentation topic (e.g., 'Climate Analysis', 'Health Outcomes', 'Research Data', 'Impact Assessment')", - }), - - organizationName: z - .string() - .min(2) - .max(30) - .default("Your Organization") - .meta({ - description: "Name of the organization or entity presenting the data", - }), - - brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: - "Professional organization logo - clean and modern design", - }).meta({ - description: "Logo or brand mark representing the organization", - }), - - barChartData: z - .array( - z.object({ - name: z.string(), - series1: z.number(), - series2: z.number(), - series3: z.number(), - }) - ) - .min(5) - .max(5) - .default([ - { name: "Item 1", series1: 5, series2: 5, series3: 8 }, - { name: "Item 2", series1: 8, series2: 8, series3: 15 }, - { name: "Item 3", series1: 15, series2: 10, series3: 18 }, - { name: "Item 4", series1: 18, series2: 14, series3: 22 }, - { name: "Item 5", series1: 22, series2: 20, series3: 8 }, - ]) - .meta({ - description: - "CRITICAL: Provide topic-specific data for the left bar chart. For global warming: 5 years of data (2020-2024) with CO2 emissions by sector (Transport, Industry, Energy) with actual values. For healthcare: Patient outcomes across 5 categories (Prevention, Treatment, Recovery) with real percentages. For education: Student performance across 5 metrics (Reading, Math, Science) with grade levels. Use realistic data patterns and values.", - }), - - areaChartData: z - .array( - z.object({ - name: z.string(), - series1: z.number(), - series2: z.number(), - series3: z.number(), - }) - ) - .min(5) - .max(5) - .default([ - { name: "Item 1", series1: 20, series2: 30, series3: 15 }, - { name: "Item 2", series1: 40, series2: 45, series3: 35 }, - { name: "Item 3", series1: 45, series2: 50, series3: 80 }, - { name: "Item 4", series1: 50, series2: 45, series3: 85 }, - { name: "Item 5", series1: 80, series2: 75, series3: 120 }, - ]) - .meta({ - description: - "CRITICAL: Provide topic-specific data for the right area chart. For global warming: Cumulative data over 5 time periods showing renewable energy adoption, carbon reduction efforts, and policy implementations with realistic growth trends. For healthcare: Cumulative patient care metrics showing improvement over time. For education: Progressive learning outcomes showing student advancement. Ensure data shows meaningful trends relevant to the topic.", - }), - - leftChartTitle: z - .string() - .min(5) - .max(40) - .default("Our Customer's Satisfaction") - .meta({ - description: - "IMPORTANT: Provide topic-specific title for left chart. For global warming: 'Global CO2 Emissions by Sector', 'Temperature Rise by Region', 'Renewable Energy Adoption'. For healthcare: 'Patient Treatment Outcomes', 'Healthcare Quality Metrics', 'Recovery Success Rates'. For education: 'Student Performance by Subject', 'Learning Progress Assessment', 'Academic Achievement Trends'.", - }), - - leftChartDescription: z - .string() - .min(20) - .max(200) - .default( - "An impressive client satisfaction rate underscores our unwavering commitment to delivering exceptional service and exceeding expectations." - ) - .meta({ - description: - "ESSENTIAL: Provide topic-relevant description explaining the left chart data. For global warming: Explain emission sources, trends, and implications. For healthcare: Describe treatment effectiveness and patient outcomes. For education: Explain performance metrics and learning indicators. Make it informative and specific to the data shown.", - }), - - rightChartTitle: z.string().min(5).max(40).default("Repeat Order Rate").meta({ - description: - "IMPORTANT: Provide topic-specific title for right chart. For global warming: 'Climate Action Progress', 'Carbon Reduction Timeline', 'Sustainability Milestones'. For healthcare: 'Patient Recovery Timeline', 'Treatment Progress Tracking', 'Health Improvement Trajectory'. For education: 'Learning Progress Over Time', 'Student Development Path', 'Academic Growth Timeline'.", - }), - - rightChartDescription: z - .string() - .min(20) - .max(200) - .default( - "Our remarkable client repeat order rate of 123 times are testament to the quality of our products/services and the trust our clients place in our ability." - ) - .meta({ - description: - "ESSENTIAL: Provide topic-relevant description explaining the right chart's cumulative/timeline data. For global warming: Describe progress in climate action, policy impact, or environmental improvements. For healthcare: Explain patient journey and recovery progression. For education: Describe learning advancement and skill development over time. Make it specific and data-driven.", - }), -}); - -// Chart configuration -const chartConfig = { - series1: { - label: "Series 1", - color: "#1D9A8A", - }, - series2: { - label: "Series 2", - color: "#A8C97F", - }, - series3: { - label: "Series 3", - color: "#E8F4B8", - }, -}; - -// Type inference -type SchemaType = z.infer; - -// Component definition -const StatisticDualChartSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - organizationName, - brandLogo, - barChartData, - areaChartData, - leftChartTitle, - leftChartDescription, - rightChartTitle, - rightChartDescription, - } = data; - - return ( -
- {/* Header Section */} -
- {/* Title */} - {sectionTitle && ( -

{sectionTitle}

- )} - - {/* Company Branding */} -
- {brandLogo?.__image_url__ && ( -
- {brandLogo.__image_prompt__} -
- )} - {organizationName && ( - - {organizationName} - - )} -
-
- - {/* Content Section */} -
- {/* Left Chart Section */} -
- {/* Chart Legend */} -
-
-
- Series 1 -
-
-
- Series 2 -
-
-
- Series 3 -
-
- - {/* Bar Chart */} - {barChartData && barChartData.length > 0 && ( -
- - - - - - } /> - - - - - -
- )} - - {/* Chart Description */} -
- {leftChartTitle && ( -

- {leftChartTitle} -

- )} - {leftChartDescription && ( -

- {leftChartDescription} -

- )} -
-
- - {/* Right Chart Section */} -
- {/* Chart Legend */} -
-
-
- Series 1 -
-
-
- Series 2 -
-
-
- Series 3 -
-
- - {/* Area Chart */} - {areaChartData && areaChartData.length > 0 && ( -
- - - - - - } /> - - - - - -
- )} - - {/* Chart Description */} -
- {rightChartTitle && ( -

- {rightChartTitle} -

- )} - {rightChartDescription && ( -

- {rightChartDescription} -

- )} -
-
-
-
- ); -}; - -export default StatisticDualChartSlide; diff --git a/servers/nextjs/presentation-templates/professional/StatisticSlide.tsx b/servers/nextjs/presentation-templates/professional/StatisticSlide.tsx deleted file mode 100644 index 74bddd34..00000000 --- a/servers/nextjs/presentation-templates/professional/StatisticSlide.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import React from "react"; -import * as z from "zod"; -import { ImageSchema, IconSchema } from "../defaultSchemes"; -import { - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "@/components/ui/chart"; -import { LineChart, Line, XAxis, YAxis, CartesianGrid } from "recharts"; - -export const layoutName = "Statistic Slide"; -export const layoutId = "statistic-slide"; -export const layoutDescription = "A slide with a statistic"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("KEY STATISTICS").meta({ - description: - "Main section heading - adapt to presentation topic (e.g., 'Climate Data', 'Health Metrics', 'Performance Stats', 'Research Findings')", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(60) - .default("DATA-DRIVEN INSIGHTS AND PERFORMANCE") - .meta({ - description: - "Supporting subtitle that frames the data - adapt to topic (e.g., 'Global Temperature Trends and Impact', 'Patient Outcomes and Recovery Rates', 'Student Achievement and Progress')", - }), - - statisticValue: z.string().min(1).max(15).default("85%").meta({ - description: - "CRITICAL: Provide the most important statistic for the topic. For global warming: '1.1°C', '+2.1°C', '410ppm', '33%'. For healthcare: '95%', '72 hours', '89%'. For education: '78%', '3.2 GPA', '92%'. Use real, impactful numbers relevant to the presentation topic.", - }), - - statisticLabel: z - .string() - .min(5) - .max(40) - .default("Client Satisfaction Rate") - .meta({ - description: - "IMPORTANT: Provide topic-specific label for the main statistic. For global warming: 'Global Temperature Rise Since 1880', 'CO2 Concentration Increase', 'Arctic Ice Loss Rate'. For healthcare: 'Patient Recovery Rate', 'Treatment Success Rate', 'Early Detection Rate'. For education: 'Graduation Success Rate', 'Student Engagement Level', 'Learning Improvement Rate'.", - }), - - supportingVisual: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1460925895917-afdab827c52f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Business analytics dashboard with charts and data visualization", - }).meta({ - description: - "ADAPT the image prompt to match the presentation topic: For global warming: 'Climate monitoring station with temperature sensors and weather equipment', 'Scientists analyzing ice core data in Arctic research facility'. For healthcare: 'Medical monitoring equipment displaying patient vital signs', 'Healthcare analytics dashboard showing treatment outcomes'. For education: 'Educational assessment data on computer screens', 'Students using digital learning platforms'.", - }), - - bulletPoints: z - .array(z.string().min(10).max(100)) - .min(2) - .max(5) - .default([ - "Consistent performance improvement over 12 months", - "High customer retention and satisfaction scores", - "Measurable ROI across all key performance indicators", - "Data-driven decision making and strategic optimization", - ]) - .meta({ - description: - "ESSENTIAL: Provide topic-relevant supporting facts and insights. For global warming: 'Global average temperature has risen 1.1°C since pre-industrial times', 'Arctic sea ice is declining at 13% per decade', 'CO2 levels are highest in 3 million years', 'Renewable energy adoption increased 85% in last decade'. For healthcare: 'Early detection improves survival rates by 85%', 'Telemedicine reduced patient wait times by 60%', 'Preventive care decreased hospital readmissions by 40%'. Always provide factual, verifiable statements related to the presentation topic.", - }), - - chartData: z - .array( - z.object({ - name: z.string(), - series1: z.number(), - series2: z.number(), - series3: z.number(), - }) - ) - .min(5) - .max(5) - .default([ - { name: "Jan", series1: 18, series2: 0, series3: 0 }, - { name: "Feb", series1: 30, series2: 12, series3: 8 }, - { name: "Mar", series1: 26, series2: 38, series3: 20 }, - { name: "Apr", series1: 40, series2: 30, series3: 35 }, - { name: "May", series1: 42, series2: 45, series3: 32 }, - ]) - .meta({ - description: - "CRITICAL: Provide topic-specific time-series data for line chart. For global warming: Monthly temperature anomalies, CO2 levels, ice coverage data with realistic values. For healthcare: Patient recovery rates, treatment success metrics, diagnostic accuracy over time. For education: Student performance trends, learning progress, engagement metrics. Use realistic data patterns showing meaningful trends.", - }), - - showYellowUnderline: z.boolean().default(true).meta({ - description: "Whether to display the decorative yellow underline accent", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), -}); - -// Chart configuration -const chartConfig = { - series1: { - label: "Series 1", - color: "#1D9A8A", - }, - series2: { - label: "Series 2", - color: "#A8C97F", - }, - series3: { - label: "Series 3", - color: "#E8F4B8", - }, -}; - -// Type inference -type SchemaType = z.infer; - -// Component definition -const StatisticSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - statisticValue, - statisticLabel, - supportingVisual, - bulletPoints, - chartData, - showYellowUnderline, - showVisualAccents, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Teal Background */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} - - {/* Yellow Decorative Underline */} - {showYellowUnderline && ( -
- )} -
- - {/* Large Statistic Display */} -
- {statisticValue && ( -
- {statisticValue} -
- )} - {statisticLabel && ( -

{statisticLabel}

- )} -
- - {/* Business Image */} - {supportingVisual?.__image_url__ && ( -
-
- {supportingVisual.__image_prompt__} -
-
- )} - - {/* Visual Accents */} - {showVisualAccents && ( - <> -
-
- - )} -
- - {/* Right Side - White Background with Chart and Bullet Points */} -
- {/* Chart Section */} -
- {/* Chart Legend */} -
-
-
- Series 1 -
-
-
- Series 2 -
-
-
- Series 3 -
-
- - {/* Chart Container */} - {chartData && chartData.length > 0 && ( -
- - - - - - } /> - - - - - -
- )} -
- - {/* Bullet Points Section */} -
- {bulletPoints && bulletPoints.length > 0 && ( - <> - {bulletPoints.map((point, index) => { - // Rotate colors for visual variety - const colors = [ - "bg-teal-600", - "bg-yellow-300", - "bg-gray-400", - ]; - const dotColor = colors[index % colors.length]; - - return ( -
-
-

- {point} -

-
- ); - })} - - )} -
-
-
- - {/* Bottom accent strip */} -
-
- ); -}; - -export default StatisticSlide; diff --git a/servers/nextjs/presentation-templates/professional/TableOfContentsSlide.tsx b/servers/nextjs/presentation-templates/professional/TableOfContentsSlide.tsx deleted file mode 100644 index b98d4e80..00000000 --- a/servers/nextjs/presentation-templates/professional/TableOfContentsSlide.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Table of Contents Slide"; -export const layoutId = "table-of-contents-slide"; -export const layoutDescription = "A slide with a table of contents"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("TABLE OF CONTENTS").meta({ - description: - "Main heading for the content overview - can be 'Agenda', 'Overview', 'Contents', or similar", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(60) - .default("PRESENTATION OVERVIEW AND AGENDA") - .meta({ - description: - "Supporting subtitle that explains what the audience will learn or see", - }), - - contentItems: z - .array( - z.object({ - itemNumber: z.string().min(1).max(3), - contentTitle: z.string().min(3).max(40), - contentDescription: z.string().min(10).max(100).optional(), - }) - ) - .min(3) - .max(8) - .default([ - { - itemNumber: "01", - contentTitle: "Introduction & Welcome", - contentDescription: "Brief overview and objectives", - }, - { - itemNumber: "02", - contentTitle: "About Our Organization", - contentDescription: "Background and mission", - }, - { - itemNumber: "03", - contentTitle: "Key Challenges", - contentDescription: "Current issues and opportunities", - }, - { - itemNumber: "04", - contentTitle: "Our Solutions", - contentDescription: "Proposed approaches and methods", - }, - { - itemNumber: "05", - contentTitle: "Implementation Plan", - contentDescription: "Timeline and next steps", - }, - { - itemNumber: "06", - contentTitle: "Questions & Discussion", - contentDescription: "Interactive engagement", - }, - ]) - .meta({ - description: - "List of presentation sections with numbered sequence and brief descriptions", - }), - - brandingVisual: ImageSchema.default({ - __image_url__: - "https://via.placeholder.com/200x100/22C55E/FFFFFF?text=BRAND", - __image_prompt__: "Organization logo or brand visual element", - }).meta({ - description: - "Logo or branding element displayed prominently for visual identity", - }), - - showDecorations: z.boolean().default(true).meta({ - description: - "Whether to display decorative visual elements like underlines and accents", - }), - - useColumnLayout: z.boolean().default(true).meta({ - description: - "Whether to arrange content items in two columns for better space utilization", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const TableOfContentsSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - contentItems, - brandingVisual, - showDecorations, - useColumnLayout, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {/* Decorative underline */} - {showDecorations && ( -
- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} -
- - {/* Content Items */} - {contentItems && contentItems.length > 0 && ( -
- {contentItems.map((item, index) => ( -
- {/* Number Circle */} -
- - {item.itemNumber} - -
- - {/* Content */} -
-

- {item.contentTitle} -

- {item.contentDescription && ( -

- {item.contentDescription} -

- )} -
-
- ))} -
- )} -
- - {/* Right Side - Branding and Visual Elements */} -
- {/* Branding Visual */} - {brandingVisual?.__image_url__ && ( -
- {brandingVisual.__image_prompt__} -
- )} - - {/* Decorative Elements */} - {showDecorations && ( - <> - {/* Decorative circles */} -
-
-
- - )} -
-
- - {/* Bottom accent strip */} -
-
- ); -}; - -export default TableOfContentsSlide; diff --git a/servers/nextjs/presentation-templates/professional/TestimonialSlide.tsx b/servers/nextjs/presentation-templates/professional/TestimonialSlide.tsx deleted file mode 100644 index 3dfe7365..00000000 --- a/servers/nextjs/presentation-templates/professional/TestimonialSlide.tsx +++ /dev/null @@ -1,221 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Testimonial Slide"; -export const layoutId = "testimonial-slide"; -export const layoutDescription = "A slide with a testimonial"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("CLIENT TESTIMONIALS").meta({ - description: - "Main section heading - can be 'Testimonials', 'Client Feedback', 'Reviews', or similar", - }), - - organizationName: z - .string() - .min(2) - .max(30) - .default("Your Organization") - .meta({ - description: "Name of the organization or entity being featured", - }), - - brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: - "Professional organization logo - clean and modern design", - }).meta({ - description: "Logo or brand mark representing the organization", - }), - - testimonialItems: z - .array( - z.object({ - clientName: z.string().min(2).max(40), - clientTitle: z.string().min(5).max(60), - clientCompany: z.string().min(2).max(40), - testimonialText: z.string().min(50).max(300), - rating: z.number().min(1).max(5), - clientPhoto: ImageSchema, - }) - ) - .min(2) - .max(3) - .default([ - { - clientName: "Sarah Johnson", - clientTitle: "Chief Executive Officer", - clientCompany: "TechCorp Solutions", - testimonialText: - "Working with this team has been transformative for our business. Their expertise, dedication, and innovative approach exceeded our expectations and delivered remarkable results.", - rating: 5, - clientPhoto: { - __image_url__: - "https://images.unsplash.com/photo-1494790108755-2616b612b830?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional businesswoman headshot", - }, - }, - { - clientName: "Michael Chen", - clientTitle: "Director of Operations", - clientCompany: "Global Innovations Inc", - testimonialText: - "The level of professionalism and quality of service provided was outstanding. They understood our needs perfectly and delivered solutions that truly made a difference.", - rating: 5, - clientPhoto: { - __image_url__: - "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional businessman headshot", - }, - }, - { - clientName: "Emily Rodriguez", - clientTitle: "Marketing Manager", - clientCompany: "Creative Dynamics", - testimonialText: - "Exceptional service and results that spoke for themselves. The team's attention to detail and commitment to excellence made our collaboration highly successful.", - rating: 5, - clientPhoto: { - __image_url__: - "https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional woman headshot", - }, - }, - ]) - .meta({ - description: - "List of client testimonials with ratings, photos, and detailed feedback", - }), - - showRatings: z.boolean().default(true).meta({ - description: "Whether to display star ratings for each testimonial", - }), - - showClientPhotos: z.boolean().default(true).meta({ - description: "Whether to show client photos alongside testimonials", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const TestimonialSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - organizationName, - brandLogo, - testimonialItems, - showRatings, - showClientPhotos, - } = data; - - // Helper function to render stars - const renderStars = (rating: number) => { - return Array.from({ length: 5 }, (_, i) => ( - - - - )); - }; - - return ( -
- {/* Header Section */} -
- {/* Title */} - {sectionTitle && ( -

{sectionTitle}

- )} - - {/* Company Branding */} -
- {brandLogo?.__image_url__ && ( -
- {brandLogo.__image_prompt__} -
- )} - {organizationName && ( - - {organizationName} - - )} -
-
- - {/* Testimonials Content */} -
- {testimonialItems && testimonialItems.length > 0 && ( -
- {testimonialItems.slice(0, 3).map((item, index) => { - // Rotate background colors for visual variety - const bgColors = ["bg-yellow-100", "bg-teal-100", "bg-gray-100"]; - const bgColor = bgColors[index % bgColors.length]; - - return ( -
- {/* Stars Rating */} - {showRatings && ( -
- {renderStars(item.rating)} -
- )} - - {/* Testimonial Text */} -

- "{item.testimonialText}" -

- - {/* Client Info */} -
- {/* Client Photo */} - {showClientPhotos && item.clientPhoto?.__image_url__ && ( -
- {item.clientPhoto.__image_prompt__} -
- )} - - {/* Client Details */} -
-

- {item.clientName} -

-

- {item.clientTitle} -

-

- {item.clientCompany} -

-
-
-
- ); - })} -
- )} -
-
- ); -}; - -export default TestimonialSlide; diff --git a/servers/nextjs/presentation-templates/professional/ThankYouSlide.tsx b/servers/nextjs/presentation-templates/professional/ThankYouSlide.tsx deleted file mode 100644 index 4467b4a6..00000000 --- a/servers/nextjs/presentation-templates/professional/ThankYouSlide.tsx +++ /dev/null @@ -1,229 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Thank You Slide"; -export const layoutId = "thank-you-slide"; -export const layoutDescription = "A slide with a thank you message"; - -// Schema definition -export const Schema = z.object({ - organizationName: z - .string() - .min(2) - .max(30) - .default("Your Organization") - .meta({ - description: "Name of the organization, company, or entity presenting", - }), - - primaryMessage: z.string().min(3).max(25).default("THANK YOU").meta({ - description: - "Main closing message - can be 'Thank You', 'Questions?', 'Let's Connect', or similar", - }), - - secondaryMessage: z - .string() - .min(5) - .max(60) - .default("FOR YOUR TIME AND ATTENTION") - .meta({ - description: - "Supporting message that completes the primary message or adds context", - }), - - brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: - "Professional organization logo - clean and modern design", - }).meta({ - description: "Logo or brand mark representing the presenting organization", - }), - - contactDetails: z - .object({ - phoneNumber: z.string().min(10).max(20).default("+1-234-567-8900"), - physicalAddress: z - .string() - .min(10) - .max(60) - .default("123 Business Ave, City, State 12345"), - websiteUrl: z - .string() - .min(10) - .max(40) - .default("www.yourorganization.com"), - }) - .default({ - phoneNumber: "+1-234-567-8900", - physicalAddress: "123 Business Ave, City, State 12345", - websiteUrl: "www.yourorganization.com", - }) - .meta({ - description: - "Contact information for follow-up communication and connection", - }), - - presentationDate: z - .string() - .min(3) - .max(20) - .default("Current Month Year") - .meta({ - description: - "Date when the presentation was given or document was created", - }), - - showDecorations: z.boolean().default(true).meta({ - description: - "Whether to display decorative visual elements like background shapes", - }), - - showNavigationArrow: z.boolean().default(true).meta({ - description: - "Whether to show a navigation arrow for interactive presentations", - }), - - showContactInfo: z.boolean().default(true).meta({ - description: "Whether to display contact information in the footer", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const ThankYouSlide = ({ data }: { data: Partial }) => { - const { - organizationName, - primaryMessage, - secondaryMessage, - brandLogo, - contactDetails, - presentationDate, - showDecorations, - showNavigationArrow, - showContactInfo, - } = data; - - return ( -
- {/* Header with Logo and Arrow */} -
- {/* Company Logo and Name */} -
- {brandLogo?.__image_url__ && ( -
- {brandLogo.__image_prompt__} -
- )} - {organizationName && ( - - {organizationName} - - )} -
- - {/* Arrow Button */} - {showNavigationArrow && ( -
- - - -
- )} -
- - {/* Decorative Circle */} - {showDecorations && ( -
- )} - - {/* Main Content */} -
-
- {/* Main Title */} - {primaryMessage && ( -

- {primaryMessage} -

- )} - - {/* Subtitle with Circle Bullet */} - {secondaryMessage && ( -
-
-

- {secondaryMessage} -

-
- )} -
-
- - {/* Footer with Contact Info */} - {showContactInfo && ( -
-
-
- {/* Telephone */} - {contactDetails?.phoneNumber && ( -
-
- Telephone -
-
{contactDetails.phoneNumber}
-
- )} - - {/* Address */} - {contactDetails?.physicalAddress && ( -
-
- Address -
-
{contactDetails.physicalAddress}
-
- )} - - {/* Website */} - {contactDetails?.websiteUrl && ( -
-
- Website -
-
{contactDetails.websiteUrl}
-
- )} -
- - {/* Presentation Date */} - {presentationDate && ( -
-
- {presentationDate} -
-
- )} -
-
- )} -
- ); -}; - -export default ThankYouSlide; diff --git a/servers/nextjs/presentation-templates/professional/TitleSlide.tsx b/servers/nextjs/presentation-templates/professional/TitleSlide.tsx deleted file mode 100644 index 943c1dd6..00000000 --- a/servers/nextjs/presentation-templates/professional/TitleSlide.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "Title Slide"; -export const layoutId = "title-slide"; -export const layoutDescription = "A slide with a title and subtitle"; - -// Schema definition -export const Schema = z.object({ - organizationName: z - .string() - .min(2) - .max(25) - .default("Your Organization") - .meta({ - description: "Name of the organization, company, or entity presenting", - }), - - primaryTitle: z.string().min(3).max(30).default("PRESENTATION TITLE").meta({ - description: - "Main headline or title for the presentation - should be impactful and attention-grabbing", - }), - - secondaryTitle: z - .string() - .min(5) - .max(50) - .default("PROFESSIONAL PRESENTATION") - .meta({ - description: - "Subtitle that provides context about the presentation type or purpose", - }), - - brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: - "Professional organization logo - clean and modern design", - }).meta({ - description: "Logo or brand mark representing the presenting organization", - }), - - contactDetails: z - .object({ - phoneNumber: z.string().min(10).max(20).default("+1-234-567-8900"), - physicalAddress: z - .string() - .min(10) - .max(60) - .default("123 Business Ave, City, State 12345"), - websiteUrl: z - .string() - .min(10) - .max(40) - .default("www.yourorganization.com"), - }) - .default({ - phoneNumber: "+1-234-567-8900", - physicalAddress: "123 Business Ave, City, State 12345", - websiteUrl: "www.yourorganization.com", - }) - .meta({ - description: - "Contact information including phone, address, and website for follow-up communication", - }), - - presentationDate: z - .string() - .min(3) - .max(20) - .default("Current Month Year") - .meta({ - description: "Date when the presentation is being given or was created", - }), - - showDecorations: z.boolean().default(true).meta({ - description: - "Whether to display decorative visual elements like background shapes", - }), - - showNavigationArrow: z.boolean().default(true).meta({ - description: - "Whether to show a navigation arrow button for presentation flow", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const ThynkTitleSlide = ({ data }: { data: Partial }) => { - const { - organizationName, - primaryTitle, - secondaryTitle, - brandLogo, - contactDetails, - presentationDate, - showDecorations, - showNavigationArrow, - } = data; - - return ( -
- {/* Header with Logo and Arrow */} -
- {/* Company Logo and Name */} -
- {brandLogo?.__image_url__ && ( -
- {brandLogo.__image_prompt__} -
- )} - {organizationName && ( - - {organizationName} - - )} -
- - {/* Arrow Button */} - {showNavigationArrow && ( -
- - - -
- )} -
- - {/* Decorative Circle */} - {showDecorations && ( -
- )} - - {/* Main Content */} -
-
- {/* Main Title */} - {primaryTitle && ( -

- {primaryTitle} -

- )} - - {/* Subtitle with Circle Bullet */} - {secondaryTitle && ( -
-
-

- {secondaryTitle} -

-
- )} -
-
- - {/* Footer with Contact Info */} -
-
-
- {/* Telephone */} - {contactDetails?.phoneNumber && ( -
-
- Telephone -
-
{contactDetails.phoneNumber}
-
- )} - - {/* Address */} - {contactDetails?.physicalAddress && ( -
-
Address
-
{contactDetails.physicalAddress}
-
- )} - - {/* Website */} - {contactDetails?.websiteUrl && ( -
-
Website
-
{contactDetails.websiteUrl}
-
- )} -
- - {/* Presentation Date */} - {presentationDate && ( -
-
- {presentationDate} -
-
- )} -
-
-
- ); -}; - -export default ThynkTitleSlide; diff --git a/servers/nextjs/presentation-templates/professional/WhatWeBelieveSlide.tsx b/servers/nextjs/presentation-templates/professional/WhatWeBelieveSlide.tsx deleted file mode 100644 index 8d6b4f67..00000000 --- a/servers/nextjs/presentation-templates/professional/WhatWeBelieveSlide.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import * as z from "zod"; - -import { ImageSchema, IconSchema } from "../defaultSchemes"; - -export const layoutName = "What We Believe Slide"; -export const layoutId = "what-we-believe-slide"; -export const layoutDescription = - "A slide that describes the organization's vision and mission"; - -// Schema definition -export const Schema = z.object({ - sectionTitle: z.string().min(3).max(30).default("OUR VISION & MISSION").meta({ - description: - "Main section heading - can be 'Our Values', 'What We Believe', 'Our Philosophy', or similar", - }), - - sectionSubtitle: z - .string() - .min(10) - .max(60) - .default("GUIDING PRINCIPLES AND CORE BELIEFS") - .meta({ - description: - "Supporting subtitle that introduces the organization's foundational concepts", - }), - - visionStatement: z - .string() - .min(30) - .max(200) - .default( - "We envision a future where innovative solutions transform challenges into opportunities, creating sustainable value for all stakeholders." - ) - .meta({ - description: - "Vision statement describing the organization's aspirational future goals and impact", - }), - - missionContent: z - .object({ - missionTitle: z.string().min(3).max(30).default("Our Mission"), - missionDescription: z - .string() - .min(50) - .max(300) - .default( - "To deliver exceptional value through strategic innovation, collaborative partnerships, and unwavering commitment to excellence. We believe in empowering organizations with the tools, insights, and support needed to achieve sustainable growth and meaningful impact in their communities." - ), - }) - .default({ - missionTitle: "Our Mission", - missionDescription: - "To deliver exceptional value through strategic innovation, collaborative partnerships, and unwavering commitment to excellence. We believe in empowering organizations with the tools, insights, and support needed to achieve sustainable growth and meaningful impact in their communities.", - }) - .meta({ - description: - "Mission section with title and detailed description of organizational purpose and approach", - }), - - supportingVisual: ImageSchema.default({ - __image_url__: - "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: - "Diverse team collaborating and planning together in modern workspace", - }).meta({ - description: - "Visual that represents collaboration, vision, or organizational culture", - }), - - showVisualAccents: z.boolean().default(true).meta({ - description: "Whether to display decorative visual accent elements", - }), - - showColorBlocks: z.boolean().default(true).meta({ - description: - "Whether to show colored background sections for visual hierarchy", - }), -}); - -// Type inference -type SchemaType = z.infer; - -// Component definition -const WhatWeBelieveSlide = ({ data }: { data: Partial }) => { - const { - sectionTitle, - sectionSubtitle, - visionStatement, - missionContent, - supportingVisual, - showVisualAccents, - showColorBlocks, - } = data; - - return ( -
- {/* Main Content Area */} -
- {/* Left Side - Image */} -
- {supportingVisual?.__image_url__ && ( -
- {supportingVisual.__image_prompt__} -
- )} - - {/* Visual Accents */} - {showVisualAccents && ( - <> - {/* Decorative circles */} -
-
- - )} -
- - {/* Right Side - Content */} -
- {/* Title Section */} -
- {sectionTitle && ( -

- {sectionTitle} -

- )} - - {sectionSubtitle && ( -

- {sectionSubtitle} -

- )} -
- - {/* Vision Section */} - {visionStatement && ( -
-

Vision

-

- {visionStatement} -

-
- )} - - {/* Mission Section with Teal Background */} - {missionContent && ( -
- {missionContent.missionTitle && ( -

- {missionContent.missionTitle} -

- )} - {missionContent.missionDescription && ( -

- {missionContent.missionDescription} -

- )} -
- )} -
-
- - {/* Color blocks for visual hierarchy */} - {showColorBlocks && ( - <> - {/* Bottom accent strip */} -
- {/* Left accent */} -
- - )} -
- ); -}; - -export default WhatWeBelieveSlide; diff --git a/servers/nextjs/presentation-templates/professional/settings.json b/servers/nextjs/presentation-templates/professional/settings.json deleted file mode 100644 index 4eeda989..00000000 --- a/servers/nextjs/presentation-templates/professional/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "description": "Professional presentation layouts with clean design and flexible content fields. Suitable for business pitches, organizational overviews, product presentations, and various corporate communications.", - "ordered": false, - "default": false -} \ No newline at end of file From 5eec194152047831221ef2bab69352fa5f5533f9 Mon Sep 17 00:00:00 2001 From: Suraj Jha Date: Tue, 9 Sep 2025 03:55:55 +0545 Subject: [PATCH 5/5] update: general template --- .../general/BasicInfoSlideLayout.tsx | 28 ++++-- .../general/BulletIconsOnlySlideLayout.tsx | 56 +++++++----- .../general/BulletWithIconsSlideLayout.tsx | 56 +++++++----- .../general/ChartWithBulletsSlideLayout.tsx | 91 +++++++++++-------- .../general/IntroSlideLayout.tsx | 41 +++++---- .../general/MetricsSlideLayout.tsx | 35 ++++--- .../general/MetricsWithImageSlideLayout.tsx | 29 +++--- .../general/NumberedBulletsSlideLayout.tsx | 39 ++++---- .../general/QuoteSlideLayout.tsx | 43 +++++---- .../general/TableInfoSlideLayout.tsx | 45 ++++++--- .../general/TableOfContentsSlideLayout.tsx | 41 +++++---- .../general/TeamSlideLayout.tsx | 39 ++++---- 12 files changed, 333 insertions(+), 210 deletions(-) diff --git a/servers/nextjs/presentation-templates/general/BasicInfoSlideLayout.tsx b/servers/nextjs/presentation-templates/general/BasicInfoSlideLayout.tsx index 3f5c4e33..e97ba984 100644 --- a/servers/nextjs/presentation-templates/general/BasicInfoSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/BasicInfoSlideLayout.tsx @@ -35,17 +35,25 @@ const BasicInfoSlideLayout: React.FC = ({ data: slide return ( <> {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Main Content */} @@ -64,21 +72,25 @@ const BasicInfoSlideLayout: React.FC = ({ data: slide {/* Right Section - Content */}
{/* Title */} -

+

{slideData?.title || 'Product Overview'}

{/* Purple accent line */} -
+
{/* Description */} -

+

{slideData?.description || 'Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.'}

+ + +
+
) diff --git a/servers/nextjs/presentation-templates/general/BulletIconsOnlySlideLayout.tsx b/servers/nextjs/presentation-templates/general/BulletIconsOnlySlideLayout.tsx index e3a1e9c2..32746732 100644 --- a/servers/nextjs/presentation-templates/general/BulletIconsOnlySlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/BulletIconsOnlySlideLayout.tsx @@ -1,10 +1,11 @@ import React from 'react' import * as z from "zod"; import { ImageSchema, IconSchema } from '@/presentation-templates/defaultSchemes'; +import { RemoteSvgIcon } from '@/app/hooks/useRemoteSvgIcon'; export const layoutId = 'bullet-icons-only-slide' export const layoutName = 'Bullet Icons Only' -export const layoutDescription = 'A slide layout with title, grid of bullet points with icons (no descriptions), and a supporting image.' +export const layoutDescription = 'A slide layout with title, grid of bullet points (title and description) with icons, and a supporting image.' const bulletIconsOnlySlideSchema = z.object({ title: z.string().min(3).max(40).default('Solutions').meta({ @@ -29,7 +30,7 @@ const bulletIconsOnlySlideSchema = z.object({ title: 'Custom Software', subtitle: 'We create tailored software to optimize processes and boost efficiency.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/code-bold.svg', __icon_query__: 'code software development' } }, @@ -37,7 +38,7 @@ const bulletIconsOnlySlideSchema = z.object({ title: 'Digital Consulting', subtitle: 'Our consultants guide organizations in leveraging the latest technologies.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/users-four-bold.svg', __icon_query__: 'users consulting team' } }, @@ -45,7 +46,7 @@ const bulletIconsOnlySlideSchema = z.object({ title: 'Support Services', subtitle: 'We provide ongoing support to help businesses adapt and maintain performance.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/headphones-bold.svg', __icon_query__: 'headphones support service' } }, @@ -53,7 +54,7 @@ const bulletIconsOnlySlideSchema = z.object({ title: 'Scalable Marketing', subtitle: 'Our data-driven strategies help businesses expand their reach and engagement.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/code-bold.svg', __icon_query__: 'trending up marketing growth' } } @@ -87,17 +88,26 @@ const BulletIconsOnlySlideLayout: React.FC = ({ return ( <> {/* Import Google Fonts */} - + +
+ {/* {(slideData as any)?.__companyName__ && ( */} +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ {/* )} */} {/* Decorative Wave Patterns */}
@@ -113,11 +123,11 @@ const BulletIconsOnlySlideLayout: React.FC = ({
{/* Main Content */} -
+
{/* Left Section - Title and Bullet Points */}
{/* Title */} -

+

{slideData?.title || 'Solutions'}

@@ -126,24 +136,26 @@ const BulletIconsOnlySlideLayout: React.FC = ({ {bulletPoints.map((bullet, index) => (
{/* Icon */} -
- {bullet.icon.__icon_query__} +
{/* Content */}
-

+

{bullet.title}

{bullet.subtitle && ( -

+

{bullet.subtitle}

)} @@ -156,14 +168,14 @@ const BulletIconsOnlySlideLayout: React.FC = ({ {/* Right Section - Image */}
{/* Decorative Elements */} -
+
- + = ({ return ( <> - {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Main Content */} -
+
{/* Title Section - Full Width */}
-

+

{slideData?.title || 'Problem'}

@@ -94,7 +102,7 @@ const BulletWithIconsSlideLayout: React.FC = ({ - + @@ -113,7 +121,7 @@ const BulletWithIconsSlideLayout: React.FC = ({
{/* Decorative Sparkle */} -
+
@@ -123,7 +131,7 @@ const BulletWithIconsSlideLayout: React.FC = ({ {/* Right Section - Content */}
{/* Description */} -

+

{slideData?.description || 'Businesses face challenges with outdated technology and rising costs, limiting efficiency and growth in competitive markets.'}

@@ -132,21 +140,23 @@ const BulletWithIconsSlideLayout: React.FC = ({ {bulletPoints.map((bullet, index) => (
{/* Icon */} -
- {bullet.icon.__icon_query__} +
{/* Content */}
-

+

{bullet.title}

-
-

+

+

{bullet.description}

diff --git a/servers/nextjs/presentation-templates/general/ChartWithBulletsSlideLayout.tsx b/servers/nextjs/presentation-templates/general/ChartWithBulletsSlideLayout.tsx index f77e554c..564af2c3 100644 --- a/servers/nextjs/presentation-templates/general/ChartWithBulletsSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/ChartWithBulletsSlideLayout.tsx @@ -1,6 +1,7 @@ import React from 'react' import * as z from "zod"; import { IconSchema } from '@/presentation-templates/defaultSchemes'; +import { RemoteSvgIcon } from '@/app/hooks/useRemoteSvgIcon'; import { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent } from "@/components/ui/chart"; import { BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Cell, ResponsiveContainer } from "recharts"; @@ -64,7 +65,7 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Total Addressable Market', description: 'Companies can use TAM to plan future expansion and investment.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/chart-line-up-bold.svg', __icon_query__: 'target market scope' } }, @@ -72,7 +73,7 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Serviceable Available Market', description: 'Indicates more measurable market segments for sales efforts.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/chart-line-up-bold.svg', __icon_query__: 'pie chart analysis' } }, @@ -80,7 +81,7 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Serviceable Obtainable Market', description: 'Help companies plan development strategies according to the market.', icon: { - __icon_url__: '/static/icons/placeholder.png', + __icon_url__: 'https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/icons/bold/chart-line-up-bold.svg', __icon_query__: 'trending up growth' } } @@ -120,7 +121,7 @@ const BULLET_COLORS = [ const ChartWithBulletsSlideLayout: React.FC = ({ data: slideData }) => { const chartData = slideData?.chartData?.data || []; const chartType = slideData?.chartData?.type; - const color = slideData?.color || '#3b82f6'; + const color = slideData?.color || 'var(--primary-accent-color,#9333ea)'; const xAxis = chartType === 'scatter' ? 'x' : 'name'; const yAxis = chartType === 'scatter' ? 'y' : 'value'; const showLegend = slideData?.showLegend || false; @@ -128,6 +129,14 @@ const ChartWithBulletsSlideLayout: React.FC = const bulletPoints = slideData?.bulletPoints || [] const renderChart = () => { + const renderPieLabel = (props: any) => { + const { name, percent, x, y, textAnchor } = props; + return ( + + {`${name} ${(percent * 100).toFixed(0)}%`} + + ); + }; const commonProps = { data: chartData, margin: { top: 20, right: 30, left: 40, bottom: 60 }, @@ -137,9 +146,9 @@ const ChartWithBulletsSlideLayout: React.FC = case 'bar': return ( - - - + + + {showTooltip && } />} {showLegend && } />} @@ -149,9 +158,9 @@ const ChartWithBulletsSlideLayout: React.FC = case 'line': return ( - - - + + + {showTooltip && } />} {showLegend && } />} = case 'area': return ( - - - + + + {showTooltip && } />} {showLegend && } />} = outerRadius={70} fill={color} dataKey={yAxis} - label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`} + label={renderPieLabel} > - {chartData.map((entry, index) => ( - + {chartData.map((_, index) => ( + ))} @@ -206,9 +215,9 @@ const ChartWithBulletsSlideLayout: React.FC = case 'scatter': return ( - - - + + + {showTooltip && } />} {showLegend && } />} @@ -222,34 +231,42 @@ const ChartWithBulletsSlideLayout: React.FC = return ( <> - {/* Import Google Fonts */} - + +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Main Content */}
{/* Left Section - Title, Description, Chart */}
{/* Title */} -

+

{slideData?.title || 'Market Size'}

{/* Description */} -

+

{slideData?.description || 'Businesses face challenges with outdated technology and rising costs, limiting efficiency and growth in competitive markets.'}

{/* Chart Container */} -
+
{renderChart()} @@ -263,25 +280,27 @@ const ChartWithBulletsSlideLayout: React.FC = key={index} className="rounded-2xl p-6 text-white" style={{ - backgroundColor: BULLET_COLORS[index % BULLET_COLORS.length] + backgroundColor: 'var(--primary-accent-color,#9333ea)' }} > {/* Icon and Title */}
-
- {bullet.icon.__icon_query__} +
-

+

{bullet.title}

{/* Description */} -

+

{bullet.description}

diff --git a/servers/nextjs/presentation-templates/general/IntroSlideLayout.tsx b/servers/nextjs/presentation-templates/general/IntroSlideLayout.tsx index 53f1a9ee..816ac529 100644 --- a/servers/nextjs/presentation-templates/general/IntroSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/IntroSlideLayout.tsx @@ -16,8 +16,8 @@ const introSlideSchema = z.object({ presenterName: z.string().min(2).max(50).default('John Doe').meta({ description: "Name of the presenter", }), - presentationDate: z.string().min(2).max(50).default('December 2024').meta({ - description: "Date of the presentation", + presentationDate: z.string().min(2).max(50).default('December 2025').meta({ + description: "Date of the presentation must be the latest date like today's date", }), image: ImageSchema.default({ __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', @@ -44,22 +44,29 @@ const IntroSlideLayout: React.FC = ({ data: slideData }) const presenterInitials = getInitials(slideData?.presenterName || 'John Doe'); return ( <> - {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Main Content */} -
+
{/* Left Section - Image */}
@@ -74,34 +81,34 @@ const IntroSlideLayout: React.FC = ({ data: slideData }) {/* Right Section - Content */}
{/* Title */} -

+

{slideData?.title || 'Product Overview'}

{/* Purple accent line */} -
+
{/* Description */} -

+

{slideData?.description || 'Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.'}

{/* Presenter Section */} -
+
{/* Custom Initials Icon */} -
- +
+ {presenterInitials}
{/* Presenter Info */}
- + {slideData?.presenterName || 'John Doe'} - + {slideData?.presentationDate || 'December 2024'}
diff --git a/servers/nextjs/presentation-templates/general/MetricsSlideLayout.tsx b/servers/nextjs/presentation-templates/general/MetricsSlideLayout.tsx index 266d0fc2..3585a430 100644 --- a/servers/nextjs/presentation-templates/general/MetricsSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/MetricsSlideLayout.tsx @@ -10,7 +10,7 @@ const metricsSlideSchema = z.object({ description: "Main title of the slide", }), metrics: z.array(z.object({ - label: z.string().min(2).max(100).meta({ + label: z.string().min(2).max(50).meta({ description: "Metric label/title" }), value: z.string().min(1).max(10).meta({ @@ -77,17 +77,25 @@ const MetricsSlideLayout: React.FC = ({ data: slideData return ( <> {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Decorative Wave Patterns */}
@@ -108,11 +116,11 @@ const MetricsSlideLayout: React.FC = ({ data: slideData {/* Main Content */} -
+
{/* Title */}
-

+

{slideData?.title || 'Company Traction'}

@@ -124,23 +132,22 @@ const MetricsSlideLayout: React.FC = ({ data: slideData {metrics.map((metric, index) => (
{/* Label */} -
+
{metric.label}
{/* Large Metric Value */} -
+
{metric.value}
{/* Description Box */}
-

+

{metric.description}

diff --git a/servers/nextjs/presentation-templates/general/MetricsWithImageSlideLayout.tsx b/servers/nextjs/presentation-templates/general/MetricsWithImageSlideLayout.tsx index f30b3f34..af7d1c70 100644 --- a/servers/nextjs/presentation-templates/general/MetricsWithImageSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/MetricsWithImageSlideLayout.tsx @@ -54,18 +54,25 @@ const MetricsWithImageSlideLayout: React.FC = return ( <> - {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Decorative Wave Patterns */}
@@ -81,7 +88,7 @@ const MetricsWithImageSlideLayout: React.FC =
{/* Main Content */} -
+
{/* Left Section - Image */}
@@ -96,12 +103,12 @@ const MetricsWithImageSlideLayout: React.FC = {/* Right Section - Content and Metrics */}
{/* Title */} -

+

{slideData?.title || 'Competitive Advantage'}

{/* Description */} -

+

{slideData?.description || 'Ginyard International Co. stands out by offering custom digital solutions tailored to client needs, alongside long-term support to ensure lasting relationships and continuous adaptation.'}

@@ -109,10 +116,10 @@ const MetricsWithImageSlideLayout: React.FC =
{metrics.map((metric, index) => (
-
+
{metric.label}
-
+
{metric.value}
diff --git a/servers/nextjs/presentation-templates/general/NumberedBulletsSlideLayout.tsx b/servers/nextjs/presentation-templates/general/NumberedBulletsSlideLayout.tsx index 3b299513..e260769c 100644 --- a/servers/nextjs/presentation-templates/general/NumberedBulletsSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/NumberedBulletsSlideLayout.tsx @@ -58,30 +58,37 @@ const NumberedBulletsSlideLayout: React.FC = ({ return ( <> - {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Main Content Container */} -
+
{/* Top Section - Title and Image */}
{/* Title Section */}
-

+

{slideData?.title || 'Market Validation'}

{/* Purple accent line */} -
+
{/* Image Section */} @@ -89,7 +96,7 @@ const NumberedBulletsSlideLayout: React.FC = ({ {slideData?.image?.__image_prompt__
@@ -100,17 +107,17 @@ const NumberedBulletsSlideLayout: React.FC = ({
{/* Number */}
-
+
{String(index + 1).padStart(2, '0')}
{/* Content */}
-

+

{bullet.title}

-

+

{bullet.description}

@@ -132,9 +139,9 @@ const NumberedBulletsSlideLayout: React.FC = ({ /> - - - + + + diff --git a/servers/nextjs/presentation-templates/general/QuoteSlideLayout.tsx b/servers/nextjs/presentation-templates/general/QuoteSlideLayout.tsx index d6b6e234..84ee087b 100644 --- a/servers/nextjs/presentation-templates/general/QuoteSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/QuoteSlideLayout.tsx @@ -36,17 +36,25 @@ const QuoteSlideLayout: React.FC = ({ data: slideData }) return ( <> {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Background Image */}
= ({ data: slideData }) }} /> - {/* Background Overlay */} -
+ {/* Background Overlay - low opacity primary accent */} +
{/* Decorative Elements */}
@@ -64,16 +75,16 @@ const QuoteSlideLayout: React.FC = ({ data: slideData })
{/* Main Content */} -
+
{/* Heading */}
-

+

{slideData?.heading || 'Words of Wisdom'}

{/* Purple accent line */} -
+
{/* Quote Section */} @@ -81,7 +92,7 @@ const QuoteSlideLayout: React.FC = ({ data: slideData }) {/* Quote Icon */}
@@ -90,24 +101,24 @@ const QuoteSlideLayout: React.FC = ({ data: slideData })
{/* Quote Text */} -
+
"{slideData?.quote || 'Success is not final, failure is not fatal: it is the courage to continue that counts. The future belongs to those who believe in the beauty of their dreams.'}"
{/* Author */}
-
+
{slideData?.author || 'Winston Churchill'} -
+
- {/* Bottom Decorative Border */} -
+ {/* Bottom Decorative Border uses heading color */} +
) diff --git a/servers/nextjs/presentation-templates/general/TableInfoSlideLayout.tsx b/servers/nextjs/presentation-templates/general/TableInfoSlideLayout.tsx index 693ae100..46da6655 100644 --- a/servers/nextjs/presentation-templates/general/TableInfoSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/TableInfoSlideLayout.tsx @@ -52,17 +52,25 @@ const TableInfoSlideLayout: React.FC = ({ data: slide return ( <> {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Decorative Wave Patterns */}
@@ -81,26 +89,26 @@ const TableInfoSlideLayout: React.FC = ({ data: slide
{/* Main Content */} -
+
{/* Title Section */}
-

+

{slideData?.title || 'Market Comparison'}

{/* Purple accent line */} -
+
{/* Table Section */}
-
+
{/* Table Header */} -
+
{tableHeaders.map((header, index) => ( -
+
{header}
))} @@ -112,11 +120,20 @@ const TableInfoSlideLayout: React.FC = ({ data: slide {tableRows.map((row, rowIndex) => (
{row.slice(0, tableHeaders.length).map((cell, cellIndex) => ( -
+
{cell}
))} @@ -131,7 +148,7 @@ const TableInfoSlideLayout: React.FC = ({ data: slide {/* Description Section */}
-

+

{slideData?.description || 'This comparison shows our competitive position in the market. While we currently have a smaller market share, our growth rate significantly exceeds competitors, indicating strong potential for future expansion.'}

diff --git a/servers/nextjs/presentation-templates/general/TableOfContentsSlideLayout.tsx b/servers/nextjs/presentation-templates/general/TableOfContentsSlideLayout.tsx index 408bb6d0..244153ed 100644 --- a/servers/nextjs/presentation-templates/general/TableOfContentsSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/TableOfContentsSlideLayout.tsx @@ -48,27 +48,34 @@ const TableOfContentsSlideLayout: React.FC = ({ return ( <> - {/* Import Google Fonts */} - +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Title Section */} -
-

+
+

Table of Contents

{/* Decorative Wave */}
- + = ({
{/* Number Box */} -
+
{section.number}
{/* Title */} - + {section.title}
{/* Page Number */}
- + {section.pageNumber} {/* Dotted line effect */} -
+
.....
@@ -115,21 +122,21 @@ const TableOfContentsSlideLayout: React.FC = ({
{/* Number Box */} -
+
{section.number}
{/* Title */} - + {section.title}
{/* Page Number */}
- + {section.pageNumber} {/* Dotted line effect */} -
+
.....
diff --git a/servers/nextjs/presentation-templates/general/TeamSlideLayout.tsx b/servers/nextjs/presentation-templates/general/TeamSlideLayout.tsx index 0e87ff1c..5ae1c08d 100644 --- a/servers/nextjs/presentation-templates/general/TeamSlideLayout.tsx +++ b/servers/nextjs/presentation-templates/general/TeamSlideLayout.tsx @@ -32,7 +32,7 @@ const teamSlideSchema = z.object({ position: 'CEO', description: 'Strategic leader with 15+ years experience in digital transformation and business growth.', image: { - __image_url__: 'https://images.unsplash.com/photo-1494790108755-2616b612994a?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', + __image_url__: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', __image_prompt__: 'Professional businesswoman CEO headshot' } }, @@ -92,18 +92,25 @@ const TeamSlideLayout: React.FC = ({ data: slideData }) => return ( <> - {/* Import Google Fonts */} - - + +
+ {(slideData as any)?.__companyName__ && ( +
+
+ + {(slideData as any)?.__companyName__ || 'Company Name'} + +
+
+
+ )} {/* Decorative Wave Pattern */}
@@ -113,19 +120,19 @@ const TeamSlideLayout: React.FC = ({ data: slideData }) =>
{/* Main Content */} -
+
{/* Left Section - Title and Company Description */}
{/* Title */} -

+

{slideData?.title || 'Our Team Members'}

{/* Purple accent line */} -
+
{/* Company Description */} -

+

{slideData?.companyDescription || 'Ginyard International Co. is a leading provider of innovative digital solutions tailored for businesses. Our mission is to empower organizations to achieve their goals through cutting-edge technology and strategic partnerships.'}

@@ -136,7 +143,7 @@ const TeamSlideLayout: React.FC = ({ data: slideData }) => {teamMembers.map((member, index) => (
{/* Member Photo */} -
+
{member.image.__image_prompt__ = ({ data: slideData }) => {/* Member Info */}
-

+

{member.name}

-

+

{member.position}

-

+

{member.description}