|
| 1 | +"use client"; |
| 2 | + |
1 | 3 | import { |
2 | 4 | useCanvas, |
3 | 5 | useCurNodes, |
4 | 6 | useSelectedNodeId, |
5 | 7 | useSelectNode, |
6 | | - useUpdateNode, |
| 8 | + useSetCanvas, |
| 9 | + useUpdateNodeLayout, |
7 | 10 | } from "@/stores/useEditorStore"; |
8 | | -import EditorNodeWrapper from "@repo/ui/core/EditorNodeWrapper.jsx"; |
9 | | -import NodeRenderer from "@repo/ui/core/NodeRenderer.jsx"; |
10 | | -import { WcxNode } from "@repo/ui/types/nodes.js"; |
11 | | -import React from "react"; |
| 11 | +import { |
| 12 | + handleMouseDown, |
| 13 | + handleMouseMove, |
| 14 | + handleMouseUp, |
| 15 | +} from "@/utils/editor/canvasMouseHandler"; |
| 16 | +import handleWheel from "@/utils/editor/handleWheel"; |
| 17 | +import EditorNodeWrapper from "@repo/ui/core/EditorNodeWrapper"; |
| 18 | +import NodeRenderer from "@repo/ui/core/NodeRenderer"; |
| 19 | +import { WcxNode } from "@repo/ui/types/nodes"; |
| 20 | +import React, { useRef } from "react"; |
12 | 21 |
|
13 | 22 | export default function Canvas() { |
14 | 23 | const nodes = useCurNodes(); |
15 | 24 | const selectedNodeId = useSelectedNodeId(); |
16 | 25 | const selectNode = useSelectNode(); |
17 | | - const updateNode = useUpdateNode(); |
| 26 | + const updateNode = useUpdateNodeLayout(); |
18 | 27 | const canvasState = useCanvas(); |
| 28 | + const setCanvas = useSetCanvas(); |
| 29 | + |
| 30 | + const isPanning = useRef(false); |
| 31 | + const lastMousePos = useRef({ x: 0, y: 0 }); |
19 | 32 |
|
20 | 33 | //FIXME-각 노드들에 key속성 추가해주기. -> 리액트 경고 발생 |
21 | 34 | //FIXME-nodes가 비어있는 상황에서 에러발생. -> Base Condition에 Root가 들어간다.(Root는 단지 더미 노드일뿐 로직에 들어가면 안된다.) |
@@ -74,5 +87,34 @@ export default function Canvas() { |
74 | 87 | ); |
75 | 88 | } |
76 | 89 |
|
77 | | - return <div className="canvas-root relative">{renderTree({ id: null })}</div>; |
| 90 | + return ( |
| 91 | + <div |
| 92 | + className="relative h-full w-full flex-1 cursor-grab overflow-hidden bg-white active:cursor-grabbing" |
| 93 | + onWheel={(e) => handleWheel({ canvas: canvasState, e, setCanvas })} |
| 94 | + onMouseDown={(e) => |
| 95 | + handleMouseDown({ e, isPanning, lastMousePos, selectNode }) |
| 96 | + } |
| 97 | + onMouseMove={(e) => |
| 98 | + handleMouseMove({ e, isPanning, lastMousePos, setCanvas, canvasState }) |
| 99 | + } |
| 100 | + onMouseUp={() => handleMouseUp({ isPanning })} |
| 101 | + onMouseLeave={() => handleMouseUp({ isPanning })} |
| 102 | + > |
| 103 | + <div |
| 104 | + style={{ |
| 105 | + transform: `translate(${canvasState.dx}px, ${canvasState.dy}px) scale(${canvasState.scale})`, |
| 106 | + transformOrigin: "0 0", |
| 107 | + width: "100%", |
| 108 | + height: "100%", |
| 109 | + }} |
| 110 | + className="relative h-full w-full" |
| 111 | + > |
| 112 | + {/* 배경 격자 (Helper Grid) */} |
| 113 | + <div className="bg-grid-pattern pointer-events-none absolute inset-[-1000%] z-0 h-[3000%] w-[3000%]" /> |
| 114 | + <div className="relative z-10 h-full w-full"> |
| 115 | + {renderTree({ id: null })} |
| 116 | + </div> |
| 117 | + </div> |
| 118 | + </div> |
| 119 | + ); |
78 | 120 | } |
0 commit comments