From 98e6354a6ed27ed0306325f5b0cd6cdc13e7b614 Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Sat, 14 Dec 2024 22:38:06 +0000 Subject: [PATCH] feat: design open image dialog --- package.json | 2 + src/components/dialogs/OpenImage.tsx | 105 ++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index bea75b6..292d236 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@pixi/react": "7", "@radix-ui/react-dialog": "^1.1.3", + "@radix-ui/react-label": "^2.1.1", "@radix-ui/react-menubar": "^1.1.2", "@radix-ui/react-slider": "^1.2.2", "@radix-ui/react-toggle": "^1.1.0", @@ -22,6 +23,7 @@ "pixi.js": "7", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-dropzone": "^14.3.5", "react-router": "^7.0.2", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7" diff --git a/src/components/dialogs/OpenImage.tsx b/src/components/dialogs/OpenImage.tsx index e22f8cf..07e4c75 100644 --- a/src/components/dialogs/OpenImage.tsx +++ b/src/components/dialogs/OpenImage.tsx @@ -1,15 +1,114 @@ +import { useCallback, useEffect, useState } from "react"; +import { useDropzone } from "react-dropzone"; + +import { CircleAlertIcon, UploadIcon } from "lucide-react"; + import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; function OpenImage() { + const { acceptedFiles, getRootProps, getInputProps } = useDropzone({ + accept: { + "image/*": [".png", ".jpg", ".jpeg", ".bmp", ".webp", ".tiff"], + }, + }); + + const [image, setImage] = useState(); + const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 }); + + useEffect(() => { + if (acceptedFiles[0]) { + const img = new Image(); + img.onload = () => { + setImage(img); + setImageDimensions({ width: img.width, height: img.height }); + }; + img.src = URL.createObjectURL(acceptedFiles[0]); + } + }, [acceptedFiles]); + + const onDimensionChange = (e: React.ChangeEvent, isWidth: boolean) => { + const newDimension = Number(e.target.value); + const aspectRatio = imageDimensions.width / imageDimensions.height; + + if (newDimension < 1 || newDimension > 10000) return; + setImageDimensions(() => { + if (isWidth) { + return { width: newDimension, height: Math.round(newDimension / aspectRatio) }; + } else { + return { width: Math.round(newDimension / aspectRatio), height: newDimension }; + } + }); + }; + return ( - Open image + Open Image Open your image to load as blocks into the canvas - - + +
+
+ + +

Drag and drop your image here

+
+ +
+ {image && acceptedFiles[0] && ( + <> + your image + +
+
+ +

{acceptedFiles[0].name}

+
+ +
+ + onDimensionChange(e, true)} /> +
+ +
+ + onDimensionChange(e, false)} + /> +
+
+ + )} +
+
+ + + {imageDimensions.height > 320 && ( +
+ + The height is above 320 blocks! +
+ )} + +
);