返回 presentation-ai
StepContent.tsx
1 "use client";
2
3 import {
4 Controller,
5 type Control,
6 type UseFormSetValue,
7 } from "react-hook-form";
8
9 import { Input } from "@/components/ui/input";
10 import { Label } from "@/components/ui/label";
11 import { type ThemeColors } from "@/lib/presentation/themes";
12 import { cn } from "@/lib/utils";
13 import { type ColorKey, type ThemeFormValues } from "../types";
14 import { ColorsStep } from "./ColorsStep";
15 import { type CreateThemeStep } from "./create-theme-types";
16 import { DesignStep } from "./DesignStep";
17 import { FontStep } from "./font-step";
18
19 interface StepContentProps {
20 step: CreateThemeStep;
21 control: Control<ThemeFormValues>;
22 selectedColorTheme: string;
23 onColorChange: (key: ColorKey, value: string) => void;
24 onSelectColorTheme: (themeId: string) => void;
25 setValue: UseFormSetValue<ThemeFormValues>;
26 isCustomizing?: boolean;
27 defaultColors?: Partial<ThemeColors>;
28 }
29
30 export function StepContent({
31 step,
32 control,
33 selectedColorTheme,
34 onColorChange,
35 onSelectColorTheme,
36 setValue,
37 isCustomizing,
38 defaultColors,
39 }: StepContentProps) {
40 if (step === "colors") {
41 return (
42 <ColorsStep
43 control={control}
44 onColorChange={onColorChange}
45 onSelectColorTheme={onSelectColorTheme}
46 selectedColorTheme={selectedColorTheme}
47 defaultColors={defaultColors}
48 />
49 );
50 }
51
52 if (step === "fonts") {
53 return <FontStep control={control} setValue={setValue} />;
54 }
55
56 if (step === "design") {
57 return <DesignStep setValue={setValue} control={control} />;
58 }
59
60 if (step === "save") {
61 return (
62 <div className="space-y-6 p-8">
63 <div className="rounded-lg border-2 border-border bg-card p-8 shadow-lg">
64 <h2 className="mb-2 text-2xl font-bold text-foreground">
65 Name Your Theme
66 </h2>
67 <p className="mb-6 text-sm text-muted-foreground">
68 Give your theme a memorable name.
69 </p>
70
71 <div className="mb-6">
72 <Label
73 htmlFor="theme-name"
74 className="mb-2 block text-sm font-semibold text-foreground"
75 >
76 Theme Name
77 </Label>
78 <Controller
79 name="name"
80 control={control}
81 render={({ field }) => (
82 <Input
83 id="theme-name"
84 {...field}
85 placeholder="Enter a name for your theme"
86 className="w-full rounded-lg border-2 border-border bg-background px-4 py-3 text-foreground transition-all outline-none focus:border-blue-600 focus:ring-2 focus:ring-blue-600/20"
87 />
88 )}
89 />
90 </div>
91
92 {!isCustomizing && (
93 <div className="mb-6">
94 <Label className="mb-3 block text-sm font-semibold text-foreground">
95 Theme Mode
96 </Label>
97 <Controller
98 name="mode"
99 control={control}
100 render={({ field }) => (
101 <div className="grid grid-cols-2 gap-4">
102 <button
103 type="button"
104 onClick={() => field.onChange("light")}
105 className={cn(
106 "rounded-lg border-2 p-6 text-left transition-all duration-200",
107 field.value === "light"
108 ? "border-blue-600 bg-blue-50 dark:bg-blue-950/30"
109 : "border-border hover:border-muted-foreground",
110 )}
111 >
112 <div className="flex items-start gap-3">
113 <div
114 className={cn(
115 "mt-0.5 flex h-5 w-5 items-center justify-center rounded-full border-2 transition-all",
116 field.value === "light"
117 ? "border-blue-600 bg-blue-600"
118 : "border-border",
119 )}
120 >
121 {field.value === "light" && (
122 <div className="h-2.5 w-2.5 rounded-full bg-white" />
123 )}
124 </div>
125 <div className="flex-1">
126 <h3 className="mb-1 font-semibold text-foreground">
127 Light Mode
128 </h3>
129 <p className="text-sm text-muted-foreground">
130 Optimized for light backgrounds
131 </p>
132 </div>
133 </div>
134 </button>
135
136 <button
137 type="button"
138 onClick={() => field.onChange("dark")}
139 className={cn(
140 "rounded-lg border-2 p-6 text-left transition-all duration-200",
141 field.value === "dark"
142 ? "border-blue-600 bg-blue-50 dark:bg-blue-950/30"
143 : "border-border hover:border-muted-foreground",
144 )}
145 >
146 <div className="flex items-start gap-3">
147 <div
148 className={cn(
149 "mt-0.5 flex h-5 w-5 items-center justify-center rounded-full border-2 transition-all",
150 field.value === "dark"
151 ? "border-blue-600 bg-blue-600"
152 : "border-border",
153 )}
154 >
155 {field.value === "dark" && (
156 <div className="h-2.5 w-2.5 rounded-full bg-white" />
157 )}
158 </div>
159 <div className="flex-1">
160 <h3 className="mb-1 font-semibold text-foreground">
161 Dark Mode
162 </h3>
163 <p className="text-sm text-muted-foreground">
164 Optimized for dark backgrounds
165 </p>
166 </div>
167 </div>
168 </button>
169 </div>
170 )}
171 />
172 </div>
173 )}
174 </div>
175 </div>
176 );
177 }
178
179 return null;
180 }
181
181 lines Plain Text