mirror of
https://github.com/jnsahaj/tweakcn.git
synced 2026-09-01 15:37:45 +08:00
d661f7d6d7
* feat: add AuthDialogWrapper to main layout to work in every route * refactor: move footer to global components * refactor: separate route components into layouts, pages, and loading components * chore: remove AuthDialogWrapper from AI page after it was moved to root layout
97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from "@/components/ui/dropdown-menu";
|
|
import { toast } from "@/components/ui/use-toast";
|
|
import { useEditorStore } from "@/store/editor-store";
|
|
import type { Theme } from "@/types/theme";
|
|
import { Edit, Moon, MoreVertical, Share, Sun } from "lucide-react";
|
|
import { notFound, useRouter } from "next/navigation";
|
|
import { useEffect } from "react";
|
|
import ThemePreviewPanel from "./editor/theme-preview-panel";
|
|
|
|
export default function ThemeView({ theme }: { theme: Theme }) {
|
|
const { themeState, setThemeState, saveThemeCheckpoint, restoreThemeCheckpoint } =
|
|
useEditorStore();
|
|
const router = useRouter();
|
|
const currentMode = themeState.currentMode;
|
|
|
|
useEffect(() => {
|
|
saveThemeCheckpoint();
|
|
setThemeState({
|
|
...themeState,
|
|
styles: theme.styles,
|
|
});
|
|
return () => {
|
|
restoreThemeCheckpoint();
|
|
};
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [theme, saveThemeCheckpoint, setThemeState, restoreThemeCheckpoint]);
|
|
|
|
if (!theme) {
|
|
notFound();
|
|
}
|
|
|
|
const toggleTheme = () => {
|
|
setThemeState({
|
|
...themeState,
|
|
currentMode: currentMode === "light" ? "dark" : "light",
|
|
});
|
|
};
|
|
|
|
const handleOpenInEditor = () => {
|
|
setThemeState({
|
|
...themeState,
|
|
styles: theme.styles,
|
|
});
|
|
saveThemeCheckpoint();
|
|
router.push("/editor/theme");
|
|
};
|
|
|
|
const handleShare = () => {
|
|
const url = `https://tweakcn.com/themes/${theme.id}`;
|
|
navigator.clipboard.writeText(url);
|
|
toast({
|
|
title: "Theme URL copied to clipboard!",
|
|
});
|
|
};
|
|
return (
|
|
<>
|
|
<div className="flex items-center justify-between">
|
|
<h1 className="text-3xl font-bold">{theme.name}</h1>
|
|
<div className="flex items-center gap-2">
|
|
<Button variant="outline" size="icon" onClick={toggleTheme}>
|
|
{currentMode === "dark" ? <Sun className="size-4" /> : <Moon className="size-4" />}
|
|
</Button>
|
|
<Button variant="outline" size="default" onClick={handleShare}>
|
|
<Share className="size-4" />
|
|
Share
|
|
</Button>
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" size="icon">
|
|
<MoreVertical className="size-4" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end">
|
|
<DropdownMenuItem className="gap-2" onClick={handleOpenInEditor}>
|
|
<Edit className="size-4" />
|
|
Open in Editor
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="-m-4 mt-6 flex h-[min(80svh,900px)] flex-col">
|
|
<ThemePreviewPanel styles={theme.styles} currentMode={currentMode} />
|
|
</div>
|
|
</>
|
|
);
|
|
}
|