返回 presentation-ai
theme-schema.ts
根目录 / src / lib / presentation / theme-schema.ts
1 import * as z from "zod";
2
3 const hexColorSchema = z
4 .string()
5 .regex(/^#[0-9a-f]{6}$/i, "Expected a 6-digit hex color");
6
7 const presentationThemeModeSchema = z.enum(["light", "dark"]);
8
9 const presentationThemeColorsSchema = z.object({
10 primary: hexColorSchema.describe(
11 "Main brand/action color used for emphasis and prominent visual accents.",
12 ),
13 accent: hexColorSchema.describe(
14 "Secondary accent color that complements the primary color.",
15 ),
16 background: hexColorSchema.describe("Main slide/page background color."),
17 text: hexColorSchema.describe(
18 "Body text color with strong contrast against background and cardBackground.",
19 ),
20 heading: hexColorSchema.describe(
21 "Heading text color with strong contrast against background and cardBackground.",
22 ),
23 smartLayout: hexColorSchema.describe(
24 "Fill color for smart layout SVGs and visual structures such as pyramids, pie charts, staircase blocks, cycles, timelines, and other diagram elements. It usually sits close to the primary color or a deliberate variant of it, not a neutral card surface color.",
25 ),
26 cardBackground: hexColorSchema.describe(
27 "Surface color for cards or text containers where text is rendered. This is separate from smartLayout and should preserve text readability.",
28 ),
29 });
30
31 const presentationThemeFontsSchema = z.object({
32 heading: z
33 .string()
34 .min(1)
35 .describe(
36 "A real, well-known font family name, such as Inter, Manrope, Poppins, IBM Plex Sans, Playfair Display, Merriweather, Sora, or Space Grotesk. Do not invent font names.",
37 ),
38 body: z
39 .string()
40 .min(1)
41 .describe(
42 "A real, well-known font family name, such as Inter, Manrope, Source Sans Pro, Work Sans, IBM Plex Sans, Lato, Open Sans, or DM Sans. Do not invent font names.",
43 ),
44 headingWeight: z.number().int().min(100).max(900).optional(),
45 bodyWeight: z.number().int().min(100).max(900).optional(),
46 headingUrl: z.string().url().optional(),
47 bodyUrl: z.string().url().optional(),
48 });
49
50 const presentationThemeBorderRadiusSchema = z.object({
51 card: z.string().min(1),
52 slide: z.string().min(1),
53 button: z.string().min(1),
54 });
55
56 const presentationThemeTransitionsSchema = z.object({
57 default: z.string().min(1),
58 });
59
60 const presentationThemeShadowsSchema = z.object({
61 card: z.string(),
62 button: z.string(),
63 slide: z.string(),
64 });
65
66 const presentationThemeMaskSchema = z
67 .object({
68 clipPath: z.string().optional(),
69 maskImage: z.string().optional(),
70 maskSize: z.string().optional(),
71 maskPosition: z.string().optional(),
72 maskRepeat: z.string().optional(),
73 })
74 .optional();
75
76 const presentationThemeBackgroundSchema = z
77 .object({
78 type: z.enum(["solid", "linear", "radial", "image"]).optional(),
79 override: z.string().optional(),
80 gradient: z
81 .object({
82 type: z.enum(["linear", "radial"]),
83 angle: z.number().optional(),
84 shape: z.enum(["circle", "ellipse"]).optional(),
85 at: z
86 .object({
87 x: z.number(),
88 y: z.number(),
89 })
90 .optional(),
91 stops: z
92 .array(
93 z.object({
94 id: z.string().min(1),
95 color: hexColorSchema,
96 position: z.number().min(0).max(100),
97 }),
98 )
99 .optional(),
100 })
101 .optional(),
102 imageUrl: z.string().url().optional(),
103 })
104 .optional();
105
106 export const presentationAiThemePropertiesSchema = z.object({
107 name: z.string().min(1).max(80).optional(),
108 description: z.string().min(1).max(240).optional(),
109 colors: presentationThemeColorsSchema.partial().optional(),
110 fonts: presentationThemeFontsSchema.partial().optional(),
111 background: presentationThemeBackgroundSchema,
112 });
113
114 export const presentationThemePropertiesSchema = z.object({
115 name: z.string().min(1).max(80),
116 description: z.string().max(240),
117 mode: presentationThemeModeSchema,
118 colors: presentationThemeColorsSchema,
119 fonts: presentationThemeFontsSchema,
120 borderRadius: presentationThemeBorderRadiusSchema,
121 transitions: presentationThemeTransitionsSchema,
122 shadows: presentationThemeShadowsSchema,
123 mask: presentationThemeMaskSchema,
124 background: presentationThemeBackgroundSchema,
125 });
126
127 export const presentationThemeStyleDataSchema =
128 presentationThemePropertiesSchema
129 .omit({
130 name: true,
131 description: true,
132 })
133 .extend({
134 name: z.string().min(1).max(80).optional(),
135 description: z.string().max(240).optional(),
136 });
137
138 export type PresentationAiThemeProperties = z.infer<
139 typeof presentationAiThemePropertiesSchema
140 >;
141
141 lines TYPESCRIPT