diff --git a/src/Home.jsx b/src/Home.jsx index 8572ad9..d6aa5e1 100644 --- a/src/Home.jsx +++ b/src/Home.jsx @@ -61,13 +61,15 @@ export const Home = () => { {!isLoading && <> -
- { - activeObject && - } -
-
+ { + activeObject && +
+ +
+ } + +
@@ -79,7 +81,7 @@ export const Home = () => {
-
+
diff --git a/src/components/ActionButtons.jsx b/src/components/ActionButtons.jsx index 0cc85e2..e9d8acf 100644 --- a/src/components/ActionButtons.jsx +++ b/src/components/ActionButtons.jsx @@ -15,7 +15,6 @@ const aspectRatios = [ { value: "4:3", label: "Standard (4:3)" }, { value: "3:2", label: "Classic (3:2)" }, { value: "16:9", label: "Widescreen (16:9)" }, - { value: "9:16", label: "Portrait (9:16)" }, { value: "21:9", label: "Ultrawide (21:9)" }, { value: "32:9", label: "Super Ultrawide (32:9)" }, { value: "1.85:1", label: "Cinema Standard (1.85:1)" }, @@ -24,7 +23,9 @@ const aspectRatios = [ { value: "5:4", label: "Large Format (5:4)" }, { value: "7:5", label: "Artistic Format (7:5)" }, { value: "11:8.5", label: "Letter Size (11:8.5)" }, - { value: "3:4", label: "Portrait (3:4)" }, + { value: "3:4", label: "Portrait (4:4)" }, + { value: "9:16", label: "Vertical (9:16)" }, + { value: "1.33:1", label: "Instagram Stories (1.33:1)" }, { value: "1.91:1", label: "Facebook Ads (1.91:1)" }, ]; diff --git a/src/components/Canvas/Canvas.jsx b/src/components/Canvas/Canvas.jsx index 07bea1f..d30388f 100644 --- a/src/components/Canvas/Canvas.jsx +++ b/src/components/Canvas/Canvas.jsx @@ -236,22 +236,9 @@ export default function Canvas() { }, [canvas, setActiveObject]); return ( - <> - {/* Zoom Controls */} -
- {zoomLevel}% - handleZoom(value[0])} - min={0} - max={100} - step={1} - className="w-32" - /> -
- +
{/* Canvas Container */} -
+
- + + {/* Zoom Controls */} +
+ {zoomLevel}% + handleZoom(value[0])} + min={0} + max={100} + step={1} + className="w-32" + /> +
+
); } diff --git a/src/components/Layouts/Header.jsx b/src/components/Layouts/Header.jsx deleted file mode 100644 index c755101..0000000 --- a/src/components/Layouts/Header.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import { AlignLeft, AlignRight } from 'lucide-react'; -import { useContext } from 'react'; -import OpenContext from '../Context/openContext/OpenContext'; - -const Header = () => { - const { setRightPanelOpen, setLeftPanelOpen } = useContext(OpenContext); - - return ( -
- -

setLeftPanelOpen(true)}>Add Element

- -

PlanPostAi Canvas

- -

setRightPanelOpen(true)}> Edit Panel

