Files
vexplor/frontend/components/screen/GridControls.tsx
2025-09-02 11:16:40 +09:00

182 lines
6.0 KiB
TypeScript

"use client";
import { useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
import { Grid, Settings, RotateCcw } from "lucide-react";
interface GridSettings {
columns: number;
gap: number;
padding: number;
snapToGrid: boolean;
}
interface GridControlsProps {
gridSettings: GridSettings;
onGridSettingsChange: (settings: GridSettings) => void;
className?: string;
}
export default function GridControls({ gridSettings, onGridSettingsChange, className }: GridControlsProps) {
const [localSettings, setLocalSettings] = useState<GridSettings>(gridSettings);
const handleSettingChange = (key: keyof GridSettings, value: number | boolean) => {
const newSettings = { ...localSettings, [key]: value };
setLocalSettings(newSettings);
onGridSettingsChange(newSettings);
};
const resetToDefault = () => {
const defaultSettings: GridSettings = {
columns: 12,
gap: 16,
padding: 16,
snapToGrid: true,
};
setLocalSettings(defaultSettings);
onGridSettingsChange(defaultSettings);
};
return (
<Card className={className}>
<CardHeader className="pb-3">
<CardTitle className="flex items-center space-x-2 text-sm">
<Grid className="h-4 w-4" />
<span> </span>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 격자 열 개수 */}
<div className="space-y-2">
<Label htmlFor="columns" className="text-xs font-medium">
</Label>
<div className="flex items-center space-x-2">
<Slider
id="columns"
min={1}
max={24}
step={1}
value={[localSettings.columns]}
onValueChange={(value) => handleSettingChange("columns", value[0])}
className="flex-1"
/>
<Input
type="number"
min={1}
max={24}
value={localSettings.columns}
onChange={(e) => handleSettingChange("columns", parseInt(e.target.value) || 12)}
className="w-16 text-xs"
/>
</div>
<div className="text-xs text-gray-500">: {localSettings.columns}</div>
</div>
{/* 격자 간격 */}
<div className="space-y-2">
<Label htmlFor="gap" className="text-xs font-medium">
(px)
</Label>
<div className="flex items-center space-x-2">
<Slider
id="gap"
min={0}
max={32}
step={2}
value={[localSettings.gap]}
onValueChange={(value) => handleSettingChange("gap", value[0])}
className="flex-1"
/>
<Input
type="number"
min={0}
max={32}
value={localSettings.gap}
onChange={(e) => handleSettingChange("gap", parseInt(e.target.value) || 16)}
className="w-16 text-xs"
/>
</div>
</div>
{/* 여백 */}
<div className="space-y-2">
<Label htmlFor="padding" className="text-xs font-medium">
(px)
</Label>
<div className="flex items-center space-x-2">
<Slider
id="padding"
min={0}
max={48}
step={4}
value={[localSettings.padding]}
onValueChange={(value) => handleSettingChange("padding", value[0])}
className="flex-1"
/>
<Input
type="number"
min={0}
max={48}
value={localSettings.padding}
onChange={(e) => handleSettingChange("padding", parseInt(e.target.value) || 16)}
className="w-16 text-xs"
/>
</div>
</div>
{/* 격자 스냅 */}
<div className="flex items-center justify-between">
<Label htmlFor="snapToGrid" className="text-xs font-medium">
</Label>
<Button
variant={localSettings.snapToGrid ? "default" : "outline"}
size="sm"
onClick={() => handleSettingChange("snapToGrid", !localSettings.snapToGrid)}
className="h-6 px-2 text-xs"
>
{localSettings.snapToGrid ? "ON" : "OFF"}
</Button>
</div>
{/* 격자 변경 안내 */}
<div className="rounded-md bg-blue-50 p-2 text-xs text-blue-700">
<div className="font-medium">💡 </div>
<div className="mt-1 text-blue-600">
.
</div>
</div>
{/* 격자 미리보기 */}
<div className="space-y-2">
<Label className="text-xs font-medium"> </Label>
<div className="rounded border bg-gray-50 p-2">
<div
className="grid h-16 gap-px"
style={{
gridTemplateColumns: `repeat(${localSettings.columns}, 1fr)`,
gap: `${Math.max(1, localSettings.gap / 4)}px`,
}}
>
{Array.from({ length: localSettings.columns }).map((_, i) => (
<div key={i} className="rounded-sm bg-blue-200" />
))}
</div>
</div>
</div>
{/* 초기화 버튼 */}
<Button variant="outline" size="sm" onClick={resetToDefault} className="w-full text-xs">
<RotateCcw className="mr-1 h-3 w-3" />
</Button>
</CardContent>
</Card>
);
}