62 lines
2.1 KiB
TypeScript
62 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import React, { useEffect, useCallback } from "react";
|
|
import { useBuilderState } from "./hooks/useBuilderState";
|
|
import BuilderToolbar from "./BuilderToolbar";
|
|
import BuilderPalette from "./BuilderPalette";
|
|
import BuilderCanvas from "./BuilderCanvas";
|
|
import BuilderProps from "./BuilderProps";
|
|
|
|
import "@/styles/developer.css";
|
|
|
|
export default function BuilderLayout() {
|
|
const blocks = useBuilderState((s) => s.blocks);
|
|
const currentView = useBuilderState((s) => s.currentView);
|
|
const tableName = useBuilderState((s) => s.tableName);
|
|
const connections = useBuilderState((s) => s.connections);
|
|
const isDirty = useBuilderState((s) => s.isDirty);
|
|
const selectedBlockId = useBuilderState((s) => s.selectedBlockId);
|
|
const removeBlock = useBuilderState((s) => s.removeBlock);
|
|
const selectBlock = useBuilderState((s) => s.selectBlock);
|
|
|
|
const viewBlocks = blocks[currentView];
|
|
const blockCount = viewBlocks.length;
|
|
|
|
// 키보드 단축키: Delete/Backspace → 블록 삭제, 화살표 → 블록 이동
|
|
useEffect(() => {
|
|
const handler = (e: KeyboardEvent) => {
|
|
if (!selectedBlockId) return;
|
|
const tag = (e.target as HTMLElement).tagName;
|
|
if (tag === "INPUT" || tag === "SELECT" || tag === "TEXTAREA") return;
|
|
|
|
if (e.key === "Delete" || e.key === "Backspace") {
|
|
e.preventDefault();
|
|
removeBlock(selectedBlockId);
|
|
}
|
|
if (e.key === "Escape") {
|
|
selectBlock(null);
|
|
}
|
|
};
|
|
document.addEventListener("keydown", handler);
|
|
return () => document.removeEventListener("keydown", handler);
|
|
}, [selectedBlockId, removeBlock, selectBlock]);
|
|
|
|
return (
|
|
<div className="dev-shell">
|
|
<BuilderToolbar />
|
|
|
|
<div className="dev-body">
|
|
<BuilderPalette />
|
|
<BuilderCanvas />
|
|
<BuilderProps />
|
|
</div>
|
|
|
|
{/* 상태바 */}
|
|
<div className="dev-status">
|
|
<span>블록 {blockCount}개 · {tableName || "테이블 미선택"} · 연결 {connections.length}개</span>
|
|
<span>{isDirty ? "수정됨" : "저장됨"}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|