- -
- ) -} - -export default Header \ No newline at end of file diff --git a/src/components/ObjectShortcut.jsx b/src/components/ObjectShortcut.jsx index 40e376b..f2a09c4 100644 --- a/src/components/ObjectShortcut.jsx +++ b/src/components/ObjectShortcut.jsx @@ -281,7 +281,7 @@ export const ObjectShortcut = ({ value }) => {

Change object position

- +
- +

{tooltipContent}

diff --git a/src/components/Panel/ProjectPanel.jsx b/src/components/Panel/ProjectPanel.jsx index 7ce1176..03a3b90 100644 --- a/src/components/Panel/ProjectPanel.jsx +++ b/src/components/Panel/ProjectPanel.jsx @@ -8,7 +8,7 @@ import { deleteProject, getProjects } from '@/api/projectApi'; import { useNavigate } from 'react-router-dom'; import { toast } from '@/hooks/use-toast'; import ActiveObjectContext from '../Context/activeObject/ObjectContext'; -import { FixedSizeList as List } from 'react-window'; // Import FixedSizeList from react-window +import { FixedSizeList as List } from 'react-window'; export const ProjectPanel = () => { const { setSelectedPanel, canvas } = useContext(CanvasContext); @@ -63,12 +63,11 @@ export const ProjectPanel = () => { } }); - // Row renderer for react-window const Row = ({ index, style }) => { - const project = projects?.data?.[index]; // Get project by index + const project = filteredProjects[index]; // Use filtered projects return ( -
+
navigate(`/${project.id}`)}>

{project?.name}

{project?.description}

