feat: Section Card/Paper 레이아웃 컴포넌트 추가 및 설정 패널 통합
새로운 그룹화 레이아웃 컴포넌트 2종 추가: - Section Card: 제목+테두리 기반 명확한 섹션 구분 - Section Paper: 배경색 기반 미니멀한 섹션 구분 주요 변경사항: - 새 컴포넌트 등록 (각 4개 파일: Component, ConfigPanel, Renderer, index) - UnifiedPropertiesPanel에 인라인 설정 UI 추가 (280줄) - DetailSettingsPanel ConfigPanel 인터페이스 통일화 (config → componentConfig) - getComponentConfigPanel에 동적 import 매핑 추가 - 기존 컴포넌트 타입 정리 (autocomplete, entity-search, modal-repeater) 특징: - shadcn/ui 기반 일관된 디자인 시스템 준수 - 중첩 박스 금지 원칙 적용 - 반응형 지원 (모바일 우선) - collapsible 기능 지원 (Section Card)
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
|
||||
interface SectionPaperConfigPanelProps {
|
||||
config: any;
|
||||
onChange: (config: any) => void;
|
||||
}
|
||||
|
||||
export function SectionPaperConfigPanel({
|
||||
config,
|
||||
onChange,
|
||||
}: SectionPaperConfigPanelProps) {
|
||||
const handleChange = (key: string, value: any) => {
|
||||
const newConfig = {
|
||||
...config,
|
||||
[key]: value,
|
||||
};
|
||||
onChange(newConfig);
|
||||
|
||||
// 🎯 실시간 업데이트를 위한 이벤트 발생
|
||||
if (typeof window !== "undefined") {
|
||||
window.dispatchEvent(new CustomEvent("componentConfigChanged", {
|
||||
detail: { config: newConfig }
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4 p-4">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-semibold">Section Paper 설정</h3>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
배경색 기반의 미니멀한 그룹화 컨테이너
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 배경색 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">배경색</Label>
|
||||
<Select
|
||||
value={config.backgroundColor || "default"}
|
||||
onValueChange={(value) => handleChange("backgroundColor", value)}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="default">기본 (연한 회색)</SelectItem>
|
||||
<SelectItem value="muted">회색</SelectItem>
|
||||
<SelectItem value="accent">강조 (연한 파랑)</SelectItem>
|
||||
<SelectItem value="primary">브랜드 컬러</SelectItem>
|
||||
<SelectItem value="custom">커스텀</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 커스텀 색상 */}
|
||||
{config.backgroundColor === "custom" && (
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">커스텀 색상</Label>
|
||||
<Input
|
||||
type="color"
|
||||
value={config.customColor || "#f0f0f0"}
|
||||
onChange={(e) => handleChange("customColor", e.target.value)}
|
||||
className="h-9"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 패딩 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">내부 여백</Label>
|
||||
<Select
|
||||
value={config.padding || "md"}
|
||||
onValueChange={(value) => handleChange("padding", value)}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게 (12px)</SelectItem>
|
||||
<SelectItem value="md">중간 (16px)</SelectItem>
|
||||
<SelectItem value="lg">크게 (24px)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 둥근 모서리 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">둥근 모서리</Label>
|
||||
<Select
|
||||
value={config.roundedCorners || "md"}
|
||||
onValueChange={(value) => handleChange("roundedCorners", value)}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게 (2px)</SelectItem>
|
||||
<SelectItem value="md">중간 (6px)</SelectItem>
|
||||
<SelectItem value="lg">크게 (8px)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 그림자 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">그림자</Label>
|
||||
<Select
|
||||
value={config.shadow || "none"}
|
||||
onValueChange={(value) => handleChange("shadow", value)}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게</SelectItem>
|
||||
<SelectItem value="md">중간</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 테두리 표시 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="showBorder"
|
||||
checked={config.showBorder || false}
|
||||
onCheckedChange={(checked) => handleChange("showBorder", checked)}
|
||||
/>
|
||||
<Label htmlFor="showBorder" className="text-xs cursor-pointer">
|
||||
미묘한 테두리 표시
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user