|
import { Square, RectangleVertical, RectangleHorizontal, ChevronDown } from 'lucide-react'; |
|
import { useState, useEffect, useRef } from 'react'; |
|
|
|
const dimensions = [ |
|
{ |
|
id: 'landscape', |
|
label: '3:2', |
|
width: 1500, |
|
height: 1000, |
|
icon: RectangleHorizontal |
|
}, |
|
{ |
|
id: 'square', |
|
label: '1:1', |
|
width: 1000, |
|
height: 1000, |
|
icon: Square |
|
}, |
|
{ |
|
id: 'portrait', |
|
label: '4:5', |
|
width: 1000, |
|
height: 1250, |
|
icon: RectangleVertical |
|
} |
|
|
|
]; |
|
|
|
const DimensionSelector = ({ currentDimension = dimensions[0], onDimensionChange }) => { |
|
const [isOpen, setIsOpen] = useState(false); |
|
const dropdownRef = useRef(null); |
|
|
|
|
|
const handleToggle = () => setIsOpen(!isOpen); |
|
|
|
|
|
const timeoutRef = useRef(null); |
|
|
|
const handleMouseEnter = () => { |
|
if (timeoutRef.current) { |
|
clearTimeout(timeoutRef.current); |
|
timeoutRef.current = null; |
|
} |
|
setIsOpen(true); |
|
}; |
|
|
|
const handleMouseLeave = () => { |
|
timeoutRef.current = setTimeout(() => { |
|
setIsOpen(false); |
|
}, 100); |
|
}; |
|
|
|
|
|
useEffect(() => { |
|
const handleClickOutside = (event) => { |
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { |
|
setIsOpen(false); |
|
} |
|
}; |
|
|
|
document.addEventListener('mousedown', handleClickOutside); |
|
return () => { |
|
document.removeEventListener('mousedown', handleClickOutside); |
|
if (timeoutRef.current) clearTimeout(timeoutRef.current); |
|
}; |
|
}, []); |
|
|
|
|
|
const current = dimensions.find(d => d.id === currentDimension.id) || dimensions[0]; |
|
const Icon = current.icon; |
|
|
|
return ( |
|
<div |
|
className="relative z-50" |
|
ref={dropdownRef} |
|
onMouseEnter={handleMouseEnter} |
|
onMouseLeave={handleMouseLeave} |
|
> |
|
{/* Current selection */} |
|
<button |
|
type="button" |
|
className="w-full flex flex-row md:flex-col items-center justify-center md:p-2 md:py-4 px-2 py-2 rounded-lg transition-colors hover:bg-gray-50" |
|
onClick={handleToggle} |
|
style={{ opacity: isOpen ? 1 : 0.7 }} |
|
> |
|
<Icon className="w-5 h-5 text-gray-900 mr-2 md:mr-0 md:mb-1" /> |
|
<span className="text-sm text-gray-900">{current.label}</span> |
|
</button> |
|
|
|
{/* Dropdown */} |
|
{isOpen && ( |
|
<> |
|
{/* Invisible bridge element that extends to the dropdown */} |
|
<div className="hidden md:block absolute left-[calc(100%-4px)] top-0 h-full w-8" |
|
onMouseEnter={handleMouseEnter} |
|
style={{ pointerEvents: 'auto' }} /> |
|
|
|
<div className="absolute left-0 md:left-[calc(100%+4px)] top-0 bg-white rounded-xl shadow-soft |
|
border border-gray-200 z-10 min-w-[80px]" |
|
onMouseEnter={handleMouseEnter} |
|
onMouseLeave={handleMouseLeave}> |
|
<div className="py-1"> |
|
{dimensions.map((dim) => { |
|
const Icon = dim.icon; |
|
return ( |
|
<button |
|
type="button" |
|
key={dim.id} |
|
onClick={() => { |
|
onDimensionChange(dim); |
|
setIsOpen(false); |
|
}} |
|
className={`w-full p-2 flex items-center gap-2 hover:bg-gray-50 transition-colors whitespace-nowrap ${ |
|
currentDimension.id === dim.id ? 'bg-gray-100 text-gray-900' : 'text-gray-600' |
|
} ${dim.id === dimensions[0].id ? 'rounded-t-lg' : ''} ${dim.id === dimensions[dimensions.length-1].id ? 'rounded-b-lg' : ''}`} |
|
> |
|
<Icon className="w-4 h-4" /> |
|
<span className="text-sm">{dim.label}</span> |
|
</button> |
|
); |
|
})} |
|
</div> |
|
</div> |
|
</> |
|
)} |
|
</div> |
|
); |
|
}; |
|
|
|
export default DimensionSelector; |