Files
invyone/frontend/components/builder/BuilderCanvas.tsx
T
2026-04-10 13:33:37 +09:00

92 lines
2.8 KiB
TypeScript

"use client";
import React, { useCallback } from "react";
import { useBuilderState, useCurrentViewBlocks } from "./hooks/useBuilderState";
import BuilderBlock from "./BuilderBlock";
import type { ComponentType } from "@/types/invyone-component";
export default function BuilderCanvas() {
const blocks = useCurrentViewBlocks();
const addBlock = useBuilderState((s) => s.addBlock);
const selectBlock = useBuilderState((s) => s.selectBlock);
const currentView = useBuilderState((s) => s.currentView);
const handleDrop = useCallback(
(e: React.DragEvent) => {
e.preventDefault();
const type = e.dataTransfer.getData("component-type") as ComponentType;
if (!type) return;
const rect = e.currentTarget.getBoundingClientRect();
const x = Math.round(e.clientX - rect.left);
const y = Math.round(e.clientY - rect.top);
addBlock(type, { x, y, w: 0, h: 0 });
},
[addBlock]
);
const handleDragOver = useCallback((e: React.DragEvent) => {
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
}, []);
const handleCanvasClick = useCallback(
(e: React.MouseEvent) => {
if ((e.target as HTMLElement).closest(".dev-block")) return;
selectBlock(null);
},
[selectBlock]
);
// 팝업 뷰 (등록/수정)
if (currentView !== "list") {
return (
<div className="dev-canvas" onClick={handleCanvasClick}>
<div className="dev-popup-overlay">
<div className="dev-popup-frame">
<div
className="dev-canvas-inner"
onDrop={handleDrop}
onDragOver={handleDragOver}
>
{blocks.length === 0 && (
<div className="dev-empty">
<div className="dev-empty-icon">📝</div>
<div className="dev-empty-text">
{currentView === "create" ? "등록" : "수정"}
</div>
</div>
)}
{blocks.map((block) => (
<BuilderBlock key={block.id} block={block} />
))}
</div>
</div>
</div>
</div>
);
}
return (
<div
className="dev-canvas"
onClick={handleCanvasClick}
onDrop={handleDrop}
onDragOver={handleDragOver}
>
<div className="dev-canvas-inner">
{blocks.length === 0 && (
<div className="dev-empty">
<div className="dev-empty-icon">🎨</div>
<div className="dev-empty-text">
</div>
</div>
)}
{blocks.map((block) => (
<BuilderBlock key={block.id} block={block} />
))}
</div>
</div>
);
}