diff --git a/src/components/builder/components/layout/AdvancedMobileStudio.tsx b/src/components/builder/components/layout/AdvancedMobileStudio.tsx new file mode 100644 index 00000000..ae619cb4 --- /dev/null +++ b/src/components/builder/components/layout/AdvancedMobileStudio.tsx @@ -0,0 +1,133 @@ +import React, { useMemo, useState } from 'react'; +import { ArrowLeft, ArrowRight, Settings2, SlidersHorizontal, Minus } from 'lucide-react'; + +type BottomTab = 'left' | 'settings' | 'right'; + +type Props = { + leftPanel: React.ReactNode; + rightPanel: React.ReactNode; + children: React.ReactNode; +}; + +const PANEL_OPTIONS = [10, 20, 30, 40] as const; + +const AdvancedMobileStudio: React.FC = ({ leftPanel, rightPanel, children }) => { + const [openPanel, setOpenPanel] = useState<'left' | 'right' | null>(null); + const [activeTab, setActiveTab] = useState('settings'); + const [resizePosterForPanel, setResizePosterForPanel] = useState(true); + const [leftPanelPercent, setLeftPanelPercent] = useState(30); + const [rightPanelPercent, setRightPanelPercent] = useState(30); + + const panelPercent = useMemo( + () => (openPanel === 'left' ? leftPanelPercent : openPanel === 'right' ? rightPanelPercent : 30), + [openPanel, leftPanelPercent, rightPanelPercent] + ); + + const posterScale = openPanel && resizePosterForPanel ? 1 - panelPercent / 100 : 1; + + const onAdjust = (side: 'left' | 'right') => { + const current = side === 'left' ? leftPanelPercent : rightPanelPercent; + const idx = PANEL_OPTIONS.indexOf(current as (typeof PANEL_OPTIONS)[number]); + const next = PANEL_OPTIONS[(idx + 1) % PANEL_OPTIONS.length]; + if (side === 'left') setLeftPanelPercent(next); + else setRightPanelPercent(next); + }; + + return ( +
+
+
+ {children} +
+ + {openPanel === 'left' && ( +
+
{leftPanel}
+
+ )} + {openPanel === 'right' && ( +
+
{rightPanel}
+
+ )} +
+ + + + {activeTab === 'settings' && ( +
+
+ Mobile Settings +
+ +
+ Panel size: Left {leftPanelPercent}% · Right {rightPanelPercent}% +
+
+ + +
+
+ )} +
+ ); +}; + +export default AdvancedMobileStudio; diff --git a/src/components/builder/index.tsx b/src/components/builder/index.tsx index 6dc99d42..2b1ce65a 100644 --- a/src/components/builder/index.tsx +++ b/src/components/builder/index.tsx @@ -30,6 +30,7 @@ import { SelectionPanel, } from './components/panels'; import MobileDock from './components/layout/MobileDock'; +import AdvancedMobileStudio from './components/layout/AdvancedMobileStudio'; import ToolbarBtn from './components/toolbar/ToolbarButton'; import ZoomOverlay from './components/canvas/ZoomOverlay'; import { EditorProvider, useEditor } from './context/EditorContext'; @@ -1331,14 +1332,16 @@ const StudioLayout: React.FC<{ {/* Sidebar Canvas Toggles removed — now in navbar */} - openCtxMenu('logo', e)} - /> + {(isDesktop || builderMode !== 'advanced') && ( + openCtxMenu('logo', e)} + /> + )} {/* Film corner accents */} {(['tl', 'tr', 'bl', 'br'] as const).map((c) => (
)} - {/* Mobile Panel (In-flow flex item) */} - {!isFullscreen && ( + {/* Advanced mobile app layout */} + {!isFullscreen && builderMode === 'advanced' && ( + } + rightPanel={renderAdvancedPanel()} + > + openCtxMenu('logo', e)} + /> + + )} + + {/* Legacy mobile panel for simple mode */} + {!isFullscreen && builderMode !== 'advanced' && (
- {/* Swipe-down dismiss handle */} -
setMobileSheetMode('hidden')} - onTouchStart={(e) => { - const startY = e.touches[0].clientY; - const onMove = (ev: TouchEvent) => { - if (ev.touches[0].clientY - startY > 40) { - setMobileSheetMode('hidden'); - window.removeEventListener('touchmove', onMove); - } - }; - window.addEventListener('touchmove', onMove, { passive: true }); - const cleanup = () => { - window.removeEventListener('touchmove', onMove); - }; - window.addEventListener('touchend', cleanup, { once: true }); - }} - > +
setMobileSheetMode('hidden')}>
-
{(activeTab === 'source' || activeTab === 'layers' || activeTab === 'poster') && ( - + )} {(activeTab === 'badges' || activeTab === 'selection') && ( @@ -1439,13 +1434,14 @@ const StudioLayout: React.FC<{ )}
- {/* Mobile dock */} - 0} - hasLogo={config.logo} - isMinimalPreset={(config.uiPreset ?? 'b') === 'm'} - selectedCount={selectedIds.size + (selectedLogo ? 1 : 0)} - /> + {builderMode !== 'advanced' && ( + 0} + hasLogo={config.logo} + isMinimalPreset={(config.uiPreset ?? 'b') === 'm'} + selectedCount={selectedIds.size + (selectedLogo ? 1 : 0)} + /> + )} {/* Zoom + fullscreen overlay — always visible */}