Files
mock_tool_image_gen/client/src/components/canvas/Canvas.tsx
T
2025-04-28 10:06:04 +10:00

94 lines
2.6 KiB
TypeScript

import React, { useRef, useCallback } from 'react';
import { Box, Center } from '@chakra-ui/react';
import { Stage, Layer, Rect } from 'react-konva';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '@/store';
import { selectComponent, clearSelection } from '@/store/slices/selectionSlice';
import ComponentRenderer from './ComponentRenderer';
import useCanvasSize from '@/hooks/useCanvasSize';
import useCanvasZoom from '@/hooks/useCanvasZoom';
const Canvas: React.FC = () => {
const dispatch = useDispatch();
const stageRef = useRef<any>(null);
const { mockup } = useSelector((state: RootState) => state);
const { components, canvas } = mockup;
// Custom hooks for canvas operations
const { containerSize, canvasContainerRef } = useCanvasSize();
const { scale, position, handleWheel, handleDragMove } = useCanvasZoom();
// Handle background click (deselect all)
const handleStageClick = useCallback((e: any) => {
// If clicked on the stage background
if (e.target === e.currentTarget) {
dispatch(clearSelection());
}
}, [dispatch]);
// Handle component selection
const handleComponentClick = useCallback((id: string, e: any) => {
e.cancelBubble = true; // Stop propagation to parent
dispatch(selectComponent(id));
}, [dispatch]);
return (
<Center
flex="1"
bg="gray.100"
overflow="hidden"
ref={canvasContainerRef}
position="relative"
>
<Box
position="absolute"
top="0"
left="0"
bottom="0"
right="0"
className="canvas-grid"
/>
<Stage
ref={stageRef}
width={containerSize.width}
height={containerSize.height}
onClick={handleStageClick}
onWheel={handleWheel}
draggable
onDragMove={handleDragMove}
x={position.x}
y={position.y}
scaleX={scale}
scaleY={scale}
>
<Layer>
{/* Canvas background */}
<Rect
x={0}
y={0}
width={canvas.width}
height={canvas.height}
fill={canvas.background}
shadowColor="rgba(0,0,0,0.2)"
shadowBlur={10}
shadowOffsetX={0}
shadowOffsetY={0}
cornerRadius={4}
/>
{/* Render components */}
{components.map((component) => (
<ComponentRenderer
key={component.id}
component={component}
onClick={(e) => handleComponentClick(component.id, e)}
/>
))}
</Layer>
</Stage>
</Center>
);
};
export default Canvas;