返回 presentation-ai
ThemeModal.tsx
1 "use client";
2
3 import { useState, type ReactNode } from "react";
4
5 import { ThemeModalContent } from "@/components/notebook/presentation/components/theme/ThemeModalContent";
6 import { ThemeModalPreview } from "@/components/notebook/presentation/components/theme/ThemeModalPreview";
7 import { useThemeModalState } from "@/components/notebook/presentation/components/theme/useThemeModalState";
8 import { Button } from "@/components/ui/button";
9 import {
10 Credenza,
11 CredenzaContent,
12 CredenzaTitle,
13 CredenzaTrigger,
14 } from "@/components/ui/credenza";
15 import { VisuallyHidden } from "@/components/ui/visually-hidden";
16 import { type ThemeProperties } from "@/lib/presentation/themes";
17
18 interface ThemeModalProps {
19 children?: ReactNode;
20 initialPreviewTheme?: {
21 id: string;
22 data: ThemeProperties;
23 };
24 }
25
26 /**
27 * Theme selection modal with preview panel
28 */
29 export function ThemeModal({ children, initialPreviewTheme }: ThemeModalProps) {
30 const [isOpen, setIsOpen] = useState(false);
31
32 const {
33 activeTab,
34 setActiveTab,
35 selectedThemeId,
36 selectedThemeData,
37 userThemes,
38 isLoadingUserThemes,
39 handlePreviewTheme,
40 handleApplyTheme,
41 } = useThemeModalState(isOpen, initialPreviewTheme);
42
43 const onApplyTheme = () => {
44 handleApplyTheme();
45 setIsOpen(false);
46 };
47
48 return (
49 <Credenza open={isOpen} onOpenChange={setIsOpen}>
50 <CredenzaTrigger asChild>
51 {children ? children : <Button variant="link">More Themes</Button>}
52 </CredenzaTrigger>
53 <CredenzaContent
54 shouldHaveClose={false}
55 className="flex h-[min(92dvh,56rem)] max-h-[calc(100dvh-1rem)] w-[min(calc(100vw-1rem),72rem)] max-w-6xl flex-col gap-0 overflow-hidden p-0 md:w-[min(calc(100vw-2rem),72rem)]"
56 >
57 <VisuallyHidden>
58 <CredenzaTitle>More Themes</CredenzaTitle>
59 </VisuallyHidden>
60 <div className="flex min-h-0 flex-1 flex-col overflow-hidden lg:flex-row">
61 {/* Left Panel - Theme Selection */}
62 <ThemeModalContent
63 activeTab={activeTab}
64 onTabChange={setActiveTab}
65 selectedThemeId={selectedThemeId}
66 onPreviewTheme={handlePreviewTheme}
67 userThemes={userThemes}
68 isLoadingUserThemes={isLoadingUserThemes}
69 onApplyTheme={onApplyTheme}
70 onClose={() => setIsOpen(false)}
71 />
72
73 {/* Right Panel - Preview */}
74 <ThemeModalPreview selectedThemeData={selectedThemeData} />
75 </div>
76 </CredenzaContent>
77 </Credenza>
78 );
79 }
80
80 lines Plain Text