ERP-node/frontend/components/barcode/designer/BarcodeDesignerCanvas.tsx

85 lines
2.7 KiB
TypeScript

"use client";
import { useRef } from "react";
import { useDrop } from "react-dnd";
import { useBarcodeDesigner, MM_TO_PX } from "@/contexts/BarcodeDesignerContext";
import { BarcodeLabelCanvasComponent } from "./BarcodeLabelCanvasComponent";
import { BarcodeLabelComponent } from "@/types/barcode";
import { v4 as uuidv4 } from "uuid";
export function BarcodeDesignerCanvas() {
const canvasRef = useRef<HTMLDivElement>(null);
const {
widthMm,
heightMm,
components,
addComponent,
selectComponent,
showGrid,
snapValueToGrid,
} = useBarcodeDesigner();
const widthPx = widthMm * MM_TO_PX;
const heightPx = heightMm * MM_TO_PX;
const [{ isOver }, drop] = useDrop(() => ({
accept: "barcode-component",
drop: (item: { component: BarcodeLabelComponent }, monitor) => {
if (!canvasRef.current) return;
const offset = monitor.getClientOffset();
const rect = canvasRef.current.getBoundingClientRect();
if (!offset) return;
let x = offset.x - rect.left;
let y = offset.y - rect.top;
// 드롭 시 요소 중앙이 커서에 오도록 보정
x -= item.component.width / 2;
y -= item.component.height / 2;
x = Math.max(0, Math.min(x, widthPx - item.component.width));
y = Math.max(0, Math.min(y, heightPx - item.component.height));
const newComp: BarcodeLabelComponent = {
...item.component,
id: `comp_${uuidv4()}`,
x: snapValueToGrid(x),
y: snapValueToGrid(y),
zIndex: components.length,
};
addComponent(newComp);
},
collect: (m) => ({ isOver: m.isOver() }),
}), [widthPx, heightPx, components.length, addComponent, snapValueToGrid]);
return (
<div className="flex flex-1 items-center justify-center overflow-auto bg-gray-100 p-6">
<div
key={`canvas-${widthMm}-${heightMm}`}
ref={(r) => {
(canvasRef as any).current = r;
drop(r);
}}
className="relative bg-white shadow-lg"
style={{
width: widthPx,
height: heightPx,
minWidth: widthPx,
minHeight: heightPx,
backgroundImage: showGrid
? `linear-gradient(to right, #e5e7eb 1px, transparent 1px),
linear-gradient(to bottom, #e5e7eb 1px, transparent 1px)`
: undefined,
backgroundSize: showGrid ? `${MM_TO_PX * 5}px ${MM_TO_PX * 5}px` : undefined,
outline: isOver ? "2px dashed #2563eb" : "1px solid #d1d5db",
}}
onClick={(e) => {
if (e.target === e.currentTarget) selectComponent(null);
}}
>
{components.map((c) => (
<BarcodeLabelCanvasComponent key={c.id} component={c} />
))}
</div>
</div>
);
}