返回 presentation-ai
ColorsStep.tsx
1 "use client";
2
3 import { Edit2, Heart } from "lucide-react";
4 import { useState } from "react";
5 import { Controller, useWatch, type Control } from "react-hook-form";
6
7 import { type ThemeColors } from "@/lib/presentation/themes";
8 import { cn } from "@/lib/utils";
9 import { type ColorKey, type ThemeFormValues } from "../types";
10 import { ColorSettingsPanel } from "./ColorSettingsPanel";
11 import { ColorThemeGrid } from "./ColorThemeGrid";
12 import { colorThemes } from "./create-theme-types";
13
14 interface ColorsStepProps {
15 control: Control<ThemeFormValues>;
16 selectedColorTheme: string;
17 onColorChange: (key: ColorKey, value: string) => void;
18 onSelectColorTheme: (themeId: string) => void;
19 defaultColors?: Partial<ThemeColors>;
20 }
21
22 export function ColorsStep({
23 control,
24 selectedColorTheme,
25 onColorChange,
26 onSelectColorTheme,
27 defaultColors,
28 }: ColorsStepProps) {
29 // Use useWatch to properly subscribe to form changes
30 const watchColors = useWatch({ control, name: "colors" });
31 const [mode, setMode] = useState<"curated" | "customize">(
32 selectedColorTheme === "custom-theme" ? "customize" : "curated",
33 );
34
35 return (
36 <div className="flex h-full flex-1 flex-col">
37 <div className="border-b border-border p-6">
38 <p className="mb-4 text-center text-sm text-muted-foreground">
39 Choose your theme and background colors
40 </p>
41 <div className="flex gap-2">
42 <button
43 onClick={() => setMode("curated")}
44 className={cn(
45 "flex flex-1 items-center justify-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors",
46 mode === "curated"
47 ? "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300"
48 : "text-muted-foreground hover:bg-muted hover:text-foreground",
49 )}
50 >
51 <Heart className="h-4 w-4" />
52 ALLWEONE®
53 </button>
54 <button
55 onClick={() => setMode("customize")}
56 className={cn(
57 "flex flex-1 items-center justify-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors",
58 mode === "customize"
59 ? "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300"
60 : "text-muted-foreground hover:bg-muted hover:text-foreground",
61 )}
62 >
63 <Edit2 className="h-4 w-4" />
64 Customize
65 </button>
66 </div>
67 </div>
68
69 <div className="flex-1 overflow-y-auto p-6">
70 {mode === "curated" ? (
71 <ColorThemeGrid
72 themes={colorThemes}
73 selectedTheme={selectedColorTheme}
74 onSelectTheme={onSelectColorTheme}
75 />
76 ) : (
77 <div className="space-y-6">
78 <Controller
79 name="background"
80 control={control}
81 defaultValue={undefined}
82 render={({ field }) => (
83 <ColorSettingsPanel
84 colors={watchColors}
85 onColorChange={onColorChange}
86 defaultColors={defaultColors}
87 background={field.value}
88 onBackgroundChange={(value) => {
89 field.onChange(value);
90 }}
91 />
92 )}
93 />
94 </div>
95 )}
96 </div>
97 </div>
98 );
99 }
100
100 lines Plain Text