diff --git a/resources/js/modules/editor/editor.tsx b/resources/js/modules/editor/editor.tsx index b31bd3f..938e423 100644 --- a/resources/js/modules/editor/editor.tsx +++ b/resources/js/modules/editor/editor.tsx @@ -4,17 +4,10 @@ import EditSidebar from "./partials/edit-sidebar" import EditorCanvas from "./partials/editor-canvas" import EditorHeader from "./partials/editor-header" import EditorControls from "./partials/editor-controls" - -// Move calculation outside the hook for best performance -const calculateResponsiveWidth = (maxWidth) => { - const viewportWidth = window.innerWidth; - const padding = 32; - const availableWidth = viewportWidth - padding; - return Math.min(availableWidth, maxWidth); -}; +import { calculateOptimalMaxWidth, calculateResponsiveWidth } from "./utils/layout-constants" // Hook to detect if viewport is below minimum width -const useViewportDetection = (minWidth = 375) => { +const useViewportDetection = (minWidth = 320) => { const [isBelowMinWidth, setIsBelowMinWidth] = useState(false); useLayoutEffect(() => { @@ -26,19 +19,13 @@ const useViewportDetection = (minWidth = 375) => { setIsBelowMinWidth(window.innerWidth < minWidth); }; - // Update immediately checkViewport(); - - // Event listeners window.addEventListener('resize', checkViewport); window.addEventListener('orientationchange', checkViewport); - // ResizeObserver for more reliable detection let resizeObserver; if (window.ResizeObserver) { - resizeObserver = new ResizeObserver(() => { - checkViewport(); - }); + resizeObserver = new ResizeObserver(checkViewport); resizeObserver.observe(document.body); } @@ -52,42 +39,45 @@ const useViewportDetection = (minWidth = 375) => { return isBelowMinWidth; }; -// Shared responsive hook -const useResponsiveWidth = (maxWidth = 350) => { - const [width, setWidth] = useState(350); +// Hook for responsive dimensions +const useResponsiveDimensions = () => { + const [dimensions, setDimensions] = useState(() => ({ + maxWidth: calculateOptimalMaxWidth(), + responsiveWidth: calculateResponsiveWidth() + })); useLayoutEffect(() => { - setWidth(calculateResponsiveWidth(maxWidth)); - }, [maxWidth]); + const newMaxWidth = calculateOptimalMaxWidth(); + const newResponsiveWidth = calculateResponsiveWidth(); + setDimensions({ + maxWidth: newMaxWidth, + responsiveWidth: newResponsiveWidth + }); + }, []); useEffect(() => { - // Update immediately - setWidth(calculateResponsiveWidth(maxWidth)); - - // Create event handlers inside effect to avoid dependency issues const handleResize = () => { - setWidth(calculateResponsiveWidth(maxWidth)); + const newMaxWidth = calculateOptimalMaxWidth(); + const newResponsiveWidth = calculateResponsiveWidth(); + setDimensions({ + maxWidth: newMaxWidth, + responsiveWidth: newResponsiveWidth + }); }; window.addEventListener('resize', handleResize); window.addEventListener('orientationchange', handleResize); - // ResizeObserver for more reliable detection let resizeObserver; if (window.ResizeObserver) { - resizeObserver = new ResizeObserver(() => { - setWidth(calculateResponsiveWidth(maxWidth)); - }); + resizeObserver = new ResizeObserver(handleResize); resizeObserver.observe(document.body); } - // MutationObserver for dev tools let mutationObserver; if (window.MutationObserver) { mutationObserver = new MutationObserver(() => { - setTimeout(() => { - setWidth(calculateResponsiveWidth(maxWidth)); - }, 50); + setTimeout(handleResize, 50); }); mutationObserver.observe(document.documentElement, { attributes: true, @@ -101,16 +91,15 @@ const useResponsiveWidth = (maxWidth = 350) => { if (resizeObserver) resizeObserver.disconnect(); if (mutationObserver) mutationObserver.disconnect(); }; - }, [maxWidth]); + }, []); - return width; + return dimensions; }; const Editor = () => { const [isEditSidebarOpen, setIsEditSidebarOpen] = useState(false) - const maxWidth = 340; - const responsiveWidth = useResponsiveWidth(maxWidth); - const isBelowMinWidth = useViewportDetection(340); + const { maxWidth, responsiveWidth } = useResponsiveDimensions(); + const isBelowMinWidth = useViewportDetection(320); const handleEditClick = () => { setIsEditSidebarOpen(!isEditSidebarOpen) @@ -122,7 +111,7 @@ const Editor = () => { return (
diff --git a/resources/js/modules/editor/partials/editor-canvas.tsx b/resources/js/modules/editor/partials/editor-canvas.tsx index 1faa4b1..e591b9d 100644 --- a/resources/js/modules/editor/partials/editor-canvas.tsx +++ b/resources/js/modules/editor/partials/editor-canvas.tsx @@ -1,72 +1,37 @@ import React, { useState, useEffect, useLayoutEffect } from 'react'; +import { LAYOUT_CONSTANTS, calculateResponsiveScale } from '../utils/layout-constants'; -// Move calculation outside the hook for best performance -const calculateResponsiveScale = (maxWidth) => { - const viewportWidth = window.innerWidth; - - // Very aggressive padding reduction for small screens - let padding = 0; - - if (viewportWidth >= 340 && viewportWidth < 389) { - padding = 110; - } - else if (viewportWidth >= 390 && viewportWidth < 409) { - padding = 60; - } - else if (viewportWidth >= 410 && viewportWidth < 767) { - padding = 40; - } - else if (viewportWidth >= 768) { - padding = 0; - } - - - - const availableWidth = viewportWidth - padding; - const constrainedWidth = Math.min(availableWidth, maxWidth); - const newScale = constrainedWidth / 720; - - - // Just cap at 100%, no minimum to avoid clipping - return Math.min(newScale, 1); -}; - -const useResponsiveCanvas = (maxWidth = 350) => { - const [scale, setScale] = useState(0.5); +const useResponsiveCanvas = (maxWidth: number = 350) => { + const [scale, setScale] = useState(() => calculateResponsiveScale(maxWidth)); useLayoutEffect(() => { setScale(calculateResponsiveScale(maxWidth)); }, [maxWidth]); useEffect(() => { - // Update immediately - setScale(calculateResponsiveScale(maxWidth)); - - // Create event handlers inside effect const handleResize = () => { setScale(calculateResponsiveScale(maxWidth)); }; - // Multiple event listeners for better coverage + // Update immediately + handleResize(); + + // Event listeners window.addEventListener('resize', handleResize); window.addEventListener('orientationchange', handleResize); - // ResizeObserver for more reliable detection in dev tools - let resizeObserver; + // ResizeObserver for more reliable detection + let resizeObserver: ResizeObserver | undefined; if (window.ResizeObserver) { - resizeObserver = new ResizeObserver(() => { - setScale(calculateResponsiveScale(maxWidth)); - }); + resizeObserver = new ResizeObserver(handleResize); resizeObserver.observe(document.body); } - // MutationObserver to catch when dev tools changes the viewport - let mutationObserver; + // MutationObserver for dev tools detection + let mutationObserver: MutationObserver | undefined; if (window.MutationObserver) { mutationObserver = new MutationObserver(() => { - setTimeout(() => { - setScale(calculateResponsiveScale(maxWidth)); - }, 50); + setTimeout(handleResize, 50); }); mutationObserver.observe(document.documentElement, { attributes: true, @@ -85,12 +50,14 @@ const useResponsiveCanvas = (maxWidth = 350) => { return scale; }; -const EditorCanvas = ({maxWidth = 350}) => { +interface EditorCanvasProps { + maxWidth?: number; +} + +const EditorCanvas: React.FC = ({maxWidth = 350}) => { const scale = useResponsiveCanvas(maxWidth); - const canvasWidth = 720; - const canvasHeight = 1280; - const displayWidth = canvasWidth * scale; - const displayHeight = canvasHeight * scale; + const displayWidth = LAYOUT_CONSTANTS.CANVAS_WIDTH * scale; + const displayHeight = LAYOUT_CONSTANTS.CANVAS_HEIGHT * scale; const convertCoordinates = (e) => { const rect = e.currentTarget.getBoundingClientRect(); @@ -111,14 +78,15 @@ const EditorCanvas = ({maxWidth = 350}) => {
{ const { x, y } = convertCoordinates(e); // Handle your canvas interactions here // x, y are the actual canvas coordinates (0-720, 0-1280) + console.log(`Canvas coordinates: x=${x}, y=${y}`); }} > {/* Your canvas content goes here */} diff --git a/resources/js/modules/editor/partials/editor-header.tsx b/resources/js/modules/editor/partials/editor-header.tsx index f38046d..0de1681 100644 --- a/resources/js/modules/editor/partials/editor-header.tsx +++ b/resources/js/modules/editor/partials/editor-header.tsx @@ -7,14 +7,14 @@ const EditorHeader = ( {className = ''} ) => { return ( -
+

MEMEAIGEN

- diff --git a/resources/js/modules/editor/utils/layout-constants.ts b/resources/js/modules/editor/utils/layout-constants.ts new file mode 100644 index 0000000..ce39888 --- /dev/null +++ b/resources/js/modules/editor/utils/layout-constants.ts @@ -0,0 +1,67 @@ +// Shared layout constants for the editor +export const LAYOUT_CONSTANTS = { + // Fixed element heights + HEADER_HEIGHT: 64, // Header with padding + CONTROLS_HEIGHT: 48, // Button controls height + + // Canvas dimensions + CANVAS_WIDTH: 720, + CANVAS_HEIGHT: 1280, + CANVAS_ASPECT_RATIO: 720 / 1280, // 9:16 aspect ratio + + // Spacing and padding + MIN_PADDING: 16, // Minimum padding around elements + CONTAINER_SPACING: 16, // Space between header, canvas, and controls (space-y-4 = 16px) + CONTAINER_VERTICAL_PADDING: 24, // py-6 = 24px top + 24px bottom +}; + +// Calculate optimal maxWidth based on viewport dimensions +export const calculateOptimalMaxWidth = (): number => { + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + + // Calculate total used height for fixed elements and spacing + const usedHeight = + LAYOUT_CONSTANTS.HEADER_HEIGHT + + LAYOUT_CONSTANTS.CONTROLS_HEIGHT + + (LAYOUT_CONSTANTS.CONTAINER_SPACING * 2) + // Space between elements + LAYOUT_CONSTANTS.CONTAINER_VERTICAL_PADDING + // py-6 padding + (LAYOUT_CONSTANTS.MIN_PADDING * 2); // Additional safety padding + + const availableHeight = viewportHeight - usedHeight; + const availableWidth = viewportWidth - (LAYOUT_CONSTANTS.MIN_PADDING * 2); + + // Calculate maxWidth based on both width and height constraints + const maxWidthFromHeight = availableHeight * LAYOUT_CONSTANTS.CANVAS_ASPECT_RATIO; + const maxWidthFromWidth = availableWidth; + + // Use the smaller constraint to ensure everything fits + const optimalMaxWidth = Math.min(maxWidthFromHeight, maxWidthFromWidth); + + // Ensure minimum viable size (but allow smaller if viewport is tiny) + const minViableWidth = 280; + + return Math.max(optimalMaxWidth, Math.min(minViableWidth, availableWidth)); +}; + +// Calculate responsive width based on optimal maxWidth +export const calculateResponsiveWidth = (): number => { + const optimalMaxWidth = calculateOptimalMaxWidth(); + const viewportWidth = window.innerWidth; + const padding = LAYOUT_CONSTANTS.MIN_PADDING * 2; + const availableWidth = viewportWidth - padding; + + return Math.min(availableWidth, optimalMaxWidth); +}; + +// Calculate responsive scale for canvas +export const calculateResponsiveScale = (maxWidth: number): number => { + const viewportWidth = window.innerWidth; + const padding = LAYOUT_CONSTANTS.MIN_PADDING * 2; + const availableWidth = viewportWidth - padding; + const constrainedWidth = Math.min(availableWidth, maxWidth); + const scale = constrainedWidth / LAYOUT_CONSTANTS.CANVAS_WIDTH; + + // Cap at 100% to avoid upscaling + return Math.min(scale, 1); +};