diff --git a/resources/js/modules/editor/editor.tsx b/resources/js/modules/editor/editor.jsx similarity index 100% rename from resources/js/modules/editor/editor.tsx rename to resources/js/modules/editor/editor.jsx diff --git a/resources/js/modules/editor/partials/edit-nav-sidebar.tsx b/resources/js/modules/editor/partials/edit-nav-sidebar.jsx similarity index 94% rename from resources/js/modules/editor/partials/edit-nav-sidebar.tsx rename to resources/js/modules/editor/partials/edit-nav-sidebar.jsx index 9b710fa..4dda09d 100644 --- a/resources/js/modules/editor/partials/edit-nav-sidebar.tsx +++ b/resources/js/modules/editor/partials/edit-nav-sidebar.jsx @@ -5,12 +5,7 @@ import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sh import useLocalSettingsStore from '@/stores/localSettingsStore'; import { SettingsIcon } from 'lucide-react'; -interface EditNavSidebarProps { - isOpen: boolean; - onClose: () => void; -} - -export default function EditNavSidebar({ isOpen, onClose }: EditNavSidebarProps) { +export default function EditNavSidebar({ isOpen, onClose }) { const { getSetting, setSetting } = useLocalSettingsStore(); return ( diff --git a/resources/js/modules/editor/partials/edit-sidebar.tsx b/resources/js/modules/editor/partials/edit-sidebar.jsx similarity index 97% rename from resources/js/modules/editor/partials/edit-sidebar.tsx rename to resources/js/modules/editor/partials/edit-sidebar.jsx index 4d63576..dcb1d61 100644 --- a/resources/js/modules/editor/partials/edit-sidebar.tsx +++ b/resources/js/modules/editor/partials/edit-sidebar.jsx @@ -7,12 +7,7 @@ import useMediaStore from '@/stores/MediaStore'; import { Edit3 } from 'lucide-react'; import { useEffect, useState } from 'react'; -interface EditSidebarProps { - isOpen: boolean; - onClose: () => void; -} - -export default function EditSidebar({ isOpen, onClose }: EditSidebarProps) { +export default function EditSidebar({ isOpen, onClose }) { const { memes, backgrounds, @@ -42,7 +37,7 @@ export default function EditSidebar({ isOpen, onClose }: EditSidebarProps) { } }, [isOpen, activeTab, memes.length, backgrounds.length, isFetchingMemes, isFetchingBackgrounds]); - const handleTabChange = (value: string) => { + const handleTabChange = (value) => { setActiveTab(value); if (value === 'memes' && memes.length === 0 && !isFetchingMemes) { fetchMemes(); diff --git a/resources/js/modules/editor/partials/editor-canvas.tsx b/resources/js/modules/editor/partials/editor-canvas.jsx similarity index 89% rename from resources/js/modules/editor/partials/editor-canvas.tsx rename to resources/js/modules/editor/partials/editor-canvas.jsx index 308c40e..79a3d2e 100644 --- a/resources/js/modules/editor/partials/editor-canvas.tsx +++ b/resources/js/modules/editor/partials/editor-canvas.jsx @@ -1,8 +1,8 @@ -import React, { useEffect, useLayoutEffect, useState } from 'react'; +import { useEffect, useLayoutEffect, useState } from 'react'; import { LAYOUT_CONSTANTS, calculateResponsiveScale } from '../utils/layout-constants'; import VideoEditor from './canvas/video-editor'; -const useResponsiveCanvas = (maxWidth: number = 350) => { +const useResponsiveCanvas = (maxWidth = 350) => { const [scale, setScale] = useState(() => calculateResponsiveScale(maxWidth)); useLayoutEffect(() => { @@ -22,14 +22,14 @@ const useResponsiveCanvas = (maxWidth: number = 350) => { window.addEventListener('orientationchange', handleResize); // ResizeObserver for more reliable detection - let resizeObserver: ResizeObserver | undefined; + let resizeObserver; if (window.ResizeObserver) { resizeObserver = new ResizeObserver(handleResize); resizeObserver.observe(document.body); } // MutationObserver for dev tools detection - let mutationObserver: MutationObserver | undefined; + let mutationObserver; if (window.MutationObserver) { mutationObserver = new MutationObserver(() => { setTimeout(handleResize, 50); @@ -51,11 +51,7 @@ const useResponsiveCanvas = (maxWidth: number = 350) => { return scale; }; -interface EditorCanvasProps { - maxWidth?: number; -} - -const EditorCanvas: React.FC = ({ maxWidth = 350 }) => { +const EditorCanvas = ({ maxWidth = 350 }) => { const scale = useResponsiveCanvas(maxWidth); const displayWidth = LAYOUT_CONSTANTS.CANVAS_WIDTH * scale; const displayHeight = LAYOUT_CONSTANTS.CANVAS_HEIGHT * scale; diff --git a/resources/js/modules/editor/partials/editor-controls.tsx b/resources/js/modules/editor/partials/editor-controls.jsx similarity index 100% rename from resources/js/modules/editor/partials/editor-controls.tsx rename to resources/js/modules/editor/partials/editor-controls.jsx diff --git a/resources/js/modules/editor/partials/editor-header.tsx b/resources/js/modules/editor/partials/editor-header.jsx similarity index 100% rename from resources/js/modules/editor/partials/editor-header.tsx rename to resources/js/modules/editor/partials/editor-header.jsx diff --git a/resources/js/modules/editor/utils/layout-constants.js b/resources/js/modules/editor/utils/layout-constants.js new file mode 100644 index 0000000..5dd2b1b --- /dev/null +++ b/resources/js/modules/editor/utils/layout-constants.js @@ -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 = () => { + 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 = () => { + 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) => { + 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); + }; diff --git a/resources/js/modules/editor/utils/layout-constants.ts b/resources/js/modules/editor/utils/layout-constants.ts deleted file mode 100644 index ce39888..0000000 --- a/resources/js/modules/editor/utils/layout-constants.ts +++ /dev/null @@ -1,67 +0,0 @@ -// 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); -}; diff --git a/resources/js/pages/home/home.tsx b/resources/js/pages/home/home.tsx index 9d58cf0..99e5c9b 100644 --- a/resources/js/pages/home/home.tsx +++ b/resources/js/pages/home/home.tsx @@ -1,4 +1,4 @@ -import Editor from '@/modules/editor/editor'; +import Editor from '@/modules/editor/editor.jsx'; const Home = () => { return ( diff --git a/resources/js/stores/MediaStore.ts b/resources/js/stores/MediaStore.js similarity index 100% rename from resources/js/stores/MediaStore.ts rename to resources/js/stores/MediaStore.js diff --git a/resources/js/stores/VideoEditorStore.ts b/resources/js/stores/VideoEditorStore.js similarity index 100% rename from resources/js/stores/VideoEditorStore.ts rename to resources/js/stores/VideoEditorStore.js diff --git a/resources/js/stores/localSettingsStore.js b/resources/js/stores/localSettingsStore.js new file mode 100644 index 0000000..a24e8a6 --- /dev/null +++ b/resources/js/stores/localSettingsStore.js @@ -0,0 +1,83 @@ +import { mountStoreDevtool } from 'simple-zustand-devtools'; +import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; + +// Immutable default settings +const defaultSettings = { + genAlphaSlang: false, + // Add more settings here +}; + +const useLocalSettingsStore = create( + persist( + (set, get) => ({ + settings: { ...defaultSettings }, // clone to avoid shared reference + + // Get a setting by key + getSetting: (key) => { + const currentSettings = get().settings; + return key in currentSettings ? currentSettings[key] : (defaultSettings[key] ?? null); + }, + + // Set or update a specific setting + setSetting: (key, value) => { + console.log(`Updating setting ${key} to`, value); // <-- Debug log + set((state) => ({ + settings: { + ...state.settings, + [key]: value, + }, + })); + }, + + // Reset all settings to default + resetSettings: () => { + set({ settings: { ...defaultSettings } }); // create new object reference + }, + + // Reset a specific setting to its default + resetSetting: (key) => { + set((state) => ({ + settings: { + ...state.settings, + [key]: defaultSettings[key], + }, + })); + }, + + // Merge default settings with current ones (useful on load) + initializeSettings: () => { + set((state) => ({ + settings: { + ...defaultSettings, + ...state.settings, + }, + })); + }, + }), + { + name: 'local-settings-storage', + // Ensure only the 'settings' key is stored + partialize: (state) => ({ settings: state.settings }), + // Explicit localStorage usage (for compatibility) + storage: { + getItem: (name) => { + const stored = localStorage.getItem(name); + return stored ? JSON.parse(stored) : null; + }, + setItem: (name, value) => { + localStorage.setItem(name, JSON.stringify(value)); + }, + removeItem: (name) => { + localStorage.removeItem(name); + }, + }, + }, + ), +); + +if (import.meta.env.APP_ENV === 'local') { + mountStoreDevtool('LocalSettingsStore', useLocalSettingsStore); +} + +export default useLocalSettingsStore; diff --git a/resources/js/stores/localSettingsStore.ts b/resources/js/stores/localSettingsStore.ts deleted file mode 100644 index 0e33a44..0000000 --- a/resources/js/stores/localSettingsStore.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { create } from 'zustand'; -import { persist } from 'zustand/middleware'; - -// Immutable default settings -const defaultSettings = { - genAlphaSlang: false, - // Add more settings here -}; - -const useLocalSettingsStore = create( - persist( - (set, get) => ({ - settings: { ...defaultSettings }, // clone to avoid shared reference - - // Get a setting by key - getSetting: (key) => { - const currentSettings = get().settings; - return key in currentSettings ? currentSettings[key] : defaultSettings[key] ?? null; - }, - - // Set or update a specific setting - setSetting: (key, value) => { - console.log(`Updating setting ${key} to`, value); // <-- Debug log - set((state) => ({ - settings: { - ...state.settings, - [key]: value, - }, - })); - }, - - - // Reset all settings to default - resetSettings: () => { - set({ settings: { ...defaultSettings } }); // create new object reference - }, - - // Reset a specific setting to its default - resetSetting: (key) => { - set((state) => ({ - settings: { - ...state.settings, - [key]: defaultSettings[key], - }, - })); - }, - - // Merge default settings with current ones (useful on load) - initializeSettings: () => { - set((state) => ({ - settings: { - ...defaultSettings, - ...state.settings, - }, - })); - }, - }), - { - name: 'local-settings-storage', - // Ensure only the 'settings' key is stored - partialize: (state) => ({ settings: state.settings }), - // Explicit localStorage usage (for compatibility) - storage: { - getItem: (name) => { - const stored = localStorage.getItem(name); - return stored ? JSON.parse(stored) : null; - }, - setItem: (name, value) => { - localStorage.setItem(name, JSON.stringify(value)); - }, - removeItem: (name) => { - localStorage.removeItem(name); - }, - } - - } - ) -); - -if (import.meta.env.APP_ENV === "local") { - mountStoreDevtool("LocalSettingsStore", useLocalSettingsStore); -} - -export default useLocalSettingsStore;