diff --git a/src/core/providers/canvas/canvas.model.ts b/src/core/providers/canvas/canvas.model.ts index 9d75fe03..3a6c1a4d 100644 --- a/src/core/providers/canvas/canvas.model.ts +++ b/src/core/providers/canvas/canvas.model.ts @@ -1,4 +1,4 @@ -import { ShapeModel, ShapeRefs, ShapeType } from '@/core/model'; +import { Coord, ShapeModel, ShapeRefs, ShapeType, Size } from '@/core/model'; import Konva from 'konva'; import { Node, NodeConfig } from 'konva/lib/Node'; @@ -22,9 +22,10 @@ export interface SelectionInfo { export interface CanvasContextModel { shapes: ShapeModel[]; - setShapes: React.Dispatch>; scale: number; setScale: React.Dispatch>; - + addNewShape: (type: ShapeType, x: number, y: number) => void; + updateShapeSizeAndPosition: (id: string, position: Coord, size: Size) => void; + updateShapePosition: (id: string, position: Coord) => void; selectionInfo: SelectionInfo; } diff --git a/src/core/providers/canvas/canvas.provider.tsx b/src/core/providers/canvas/canvas.provider.tsx index 2327ceb9..55952ea6 100644 --- a/src/core/providers/canvas/canvas.provider.tsx +++ b/src/core/providers/canvas/canvas.provider.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { ShapeModel } from '@/core/model'; +import { Coord, ShapeModel, ShapeType, Size } from '@/core/model'; import { CanvasContext } from './canvas.context'; import { useSelection } from './use-selection.hook'; +import { createShape } from '@/pods/canvas/canvas.model'; interface Props { children: React.ReactNode; @@ -13,15 +14,38 @@ export const CanvasProvider: React.FC = props => { const [scale, setScale] = React.useState(1); const selectionInfo = useSelection(shapes, setShapes); + const addNewShape = (type: ShapeType, x: number, y: number) => { + setShapes(shapes => [...shapes, createShape({ x, y }, type)]); + }; + + const updateShapeSizeAndPosition = ( + id: string, + position: Coord, + size: Size + ) => { + setShapes(prevShapes => + prevShapes.map(shape => + shape.id === id ? { ...shape, ...position, ...size } : shape + ) + ); + }; + + const updateShapePosition = (id: string, { x, y }: Coord) => { + setShapes(prevShapes => + prevShapes.map(shape => (shape.id === id ? { ...shape, x, y } : shape)) + ); + }; return ( {children} diff --git a/src/pods/canvas/canvas.pod.tsx b/src/pods/canvas/canvas.pod.tsx index 9946309e..7b1506cc 100644 --- a/src/pods/canvas/canvas.pod.tsx +++ b/src/pods/canvas/canvas.pod.tsx @@ -10,7 +10,14 @@ import classes from './canvas.pod.module.css'; import { EditableComponent } from '@/common/components/inline-edit'; export const CanvasPod = () => { - const { shapes, setShapes, scale, selectionInfo } = useCanvasContext(); + const { + shapes, + scale, + selectionInfo, + addNewShape, + updateShapeSizeAndPosition, + updateShapePosition, + } = useCanvasContext(); const { shapeRefs, @@ -24,10 +31,10 @@ export const CanvasPod = () => { } = selectionInfo; const { isDraggedOver, dropRef } = useDropShape(); - const { stageRef } = useMonitorShape(dropRef, setShapes); + const { stageRef } = useMonitorShape(dropRef, addNewShape); const { handleTransform, handleTransformerBoundBoxFunc } = useTransform( - setShapes, + updateShapeSizeAndPosition, { selectedShapeRef, selectedShapeId, @@ -38,9 +45,7 @@ export const CanvasPod = () => { const handleDragEnd = (id: string) => (e: Konva.KonvaEventObject) => { const { x, y } = e.target.position(); - setShapes(prevShapes => - prevShapes.map(shape => (shape.id === id ? { ...shape, x, y } : shape)) - ); + updateShapePosition(id, { x, y }); }; { diff --git a/src/pods/canvas/use-monitor-shape.hook.ts b/src/pods/canvas/use-monitor-shape.hook.ts index 10c127ae..40009c7c 100644 --- a/src/pods/canvas/use-monitor-shape.hook.ts +++ b/src/pods/canvas/use-monitor-shape.hook.ts @@ -7,12 +7,11 @@ import { convertFromDivElementCoordsToKonvaCoords, } from './canvas.util'; import Konva from 'konva'; -import { createShape } from './canvas.model'; -import { ShapeModel } from '@/core/model'; +import { ShapeType } from '@/core/model'; export const useMonitorShape = ( dropRef: React.MutableRefObject, - setShapes: React.Dispatch> + addNewShape: (type: ShapeType, x: number, y: number) => void ) => { const stageRef = useRef(null); @@ -22,7 +21,7 @@ export const useMonitorShape = ( const destination = location.current.dropTargets[0]; invariant(destination); - const type = source.data.type; + const type = source.data.type as ShapeType; const screenPosition = extractScreenCoordinatesFromPragmaticLocation(location); @@ -50,11 +49,7 @@ export const useMonitorShape = ( positionX = konvaCoord.x; positionY = konvaCoord.y; } - - setShapes(shapes => [ - ...shapes, - createShape({ x: positionX, y: positionY }, type as any), - ]); + addNewShape(type, positionX, positionY); }, }); }, []); diff --git a/src/pods/canvas/use-transform.hook.ts b/src/pods/canvas/use-transform.hook.ts index c43af33b..7a3fc66c 100644 --- a/src/pods/canvas/use-transform.hook.ts +++ b/src/pods/canvas/use-transform.hook.ts @@ -1,6 +1,6 @@ import { Node, NodeConfig } from 'konva/lib/Node'; import { Box } from 'konva/lib/shapes/Transformer'; -import { Coord, ShapeModel, ShapeType, Size } from '@/core/model'; +import { Coord, ShapeType, Size } from '@/core/model'; interface TransFormSelectedInfo { selectedShapeRef: React.MutableRefObject | null>; @@ -9,23 +9,11 @@ interface TransFormSelectedInfo { } export const useTransform = ( - setShapes: (value: React.SetStateAction) => void, + updateShapeSizeAndPosition: (id: string, position: Coord, size: Size) => void, transformSelectedInfo: TransFormSelectedInfo ) => { const { selectedShapeId, selectedShapeRef } = transformSelectedInfo; - const updateShapeSizeAndPosition = ( - id: string, - position: Coord, - size: Size - ) => { - setShapes(prevShapes => - prevShapes.map(shape => - shape.id === id ? { ...shape, ...position, ...size } : shape - ) - ); - }; - const handleTransform = () => { const node = selectedShapeRef.current; if (!node) {