import { useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { Copy, Check, Heart } from "lucide-react"; import { ThemeEditorState } from "@/types/editor"; import { ScrollArea, ScrollBar } from "../ui/scroll-area"; import { ColorFormat } from "../../types"; import { Select, SelectContent, SelectTrigger, SelectValue, SelectItem, } from "../ui/select"; import { usePostHog } from "posthog-js/react"; import { useEditorStore } from "@/store/editor-store"; import { usePreferencesStore } from "@/store/preferences-store"; import { generateThemeCode } from "@/utils/theme-style-generator"; import { useThemePresetStore } from "@/store/theme-preset-store"; import { Alert, AlertDescription, AlertTitle } from "../ui/alert"; interface CodePanelProps { themeEditorState: ThemeEditorState; } const CodePanel: React.FC = ({ themeEditorState }) => { const [registryCopied, setRegistryCopied] = useState(false); const [copied, setCopied] = useState(false); const posthog = usePostHog(); const preset = useEditorStore((state) => state.themeState.preset); const colorFormat = usePreferencesStore((state) => state.colorFormat); const tailwindVersion = usePreferencesStore((state) => state.tailwindVersion); const packageManager = usePreferencesStore((state) => state.packageManager); const setColorFormat = usePreferencesStore((state) => state.setColorFormat); const setTailwindVersion = usePreferencesStore( (state) => state.setTailwindVersion ); const setPackageManager = usePreferencesStore( (state) => state.setPackageManager ); const hasUnsavedChanges = useEditorStore((state) => state.hasUnsavedChanges); const isSavedPreset = useThemePresetStore( (state) => preset && state.getPreset(preset)?.source === "SAVED" ); const code = generateThemeCode( themeEditorState, colorFormat, tailwindVersion ); const getRegistryCommand = (preset: string) => { const url = isSavedPreset ? `https://tweakcn.com/r/themes/${preset}` : `https://tweakcn.com/r/themes/${preset}.json`; switch (packageManager) { case "pnpm": return `pnpm dlx shadcn@latest add ${url}`; case "npm": return `npx shadcn@latest add ${url}`; case "yarn": return `yarn dlx shadcn@latest add ${url}`; case "bun": return `bunx shadcn@latest add ${url}`; } }; const copyRegistryCommand = async () => { try { await navigator.clipboard.writeText( getRegistryCommand(preset ?? "default") ); setRegistryCopied(true); setTimeout(() => setRegistryCopied(false), 2000); captureCopyEvent("COPY_REGISTRY_COMMAND"); } catch (err) { console.error("Failed to copy text:", err); } }; const captureCopyEvent = (event: string) => { posthog.capture(event, { editorType: "theme", preset, colorFormat, tailwindVersion, }); }; const copyToClipboard = async (text: string) => { try { await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); captureCopyEvent("COPY_CODE"); } catch (err) { console.error("Failed to copy text:", err); } }; const showRegistryCommand = useMemo(() => { return preset && preset !== "default" && !hasUnsavedChanges(); }, [preset, hasUnsavedChanges]); return (

Theme Code

{showRegistryCommand ? (
{(["pnpm", "npm", "yarn", "bun"] as const).map((pm) => ( ))}
{getRegistryCommand(preset as string)}
) : ( You have unsaved changes.
Save
your theme to get the registry command.
)}
index.css
            {code}
          
); }; export default CodePanel;