diff --git a/src/components/canvas.tsx b/src/components/canvas.tsx index 369298d..db2443c 100644 --- a/src/components/canvas.tsx +++ b/src/components/canvas.tsx @@ -60,7 +60,9 @@ const Canvas = () => {
{ if (e.target !== e.currentTarget) { return; diff --git a/src/components/delete-shape-button.tsx b/src/components/delete-shape-button.tsx index f2ac942..cebeae8 100644 --- a/src/components/delete-shape-button.tsx +++ b/src/components/delete-shape-button.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { Button } from "@/components/ui/button"; import { deleteStageItem } from "@/store/app.slice"; import { useAppDispatch } from "@/hooks"; -import { BsTrash3 } from "react-icons/bs"; +import { IconButton } from "@radix-ui/themes"; +import { Trash2 } from "lucide-react"; type Props = { selectedItemId: string; @@ -14,12 +14,8 @@ export const DeleteShapeButton = ({ selectedItemId }: Props) => { dispatch(deleteStageItem(selectedItemId)); }; return ( - + deleteTextHandler(selectedItemId)}> + + ); }; diff --git a/src/components/layer-item.tsx b/src/components/layer-item.tsx index 41ffc45..d40510e 100644 --- a/src/components/layer-item.tsx +++ b/src/components/layer-item.tsx @@ -6,14 +6,15 @@ import { type StageItem, StageItemType, } from "@/store/app.slice"; -import { useAppDispatch } from "@/hooks"; -import { Button } from "@/components/ui/button"; -import { HiOutlineLockClosed, HiOutlineLockOpen } from "react-icons/hi2"; +import { useAppDispatch, useAppSelector } from "@/hooks"; import { IconButton } from "@radix-ui/themes"; -import { GripVertical } from "lucide-react"; +import { Eye, GripVertical, Lock, Trash2, Unlock } from "lucide-react"; +import { DeleteShapeButton } from "@/components/delete-shape-button"; +import VisibleShapeToggle from "@/components/visible-shape-toggle"; export default function LayerItem({ item }: { item: StageItem }) { const dispatch = useAppDispatch(); + const selectedItemId = useAppSelector((state) => state.app.selectedItemId); const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: item.id, @@ -33,12 +34,12 @@ export default function LayerItem({ item }: { item: StageItem }) { style={style} ref={setNodeRef} {...attributes} - className="m-2 flex items-center justify-between rounded-md border p-2 text-black" + className="flex items-center justify-between rounded-md border bg-yellow-50 p-2 text-black" > - + - {item.type} + {item.type} {item.type === StageItemType.Text ? ( item.params.text < 5 ? ( @@ -53,9 +54,14 @@ export default function LayerItem({ item }: { item: StageItem }) { src={item.params.imageUrl} /> )} - + + + + + + handleBlockItemClicked()}> + {item.isBlocked ? : } +
); } diff --git a/src/components/transformable-image.tsx b/src/components/transformable-image.tsx index ad6630a..9082988 100644 --- a/src/components/transformable-image.tsx +++ b/src/components/transformable-image.tsx @@ -1,6 +1,6 @@ import { type ImageConfig } from "konva/lib/shapes/Image"; -import { useRef, useEffect, type ElementRef } from "react"; -import { Transformer, Image } from "react-konva"; +import { type ElementRef, useEffect, useRef } from "react"; +import { Image, Transformer } from "react-konva"; import useImage from "use-image"; type TransformableImageConfig = Omit & { @@ -37,10 +37,26 @@ export const TransformableImage = ({ trRef.current?.getLayer()?.batchDraw(); } }, [isSelected]); - return ( <> { + console.log(e); + const positionX = e.target.x() + e.target.width() / 2; + const positionY = e.target.y() + e.target.height() / 2; + const canvasXCenter = (e.target.getStage()?.width() ?? 0) / 2; + const canvasYCenter = (e.target.getStage()?.height() ?? 0) / 2; + const isInTheXCenter = + Math.abs(Math.round(canvasXCenter) - Math.round(positionX)) <= 5; + const isInTheYCenter = + Math.abs(Math.round(canvasYCenter) - Math.round(positionY)) <= 5; + + document.body.classList.toggle("show-vertical-line", isInTheXCenter); + document.body.classList.toggle( + "show-horizontal-line", + isInTheYCenter, + ); + }} id={id} alt={"canvas image"} onClick={onSelect} @@ -53,10 +69,16 @@ export const TransformableImage = ({ if (isBlocked) { return; } + const positionX = e.target.x() + e.target.width() / 2; + const canvasXCenter = (e.target.getStage()?.width() ?? 0) / 2; + const isInTheCenter = + Math.abs(Math.round(canvasXCenter) - Math.round(positionX)) <= 5; onChange({ ...imageProps, image, - x: e.target.x(), + x: isInTheCenter + ? canvasXCenter - e.target.width() / 2 + : e.target.x(), y: e.target.y(), }); }} @@ -80,6 +102,8 @@ export const TransformableImage = ({ height: Math.max(node.height() * scaleY), }); }} + x={imageProps.x} + y={imageProps.y} /> {isSelected && ( ; +} diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..4c1847a --- /dev/null +++ b/src/index.css @@ -0,0 +1,15 @@ +.show-horizontal-line .horizontal-line::before { + content: ''; + border-bottom: 1px solid red; + width: 100%; + position: absolute; + top: 50%; + z-index:9999 +} +.show-vertical-line .vertical-line::after { + content: ''; + border-right: 1px dotted #8a8888; + height: 100%; + position: absolute; + left: 50% +} \ No newline at end of file diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 0059781..b3c1f5c 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -5,6 +5,8 @@ import { type AppType } from "next/app"; import { api } from "@/utils/api"; import "@/styles/globals.css"; +import "../index.css"; + import { Layout } from "@/components/layout/layout"; import { Provider } from "react-redux"; import { store } from "@/store/store"; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 7e88520..2c97f0f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,5 @@ import dynamic from "next/dynamic"; import Head from "next/head"; - const Canvas = dynamic(() => import("../components/canvas"), { ssr: false }); export default function Home() {