import * as React from 'react'; import styles from './TopNav.module.scss'; import { ScreenKey } from './types'; import { texts } from '../../texts'; interface ITab { key: ScreenKey; label: string; } const TABS: ITab[] = [ { key: 'dashboard', label: texts.nav.dashboard }, { key: 'requestTypes', label: texts.nav.requestTypes }, { key: 'routes', label: texts.nav.routes }, { key: 'resolve', label: texts.nav.resolve } ]; export interface ITopNavProps { active: ScreenKey; onSelect: (key: ScreenKey) => void; } function isTabActive(active: ScreenKey, tabKey: ScreenKey): boolean { // Экран шагов маршрута — вложенный, подсвечиваем вкладку «Маршруты». return active === tabKey || (active === 'routeSteps' && tabKey === 'routes'); } export const TopNav: React.FC = ({ active, onSelect }) => { const tabsRef = React.useRef(null); const activeTabRef = React.useRef(null); // Вкладки скроллятся по горизонтали, поэтому активная может оказаться за // краем. Подкручиваем контейнер вручную (не scrollIntoView — тот способен // утащить за собой прокрутку всей страницы SharePoint). React.useEffect(() => { const reveal = (): void => { const container = tabsRef.current; const tab = activeTabRef.current; if (!container || !tab) return; const left = tab.offsetLeft; const width = tab.offsetWidth; if (width > container.clientWidth) { // Вкладка шире видимой полосы — показываем её начало, чтобы подпись // читалась с первого слова. container.scrollLeft = left; } else if (left < container.scrollLeft) { container.scrollLeft = left; } else if (left + width > container.scrollLeft + container.clientWidth) { container.scrollLeft = left + width - container.clientWidth; } }; reveal(); // Шрифты (Lora/Inter) подключаются рантаймом: пока они не применились, // ширины вкладок другие и позиция прокрутки получается устаревшей. const fonts = (document as Document & { fonts?: FontFaceSet }).fonts; let cancelled = false; if (fonts?.ready) { fonts.ready.then(() => { if (!cancelled) reveal(); }).catch(() => { /* не критично */ }); } window.addEventListener('resize', reveal); return () => { cancelled = true; window.removeEventListener('resize', reveal); }; }, [active]); return ( ); };