import { useEffect, useRef } from 'react'; import { DSP, AppPage } from '../../types/types'; import AnimatedLogo from '../../assets/icons/AnimatedLogo'; import { PlusIcon } from '../../assets/icons/PlusIcon'; import { CrownIcon } from '../../assets/icons/CrownIcon'; import Led from '../Led/Led'; import { CloseIcon } from '../../assets/icons/CloseIcon'; import './Topbar.css'; function getStep(count: number) { if (count <= 4) return 4; if (count <= 6) return 6; if (count <= 8) return 8; return 10; } function Tab({ dsp, active, dimmed, step, onSelect, onRemove, onConnect, onDisconnect, }: { dsp: DSP; active: boolean; dimmed: boolean; step: number; onSelect: () => void; onRemove: () => void; onConnect: (dsp: DSP) => void; onDisconnect: (dsp: DSP) => void; }) { const isConnected = dsp.status === 'connected'; const handleTabKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect(); } }; return (
{dsp.name}
); } function TopBar({ dsps, selected, page, setPage, setSelect, onSelect, onRemove, onAddClick, onConnect, onDisconnect, }: { dsps: DSP[]; selected: number | null; page: AppPage; setPage: (page: AppPage) => void; setSelect: (select: number | null) => void; onSelect: (id: number) => void; onRemove: (dsp: DSP) => void; onAddClick: () => void; onConnect: (dsp: DSP) => void; onDisconnect: (dsp: DSP) => void; }) { const hasTabs = dsps.length > 0; const tabstripRef = useRef(null); const prevCount = useRef(dsps.length); const step = getStep(dsps.length); const updateFade = () => { const el = tabstripRef.current; if (!el) return; const atStart = el.scrollLeft <= 1; const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 1; el.dataset.fadeStart = String(!atStart); el.dataset.fadeEnd = String(!atEnd && el.scrollWidth > el.clientWidth); }; useEffect(() => { const el = tabstripRef.current; if (!el) return; const onWheel = (e: WheelEvent) => { if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) { el.scrollLeft += e.deltaY; e.preventDefault(); } }; el.addEventListener('wheel', onWheel, { passive: false }); return () => el.removeEventListener('wheel', onWheel); }, []); useEffect(() => { updateFade(); const el = tabstripRef.current; el?.addEventListener('scroll', updateFade); window.addEventListener('resize', updateFade); return () => { el?.removeEventListener('scroll', updateFade); window.removeEventListener('resize', updateFade); }; }, [dsps.length]); useEffect(() => { if (dsps.length > prevCount.current && tabstripRef.current) { tabstripRef.current.scrollTo({ left: tabstripRef.current.scrollWidth, behavior: 'smooth', }); } prevCount.current = dsps.length; }, [dsps.length]); return (
{dsps.map((dsp) => ( onSelect(dsp.id)} onRemove={() => onRemove(dsp)} onConnect={onConnect} onDisconnect={onDisconnect} /> ))}
{hasTabs ? ( ) : ( )}
); } export default TopBar;