diff --git a/packages/studio/src/components/VideoStudio.jsx b/packages/studio/src/components/VideoStudio.jsx index 6604798..06f4c4c 100644 --- a/packages/studio/src/components/VideoStudio.jsx +++ b/packages/studio/src/components/VideoStudio.jsx @@ -174,18 +174,6 @@ function ControlBtn({ icon, label, onClick, style }) { // ── Dropdown panel ───────────────────────────────────────────────────────────── // Rendered inside a `relative` wrapper div; floats above the anchor button. -function DropdownPanel({ type, open, onClose, children }) { - const isModel = type === 'model'; - - return ( -
e.stopPropagation()} - className={`absolute bottom-[calc(100%+8px)] left-0 z-50 transition-all origin-bottom-left glass rounded-3xl p-3 shadow-4xl border border-white/10 flex flex-col ${isModel ? 'w-[calc(100vw-3rem)] max-w-xs' : 'w-52 max-w-[240px]'} ${open ? 'opacity-100 pointer-events-auto scale-100' : 'opacity-0 pointer-events-none scale-95'}`} - > - {children} -
- ); -} // ── Main component ──────────────────────────────────────────────────────────── @@ -242,12 +230,7 @@ export default function VideoStudio({ apiKey, onGenerationComplete, historyItems // ── refs ── const containerRef = useRef(null); const textareaRef = useRef(null); - const modelBtnRef = useRef(null); - const arBtnRef = useRef(null); - const durationBtnRef = useRef(null); - const resolutionBtnRef = useRef(null); - const qualityBtnRef = useRef(null); - const modeBtnRef = useRef(null); + const dropdownRef = useRef(null); const imageFileInputRef = useRef(null); const videoFileInputRef = useRef(null); const resultVideoRef = useRef(null); @@ -319,9 +302,9 @@ export default function VideoStudio({ apiKey, onGenerationComplete, historyItems useEffect(() => { if (!openDropdown) return; const handler = (e) => { - const isInsideDropdown = [modelBtnRef, arBtnRef, durationBtnRef, resolutionBtnRef, qualityBtnRef, modeBtnRef] - .some(ref => ref.current && ref.current.contains(e.target)); - if (!isInsideDropdown) setOpenDropdown(null); + if (dropdownRef.current && !dropdownRef.current.contains(e.target)) { + setOpenDropdown(null); + } }; window.addEventListener('click', handler); return () => window.removeEventListener('click', handler); @@ -845,7 +828,7 @@ export default function VideoStudio({ apiKey, onGenerationComplete, historyItems
{/* Model btn */} -
+
@@ -855,120 +838,132 @@ export default function VideoStudio({ apiKey, onGenerationComplete, historyItems label={selectedModelName} onClick={toggleDropdown('model')} /> - setOpenDropdown(null)}> - setOpenDropdown(null)} - /> - + {openDropdown === 'model' && ( +
e.stopPropagation()} className="absolute bottom-[calc(100%+8px)] left-0 z-50 bg-[#111] rounded-3xl p-3 border border-white/10 flex flex-col w-[calc(100vw-3rem)] max-w-xs"> + setOpenDropdown(null)} + /> +
+ )}
{/* Aspect ratio btn */} {showAr && ( -
+
} label={selectedAr} onClick={toggleDropdown('ar')} /> - setOpenDropdown(null)}> -
Aspect Ratio
-
- {getCurrentAspectRatios(selectedModel).map(r => ( -
{ e.stopPropagation(); setSelectedAr(r); setOpenDropdown(null); }} - > -
-
-
+ {openDropdown === 'ar' && ( +
e.stopPropagation()} className="absolute bottom-[calc(100%+8px)] left-0 z-50 bg-[#111] rounded-3xl p-3 border border-white/10 flex flex-col w-52 max-w-[240px]"> +
Aspect Ratio
+
+ {getCurrentAspectRatios(selectedModel).map(r => ( +
{ e.stopPropagation(); setSelectedAr(r); setOpenDropdown(null); }} + > +
+
+
+
+ {r}
- {r} + {selectedAr === r && }
- {selectedAr === r && } -
- ))} + ))} +
- + )}
)} {/* Duration btn */} {showDuration && ( -
+
} label={`${selectedDuration}s`} onClick={toggleDropdown('duration')} /> - setOpenDropdown(null)}> -
Duration
-
- {getCurrentDurations(selectedModel).map(d => ( - { e.stopPropagation(); setSelectedDuration(d); setOpenDropdown(null); }} /> - ))} + {openDropdown === 'duration' && ( +
e.stopPropagation()} className="absolute bottom-[calc(100%+8px)] left-0 z-50 bg-[#111] rounded-3xl p-3 border border-white/10 flex flex-col w-52 max-w-[240px]"> +
Duration
+
+ {getCurrentDurations(selectedModel).map(d => ( + { e.stopPropagation(); setSelectedDuration(d); setOpenDropdown(null); }} /> + ))} +
- + )}
)} {/* Resolution btn */} {showResolution && ( -
+
} label={selectedResolution || '720p'} onClick={toggleDropdown('resolution')} /> - setOpenDropdown(null)}> -
Resolution
-
- {getCurrentResolutions(selectedModel).map(r => ( - { e.stopPropagation(); setSelectedResolution(r); setOpenDropdown(null); }} /> - ))} + {openDropdown === 'resolution' && ( +
e.stopPropagation()} className="absolute bottom-[calc(100%+8px)] left-0 z-50 bg-[#111] rounded-3xl p-3 border border-white/10 flex flex-col w-52 max-w-[240px]"> +
Resolution
+
+ {getCurrentResolutions(selectedModel).map(r => ( + { e.stopPropagation(); setSelectedResolution(r); setOpenDropdown(null); }} /> + ))} +
- + )}
)} {/* Quality btn */} {showQuality && ( -
+
} label={selectedQuality || 'basic'} onClick={toggleDropdown('quality')} /> - setOpenDropdown(null)}> -
Quality
-
- {getQualitiesForModel(getCurrentModels(), selectedModel).map(q => ( - { e.stopPropagation(); setSelectedQuality(q); setOpenDropdown(null); }} /> - ))} + {openDropdown === 'quality' && ( +
e.stopPropagation()} className="absolute bottom-[calc(100%+8px)] left-0 z-50 bg-[#111] rounded-3xl p-3 border border-white/10 flex flex-col w-52 max-w-[240px]"> +
Quality
+
+ {getQualitiesForModel(getCurrentModels(), selectedModel).map(q => ( + { e.stopPropagation(); setSelectedQuality(q); setOpenDropdown(null); }} /> + ))} +
- + )}
)} {/* Mode btn */} {showMode && ( -
+
} label={selectedMode || 'normal'} onClick={toggleDropdown('mode')} /> - setOpenDropdown(null)}> -
Mode
-
- {getModesForModel(selectedModel).map(m => ( - { e.stopPropagation(); setSelectedMode(m); setOpenDropdown(null); }} /> - ))} + {openDropdown === 'mode' && ( +
e.stopPropagation()} className="absolute bottom-[calc(100%+8px)] left-0 z-50 bg-[#111] rounded-3xl p-3 border border-white/10 flex flex-col w-52 max-w-[240px]"> +
Mode
+
+ {getModesForModel(selectedModel).map(m => ( + { e.stopPropagation(); setSelectedMode(m); setOpenDropdown(null); }} /> + ))} +
- + )}
)}