Merge branch 'feat/new_templates' of github.com:presenton/presenton into feat/new_templates
This commit is contained in:
commit
b1c7c3fd27
25 changed files with 479 additions and 466 deletions
0
.codex
Normal file
0
.codex
Normal file
|
|
@ -27,7 +27,7 @@ export const Schema = z.object({
|
|||
requestSnippet: z.object({
|
||||
language: z.string().min(2).max(10),
|
||||
fileName: z.string().min(3).max(24),
|
||||
content: z.string().min(20).max(220),
|
||||
content: z.string().min(20).max(500),
|
||||
}).default({
|
||||
language: "json",
|
||||
fileName: "request.json",
|
||||
|
|
@ -59,9 +59,6 @@ export const Schema = z.object({
|
|||
}).meta({
|
||||
description: "Response payload example.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("3 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -167,17 +164,6 @@ const CodeSlide03ApiRequestResponse = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] z-50 left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -88,9 +88,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Six feature cards displayed in a 3x2 grid.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("4 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -143,18 +140,6 @@ const CodeSlide04FeatureGrid = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] z-50 left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
import * as z from "zod";
|
||||
|
||||
const CODE_BLOCK_MAX_FONT_SIZE = 16;
|
||||
const CODE_BLOCK_MIN_FONT_SIZE = 8;
|
||||
const CODE_BLOCK_WIDTH = 506;
|
||||
const CODE_BLOCK_HEIGHT = 430;
|
||||
const CODE_CHAR_WIDTH_RATIO = 0.62;
|
||||
const CODE_LINE_HEIGHT_RATIO = 1.25;
|
||||
const CODE_FONT_FAMILY = "var(--code-font-family,'Liberation Mono', monospace)";
|
||||
|
||||
function splitCollapsedPythonImports(line: string) {
|
||||
const importSegments = line
|
||||
.split(/(?=\sfrom\s+[A-Za-z0-9_.]+\s+import\s+)/g)
|
||||
.map((segment) => segment.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
return importSegments.length > 1 ? importSegments : [line];
|
||||
}
|
||||
|
||||
function expandInlinePythonStatement(line: string) {
|
||||
const inlineReturnMatch = line.match(/^(\s*def\s+[^(]+\([^)]*\):)\s+return\s+(.+)$/);
|
||||
|
||||
if (!inlineReturnMatch) {
|
||||
return [line];
|
||||
}
|
||||
|
||||
return [inlineReturnMatch[1], ` return ${inlineReturnMatch[2]}`];
|
||||
}
|
||||
|
||||
function expandPathListAssignment(line: string) {
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
if (!trimmedLine.startsWith("urlpatterns = [") || !trimmedLine.endsWith("]")) {
|
||||
return [line];
|
||||
}
|
||||
|
||||
const pathCalls = trimmedLine.match(/path\([^)]*\)/g);
|
||||
|
||||
if (!pathCalls?.length) {
|
||||
return [line];
|
||||
}
|
||||
|
||||
return [
|
||||
"urlpatterns = [",
|
||||
...pathCalls.map((pathCall) => ` ${pathCall},`),
|
||||
"]",
|
||||
];
|
||||
}
|
||||
|
||||
function normalizePythonCode(content: string) {
|
||||
const normalizedLines: string[] = [];
|
||||
|
||||
for (const line of content.split("\n")) {
|
||||
const importLines = splitCollapsedPythonImports(line);
|
||||
|
||||
for (const importLine of importLines) {
|
||||
const expandedPathLines = expandPathListAssignment(importLine);
|
||||
|
||||
for (const expandedPathLine of expandedPathLines) {
|
||||
normalizedLines.push(...expandInlinePythonStatement(expandedPathLine));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return normalizedLines.join("\n").replace(/\n{3,}/g, "\n\n");
|
||||
}
|
||||
|
||||
function normalizeCodeContent(language?: string, content?: string) {
|
||||
let normalizedContent = (content || "")
|
||||
.replace(/\r\n?/g, "\n")
|
||||
.replace(/\\\[/g, "[")
|
||||
.replace(/\\\]/g, "]")
|
||||
.trimEnd();
|
||||
|
||||
if (language?.toLowerCase() === "python") {
|
||||
normalizedContent = normalizePythonCode(normalizedContent);
|
||||
}
|
||||
|
||||
return normalizedContent;
|
||||
}
|
||||
|
||||
function getCodeBlockTypography(content?: string) {
|
||||
const normalizedLines = (content || "").replace(/\t/g, " ").split("\n");
|
||||
const longestLineLength = Math.max(
|
||||
1,
|
||||
...normalizedLines.map((line) => line.length)
|
||||
);
|
||||
|
||||
for (let fontSize = CODE_BLOCK_MAX_FONT_SIZE; fontSize >= CODE_BLOCK_MIN_FONT_SIZE; fontSize -= 0.5) {
|
||||
const lineHeight = Math.round(fontSize * CODE_LINE_HEIGHT_RATIO);
|
||||
const fitsWidth = longestLineLength * fontSize * CODE_CHAR_WIDTH_RATIO <= CODE_BLOCK_WIDTH;
|
||||
const fitsHeight = normalizedLines.length * lineHeight <= CODE_BLOCK_HEIGHT;
|
||||
|
||||
if (fitsWidth && fitsHeight) {
|
||||
return { fontSize, lineHeight };
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
fontSize: CODE_BLOCK_MIN_FONT_SIZE,
|
||||
lineHeight: Math.round(CODE_BLOCK_MIN_FONT_SIZE * CODE_LINE_HEIGHT_RATIO),
|
||||
};
|
||||
}
|
||||
|
||||
function getCodeLineRuns(content: string, lineHeight: number) {
|
||||
const codeLineRuns: { text: string; marginTop: number }[] = [];
|
||||
let blankLineCount = 0;
|
||||
|
||||
for (const line of content.split("\n")) {
|
||||
if (line.length === 0) {
|
||||
blankLineCount += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
codeLineRuns.push({
|
||||
text: line,
|
||||
marginTop: blankLineCount * lineHeight,
|
||||
});
|
||||
blankLineCount = 0;
|
||||
}
|
||||
|
||||
return codeLineRuns;
|
||||
}
|
||||
|
||||
export const slideLayoutId = "code-explanation-split-slide";
|
||||
export const slideLayoutName = "Code Explanation Split Slide";
|
||||
export const slideLayoutDescription =
|
||||
"A two-column slide with a code panel on the left and description on the right.";
|
||||
|
||||
export const Schema = z.object({
|
||||
title: z.string().min(8).max(24).default("Code + Explanation").meta({
|
||||
description: "Slide heading shown at the top-left.",
|
||||
}),
|
||||
codeSnippet: z.object({
|
||||
language: z.string().min(2).max(10).meta({
|
||||
description: "Programming language of the snippet",
|
||||
}),
|
||||
fileName: z.string().min(3).max(30).meta({
|
||||
description: "File name label shown above the code snippet.",
|
||||
}),
|
||||
content: z.string().min(20).max(520).meta({
|
||||
description: "The actual code content to be displayed.",
|
||||
}),
|
||||
}).default({
|
||||
language: "tsx",
|
||||
fileName: "components/UserAuth.tsx",
|
||||
content: `import { useState } from "react";
|
||||
import { login } from "@/lib/auth";
|
||||
|
||||
export function UserAuth() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
const user = await login(email, password);
|
||||
console.log("Logged in:", user);
|
||||
};
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
`,
|
||||
}).meta({
|
||||
description: "Code sample shown in the left panel.",
|
||||
}),
|
||||
descriptionTitle: z.string().min(4).max(20).default("Description").meta({
|
||||
description: "Heading shown above the paragraph.",
|
||||
}),
|
||||
description: z
|
||||
.string()
|
||||
.min(40)
|
||||
.max(360)
|
||||
.default(
|
||||
"This component manages credentials as local state and submits them through an async handler. The login utility abstracts network details while the handler keeps the UI flow predictable. Keep validation and side effects isolated so changes remain safe when authentication requirements evolve. "
|
||||
)
|
||||
.meta({
|
||||
description: "Description paragraph shown in the right column.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
const CodeSlide02CodeExplanationSplit = ({
|
||||
data,
|
||||
}: {
|
||||
data: Partial<SchemaType>;
|
||||
}) => {
|
||||
const normalizedCodeContent = normalizeCodeContent(
|
||||
data.codeSnippet?.language,
|
||||
data.codeSnippet?.content
|
||||
);
|
||||
const codeTypography = getCodeBlockTypography(normalizedCodeContent);
|
||||
const codeLineRuns = getCodeLineRuns(normalizedCodeContent, codeTypography.lineHeight);
|
||||
|
||||
return (
|
||||
<>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&display=swap" rel="stylesheet" />
|
||||
<div
|
||||
className="relative h-[720px] w-[1280px] overflow-hidden p-[53px]"
|
||||
style={{
|
||||
backgroundColor: "var(--background-color,#101B37)",
|
||||
fontFamily: "var(--body-font-family,Nunito Sans)",
|
||||
}}
|
||||
>
|
||||
|
||||
<div className="relative z-10 flex h-full flex-col">
|
||||
<h2 className="text-[64px] font-medium" style={{ color: "var(--background-text,#ffffff)" }}>{data.title}</h2>
|
||||
|
||||
<div className="mt-[22px] grid min-h-0 flex-1 grid-cols-2 gap-[34px]">
|
||||
<div
|
||||
className="flex h-full min-h-0 flex-col overflow-hidden rounded-[18px] border"
|
||||
style={{
|
||||
backgroundColor: "var(--card-color,#0F172B80)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="text-[18px] capitalize rounded-t-[18px] border px-[26px] py-3"
|
||||
style={{
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
backgroundColor: "var(--card-color,#0F172BCC)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
{data.codeSnippet?.fileName}
|
||||
</p>
|
||||
<div
|
||||
className="min-h-0 w-full flex-1 overflow-hidden px-[32px] py-[20px]"
|
||||
style={{
|
||||
color: "var(--background-text,#ffffff)",
|
||||
fontFamily: CODE_FONT_FAMILY,
|
||||
}}
|
||||
>
|
||||
{codeLineRuns.map((codeLineRun, index) => (
|
||||
<div
|
||||
key={`code-line-${index}`}
|
||||
style={{
|
||||
marginTop: codeLineRun.marginTop ? `${codeLineRun.marginTop}px` : undefined,
|
||||
fontSize: `${codeTypography.fontSize}px`,
|
||||
lineHeight: `${codeTypography.lineHeight}px`,
|
||||
whiteSpace: "pre",
|
||||
}}
|
||||
>
|
||||
{codeLineRun.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className=" ">
|
||||
<h3 className="text-[24px] font-medium" style={{ color: "var(--background-text,#f1f4ff)" }}>{data.descriptionTitle}</h3>
|
||||
<p className="mt-[18px] text-[22px] leading-[145%]" style={{ color: "var(--background-text,#d2d9ff)" }}>
|
||||
{data.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeSlide02CodeExplanationSplit;
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
|
||||
export const slideLayoutId = "code-explanation-split-slide";
|
||||
export const slideLayoutName = "Code Explanation Split Slide";
|
||||
export const slideLayoutDescription =
|
||||
"A two-column slide with a code panel on the left and description on the right.";
|
||||
|
||||
export const Schema = z.object({
|
||||
title: z.string().min(8).max(24).default("Code + Explanation").meta({
|
||||
description: "Slide heading shown at the top-left.",
|
||||
}),
|
||||
codeSnippet: z.object({
|
||||
language: z.string().min(2).max(10).meta({
|
||||
description: "Programming language of the snippet",
|
||||
}),
|
||||
fileName: z.string().min(3).max(30).meta({
|
||||
description: "File name label shown above the code snippet.",
|
||||
}),
|
||||
content: z.string().min(20).max(520).meta({
|
||||
description: "The actual code content to be displayed.",
|
||||
}),
|
||||
}).default({
|
||||
language: "tsx",
|
||||
fileName: "components/UserAuth.tsx",
|
||||
content: `import { useState } from "react";
|
||||
import { login } from "@/lib/auth";
|
||||
|
||||
export function UserAuth() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
const user = await login(email, password);
|
||||
console.log("Logged in:", user);
|
||||
};
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
`,
|
||||
}).meta({
|
||||
description: "Code sample shown in the left panel.",
|
||||
}),
|
||||
descriptionTitle: z.string().min(4).max(20).default("Description").meta({
|
||||
description: "Heading shown above the paragraph.",
|
||||
}),
|
||||
description: z
|
||||
.string()
|
||||
.min(40)
|
||||
.max(360)
|
||||
.default(
|
||||
"This component manages credentials as local state and submits them through an async handler. The login utility abstracts network details while the handler keeps the UI flow predictable. Keep validation and side effects isolated so changes remain safe when authentication requirements evolve. "
|
||||
)
|
||||
.meta({
|
||||
description: "Description paragraph shown in the right column.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("2 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
const CodeSlide02CodeExplanationSplit = ({
|
||||
data,
|
||||
}: {
|
||||
data: Partial<SchemaType>;
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&display=swap" rel="stylesheet" />
|
||||
<div
|
||||
className="relative h-[720px] w-[1280px] overflow-hidden p-[53px]"
|
||||
style={{
|
||||
backgroundColor: "var(--background-color,#101B37)",
|
||||
fontFamily: "var(--body-font-family,Nunito Sans)",
|
||||
}}
|
||||
>
|
||||
|
||||
<div className="relative z-10 flex h-full flex-col">
|
||||
<h2 className="text-[64px] font-medium" style={{ color: "var(--background-text,#ffffff)" }}>{data.title}</h2>
|
||||
|
||||
<div className="mt-[22px] grid min-h-0 flex-1 grid-cols-2 gap-[34px]">
|
||||
<div
|
||||
className=" flex-1 border rounded-[18px]"
|
||||
style={{
|
||||
backgroundColor: "var(--card-color,#0F172B80)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="text-[18px] capitalize rounded-t-[18px] border px-[26px] py-3"
|
||||
style={{
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
backgroundColor: "var(--card-color,#0F172BCC)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
{data.codeSnippet?.fileName}
|
||||
</p>
|
||||
<pre className=" w-full px-[32px] py-[20px] whitespace-pre-wrap break-words overflow-hidden" style={{ color: "var(--background-text,#ffffff)" }}>
|
||||
|
||||
<code className="w-full ">
|
||||
{data.codeSnippet?.content}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div className=" ">
|
||||
<h3 className="text-[24px] font-medium" style={{ color: "var(--background-text,#f1f4ff)" }}>{data.descriptionTitle}</h3>
|
||||
<p className="mt-[18px] text-[22px] leading-[145%]" style={{ color: "var(--background-text,#d2d9ff)" }}>
|
||||
{data.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] z-50 left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeSlide02CodeExplanationSplit;
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
const ComparisonRowSchema = z.object({
|
||||
feature: z.string().min(4).max(17).meta({
|
||||
description: "Feature label shown in the first column.",
|
||||
}),
|
||||
column1: z.string().max(10).meta({
|
||||
description: "Column 1 cell value.",
|
||||
}),
|
||||
column2: z.string().max(10).meta({
|
||||
description: "Column 2 cell value.",
|
||||
}),
|
||||
column3: z.string().max(10).meta({
|
||||
description: "Column 3 cell value.",
|
||||
}),
|
||||
});
|
||||
|
||||
export const slideLayoutId = "table-slide";
|
||||
export const slideLayoutName = "Table Slide";
|
||||
export const slideLayoutDescription =
|
||||
"A slide with title and a table.";
|
||||
|
||||
export const Schema = z.object({
|
||||
title: z.string().min(6).max(18).default("Comparison").meta({
|
||||
description: "Slide title shown above the table.",
|
||||
}),
|
||||
tableColumns: z.array(z.string().max(4)).meta({
|
||||
description: "Table columns shown in the first row.",
|
||||
}).default(["Feature", "Column 1", "Column 2", "Column 3"]),
|
||||
rows: z
|
||||
.array(ComparisonRowSchema)
|
||||
.min(1)
|
||||
.max(6)
|
||||
.default([
|
||||
{ feature: "Component-based", column1: "check", column2: "check", column3: "check" },
|
||||
{ feature: "TypeScript Support", column1: "check", column2: "check", column3: "check" },
|
||||
{ feature: "Learning Curve", column1: "Medium", column2: "Easy", column3: "Steep" },
|
||||
{ feature: "Bundle Size", column1: "40KB", column2: "34KB", column3: "167KB" },
|
||||
{ feature: "Performance", column1: "Excellent", column2: "Excellent", column3: "Good" },
|
||||
{ feature: "Community Size", column1: "Huge", column2: "Large", column3: "Large" },
|
||||
])
|
||||
.meta({
|
||||
description: "Six comparison rows shown in the table.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("5 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
function renderCell(value: string) {
|
||||
if (value && value.toLowerCase() === "check") {
|
||||
return <span className="text-[26px] px-[32px]" style={{ color: "var(--graph-2,#37f08e)" }}>✓</span>;
|
||||
}
|
||||
|
||||
return <span className="text-[18px] px-[32px]" style={{ color: "var(--background-text,#CAD5E2)" }}>{value}</span>;
|
||||
}
|
||||
|
||||
const CodeSlide05ComparisonTable = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&display=swap" rel="stylesheet" />
|
||||
<div
|
||||
className="relative h-[720px] w-[1280px] overflow-hidden p-[53px]"
|
||||
style={{
|
||||
backgroundColor: "var(--background-color,#101B37)",
|
||||
fontFamily: "var(--body-font-family,Nunito Sans)",
|
||||
}}
|
||||
>
|
||||
|
||||
<h2 className="text-[64px] font-medium" style={{ color: "var(--background-text,#ffffff)" }}>{data.title}</h2>
|
||||
|
||||
<div
|
||||
className="mt-[22px] min-h-0 flex-1 rounded-[16px] border"
|
||||
style={{
|
||||
backgroundColor: "var(--card-color,#0F172BCC)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="grid grid-cols-[0.4fr_0.20fr_0.20fr_0.20fr] items-center"
|
||||
style={{
|
||||
color: "var(--background-text,#8ea1da)",
|
||||
gridTemplateColumns: `repeat(${data?.tableColumns?.length || 1}, 1fr)`,
|
||||
}}
|
||||
>
|
||||
|
||||
{data?.tableColumns?.map((column) => (
|
||||
<p
|
||||
key={column}
|
||||
className="px-[32px] py-[16px] text-[18px] text-center border-b border-r"
|
||||
style={{
|
||||
color: "var(--background-text,#ffffff)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
{column}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="">
|
||||
{data?.rows?.map((row) => (
|
||||
<div
|
||||
key={row.feature}
|
||||
className="grid grid-cols-[0.4fr_0.20fr_0.20fr_0.20fr]"
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${data?.tableColumns?.length || 1}, 1fr)`,
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="px-[32px] py-[20px] text-center text-[18px] border-b border-r"
|
||||
style={{
|
||||
color: "var(--background-text,#d5dcff)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
{row.feature}
|
||||
</p>
|
||||
<div className="flex justify-center items-center text-[18px] border-b border-r" style={{ borderColor: "var(--stroke,#1D293D80)" }}>{renderCell(row.column1)}</div>
|
||||
<div className="flex justify-center items-center text-[18px] border-b border-r" style={{ borderColor: "var(--stroke,#1D293D80)" }}>{renderCell(row.column2)}</div>
|
||||
<div className="flex justify-center items-center text-[18px] border-b border-r" style={{ borderColor: "var(--stroke,#1D293D80)" }}>{renderCell(row.column3)}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] z-50 left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeSlide05ComparisonTable;
|
||||
|
|
@ -22,9 +22,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Supporting subtitle shown under the heading.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("1 / 11").meta({
|
||||
description: "",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -47,17 +44,6 @@ const CodeSlide01RoadmapCover = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
</h2>
|
||||
<p className="mt-[35px] text-[26px] leading-[132%]" style={{ color: "var(--background-text,#d8ddff)" }}>{data.subtitle}</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -41,14 +41,11 @@ export const Schema = z.object({
|
|||
{ value: "50k+", label: "Active Users", subtext: "Last 12 months" },
|
||||
{ value: "50k+", label: "Active Users", subtext: "Last 12 months" },
|
||||
{ value: "50k+", label: "Active Users", subtext: "Last 12 months" },
|
||||
{ value: "50k+", label: "Active Users", subtext: "Last 12 months" }
|
||||
|
||||
])
|
||||
.meta({
|
||||
description: "Metric cards shown in the right column.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("10 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -70,17 +67,17 @@ const CodeSlide10MetricsSplit = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
|
||||
|
||||
<h2 className="text-[64px] font-medium tracking-[-0.03em]" style={{ color: "var(--background-text,#f2f4ff)" }}>{data.title}</h2>
|
||||
<div className="relative z-10 flex gap-10 ">
|
||||
<div className="relative z-10 flex min-h-[520px] gap-10">
|
||||
<div className="w-1/2">
|
||||
<h3 className="mt-[28px] text-[24px] font-medium" style={{ color: "var(--background-text,#f1f4ff)" }}>{data.explanationTitle}</h3>
|
||||
<p className="mt-[16px] text-[22px] leading-[145%]" style={{ color: "var(--background-text,#d2d9ff)" }}>{data.explanation}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col justify-center items-end gap-[25px] w-1/2">
|
||||
<div className="grid w-1/2 grid-cols-2 auto-rows-max place-content-center justify-items-center gap-x-[16px] gap-y-[25px]">
|
||||
{data?.metrics?.map((metric, index) => (
|
||||
<div
|
||||
key={`metric-grid-${index}`}
|
||||
className="rounded-[16px] w-[310px] border pt-[26px] px-[26px] pb-[16px] text-center"
|
||||
className="rounded-[16px] w-[280px] border pt-[26px] px-[26px] pb-[16px] text-center"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
backgroundColor: "var(--card-color,#0F172B80)",
|
||||
|
|
@ -93,17 +90,6 @@ const CodeSlide10MetricsSplit = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data?.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -22,9 +22,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Long-form explanation body.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("8 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -48,17 +45,6 @@ const CodeSlide08CodeExplanationText = ({ data }: { data: Partial<SchemaType> })
|
|||
<h3 className="mt-[34px] text-[24px] font-medium" style={{ color: "var(--background-text,#f1f4ff)" }}>{data.descriptionTitle}</h3>
|
||||
<p className="mt-[16px] text-[22px] leading-[145%]" style={{ color: "var(--background-text,#d2d9ff)" }}>{data.description}</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -36,9 +36,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Metrics cards in a grid.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("11 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -78,18 +75,6 @@ const CodeSlide11MetricsGrid = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -34,10 +34,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Table of contents entries.",
|
||||
}),
|
||||
|
||||
pageLabel: z.string().min(3).max(8).optional().default("9 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -49,13 +45,14 @@ function TocColumn({ items }: { items: { number: string; label: string, descript
|
|||
|
||||
|
||||
return (
|
||||
<div key={`${item.number}-${item.label}`} className="flex items-center gap-[10px]" style={{ color: "var(--background-text,#d5dcff)" }}>
|
||||
<div className=""><svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
<path d="M17.7778 17.7776C18.2493 17.7776 18.7015 17.5903 19.0349 17.2569C19.3683 16.9235 19.5556 16.4713 19.5556 15.9998V7.11095C19.5556 6.63945 19.3683 6.18727 19.0349 5.85387C18.7015 5.52047 18.2493 5.33317 17.7778 5.33317H10.7556C10.4583 5.33609 10.165 5.26438 9.90254 5.12462C9.6401 4.98486 9.41691 4.7815 9.25339 4.53317L8.53339 3.4665C8.37151 3.2207 8.15114 3.01893 7.89205 2.8793C7.63296 2.73967 7.34326 2.66655 7.04894 2.6665H3.55561C3.08411 2.6665 2.63193 2.8538 2.29853 3.1872C1.96513 3.5206 1.77783 3.97279 1.77783 4.44428V15.9998C1.77783 16.4713 1.96513 16.9235 2.29853 17.2569C2.63193 17.5903 3.08411 17.7776 3.55561 17.7776H17.7778Z" stroke="var(--primary-color,#51A2FF)" strokeWidth="1.77778" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg></div>
|
||||
<div key={`${item.number}-${item.label}`} className="flex items-start gap-[10px]" style={{ color: "var(--background-text,#d5dcff)" }}>
|
||||
<div className="flex items-center gap-[10px]">
|
||||
<div className=""><svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
<path d="M17.7778 17.7776C18.2493 17.7776 18.7015 17.5903 19.0349 17.2569C19.3683 16.9235 19.5556 16.4713 19.5556 15.9998V7.11095C19.5556 6.63945 19.3683 6.18727 19.0349 5.85387C18.7015 5.52047 18.2493 5.33317 17.7778 5.33317H10.7556C10.4583 5.33609 10.165 5.26438 9.90254 5.12462C9.6401 4.98486 9.41691 4.7815 9.25339 4.53317L8.53339 3.4665C8.37151 3.2207 8.15114 3.01893 7.89205 2.8793C7.63296 2.73967 7.34326 2.66655 7.04894 2.6665H3.55561C3.08411 2.6665 2.63193 2.8538 2.29853 3.1872C1.96513 3.5206 1.77783 3.97279 1.77783 4.44428V15.9998C1.77783 16.4713 1.96513 16.9235 2.29853 17.2569C2.63193 17.5903 3.08411 17.7776 3.55561 17.7776H17.7778Z" stroke="var(--primary-color,#51A2FF)" strokeWidth="1.77778" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg></div>
|
||||
<p className="w-[36px] text-[18px] leading-none" style={{ color: "var(--primary-color,#8EC5FF)" }}>{item.number}</p>
|
||||
</div>
|
||||
<div className="flex gap-[26px]">
|
||||
|
||||
<p className="w-[36px] text-[18px]" style={{ color: "var(--primary-color,#8EC5FF)" }}>{item.number}</p>
|
||||
<p className="text-[18px]" style={{ color: "var(--background-text,#ffffff)" }}>{item.label}</p>
|
||||
{item.description && <p className="text-[18px]" style={{ color: "var(--background-text,#ffffff)" }}>{item.description}</p>}
|
||||
</div>
|
||||
|
|
@ -91,17 +88,6 @@ const CodeSlide09TableOfContent = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
<TocColumn items={rightItems || []} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] z-50 left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
import * as z from "zod";
|
||||
|
||||
const DEFAULT_TABLE_COLUMNS = ["Feature", "Column 1", "Column 2", "Column 3"];
|
||||
|
||||
const DEFAULT_ROWS = [
|
||||
{ cells: ["Component-based", "check", "check", "check"] },
|
||||
{ cells: ["TypeScript Support", "check", "check", "check"] },
|
||||
{ cells: ["Learning Curve", "Medium", "Easy", "Steep"] },
|
||||
{ cells: ["Bundle Size", "40KB", "34KB", "167KB"] },
|
||||
{ cells: ["Performance", "Excellent", "Excellent", "Good"] },
|
||||
{ cells: ["Community Size", "Huge", "Large", "Large"] },
|
||||
];
|
||||
|
||||
const ComparisonRowSchema = z.object({
|
||||
cells: z.array(z.string().max(24)).min(1).max(6).meta({
|
||||
description: "Cell values for this row in left-to-right order. Match the number of table columns.",
|
||||
}),
|
||||
});
|
||||
|
||||
export const slideLayoutId = "table-slide";
|
||||
export const slideLayoutName = "Table Slide";
|
||||
export const slideLayoutDescription =
|
||||
"A slide with title and a table.";
|
||||
|
||||
export const Schema = z.object({
|
||||
title: z.string().min(6).max(18).default("Comparison").meta({
|
||||
description: "Slide title shown above the table.",
|
||||
}),
|
||||
tableColumns: z.array(z.string().max(18)).min(1).max(6).meta({
|
||||
description: "Table columns shown in the first row.",
|
||||
}).default(DEFAULT_TABLE_COLUMNS),
|
||||
rows: z
|
||||
.array(ComparisonRowSchema)
|
||||
.min(1)
|
||||
.max(6)
|
||||
.default(DEFAULT_ROWS)
|
||||
.meta({
|
||||
description: "Table rows where each row contains a cells array matching the table columns.",
|
||||
}),
|
||||
}).superRefine((value, ctx) => {
|
||||
value.rows.forEach((row, rowIndex) => {
|
||||
if (row.cells.length !== value.tableColumns.length) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["rows", rowIndex, "cells"],
|
||||
message: "Each row must contain the same number of cells as tableColumns.",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
function getGridTemplateColumns(columnCount: number) {
|
||||
if (columnCount <= 1) {
|
||||
return "minmax(0, 1fr)";
|
||||
}
|
||||
|
||||
return `minmax(0, 1.4fr) repeat(${columnCount - 1}, minmax(0, 1fr))`;
|
||||
}
|
||||
|
||||
function renderCell(value: string, isFirstColumn: boolean) {
|
||||
if (!isFirstColumn && value && value.toLowerCase() === "check") {
|
||||
return <span className="text-[26px] px-[32px]" style={{ color: "var(--graph-2,#37f08e)" }}>✓</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className="text-[18px] px-[32px]"
|
||||
style={{
|
||||
color: isFirstColumn
|
||||
? "var(--background-text,#d5dcff)"
|
||||
: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const CodeSlide05ComparisonTable = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const tableColumns = data.tableColumns?.length ? data.tableColumns : DEFAULT_TABLE_COLUMNS;
|
||||
const rows = data.rows?.length ? data.rows : DEFAULT_ROWS;
|
||||
const gridTemplateColumns = getGridTemplateColumns(tableColumns.length);
|
||||
|
||||
return (
|
||||
<>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&display=swap" rel="stylesheet" />
|
||||
<div
|
||||
className="relative h-[720px] w-[1280px] overflow-hidden p-[53px]"
|
||||
style={{
|
||||
backgroundColor: "var(--background-color,#101B37)",
|
||||
fontFamily: "var(--body-font-family,Nunito Sans)",
|
||||
}}
|
||||
>
|
||||
|
||||
<h2 className="text-[64px] font-medium" style={{ color: "var(--background-text,#ffffff)" }}>{data.title}</h2>
|
||||
|
||||
<div
|
||||
className="mt-[22px] min-h-0 flex-1 rounded-[16px] border"
|
||||
style={{
|
||||
backgroundColor: "var(--card-color,#0F172BCC)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="grid items-center"
|
||||
style={{
|
||||
color: "var(--background-text,#8ea1da)",
|
||||
gridTemplateColumns,
|
||||
}}
|
||||
>
|
||||
|
||||
{tableColumns.map((column, columnIndex) => (
|
||||
<p
|
||||
key={`${column}-${columnIndex}`}
|
||||
className="px-[32px] py-[16px] text-[18px] text-center border-b border-r"
|
||||
style={{
|
||||
color: "var(--background-text,#ffffff)",
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
borderRightWidth: columnIndex === tableColumns.length - 1 ? "0px" : undefined,
|
||||
}}
|
||||
>
|
||||
{column}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="">
|
||||
{rows.map((row, rowIndex) => (
|
||||
<div
|
||||
key={`row-${rowIndex}`}
|
||||
className="grid"
|
||||
style={{
|
||||
gridTemplateColumns,
|
||||
}}
|
||||
>
|
||||
{row.cells.map((cell, cellIndex) => (
|
||||
<div
|
||||
key={`row-${rowIndex}-cell-${cellIndex}`}
|
||||
className="flex items-center justify-center border-b border-r px-[20px] py-[20px] text-center"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#1D293D80)",
|
||||
borderRightWidth: cellIndex === row.cells.length - 1 ? "0px" : undefined,
|
||||
}}
|
||||
>
|
||||
{renderCell(cell, cellIndex === 0)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeSlide05ComparisonTable;
|
||||
|
|
@ -26,9 +26,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Eight use-case items shown in two columns.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("7 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -74,18 +71,6 @@ const CodeSlide07UseCaseList = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -71,9 +71,6 @@ export const Schema = z.object({
|
|||
.meta({
|
||||
description: "Workflow steps shown in sequence.",
|
||||
}),
|
||||
pageLabel: z.string().min(3).max(8).optional().default("6 / 11").meta({
|
||||
description: "Bottom pagination label.",
|
||||
}),
|
||||
});
|
||||
|
||||
export type SchemaType = z.infer<typeof Schema>;
|
||||
|
|
@ -130,17 +127,6 @@ const CodeSlide06Workflow = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
))}
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="absolute bottom-[26px] left-1/2 -translate-x-1/2 rounded-full border px-[22px] py-[8px] text-[14px]"
|
||||
style={{
|
||||
borderColor: "var(--stroke,#31415880)",
|
||||
backgroundColor: "var(--card-color,#1D293DCC)",
|
||||
color: "var(--background-text,#CAD5E2)",
|
||||
}}
|
||||
>
|
||||
{data.pageLabel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -113,7 +113,7 @@ const TeamSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
|||
{member.title}
|
||||
</p>
|
||||
<p className="mt-[14px] text-[28px] ">
|
||||
{member.name}
|
||||
{member.subtext}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -4,17 +4,17 @@ import { TemplateWithData, TemplateGroupSettings, createTemplateEntry, TemplateL
|
|||
// TODO: Step 1: Import All templates Layouts Here (like the ones below)
|
||||
|
||||
// Code templates
|
||||
import CodeSlide01RoadmapCover, { Schema as CodeRoadmapCoverSchema, slideLayoutId as CodeRoadmapCoverId, slideLayoutName as CodeRoadmapCoverName, slideLayoutDescription as CodeRoadmapCoverDesc } from "./Code/CodeSlide01RoadmapCover";
|
||||
import CodeSlide02CodeExplanationSplit, { Schema as CodeExplanationSplitSchema, slideLayoutId as CodeExplanationSplitId, slideLayoutName as CodeExplanationSplitName, slideLayoutDescription as CodeExplanationSplitDesc } from "./Code/CodeSlide02CodeExplanationSplit";
|
||||
import CodeSlide03ApiRequestResponse, { Schema as CodeApiRequestResponseSchema, slideLayoutId as CodeApiRequestResponseId, slideLayoutName as CodeApiRequestResponseName, slideLayoutDescription as CodeApiRequestResponseDesc } from "./Code/CodeSlide03ApiRequestResponse";
|
||||
import CodeSlide04FeatureGrid, { Schema as CodeFeatureGridSchema, slideLayoutId as CodeFeatureGridId, slideLayoutName as CodeFeatureGridName, slideLayoutDescription as CodeFeatureGridDesc } from "./Code/CodeSlide04FeatureGrid";
|
||||
import CodeSlide05ComparisonTable, { Schema as CodeComparisonTableSchema, slideLayoutId as CodeComparisonTableId, slideLayoutName as CodeComparisonTableName, slideLayoutDescription as CodeComparisonTableDesc } from "./Code/CodeSlide05ComparisonTable";
|
||||
import CodeSlide06Workflow, { Schema as CodeWorkflowSchema, slideLayoutId as CodeWorkflowId, slideLayoutName as CodeWorkflowName, slideLayoutDescription as CodeWorkflowDesc } from "./Code/CodeSlide06Workflow";
|
||||
import CodeSlide07UseCaseList, { Schema as CodeUseCaseListSchema, slideLayoutId as CodeUseCaseListId, slideLayoutName as CodeUseCaseListName, slideLayoutDescription as CodeUseCaseListDesc } from "./Code/CodeSlide07UseCaseList";
|
||||
import CodeSlide08CodeExplanationText, { Schema as CodeExplanationTextSchema, slideLayoutId as CodeExplanationTextId, slideLayoutName as CodeExplanationTextName, slideLayoutDescription as CodeExplanationTextDesc } from "./Code/CodeSlide08CodeExplanationText";
|
||||
import CodeSlide09TableOfContent, { Schema as CodeTableOfContentSchema, slideLayoutId as CodeTableOfContentId, slideLayoutName as CodeTableOfContentName, slideLayoutDescription as CodeTableOfContentDesc } from "./Code/CodeSlide09TableOfContent";
|
||||
import CodeSlide10MetricsSplit, { Schema as CodeMetricsSplitSchema, slideLayoutId as CodeMetricsSplitId, slideLayoutName as CodeMetricsSplitName, slideLayoutDescription as CodeMetricsSplitDesc } from "./Code/CodeSlide10MetricsSplit";
|
||||
import CodeSlide11MetricsGrid, { Schema as CodeMetricsGridSchema, slideLayoutId as CodeMetricsGridId, slideLayoutName as CodeMetricsGridName, slideLayoutDescription as CodeMetricsGridDesc } from "./Code/CodeSlide11MetricsGrid";
|
||||
import CodeSlide01RoadmapCover, { Schema as CodeRoadmapCoverSchema, slideLayoutId as CodeRoadmapCoverId, slideLayoutName as CodeRoadmapCoverName, slideLayoutDescription as CodeRoadmapCoverDesc } from "./Code/CoverSlide";
|
||||
import CodeSlide02CodeExplanationSplit, { Schema as CodeExplanationSplitSchema, slideLayoutId as CodeExplanationSplitId, slideLayoutName as CodeExplanationSplitName, slideLayoutDescription as CodeExplanationSplitDesc } from "./Code/CodeExplanationSplitSlide";
|
||||
import CodeSlide03ApiRequestResponse, { Schema as CodeApiRequestResponseSchema, slideLayoutId as CodeApiRequestResponseId, slideLayoutName as CodeApiRequestResponseName, slideLayoutDescription as CodeApiRequestResponseDesc } from "./Code/APIRequestResponseSlide";
|
||||
import CodeSlide04FeatureGrid, { Schema as CodeFeatureGridSchema, slideLayoutId as CodeFeatureGridId, slideLayoutName as CodeFeatureGridName, slideLayoutDescription as CodeFeatureGridDesc } from "./Code/CardsGridSlide";
|
||||
import CodeSlide05ComparisonTable, { Schema as CodeComparisonTableSchema, slideLayoutId as CodeComparisonTableId, slideLayoutName as CodeComparisonTableName, slideLayoutDescription as CodeComparisonTableDesc } from "./Code/TableSlide";
|
||||
import CodeSlide06Workflow, { Schema as CodeWorkflowSchema, slideLayoutId as CodeWorkflowId, slideLayoutName as CodeWorkflowName, slideLayoutDescription as CodeWorkflowDesc } from "./Code/WorkflowSlide";
|
||||
import CodeSlide07UseCaseList, { Schema as CodeUseCaseListSchema, slideLayoutId as CodeUseCaseListId, slideLayoutName as CodeUseCaseListName, slideLayoutDescription as CodeUseCaseListDesc } from "./Code/TwoColumnBulletListSlide";
|
||||
import CodeSlide08CodeExplanationText, { Schema as CodeExplanationTextSchema, slideLayoutId as CodeExplanationTextId, slideLayoutName as CodeExplanationTextName, slideLayoutDescription as CodeExplanationTextDesc } from "./Code/DescriptionTextSlide";
|
||||
import CodeSlide09TableOfContent, { Schema as CodeTableOfContentSchema, slideLayoutId as CodeTableOfContentId, slideLayoutName as CodeTableOfContentName, slideLayoutDescription as CodeTableOfContentDesc } from "./Code/TableOfContentSlide";
|
||||
import CodeSlide10MetricsSplit, { Schema as CodeMetricsSplitSchema, slideLayoutId as CodeMetricsSplitId, slideLayoutName as CodeMetricsSplitName, slideLayoutDescription as CodeMetricsSplitDesc } from "./Code/DescriptionAndMetricsSlide";
|
||||
import CodeSlide11MetricsGrid, { Schema as CodeMetricsGridSchema, slideLayoutId as CodeMetricsGridId, slideLayoutName as CodeMetricsGridName, slideLayoutDescription as CodeMetricsGridDesc } from "./Code/MetricsGridSlide";
|
||||
|
||||
// Education templates
|
||||
import EducationCoverSlide, { Schema as EduCoverSchema, slideLayoutId as EduCoverId, slideLayoutName as EduCoverName, slideLayoutDescription as EduCoverDesc } from "./Education/EducationCoverSlide";
|
||||
|
|
@ -46,19 +46,19 @@ import ReportSnapshotSlide, { Schema as PoReportSnapshotSchema, slideLayoutId as
|
|||
import TableOfContentSlide, { Schema as PoTableOfContentSchema, slideLayoutId as PoTableOfContentId, slideLayoutName as PoTableOfContentName, slideLayoutDescription as PoTableOfContentDesc } from "./ProductOverview/TableOfContentSlide";
|
||||
|
||||
// Report templates
|
||||
import ReportIntroSlide, { Schema as RepIntroSchema, slideLayoutId as RepIntroId, slideLayoutName as RepIntroName, slideLayoutDescription as RepIntroDesc } from "./Report/IntroSlide";
|
||||
import ReportIntroSlide, { Schema as RepIntroSchema, slideLayoutId as RepIntroId, slideLayoutName as RepIntroName, slideLayoutDescription as RepIntroDesc } from "./Report/IntroCoverSlide";
|
||||
import TitleDescriptionImageSlide, { Schema as RepIntroductionImageSchema, slideLayoutId as RepIntroductionImageId, slideLayoutName as RepIntroductionImageName, slideLayoutDescription as RepIntroductionImageDesc } from "./Report/TitleDescriptionImageSlide";
|
||||
import IntroductionStatsSlide, { Schema as RepIntroductionStatsSchema, slideLayoutId as RepIntroductionStatsId, slideLayoutName as RepIntroductionStatsName, slideLayoutDescription as RepIntroductionStatsDesc } from "./Report/IntroductionStatsSlide";
|
||||
import SolutionSlide, { Schema as RepSolutionSchema, slideLayoutId as RepSolutionId, slideLayoutName as RepSolutionName, slideLayoutDescription as RepSolutionDesc } from "./Report/SolutionSlide";
|
||||
import IntroductionStatsSlide, { Schema as RepIntroductionStatsSchema, slideLayoutId as RepIntroductionStatsId, slideLayoutName as RepIntroductionStatsName, slideLayoutDescription as RepIntroductionStatsDesc } from "./Report/MetricsSlide";
|
||||
import SolutionSlide, { Schema as RepSolutionSchema, slideLayoutId as RepSolutionId, slideLayoutName as RepSolutionName, slideLayoutDescription as RepSolutionDesc } from "./Report/TitleImageBulletCardsSlide";
|
||||
import MilestoneSlide, { Schema as RepMilestoneSchema, slideLayoutId as RepMilestoneId, slideLayoutName as RepMilestoneName, slideLayoutDescription as RepMilestoneDesc } from "./Report/MilestoneSlide";
|
||||
import DataAnalysisListSlide, { Schema as RepDataAnalysisListSchema, slideLayoutId as RepDataAnalysisListId, slideLayoutName as RepDataAnalysisListName, slideLayoutDescription as RepDataAnalysisListDesc } from "./Report/DataAnalysisListSlide";
|
||||
import DataAnalysisBarSlide, { Schema as RepDataAnalysisBarSchema, slideLayoutId as RepDataAnalysisBarId, slideLayoutName as RepDataAnalysisBarName, slideLayoutDescription as RepDataAnalysisBarDesc } from "./Report/DataAnalysisBarSlide";
|
||||
import DataAnalysisInsightBarSlide, { Schema as RepDataAnalysisInsightBarSchema, slideLayoutId as RepDataAnalysisInsightBarId, slideLayoutName as RepDataAnalysisInsightBarName, slideLayoutDescription as RepDataAnalysisInsightBarDesc } from "./Report/DataAnalysisInsightBarSlide";
|
||||
import DataAnalysisLineStatsSlide, { Schema as RepDataAnalysisLineStatsSchema, slideLayoutId as RepDataAnalysisLineStatsId, slideLayoutName as RepDataAnalysisLineStatsName, slideLayoutDescription as RepDataAnalysisLineStatsDesc } from "./Report/DataAnalysisLineStatsSlide";
|
||||
import DataAnalysisListSlide, { Schema as RepDataAnalysisListSchema, slideLayoutId as RepDataAnalysisListId, slideLayoutName as RepDataAnalysisListName, slideLayoutDescription as RepDataAnalysisListDesc } from "./Report/BulletListWithIconTitleDescriptionSlide";
|
||||
import DataAnalysisBarSlide, { Schema as RepDataAnalysisBarSchema, slideLayoutId as RepDataAnalysisBarId, slideLayoutName as RepDataAnalysisBarName, slideLayoutDescription as RepDataAnalysisBarDesc } from "./Report/BarChartWithBulletListWithTitleDescriptionIconSlide";
|
||||
import DataAnalysisInsightBarSlide, { Schema as RepDataAnalysisInsightBarSchema, slideLayoutId as RepDataAnalysisInsightBarId, slideLayoutName as RepDataAnalysisInsightBarName, slideLayoutDescription as RepDataAnalysisInsightBarDesc } from "./Report/TitleDescriptionChartSlide";
|
||||
import DataAnalysisLineStatsSlide, { Schema as RepDataAnalysisLineStatsSchema, slideLayoutId as RepDataAnalysisLineStatsId, slideLayoutName as RepDataAnalysisLineStatsName, slideLayoutDescription as RepDataAnalysisLineStatsDesc } from "./Report/TitleChartWithMetricsCardsSlide";
|
||||
import DataAnalysisDashboardSlide, { Schema as RepDataAnalysisDashboardSchema, slideLayoutId as RepDataAnalysisDashboardId, slideLayoutName as RepDataAnalysisDashboardName, slideLayoutDescription as RepDataAnalysisDashboardDesc } from "./Report/DataAnalysisDashboardSlide";
|
||||
import PerformanceSnapshotSlide, { Schema as RepPerformanceSnapshotSchema, slideLayoutId as RepPerformanceSnapshotId, slideLayoutName as RepPerformanceSnapshotName, slideLayoutDescription as RepPerformanceSnapshotDesc } from "./Report/PerformanceSnapshotSlide";
|
||||
import ReportServicesSlide, { Schema as RepServicesSchema, slideLayoutId as RepServicesId, slideLayoutName as RepServicesName, slideLayoutDescription as RepServicesDesc } from "./Report/ServicesSlide";
|
||||
import ReportTeamSlide, { Schema as RepTeamSchema, slideLayoutId as RepTeamId, slideLayoutName as RepTeamName, slideLayoutDescription as RepTeamDesc } from "./Report/TeamSlide";
|
||||
import PerformanceSnapshotSlide, { Schema as RepPerformanceSnapshotSchema, slideLayoutId as RepPerformanceSnapshotId, slideLayoutName as RepPerformanceSnapshotName, slideLayoutDescription as RepPerformanceSnapshotDesc } from "./Report/TitleMetricsSlide";
|
||||
import ReportServicesSlide, { Schema as RepServicesSchema, slideLayoutId as RepServicesId, slideLayoutName as RepServicesName, slideLayoutDescription as RepServicesDesc } from "./Report/TitleWorkflowWithTitleDescriptionSlide";
|
||||
import ReportTeamSlide, { Schema as RepTeamSchema, slideLayoutId as RepTeamId, slideLayoutName as RepTeamName, slideLayoutDescription as RepTeamDesc } from "./Report/HorizontalHeightSpanningImagesWithTitleSlide";
|
||||
|
||||
// General templates
|
||||
import GeneralIntroSlideLayout, { Schema as GeneralIntroSchema, layoutId as GeneralIntroId, layoutName as GeneralIntroName, layoutDescription as GeneralIntroDesc } from "./general/IntroSlideLayout";
|
||||
|
|
@ -244,17 +244,17 @@ import reportSettings from "./Report/settings.json";
|
|||
// TODO: Step 3: Create template entries for each template (like the ones below)
|
||||
|
||||
export const codeTemplates: TemplateWithData[] = [
|
||||
createTemplateEntry(CodeSlide01RoadmapCover, CodeRoadmapCoverSchema, CodeRoadmapCoverId, CodeRoadmapCoverName, CodeRoadmapCoverDesc, "code", "CodeSlide01RoadmapCover"),
|
||||
createTemplateEntry(CodeSlide02CodeExplanationSplit, CodeExplanationSplitSchema, CodeExplanationSplitId, CodeExplanationSplitName, CodeExplanationSplitDesc, "code", "CodeSlide02CodeExplanationSplit"),
|
||||
createTemplateEntry(CodeSlide03ApiRequestResponse, CodeApiRequestResponseSchema, CodeApiRequestResponseId, CodeApiRequestResponseName, CodeApiRequestResponseDesc, "code", "CodeSlide03ApiRequestResponse"),
|
||||
createTemplateEntry(CodeSlide04FeatureGrid, CodeFeatureGridSchema, CodeFeatureGridId, CodeFeatureGridName, CodeFeatureGridDesc, "code", "CodeSlide04FeatureGrid"),
|
||||
createTemplateEntry(CodeSlide05ComparisonTable, CodeComparisonTableSchema, CodeComparisonTableId, CodeComparisonTableName, CodeComparisonTableDesc, "code", "CodeSlide05ComparisonTable"),
|
||||
createTemplateEntry(CodeSlide06Workflow, CodeWorkflowSchema, CodeWorkflowId, CodeWorkflowName, CodeWorkflowDesc, "code", "CodeSlide06Workflow"),
|
||||
createTemplateEntry(CodeSlide07UseCaseList, CodeUseCaseListSchema, CodeUseCaseListId, CodeUseCaseListName, CodeUseCaseListDesc, "code", "CodeSlide07UseCaseList"),
|
||||
createTemplateEntry(CodeSlide08CodeExplanationText, CodeExplanationTextSchema, CodeExplanationTextId, CodeExplanationTextName, CodeExplanationTextDesc, "code", "CodeSlide08CodeExplanationText"),
|
||||
createTemplateEntry(CodeSlide09TableOfContent, CodeTableOfContentSchema, CodeTableOfContentId, CodeTableOfContentName, CodeTableOfContentDesc, "code", "CodeSlide09TableOfContent"),
|
||||
createTemplateEntry(CodeSlide10MetricsSplit, CodeMetricsSplitSchema, CodeMetricsSplitId, CodeMetricsSplitName, CodeMetricsSplitDesc, "code", "CodeSlide10MetricsSplit"),
|
||||
createTemplateEntry(CodeSlide11MetricsGrid, CodeMetricsGridSchema, CodeMetricsGridId, CodeMetricsGridName, CodeMetricsGridDesc, "code", "CodeSlide11MetricsGrid"),
|
||||
createTemplateEntry(CodeSlide01RoadmapCover, CodeRoadmapCoverSchema, CodeRoadmapCoverId, CodeRoadmapCoverName, CodeRoadmapCoverDesc, "code", "CoverSlide"),
|
||||
createTemplateEntry(CodeSlide02CodeExplanationSplit, CodeExplanationSplitSchema, CodeExplanationSplitId, CodeExplanationSplitName, CodeExplanationSplitDesc, "code", "CodeExplanationSplitSlide"),
|
||||
createTemplateEntry(CodeSlide03ApiRequestResponse, CodeApiRequestResponseSchema, CodeApiRequestResponseId, CodeApiRequestResponseName, CodeApiRequestResponseDesc, "code", "APIRequestResponseSlide"),
|
||||
createTemplateEntry(CodeSlide04FeatureGrid, CodeFeatureGridSchema, CodeFeatureGridId, CodeFeatureGridName, CodeFeatureGridDesc, "code", "CardsGridSlide"),
|
||||
createTemplateEntry(CodeSlide05ComparisonTable, CodeComparisonTableSchema, CodeComparisonTableId, CodeComparisonTableName, CodeComparisonTableDesc, "code", "TableSlide"),
|
||||
createTemplateEntry(CodeSlide06Workflow, CodeWorkflowSchema, CodeWorkflowId, CodeWorkflowName, CodeWorkflowDesc, "code", "WorkflowSlide"),
|
||||
createTemplateEntry(CodeSlide07UseCaseList, CodeUseCaseListSchema, CodeUseCaseListId, CodeUseCaseListName, CodeUseCaseListDesc, "code", "TwoColumnBulletListSlide"),
|
||||
createTemplateEntry(CodeSlide08CodeExplanationText, CodeExplanationTextSchema, CodeExplanationTextId, CodeExplanationTextName, CodeExplanationTextDesc, "code", "DescriptionTextSlide"),
|
||||
createTemplateEntry(CodeSlide09TableOfContent, CodeTableOfContentSchema, CodeTableOfContentId, CodeTableOfContentName, CodeTableOfContentDesc, "code", "TableOfContentSlide"),
|
||||
createTemplateEntry(CodeSlide10MetricsSplit, CodeMetricsSplitSchema, CodeMetricsSplitId, CodeMetricsSplitName, CodeMetricsSplitDesc, "code", "DescriptionAndMetricsSlide"),
|
||||
createTemplateEntry(CodeSlide11MetricsGrid, CodeMetricsGridSchema, CodeMetricsGridId, CodeMetricsGridName, CodeMetricsGridDesc, "code", "MetricsGridSlide"),
|
||||
];
|
||||
|
||||
export const educationTemplates: TemplateWithData[] = [
|
||||
|
|
@ -289,19 +289,19 @@ export const productOverviewTemplates: TemplateWithData[] = [
|
|||
];
|
||||
|
||||
export const reportTemplates: TemplateWithData[] = [
|
||||
createTemplateEntry(ReportIntroSlide, RepIntroSchema, RepIntroId, RepIntroName, RepIntroDesc, "report", "IntroSlide"),
|
||||
createTemplateEntry(ReportIntroSlide, RepIntroSchema, RepIntroId, RepIntroName, RepIntroDesc, "report", "IntroCoverSlide"),
|
||||
createTemplateEntry(TitleDescriptionImageSlide, RepIntroductionImageSchema, RepIntroductionImageId, RepIntroductionImageName, RepIntroductionImageDesc, "report", "TitleDescriptionImageSlide"),
|
||||
createTemplateEntry(IntroductionStatsSlide, RepIntroductionStatsSchema, RepIntroductionStatsId, RepIntroductionStatsName, RepIntroductionStatsDesc, "report", "IntroductionStatsSlide"),
|
||||
createTemplateEntry(SolutionSlide, RepSolutionSchema, RepSolutionId, RepSolutionName, RepSolutionDesc, "report", "SolutionSlide"),
|
||||
createTemplateEntry(IntroductionStatsSlide, RepIntroductionStatsSchema, RepIntroductionStatsId, RepIntroductionStatsName, RepIntroductionStatsDesc, "report", "MetricsSlide"),
|
||||
createTemplateEntry(SolutionSlide, RepSolutionSchema, RepSolutionId, RepSolutionName, RepSolutionDesc, "report", "TitleImageBulletCardsSlide"),
|
||||
createTemplateEntry(MilestoneSlide, RepMilestoneSchema, RepMilestoneId, RepMilestoneName, RepMilestoneDesc, "report", "MilestoneSlide"),
|
||||
createTemplateEntry(DataAnalysisListSlide, RepDataAnalysisListSchema, RepDataAnalysisListId, RepDataAnalysisListName, RepDataAnalysisListDesc, "report", "DataAnalysisListSlide"),
|
||||
createTemplateEntry(DataAnalysisBarSlide, RepDataAnalysisBarSchema, RepDataAnalysisBarId, RepDataAnalysisBarName, RepDataAnalysisBarDesc, "report", "DataAnalysisBarSlide"),
|
||||
createTemplateEntry(DataAnalysisInsightBarSlide, RepDataAnalysisInsightBarSchema, RepDataAnalysisInsightBarId, RepDataAnalysisInsightBarName, RepDataAnalysisInsightBarDesc, "report", "DataAnalysisInsightBarSlide"),
|
||||
createTemplateEntry(DataAnalysisLineStatsSlide, RepDataAnalysisLineStatsSchema, RepDataAnalysisLineStatsId, RepDataAnalysisLineStatsName, RepDataAnalysisLineStatsDesc, "report", "DataAnalysisLineStatsSlide"),
|
||||
createTemplateEntry(DataAnalysisListSlide, RepDataAnalysisListSchema, RepDataAnalysisListId, RepDataAnalysisListName, RepDataAnalysisListDesc, "report", "BulletListWithIconTitleDescriptionSlide"),
|
||||
createTemplateEntry(DataAnalysisBarSlide, RepDataAnalysisBarSchema, RepDataAnalysisBarId, RepDataAnalysisBarName, RepDataAnalysisBarDesc, "report", "BarChartWithBulletListWithTitleDescriptionIconSlide"),
|
||||
createTemplateEntry(DataAnalysisInsightBarSlide, RepDataAnalysisInsightBarSchema, RepDataAnalysisInsightBarId, RepDataAnalysisInsightBarName, RepDataAnalysisInsightBarDesc, "report", "TitleDescriptionChartSlide"),
|
||||
createTemplateEntry(DataAnalysisLineStatsSlide, RepDataAnalysisLineStatsSchema, RepDataAnalysisLineStatsId, RepDataAnalysisLineStatsName, RepDataAnalysisLineStatsDesc, "report", "TitleChartWithMetricsCardsSlide"),
|
||||
createTemplateEntry(DataAnalysisDashboardSlide, RepDataAnalysisDashboardSchema, RepDataAnalysisDashboardId, RepDataAnalysisDashboardName, RepDataAnalysisDashboardDesc, "report", "DataAnalysisDashboardSlide"),
|
||||
createTemplateEntry(PerformanceSnapshotSlide, RepPerformanceSnapshotSchema, RepPerformanceSnapshotId, RepPerformanceSnapshotName, RepPerformanceSnapshotDesc, "report", "PerformanceSnapshotSlide"),
|
||||
createTemplateEntry(ReportServicesSlide, RepServicesSchema, RepServicesId, RepServicesName, RepServicesDesc, "report", "ServicesSlide"),
|
||||
createTemplateEntry(ReportTeamSlide, RepTeamSchema, RepTeamId, RepTeamName, RepTeamDesc, "report", "TeamSlide"),
|
||||
createTemplateEntry(PerformanceSnapshotSlide, RepPerformanceSnapshotSchema, RepPerformanceSnapshotId, RepPerformanceSnapshotName, RepPerformanceSnapshotDesc, "report", "TitleMetricsSlide"),
|
||||
createTemplateEntry(ReportServicesSlide, RepServicesSchema, RepServicesId, RepServicesName, RepServicesDesc, "report", "TitleWorkflowWithTitleDescriptionSlide"),
|
||||
createTemplateEntry(ReportTeamSlide, RepTeamSchema, RepTeamId, RepTeamName, RepTeamDesc, "report", "HorizontalHeightSpanningImagesWithTitleSlide"),
|
||||
];
|
||||
|
||||
export const neoGeneralTemplates: TemplateWithData[] = [
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue