diff --git a/image-ai/bun.lockb b/image-ai/bun.lockb index 2b32c5f..e6235a2 100644 Binary files a/image-ai/bun.lockb and b/image-ai/bun.lockb differ diff --git a/image-ai/package.json b/image-ai/package.json index 59b2b7b..6d0d4df 100644 --- a/image-ai/package.json +++ b/image-ai/package.json @@ -9,15 +9,19 @@ "lint": "next lint" }, "dependencies": { + "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-tooltip": "^1.1.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "fabric": "5.3.0-browser", "jsdom": "^25.0.1", "lucide-react": "^0.453.0", - "next": "15.0.0", - "react": "19.0.0-rc-65a56d0e-20241020", - "react-dom": "19.0.0-rc-65a56d0e-20241020", + "next": "^15.0.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-icons": "^5.3.0", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7" }, diff --git a/image-ai/public/logo.svg b/image-ai/public/logo.svg new file mode 100644 index 0000000..81a6615 --- /dev/null +++ b/image-ai/public/logo.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/image-ai/src/components/ui/dropdown-menu.tsx b/image-ai/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..0fc4c0e --- /dev/null +++ b/image-ai/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/image-ai/src/components/ui/separator.tsx b/image-ai/src/components/ui/separator.tsx new file mode 100644 index 0000000..12d81c4 --- /dev/null +++ b/image-ai/src/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client" + +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/image-ai/src/components/ui/tooltip.tsx b/image-ai/src/components/ui/tooltip.tsx new file mode 100644 index 0000000..30fc44d --- /dev/null +++ b/image-ai/src/components/ui/tooltip.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" + +import { cn } from "@/lib/utils" + +const TooltipProvider = TooltipPrimitive.Provider + +const Tooltip = TooltipPrimitive.Root + +const TooltipTrigger = TooltipPrimitive.Trigger + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/image-ai/src/features/editor/components/editor.tsx b/image-ai/src/features/editor/components/editor.tsx index 99e1ca2..81565a4 100644 --- a/image-ai/src/features/editor/components/editor.tsx +++ b/image-ai/src/features/editor/components/editor.tsx @@ -4,6 +4,11 @@ import { fabric } from "fabric"; import { useEditor } from "@/features/editor/hooks/use-editor"; import { useEffect, useRef } from "react"; +import { Navbar } from "./navbar"; +import { Sidebar } from "./sidebar"; +import { Toolbar } from "./toolbar"; +import { Footer } from "./footer"; + export const Editor = () => { const { init } = useEditor(); @@ -21,12 +26,25 @@ export const Editor = () => { initialCanvas: canvas, initialContainer: ContainerRef.current!, }); + + return () => { + canvas.dispose(); // clean up the canvas + }; }, [init]); return (
-
- + +
+ +
+ +
+ +
+
+
); diff --git a/image-ai/src/features/editor/components/footer.tsx b/image-ai/src/features/editor/components/footer.tsx new file mode 100644 index 0000000..9f9530d --- /dev/null +++ b/image-ai/src/features/editor/components/footer.tsx @@ -0,0 +1,8 @@ +export const Footer = () => { + return ( +
+ +
+ ); +}; \ No newline at end of file diff --git a/image-ai/src/features/editor/components/logo.tsx b/image-ai/src/features/editor/components/logo.tsx new file mode 100644 index 0000000..9e79c1f --- /dev/null +++ b/image-ai/src/features/editor/components/logo.tsx @@ -0,0 +1,17 @@ +import Link from "next/link"; +import Image from "next/image"; + +export const Logo = () => { + return( + +
+ Image AI +
+ + ); +}; \ No newline at end of file diff --git a/image-ai/src/features/editor/components/navbar.tsx b/image-ai/src/features/editor/components/navbar.tsx new file mode 100644 index 0000000..6f4ade4 --- /dev/null +++ b/image-ai/src/features/editor/components/navbar.tsx @@ -0,0 +1,45 @@ +"use client"; + +import {Logo} from "./logo"; + +import {ChevronDown} from "lucide-react"; +import {CiFileOn} from "react-icons/ci"; +import {Button} from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuItem, + DropdownMenuContent, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; + +export const Navbar = () => { + return ( + + ); +}; \ No newline at end of file diff --git a/image-ai/src/features/editor/components/sidebar.tsx b/image-ai/src/features/editor/components/sidebar.tsx new file mode 100644 index 0000000..fd2d412 --- /dev/null +++ b/image-ai/src/features/editor/components/sidebar.tsx @@ -0,0 +1,10 @@ +"use client"; + +export const Sidebar = () => { + return ( + + ); +}; \ No newline at end of file diff --git a/image-ai/src/features/editor/components/toolbar.tsx b/image-ai/src/features/editor/components/toolbar.tsx new file mode 100644 index 0000000..1d2fca2 --- /dev/null +++ b/image-ai/src/features/editor/components/toolbar.tsx @@ -0,0 +1,8 @@ +export const Toolbar = () => { + return ( +
+ +
+ ); +}; \ No newline at end of file diff --git a/image-ai/src/features/editor/hooks/use-auto-resize.ts b/image-ai/src/features/editor/hooks/use-auto-resize.ts index 5b26b4b..7623392 100644 --- a/image-ai/src/features/editor/hooks/use-auto-resize.ts +++ b/image-ai/src/features/editor/hooks/use-auto-resize.ts @@ -23,7 +23,7 @@ UseAutoResizeProps) => { const localWorkspace = canvas.getObjects() .find((object) => object.name === "clip"); - //@ts-ignore + const scale = fabric.util.findScaleToFit(localWorkspace, { width : width, height: height, diff --git a/logoipsum-291.svg b/logoipsum-291.svg new file mode 100644 index 0000000..8a164e4 --- /dev/null +++ b/logoipsum-291.svg @@ -0,0 +1 @@ + \ No newline at end of file