97 lines
2.5 KiB
TypeScript
97 lines
2.5 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import { useDrag } from "react-dnd";
|
||
|
|
import { cn } from "@/lib/utils";
|
||
|
|
import { PopComponentType } from "../types/pop-layout";
|
||
|
|
import { Square } from "lucide-react";
|
||
|
|
|
||
|
|
// DnD 타입 상수
|
||
|
|
const DND_ITEM_TYPES = {
|
||
|
|
COMPONENT: "component",
|
||
|
|
} as const;
|
||
|
|
|
||
|
|
// 컴포넌트 정의
|
||
|
|
interface PaletteItem {
|
||
|
|
type: PopComponentType;
|
||
|
|
label: string;
|
||
|
|
icon: React.ElementType;
|
||
|
|
description: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
const PALETTE_ITEMS: PaletteItem[] = [
|
||
|
|
{
|
||
|
|
type: "pop-sample",
|
||
|
|
label: "샘플 박스",
|
||
|
|
icon: Square,
|
||
|
|
description: "크기 조정 테스트용",
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
// 드래그 가능한 컴포넌트 아이템
|
||
|
|
function DraggablePaletteItem({ item }: { item: PaletteItem }) {
|
||
|
|
const [{ isDragging }, drag] = useDrag(
|
||
|
|
() => ({
|
||
|
|
type: DND_ITEM_TYPES.COMPONENT,
|
||
|
|
item: { type: DND_ITEM_TYPES.COMPONENT, componentType: item.type },
|
||
|
|
collect: (monitor) => ({
|
||
|
|
isDragging: monitor.isDragging(),
|
||
|
|
}),
|
||
|
|
}),
|
||
|
|
[item.type]
|
||
|
|
);
|
||
|
|
|
||
|
|
const Icon = item.icon;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
ref={drag}
|
||
|
|
className={cn(
|
||
|
|
"flex cursor-grab items-center gap-3 rounded-md border bg-white p-3",
|
||
|
|
"transition-all hover:border-primary hover:shadow-sm",
|
||
|
|
isDragging && "opacity-50 cursor-grabbing"
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
<div className="flex h-9 w-9 items-center justify-center rounded bg-muted">
|
||
|
|
<Icon className="h-4 w-4 text-muted-foreground" />
|
||
|
|
</div>
|
||
|
|
<div className="flex-1 min-w-0">
|
||
|
|
<div className="text-sm font-medium">{item.label}</div>
|
||
|
|
<div className="text-xs text-muted-foreground truncate">
|
||
|
|
{item.description}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 컴포넌트 팔레트 패널
|
||
|
|
export default function ComponentPalette() {
|
||
|
|
return (
|
||
|
|
<div className="flex h-full flex-col bg-gray-50">
|
||
|
|
{/* 헤더 */}
|
||
|
|
<div className="border-b bg-white px-4 py-3">
|
||
|
|
<h3 className="text-sm font-semibold">컴포넌트</h3>
|
||
|
|
<p className="text-xs text-muted-foreground">
|
||
|
|
드래그하여 캔버스에 배치
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 컴포넌트 목록 */}
|
||
|
|
<div className="flex-1 overflow-y-auto p-3">
|
||
|
|
<div className="space-y-2">
|
||
|
|
{PALETTE_ITEMS.map((item) => (
|
||
|
|
<DraggablePaletteItem key={item.type} item={item} />
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 하단 안내 */}
|
||
|
|
<div className="border-t bg-white px-4 py-3">
|
||
|
|
<p className="text-xs text-muted-foreground">
|
||
|
|
Tip: 캔버스의 그리드 칸에 드롭하세요
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|