ERP-node/frontend/components/screen/StyleEditor.tsx

364 lines
15 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Separator } from "@/components/ui/separator";
import { Palette, Layout, Type, Square, Box, Eye, RotateCcw } from "lucide-react";
import { ComponentStyle } from "@/types/screen";
interface StyleEditorProps {
style: ComponentStyle;
onStyleChange: (style: ComponentStyle) => void;
className?: string;
}
export default function StyleEditor({ style, onStyleChange, className }: StyleEditorProps) {
const [localStyle, setLocalStyle] = useState<ComponentStyle>(style);
useEffect(() => {
setLocalStyle(style);
}, [style]);
const handleStyleChange = (property: keyof ComponentStyle, value: any) => {
const newStyle = { ...localStyle, [property]: value };
setLocalStyle(newStyle);
onStyleChange(newStyle);
};
const resetStyle = () => {
const resetStyle: ComponentStyle = {};
setLocalStyle(resetStyle);
onStyleChange(resetStyle);
};
const applyStyle = () => {
onStyleChange(localStyle);
};
return (
<div className={`space-y-4 ${className}`}>
<Card>
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle className="flex items-center gap-2 text-sm font-medium">
<Palette className="h-4 w-4" />
</CardTitle>
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" onClick={resetStyle}>
<RotateCcw className="mr-1 h-3 w-3" />
</Button>
<Button size="sm" onClick={applyStyle}>
<Eye className="mr-1 h-3 w-3" />
</Button>
</div>
</div>
</CardHeader>
<CardContent>
<Tabs defaultValue="layout" className="w-full">
<TabsList className="grid w-full grid-cols-5">
<TabsTrigger value="layout">
<Layout className="mr-1 h-3 w-3" />
</TabsTrigger>
<TabsTrigger value="spacing">
<Box className="mr-1 h-3 w-3" />
</TabsTrigger>
<TabsTrigger value="border">
<Square className="mr-1 h-3 w-3" />
</TabsTrigger>
<TabsTrigger value="background">
<Palette className="mr-1 h-3 w-3" />
</TabsTrigger>
<TabsTrigger value="typography">
<Type className="mr-1 h-3 w-3" />
</TabsTrigger>
</TabsList>
{/* 레이아웃 탭 */}
<TabsContent value="layout" className="space-y-4">
{/* 너비/높이는 위젯 속성에서만 관리하도록 제거 */}
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="display"> </Label>
<Select
value={localStyle.display || "block"}
onValueChange={(value) => handleStyleChange("display", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="block">Block</SelectItem>
<SelectItem value="inline">Inline</SelectItem>
<SelectItem value="inline-block">Inline-Block</SelectItem>
<SelectItem value="flex">Flex</SelectItem>
<SelectItem value="grid">Grid</SelectItem>
<SelectItem value="none">None</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="position"></Label>
<Select
value={localStyle.position || "static"}
onValueChange={(value) => handleStyleChange("position", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="static">Static</SelectItem>
<SelectItem value="relative">Relative</SelectItem>
<SelectItem value="absolute">Absolute</SelectItem>
<SelectItem value="fixed">Fixed</SelectItem>
<SelectItem value="sticky">Sticky</SelectItem>
</SelectContent>
</Select>
</div>
</div>
{localStyle.display === "flex" && (
<>
<Separator />
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="flexDirection"></Label>
<Select
value={localStyle.flexDirection || "row"}
onValueChange={(value) => handleStyleChange("flexDirection", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="row"> (Row)</SelectItem>
<SelectItem value="row-reverse"> </SelectItem>
<SelectItem value="column"> (Column)</SelectItem>
<SelectItem value="column-reverse"> </SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="justifyContent"> </Label>
<Select
value={localStyle.justifyContent || "flex-start"}
onValueChange={(value) => handleStyleChange("justifyContent", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="flex-start"></SelectItem>
<SelectItem value="center"></SelectItem>
<SelectItem value="flex-end"></SelectItem>
<SelectItem value="space-between"></SelectItem>
<SelectItem value="space-around"></SelectItem>
</SelectContent>
</Select>
</div>
</div>
</>
)}
</TabsContent>
{/* 여백 탭 */}
<TabsContent value="spacing" className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="margin"> </Label>
<Input
id="margin"
type="text"
placeholder="10px, 1rem"
value={localStyle.margin || ""}
onChange={(e) => handleStyleChange("margin", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="padding"> </Label>
<Input
id="padding"
type="text"
placeholder="10px, 1rem"
value={localStyle.padding || ""}
onChange={(e) => handleStyleChange("padding", e.target.value)}
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="gap"></Label>
<Input
id="gap"
type="text"
placeholder="10px, 1rem"
value={localStyle.gap || ""}
onChange={(e) => handleStyleChange("gap", e.target.value)}
/>
</div>
</div>
</TabsContent>
{/* 테두리 탭 */}
<TabsContent value="border" className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="borderWidth"> </Label>
<Input
id="borderWidth"
type="text"
placeholder="1px, 2px"
value={localStyle.borderWidth || ""}
onChange={(e) => handleStyleChange("borderWidth", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="borderStyle"> </Label>
<Select
value={localStyle.borderStyle || "solid"}
onValueChange={(value) => handleStyleChange("borderStyle", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="solid"></SelectItem>
<SelectItem value="dashed"></SelectItem>
<SelectItem value="dotted"></SelectItem>
<SelectItem value="none"></SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="borderColor"> </Label>
<Input
id="borderColor"
type="color"
value={localStyle.borderColor || "#000000"}
onChange={(e) => handleStyleChange("borderColor", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="borderRadius"> </Label>
<Input
id="borderRadius"
type="text"
placeholder="5px, 10px"
value={localStyle.borderRadius || ""}
onChange={(e) => handleStyleChange("borderRadius", e.target.value)}
/>
</div>
</div>
</TabsContent>
{/* 배경 탭 */}
<TabsContent value="background" className="space-y-4">
<div className="space-y-2">
<Label htmlFor="backgroundColor"> </Label>
<Input
id="backgroundColor"
type="color"
value={localStyle.backgroundColor || "#ffffff"}
onChange={(e) => handleStyleChange("backgroundColor", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="backgroundImage"> </Label>
<Input
id="backgroundImage"
type="text"
placeholder="url('image.jpg')"
value={localStyle.backgroundImage || ""}
onChange={(e) => handleStyleChange("backgroundImage", e.target.value)}
/>
</div>
</TabsContent>
{/* 텍스트 탭 */}
<TabsContent value="typography" className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="color"> </Label>
<Input
id="color"
type="color"
value={localStyle.color || "#000000"}
onChange={(e) => handleStyleChange("color", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="fontSize"> </Label>
<Input
id="fontSize"
type="text"
placeholder="14px, 1rem"
value={localStyle.fontSize || ""}
onChange={(e) => handleStyleChange("fontSize", e.target.value)}
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="fontWeight"> </Label>
<Select
value={localStyle.fontWeight || "normal"}
onValueChange={(value) => handleStyleChange("fontWeight", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="normal"></SelectItem>
<SelectItem value="bold"></SelectItem>
<SelectItem value="100">100</SelectItem>
<SelectItem value="400">400</SelectItem>
<SelectItem value="500">500</SelectItem>
<SelectItem value="600">600</SelectItem>
<SelectItem value="700">700</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="textAlign"> </Label>
<Select
value={localStyle.textAlign || "left"}
onValueChange={(value) => handleStyleChange("textAlign", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="left"></SelectItem>
<SelectItem value="center"></SelectItem>
<SelectItem value="right"></SelectItem>
<SelectItem value="justify"></SelectItem>
</SelectContent>
</Select>
</div>
</div>
</TabsContent>
</Tabs>
</CardContent>
</Card>
</div>
);
}