From 24c78d5cca18761eb1ffa5878872a134c308cf44 Mon Sep 17 00:00:00 2001 From: ct Date: Wed, 28 May 2025 21:07:21 +0800 Subject: [PATCH] Update --- .../custom/use-tailwind-breakpoint.jsx | 41 ++++++++++ resources/js/modules/editor/editor.tsx | 77 ++++++++++++++++--- .../modules/editor/partials/editor-canvas.tsx | 50 ++++++++++-- .../editor/partials/editor-controls.tsx | 17 ++-- .../modules/editor/partials/editor-header.tsx | 2 +- 5 files changed, 163 insertions(+), 24 deletions(-) create mode 100644 resources/js/components/custom/use-tailwind-breakpoint.jsx diff --git a/resources/js/components/custom/use-tailwind-breakpoint.jsx b/resources/js/components/custom/use-tailwind-breakpoint.jsx new file mode 100644 index 0000000..211fef8 --- /dev/null +++ b/resources/js/components/custom/use-tailwind-breakpoint.jsx @@ -0,0 +1,41 @@ +import { useEffect, useState } from 'react'; + +// Hardcoded breakpoints based on your Tailwind config +const breakpoints = { + xxxxs: 0, + xxxs: 275, + xxs: 320, + xs: 475, + sm: 640, + md: 768, + lg: 1024, + xl: 1280, + '2xl': 1400, +}; + +const getCurrentBreakpoint = () => { + if (typeof window === 'undefined') return null; // Handle SSR + + const sortedBreakpoints = Object.entries(breakpoints).sort((a, b) => b[1] - a[1]); + + return sortedBreakpoints.find(([_, width]) => window.innerWidth >= width)?.[0] || 'xxs'; +}; + +const useTailwindBreakpoint = () => { + const [breakpoint, setBreakpoint] = useState(null); + + useEffect(() => { + const handleResize = () => { + setBreakpoint(getCurrentBreakpoint()); + }; + + handleResize(); // Set initial breakpoint + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, []); + + return breakpoint; +}; + +export default useTailwindBreakpoint; diff --git a/resources/js/modules/editor/editor.tsx b/resources/js/modules/editor/editor.tsx index e6265ed..89add36 100644 --- a/resources/js/modules/editor/editor.tsx +++ b/resources/js/modules/editor/editor.tsx @@ -1,14 +1,68 @@ -import { useState } from "react" +import { useState, useEffect, useLayoutEffect } from "react" import EditSidebar from "./partials/edit-sidebar" import EditorCanvas from "./partials/editor-canvas" - import EditorHeader from "./partials/editor-header" import EditorControls from "./partials/editor-controls" +// Shared responsive hook +const useResponsiveWidth = (maxWidth = 350) => { + const [width, setWidth] = useState(350); + + const calculateWidth = () => { + const viewportWidth = window.innerWidth; + const padding = 32; + const availableWidth = viewportWidth - padding; + const constrainedWidth = Math.min(availableWidth, maxWidth); + setWidth(constrainedWidth); + }; + + useLayoutEffect(() => { + calculateWidth(); + }, [maxWidth]); + + useEffect(() => { + calculateWidth(); + + const handleResize = () => calculateWidth(); + + window.addEventListener('resize', handleResize); + window.addEventListener('orientationchange', handleResize); + + // ResizeObserver for more reliable detection + let resizeObserver; + if (window.ResizeObserver) { + resizeObserver = new ResizeObserver(calculateWidth); + resizeObserver.observe(document.body); + } + + // MutationObserver for dev tools + let mutationObserver; + if (window.MutationObserver) { + mutationObserver = new MutationObserver(() => { + setTimeout(calculateWidth, 50); + }); + mutationObserver.observe(document.documentElement, { + attributes: true, + attributeFilter: ['style'] + }); + } + + return () => { + window.removeEventListener('resize', handleResize); + window.removeEventListener('orientationchange', handleResize); + if (resizeObserver) resizeObserver.disconnect(); + if (mutationObserver) mutationObserver.disconnect(); + }; + }, [maxWidth]); + + return width; +}; + const Editor = () => { const [isEditSidebarOpen, setIsEditSidebarOpen] = useState(false) - const maxWidth = 350; + const maxWidth = 325; + const responsiveWidth = useResponsiveWidth(maxWidth); const handleEditClick = () => { setIsEditSidebarOpen(!isEditSidebarOpen) @@ -18,18 +72,23 @@ const Editor = () => { setIsEditSidebarOpen(false) } - - return ( -
+
- + - +
) } - export default Editor; diff --git a/resources/js/modules/editor/partials/editor-canvas.tsx b/resources/js/modules/editor/partials/editor-canvas.tsx index e3e8215..ad02c62 100644 --- a/resources/js/modules/editor/partials/editor-canvas.tsx +++ b/resources/js/modules/editor/partials/editor-canvas.tsx @@ -5,31 +5,65 @@ const useResponsiveCanvas = (maxWidth = 350) => { const calculateScale = () => { const viewportWidth = window.innerWidth; - const padding = 0; // 16px padding on each side - const availableWidth = viewportWidth - padding; + // Very aggressive padding reduction for small screens + let padding; + if (viewportWidth < 320) { + padding = 0; // Almost no padding on very small screens + } else if (viewportWidth < 400) { + padding = 0; // Minimal padding on small screens + } else { + padding = 0; // Normal padding on larger screens + } + + const availableWidth = viewportWidth - padding; const constrainedWidth = Math.min(availableWidth, maxWidth); const newScale = constrainedWidth / 720; - // Don't scale above 100% and ensure minimum scale for very small screens - setScale(Math.max(0.3, Math.min(newScale, 1))); + // Just cap at 100%, no minimum to avoid clipping + const finalScale = Math.min(newScale, 1); + setScale(finalScale); }; useLayoutEffect(() => { calculateScale(); - }, []); + }, [maxWidth]); useEffect(() => { + calculateScale(); + const handleResize = () => calculateScale(); + // Multiple event listeners for better coverage window.addEventListener('resize', handleResize); window.addEventListener('orientationchange', handleResize); + // ResizeObserver for more reliable detection in dev tools + let resizeObserver; + if (window.ResizeObserver) { + resizeObserver = new ResizeObserver(calculateScale); + resizeObserver.observe(document.body); + } + + // MutationObserver to catch when dev tools changes the viewport + let mutationObserver; + if (window.MutationObserver) { + mutationObserver = new MutationObserver(() => { + setTimeout(calculateScale, 50); + }); + mutationObserver.observe(document.documentElement, { + attributes: true, + attributeFilter: ['style'] + }); + } + return () => { window.removeEventListener('resize', handleResize); window.removeEventListener('orientationchange', handleResize); + if (resizeObserver) resizeObserver.disconnect(); + if (mutationObserver) mutationObserver.disconnect(); }; - }, []); + }, [maxWidth]); return scale; }; @@ -50,7 +84,7 @@ const EditorCanvas = ({maxWidth = 350}) => { }; return ( -
+
{ }} >
{}, isEditActive = + + -
- 9:16 -
@@ -40,7 +45,7 @@ const EditorControls = ({ className = '', onEditClick = () => {}, isEditActive = diff --git a/resources/js/modules/editor/partials/editor-header.tsx b/resources/js/modules/editor/partials/editor-header.tsx index 779e93d..f38046d 100644 --- a/resources/js/modules/editor/partials/editor-header.tsx +++ b/resources/js/modules/editor/partials/editor-header.tsx @@ -7,7 +7,7 @@ const EditorHeader = ( {className = ''} ) => { return ( -
+