mirror of
https://github.com/trafficlunar/blockmatic.git
synced 2026-06-28 14:44:12 +00:00
feat: add toolbar
This commit is contained in:
parent
c836c26a05
commit
f0445c208b
8 changed files with 199 additions and 18 deletions
|
|
@ -3,7 +3,7 @@ import { Image as KonvaImage } from "react-konva";
|
|||
|
||||
import blocksData from "@/lib/blocks/programmer-art/average_colors.json";
|
||||
|
||||
function Blocks({ blocks, setBlocks }: { blocks: Block[], setBlocks: React.Dispatch<React.SetStateAction<Block[]>> }) {
|
||||
function Blocks({ blocks, setBlocks }: { blocks: Block[]; setBlocks: React.Dispatch<React.SetStateAction<Block[]>> }) {
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Block>();
|
||||
|
||||
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 <div className="absolute left-4 bottom-4 flex flex-col gap-1">
|
||||
<div className="bg-zinc-900 px-2 py-1 rounded shadow-xl w-fit">{block?.name ?? "air"}</div>
|
||||
return (
|
||||
<div className="absolute left-4 bottom-4 flex flex-col gap-1">
|
||||
<div className="bg-white dark:bg-zinc-950 px-2 py-1 rounded shadow-xl w-fit border border-zinc-200 dark:border-zinc-800">
|
||||
{block?.name ?? "air"}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 bg-zinc-900 px-2 py-1 rounded shadow-xl w-fit">
|
||||
<span>X: {position.x}</span>
|
||||
<span>Y: {position.y}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4 bg-white dark:bg-zinc-950 px-2 py-1 rounded shadow-xl w-fit border border-zinc-200 dark:border-zinc-800">
|
||||
<span>X: {position.x}</span>
|
||||
<span>Y: {position.y}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CursorInformation
|
||||
export default CursorInformation;
|
||||
|
|
|
|||
59
src/components/ui/toggle-group.tsx
Normal file
59
src/components/ui/toggle-group.tsx
Normal file
|
|
@ -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<typeof toggleVariants>
|
||||
>({
|
||||
size: "default",
|
||||
variant: "default",
|
||||
})
|
||||
|
||||
const ToggleGroup = React.forwardRef<
|
||||
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
|
||||
VariantProps<typeof toggleVariants>
|
||||
>(({ className, variant, size, children, ...props }, ref) => (
|
||||
<ToggleGroupPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn("flex items-center justify-center gap-1", className)}
|
||||
{...props}
|
||||
>
|
||||
<ToggleGroupContext.Provider value={{ variant, size }}>
|
||||
{children}
|
||||
</ToggleGroupContext.Provider>
|
||||
</ToggleGroupPrimitive.Root>
|
||||
))
|
||||
|
||||
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
|
||||
|
||||
const ToggleGroupItem = React.forwardRef<
|
||||
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
|
||||
VariantProps<typeof toggleVariants>
|
||||
>(({ className, children, variant, size, ...props }, ref) => {
|
||||
const context = React.useContext(ToggleGroupContext)
|
||||
|
||||
return (
|
||||
<ToggleGroupPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
toggleVariants({
|
||||
variant: context.variant || variant,
|
||||
size: context.size || size,
|
||||
}),
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</ToggleGroupPrimitive.Item>
|
||||
)
|
||||
})
|
||||
|
||||
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
|
||||
|
||||
export { ToggleGroup, ToggleGroupItem }
|
||||
45
src/components/ui/toggle.tsx
Normal file
45
src/components/ui/toggle.tsx
Normal file
|
|
@ -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<typeof TogglePrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
|
||||
VariantProps<typeof toggleVariants>
|
||||
>(({ className, variant, size, ...props }, ref) => (
|
||||
<TogglePrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(toggleVariants({ variant, size, className }))}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
||||
Toggle.displayName = TogglePrimitive.Root.displayName
|
||||
|
||||
export { Toggle, toggleVariants }
|
||||
Loading…
Add table
Add a link
Reference in a new issue