diff --git a/package.json b/package.json index c4f4162..bea75b6 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@pixi/react": "7", + "@radix-ui/react-dialog": "^1.1.3", "@radix-ui/react-menubar": "^1.1.2", "@radix-ui/react-slider": "^1.2.2", "@radix-ui/react-toggle": "^1.1.0", diff --git a/src/components/Blocks.tsx b/src/components/Blocks.tsx index ad70530..441d131 100644 --- a/src/components/Blocks.tsx +++ b/src/components/Blocks.tsx @@ -11,7 +11,7 @@ interface Props { textures: Record; } -function Blocks({ blocks, setBlocks, textures }: Props) { +function Blocks({ blocks, setBlocks, textures }: Props) { const findClosestBlock = (r: number, g: number, b: number, a: number) => { let closestBlock = ""; let closestDistance = Infinity; @@ -28,40 +28,39 @@ function Blocks({ blocks, setBlocks, textures }: Props) { }; useEffect(() => { - // // TESTING: convert image to blocks - // const image = new Image(); - // image.src = "/bliss.png"; - // image.addEventListener("load", () => { - // const canvas = document.createElement("canvas"); - // const ctx = canvas.getContext("2d"); + // TESTING: convert image to blocks + const image = new Image(); + image.src = "/bliss.png"; + image.addEventListener("load", () => { + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); - // if (ctx) { - // canvas.width = image.width; - // canvas.height = image.height; - // ctx.drawImage(image, 0, 0, image.width / 4, image.height / 4); + if (ctx) { + canvas.width = image.width; + canvas.height = image.height; + ctx.drawImage(image, 0, 0, image.width / 4, image.height / 4); - // const imageData = ctx.getImageData(0, 0, image.width / 4, image.height / 4); - // const newBlocks: Block[] = []; + const imageData = ctx.getImageData(0, 0, image.width / 4, image.height / 4); + const newBlocks: Block[] = []; - // for (let i = 0; i < imageData.data.length; i += 4) { - // const block = findClosestBlock(imageData.data[i], imageData.data[i + 1], imageData.data[i + 2], imageData.data[i + 3]); + for (let i = 0; i < imageData.data.length; i += 4) { + const block = findClosestBlock(imageData.data[i], imageData.data[i + 1], imageData.data[i + 2], imageData.data[i + 3]); - // const x = Math.floor((i / 4) % imageData.width); - // const y = Math.floor(i / 4 / imageData.width); + const x = Math.floor((i / 4) % imageData.width); + const y = Math.floor(i / 4 / imageData.width); - // newBlocks.push({ - // name: block, - // x, - // y, - // }); - // } + newBlocks.push({ + name: block, + x, + y, + }); + } - // setBlocks(newBlocks); - // } - // }); + setBlocks(newBlocks); + } + }); setBlocks(welcomeBlocksData); - console.log(textures) }, [textures]); return ( diff --git a/src/components/dialogs/OpenImage.tsx b/src/components/dialogs/OpenImage.tsx new file mode 100644 index 0000000..e22f8cf --- /dev/null +++ b/src/components/dialogs/OpenImage.tsx @@ -0,0 +1,18 @@ +import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; + +function OpenImage() { + return ( + + + Open image + Open your image to load as blocks into the canvas + + + + + + ); +} + +export default OpenImage; diff --git a/src/components/menubar/FileMenu.tsx b/src/components/menubar/FileMenu.tsx index 5058fd4..5f29a50 100644 --- a/src/components/menubar/FileMenu.tsx +++ b/src/components/menubar/FileMenu.tsx @@ -1,3 +1,5 @@ +import { useContext } from "react"; + import { MenubarContent, MenubarItem, @@ -9,14 +11,17 @@ import { MenubarTrigger, } from "@/components/ui/menubar"; +import { DialogContext } from "@/context/DialogContext"; + function FileMenu() { + const openDialog = useContext(DialogContext); + return ( File Open Schematic - Open Image - + openDialog("OpenImage")}>Open Image diff --git a/src/components/menubar/index.tsx b/src/components/menubar/index.tsx index 33d784e..7dda6b2 100644 --- a/src/components/menubar/index.tsx +++ b/src/components/menubar/index.tsx @@ -1,20 +1,24 @@ import { Menubar as UIMenubar } from "@/components/ui/menubar"; +import { DialogProvider } from "@/context/DialogContext"; + import FileMenu from "./FileMenu"; import ViewMenu from "./ViewMenu"; import MoreMenu from "./MoreMenu"; function Menubar() { return ( - - - blockmatic - + + + + blockmatic + - - - - + + + + + ); } diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..bd4f282 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,120 @@ +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/src/context/DialogContext.tsx b/src/context/DialogContext.tsx new file mode 100644 index 0000000..6137091 --- /dev/null +++ b/src/context/DialogContext.tsx @@ -0,0 +1,34 @@ +import { Dialog } from "@/components/ui/dialog"; +import { createContext, lazy, ReactNode, Suspense, useState } from "react"; + +interface Props { + children: ReactNode; +} + +export const DialogContext = createContext((id: string) => {}); + +export const DialogProvider = ({ children }: Props) => { + const [open, setOpen] = useState(false); + const [id, setId] = useState(""); + + const openDialog = (id: string) => { + setId(id); + setOpen(true); + }; + + const LazyDialogContent = id ? lazy(() => import(`@/components/dialogs/${id}.tsx`)) : null; + + return ( + + setOpen(value)}> + {LazyDialogContent && ( + Loading dialog...
}> + + + )} + + + {children} + + ); +};