2025-11-10 14:21:29 +09:00
|
|
|
|
"use client";
|
|
|
|
|
|
|
2025-09-02 16:18:38 +09:00
|
|
|
|
import React from "react";
|
|
|
|
|
|
import { Label } from "@/components/ui/label";
|
2025-11-10 14:21:29 +09:00
|
|
|
|
import { Input } from "@/components/ui/input";
|
2025-09-02 16:18:38 +09:00
|
|
|
|
import { Checkbox } from "@/components/ui/checkbox";
|
2025-11-10 14:21:29 +09:00
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
|
import { Separator } from "@/components/ui/separator";
|
|
|
|
|
|
import { Slider } from "@/components/ui/slider";
|
2025-11-10 15:05:34 +09:00
|
|
|
|
import { Grid3X3, RotateCcw, Eye, EyeOff, Zap } from "lucide-react";
|
2025-11-10 14:21:29 +09:00
|
|
|
|
import { GridSettings, ScreenResolution } from "@/types/screen";
|
2025-12-09 17:08:10 +09:00
|
|
|
|
import { ColorPickerWithTransparent } from "../common/ColorPickerWithTransparent";
|
2025-09-02 16:18:38 +09:00
|
|
|
|
|
|
|
|
|
|
interface GridPanelProps {
|
|
|
|
|
|
gridSettings: GridSettings;
|
|
|
|
|
|
onGridSettingsChange: (settings: GridSettings) => void;
|
2025-11-10 14:21:29 +09:00
|
|
|
|
onResetGrid: () => void;
|
2025-11-10 15:05:34 +09:00
|
|
|
|
screenResolution?: ScreenResolution;
|
2025-09-02 16:18:38 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 14:21:29 +09:00
|
|
|
|
export const GridPanel: React.FC<GridPanelProps> = ({
|
|
|
|
|
|
gridSettings,
|
|
|
|
|
|
onGridSettingsChange,
|
|
|
|
|
|
onResetGrid,
|
|
|
|
|
|
screenResolution,
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
const updateSetting = (key: keyof GridSettings, value: any) => {
|
2025-09-02 16:18:38 +09:00
|
|
|
|
onGridSettingsChange({
|
|
|
|
|
|
...gridSettings,
|
|
|
|
|
|
[key]: value,
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2025-11-10 14:21:29 +09:00
|
|
|
|
<div className="flex h-full flex-col">
|
|
|
|
|
|
{/* 헤더 */}
|
|
|
|
|
|
<div className="border-b p-4">
|
|
|
|
|
|
<div className="mb-3 flex items-center justify-between">
|
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
|
<Grid3X3 className="text-muted-foreground h-4 w-4" />
|
|
|
|
|
|
<h3 className="text-sm font-semibold">격자 설정</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<Button size="sm" variant="outline" onClick={onResetGrid} className="h-7 px-2 text-xs">
|
|
|
|
|
|
<RotateCcw className="mr-1 h-3 w-3" />
|
|
|
|
|
|
초기화
|
|
|
|
|
|
</Button>
|
2025-09-02 16:18:38 +09:00
|
|
|
|
</div>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
|
|
|
|
|
|
{/* 주요 토글들 */}
|
|
|
|
|
|
<div className="space-y-2.5">
|
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
|
{gridSettings.showGrid ? (
|
|
|
|
|
|
<Eye className="text-primary h-3.5 w-3.5" />
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<EyeOff className="text-muted-foreground h-3.5 w-3.5" />
|
|
|
|
|
|
)}
|
|
|
|
|
|
<Label htmlFor="showGrid" className="text-xs font-medium">
|
|
|
|
|
|
격자 표시
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<Checkbox
|
|
|
|
|
|
id="showGrid"
|
|
|
|
|
|
checked={gridSettings.showGrid}
|
|
|
|
|
|
onCheckedChange={(checked) => updateSetting("showGrid", checked)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
|
<Zap className="text-primary h-3.5 w-3.5" />
|
|
|
|
|
|
<Label htmlFor="snapToGrid" className="text-xs font-medium">
|
|
|
|
|
|
격자 스냅
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<Checkbox
|
|
|
|
|
|
id="snapToGrid"
|
|
|
|
|
|
checked={gridSettings.snapToGrid}
|
|
|
|
|
|
onCheckedChange={(checked) => updateSetting("snapToGrid", checked)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-09-02 16:18:38 +09:00
|
|
|
|
</div>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 설정 영역 */}
|
|
|
|
|
|
<div className="flex-1 space-y-4 overflow-y-auto p-4">
|
2025-11-10 15:05:34 +09:00
|
|
|
|
{/* 10px 단위 스냅 안내 */}
|
2025-11-10 14:21:29 +09:00
|
|
|
|
<div className="space-y-3">
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<h4 className="text-xs font-semibold">격자 시스템</h4>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
|
2025-11-10 14:41:58 +09:00
|
|
|
|
<div className="bg-muted/50 rounded-md p-3">
|
|
|
|
|
|
<p className="text-xs text-muted-foreground">
|
2025-11-10 15:05:34 +09:00
|
|
|
|
모든 컴포넌트는 10px 단위로 자동 배치됩니다.
|
2025-11-10 14:41:58 +09:00
|
|
|
|
</p>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
</div>
|
2025-09-02 16:18:38 +09:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-11-10 14:21:29 +09:00
|
|
|
|
<Separator />
|
|
|
|
|
|
|
|
|
|
|
|
{/* 격자 스타일 */}
|
|
|
|
|
|
<div className="space-y-4">
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<h4 className="text-xs font-semibold">격자 스타일</h4>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
|
|
|
|
|
|
<div>
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<Label htmlFor="gridColor" className="text-xs font-medium">
|
2025-11-10 14:21:29 +09:00
|
|
|
|
격자 색상
|
|
|
|
|
|
</Label>
|
2025-12-09 17:08:10 +09:00
|
|
|
|
<div className="mt-1">
|
|
|
|
|
|
<ColorPickerWithTransparent
|
2025-11-10 14:21:29 +09:00
|
|
|
|
id="gridColor"
|
2025-12-09 17:08:10 +09:00
|
|
|
|
value={gridSettings.gridColor}
|
|
|
|
|
|
onChange={(value) => updateSetting("gridColor", value)}
|
|
|
|
|
|
defaultColor="#d1d5db"
|
2025-11-10 14:21:29 +09:00
|
|
|
|
placeholder="#d1d5db"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<Label htmlFor="gridOpacity" className="mb-2 block text-xs font-medium">
|
2025-11-10 14:21:29 +09:00
|
|
|
|
격자 투명도: {Math.round((gridSettings.gridOpacity || 0.5) * 100)}%
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Slider
|
|
|
|
|
|
id="gridOpacity"
|
|
|
|
|
|
min={0.1}
|
|
|
|
|
|
max={1}
|
|
|
|
|
|
step={0.1}
|
|
|
|
|
|
value={[gridSettings.gridOpacity || 0.5]}
|
|
|
|
|
|
onValueChange={([value]) => updateSetting("gridOpacity", value)}
|
|
|
|
|
|
className="w-full"
|
|
|
|
|
|
/>
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<div className="mt-1 flex justify-between text-xs text-muted-foreground">
|
2025-11-10 14:21:29 +09:00
|
|
|
|
<span>10%</span>
|
|
|
|
|
|
<span>100%</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-09-02 16:18:38 +09:00
|
|
|
|
</div>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
|
|
|
|
|
|
<Separator />
|
|
|
|
|
|
|
|
|
|
|
|
{/* 미리보기 */}
|
|
|
|
|
|
<div className="space-y-3">
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<h4 className="text-xs font-semibold">미리보기</h4>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
|
|
|
|
|
|
<div
|
2025-11-10 15:05:34 +09:00
|
|
|
|
className="rounded-md border bg-white p-4"
|
2025-11-10 14:21:29 +09:00
|
|
|
|
style={{
|
|
|
|
|
|
backgroundImage: gridSettings.showGrid
|
|
|
|
|
|
? `linear-gradient(to right, ${gridSettings.gridColor || "#d1d5db"} 1px, transparent 1px),
|
|
|
|
|
|
linear-gradient(to bottom, ${gridSettings.gridColor || "#d1d5db"} 1px, transparent 1px)`
|
|
|
|
|
|
: "none",
|
2025-11-10 15:05:34 +09:00
|
|
|
|
backgroundSize: gridSettings.showGrid ? "10px 10px" : "none",
|
2025-11-10 14:21:29 +09:00
|
|
|
|
opacity: gridSettings.gridOpacity || 0.5,
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div className="bg-primary/20 flex h-16 items-center justify-center rounded border-2 border-dashed border-blue-300">
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<span className="text-primary text-xs">10px 격자</span>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 푸터 */}
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<div className="border-t bg-muted/30 p-3">
|
2025-11-10 14:41:58 +09:00
|
|
|
|
{screenResolution && (
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
|
<h4 className="text-xs font-semibold">화면 정보</h4>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="space-y-2 text-xs">
|
|
|
|
|
|
<div className="flex justify-between">
|
|
|
|
|
|
<span className="text-muted-foreground">해상도:</span>
|
|
|
|
|
|
<span className="font-mono">
|
|
|
|
|
|
{screenResolution.width} × {screenResolution.height}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
|
2025-11-10 15:05:34 +09:00
|
|
|
|
<div className="flex justify-between">
|
|
|
|
|
|
<span className="text-muted-foreground">격자 단위:</span>
|
|
|
|
|
|
<span className="font-mono text-primary">10px</span>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-11-10 15:05:34 +09:00
|
|
|
|
</div>
|
2025-11-10 14:21:29 +09:00
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-09-02 16:18:38 +09:00
|
|
|
|
);
|
2025-11-10 14:21:29 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default GridPanel;
|