diff --git a/package.json b/package.json index c0ca082..ff9727b 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ }, "dependencies": { "@radix-ui/react-menubar": "^1.1.2", + "@radix-ui/react-toggle": "^1.1.0", + "@radix-ui/react-toggle-group": "^1.1.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "konva": "^9.3.16", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ad06b1..0b2cbdc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,12 @@ importers: '@radix-ui/react-menubar': specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toggle': + specifier: ^1.1.0 + version: 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toggle-group': + specifier: ^1.1.0 + version: 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -634,6 +640,32 @@ packages: '@types/react': optional: true + '@radix-ui/react-toggle-group@1.1.0': + resolution: {integrity: sha512-PpTJV68dZU2oqqgq75Uzto5o/XfOVgkrJ9rulVmfTKxWp3HfUjHE6CP/WLRR4AzPX9HWxw7vFow2me85Yu+Naw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toggle@1.1.0': + resolution: {integrity: sha512-gwoxaKZ0oJ4vIgzsfESBuSgJNdc0rv12VhHgcqN0TEJmmZixXG/2XpsLK8kzNWYcnaoRIEEQc0bEi3dIvdUpjw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-use-callback-ref@1.1.0': resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} peerDependencies: @@ -2279,6 +2311,32 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + '@radix-ui/react-toggle-group@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toggle': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + + '@radix-ui/react-toggle@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: react: 18.3.1 diff --git a/src/App.tsx b/src/App.tsx index 0833581..96f18a1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import { useEffect, useRef, useState } from "react"; import { Layer, Stage } from "react-konva"; +import { Hand } from "lucide-react"; import { Menubar, @@ -12,6 +13,7 @@ import { MenubarSubTrigger, MenubarTrigger, } from "@/components/ui/menubar"; +import { ToggleGroup, ToggleGroupItem } from "./components/ui/toggle-group"; import ThemeChanger from "./components/menubar/theme-changer"; import Blocks from "./components/blocks"; @@ -31,6 +33,7 @@ function App() { const [stageCoords, setStageCoords] = useState({ x: 0, y: 0 }); const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); + const [tool, setTool] = useState("hand"); const [blocks, setBlocks] = useState([]); const onMouseMove = (e) => { @@ -68,10 +71,12 @@ function App() { }, []); return ( -
- +
+ - blockmatic + + blockmatic + File @@ -99,6 +104,12 @@ function App() { + + + + + +
> }) { +function Blocks({ blocks, setBlocks }: { blocks: Block[]; setBlocks: React.Dispatch> }) { const [images, setImages] = useState<{ [key: string]: HTMLImageElement }>({}); const findClosestBlock = (r: number, g: number, b: number) => { @@ -52,12 +52,12 @@ function Blocks({ blocks, setBlocks }: { blocks: Block[], setBlocks: React.Dispa const block = findClosestBlock(imageData.data[i], imageData.data[i + 1], imageData.data[i + 2]); const x = Math.floor((i / 4) % imageData.width); - const y = Math.floor((i / 4) / imageData.width); + const y = Math.floor(i / 4 / imageData.width); newBlocks.push({ name: block, x, - y + y, }); } diff --git a/src/components/cursor-information.tsx b/src/components/cursor-information.tsx index 9f3efcf..06afffd 100644 --- a/src/components/cursor-information.tsx +++ b/src/components/cursor-information.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; -function CursorInformation({ mousePosition, blocks }: { mousePosition: Position, blocks: Block[] }) { - const [position, setPosition] = useState({ x: 0, y: 0 }); +function CursorInformation({ mousePosition, blocks }: { mousePosition: Position; blocks: Block[] }) { + const [position, setPosition] = useState({ x: 0, y: 0 }); const [block, setBlock] = useState(); useEffect(() => { @@ -14,18 +14,22 @@ function CursorInformation({ mousePosition, blocks }: { mousePosition: Position, y: snappedY, }); - setBlock(blocks.find(b => b.x === snappedX && b.y === snappedY)); + setBlock(blocks.find((b) => b.x === snappedX && b.y === snappedY)); } }, [mousePosition]); - return
-
{block?.name ?? "air"}
+ return ( +
+
+ {block?.name ?? "air"} +
-
- X: {position.x} - Y: {position.y} -
-
+
+ X: {position.x} + Y: {position.y} +
+
+ ); } -export default CursorInformation \ No newline at end of file +export default CursorInformation; diff --git a/src/components/ui/toggle-group.tsx b/src/components/ui/toggle-group.tsx new file mode 100644 index 0000000..afe5da6 --- /dev/null +++ b/src/components/ui/toggle-group.tsx @@ -0,0 +1,59 @@ +import * as React from "react" +import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" +import { type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { toggleVariants } from "@/components/ui/toggle" + +const ToggleGroupContext = React.createContext< + VariantProps +>({ + size: "default", + variant: "default", +}) + +const ToggleGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, children, ...props }, ref) => ( + + + {children} + + +)) + +ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName + +const ToggleGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, children, variant, size, ...props }, ref) => { + const context = React.useContext(ToggleGroupContext) + + return ( + + {children} + + ) +}) + +ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName + +export { ToggleGroup, ToggleGroupItem } diff --git a/src/components/ui/toggle.tsx b/src/components/ui/toggle.tsx new file mode 100644 index 0000000..14b0108 --- /dev/null +++ b/src/components/ui/toggle.tsx @@ -0,0 +1,45 @@ +"use client" + +import * as React from "react" +import * as TogglePrimitive from "@radix-ui/react-toggle" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const toggleVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors hover:bg-zinc-100 hover:text-zinc-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-zinc-100 data-[state=on]:text-zinc-900 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2 dark:ring-offset-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-400 dark:focus-visible:ring-zinc-300 dark:data-[state=on]:bg-zinc-800 dark:data-[state=on]:text-zinc-50", + { + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-zinc-200 bg-transparent hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-50", + }, + size: { + default: "h-10 px-3 min-w-10", + sm: "h-9 px-2.5 min-w-9", + lg: "h-11 px-5 min-w-11", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +const Toggle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, ...props }, ref) => ( + +)) + +Toggle.displayName = TogglePrimitive.Root.displayName + +export { Toggle, toggleVariants } diff --git a/src/types.d.ts b/src/types.d.ts index ba64a58..a451695 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -5,4 +5,6 @@ interface Position { interface Block extends Position { name: string; -} \ No newline at end of file +} + +type Tool = "hand"; \ No newline at end of file