@@ -77,11 +76,16 @@ export const ProjectPanel = () => { + className="w-fit p-1 ml-auto" size="small" onClick={() => { projectDelete(project?.id) }}> + +
); }; + // Filter projects where preview_url is not empty or null + const filteredProjects = projects?.data?.filter(project => project?.preview_url) || []; + return (
@@ -102,9 +106,9 @@ export const ProjectPanel = () => { { !projectLoading && projectSuccess && projects?.status === 200 && {Row} diff --git a/src/components/Panel/TopBar.jsx b/src/components/Panel/TopBar.jsx index 8e6da74..6c71563 100644 --- a/src/components/Panel/TopBar.jsx +++ b/src/components/Panel/TopBar.jsx @@ -21,220 +21,124 @@ export function TopBar() { const activeObjectType = activeObject?.type; const hasClipPath = !!activeObject?.clipPath; const customClipPath = activeObject?.isClipPath; - const scrollContainerRef = useRef(null); - const [showScrollButtons, setShowScrollButtons] = useState(false); - - const scroll = (direction) => { - const container = scrollContainerRef.current; - if (container) { - const scrollAmount = 200; // Adjust this value to change scroll distance - container.scrollBy({ - left: direction * scrollAmount, - behavior: "smooth", - }); - } - }; - + // w - [calc(100 % -80px)] h - full return ( -
setShowScrollButtons(true)} - onMouseLeave={() => setShowScrollButtons(false)} - > -
- {showScrollButtons && ( - <> +
+
+
+
+ +
+ +
- - - )} -
-
+ + {/* Canvas settings */}
- -
-
- - - {/* canvas settings */} - + + + + + + + + + +
-
- {activeObjectType !== "image" && - activeObject?.type !== "i-text" && - !hasClipPath && - !customClipPath && ( - - - - )} - - - {!customClipPath && ( - + + - - -
-
- -
-
- + + + +
+
+ +
+
+ +
diff --git a/src/components/loadCanvas.js b/src/components/loadCanvas.js deleted file mode 100644 index 2f8e762..0000000 --- a/src/components/loadCanvas.js +++ /dev/null @@ -1,107 +0,0 @@ -const loadCanvasState = (state) => { - if (!canvas2) { - console.error('Canvas2 is not initialized!'); - return; - } - try { - const canvasData = typeof state === 'string' ? JSON.parse(state) : state; - - // Clear the existing canvas - canvas2.clear(); - - // Set the background color if it exists - if (canvasData.backgroundColor) { - canvas2.set({ backgroundColor: canvasData.backgroundColor }); - } - - // Function to load background image - const loadBackgroundImage = () => { - return new Promise((resolve) => { - if (!canvasData.background) { - resolve(); - return; - } - - const imgElement = new Image(); - imgElement.crossOrigin = 'anonymous'; // Handle CORS if needed - - imgElement.onload = () => { - const imgInstance = new fabric.Image(imgElement, { - originX: canvasData.background.originX || 'left', - originY: canvasData.background.originY || 'top', - scaleX: canvasData.background.scaleX || canvas2.width / imgElement.width, - scaleY: canvasData.background.scaleY || canvas2.height / imgElement.height, - opacity: canvasData.background.opacity || 1, - }); - - // Set background image using the set method - canvas2.set({ backgroundImage: imgInstance }); - resolve(); - }; - - imgElement.onerror = () => { - console.error("Failed to load the background image"); - resolve(); // Resolve anyway to continue loading objects - }; - - imgElement.src = canvasData.background.src; - }); - }; - - // Function to load objects - const loadObjects = () => { - return new Promise((resolve) => { - canvas2.loadFromJSON({ objects: canvasData.objects }, () => { - resolve(); - }, (obj, element) => { - return obj; - }); - }); - }; - - // Load background image and objects if they exist - const loadTasks = []; - if (canvasData.background || canvasData.objects?.length) { - if (canvasData.background) { - loadTasks.push(loadBackgroundImage()); - } - if (canvasData.objects?.length) { - loadTasks.push(loadObjects()); - } - - Promise.all(loadTasks) - .then(() => { - canvas2.requestRenderAll(); // Ensure re-rendering - }) - .catch((error) => { - console.error('Error during canvas loading:', error); - }); - } else { - // If only background color exists - if (canvasData.backgroundColor) { - canvas2.requestRenderAll(); // Apply background color and render - } - } - - } catch (error) { - console.error('Error loading canvas state:', error); - } -}; - - -// for download image/canvas -const exportScaledCanvasImage = (scale = 2) => { - if (canvas) { - const imageBase64 = canvas.toDataURL({ - format: 'png', // or 'jpeg' - quality: 1, // (0 to 1) for JPEG compression, ignored for PNG - multiplier: scale, // Scale the canvas size - }); - - // Download the scaled image - const link = document.createElement('a'); - link.href = imageBase64; - link.download = `canvas-image-${scale}x.png`; - link.click(); - } -}; \ No newline at end of file diff --git a/src/index.css b/src/index.css index e456a86..13c4249 100644 --- a/src/index.css +++ b/src/index.css @@ -152,4 +152,24 @@ body { @apply bg-[#f5f0ff] text-foreground; } +} + +::-webkit-scrollbar { + width: 0px; + height: 5px; + border-radius: 5px; + cursor: pointer; + /* background-color: var(--primary-600); */ + @apply bg-red-50 +} + +::-webkit-scrollbar-track { + background-color: var(--primary-500); +} + +::-webkit-scrollbar-thumb { + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); + width: 5px; + background-color: red; + border-radius: 5px; } \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index f5edc3a..e187998 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -3,71 +3,71 @@ import scrollbarHide from "tailwind-scrollbar-hide"; /** @type {import('tailwindcss').Config} */ export default { - darkMode: ["class"], - content: ["./index.html", "./src/**/*.{ts,tsx,js,jsx}"], - theme: { - extend: { - textColor: { - primary: { - DEFAULT: 'hsl(var(--primary-text))', - foreground: 'hsl(var(--primary-foreground))' - } - }, - screens: { - mdxl: '1100px' - }, - colors: { - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - selection: { - DEFAULT: 'hsl(var(--selection))', - foreground: 'hsl(var(--selection-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - } - } - }, - plugins: [scrollbar, scrollbarHide, require("tailwindcss-animate")], + darkMode: ["class"], + content: ["./index.html", "./src/**/*.{ts,tsx,js,jsx}"], + theme: { + extend: { + textColor: { + primary: { + DEFAULT: 'hsl(var(--primary-text))', + foreground: 'hsl(var(--primary-foreground))' + } + }, + screens: { + mdxl: '1100px' + }, + colors: { + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + selection: { + DEFAULT: 'hsl(var(--selection))', + foreground: 'hsl(var(--selection-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + } + } + }, + plugins: [scrollbar, scrollbarHide, require("tailwindcss-animate")], };