import React, { useCallback, useEffect, useRef } from 'react'; import { ResizeObserver as ResizeObserverPolyfill } from '@juggle/resize-observer'; import cn from 'classnames'; import { KeyboardFocusable } from '@alfalab/core-components-keyboard-focusable'; import { fnUtils } from '@alfalab/core-components-shared'; import { useTabs } from '../../hooks/use-tabs'; import { type PlatformProps, type Styles, type TabListProps } from '../../typings'; import { ScrollableContainer } from '../scrollable-container'; import { Title } from '../title'; export const PrimaryTabList = ({ size, styles = {}, className, containerClassName, scrollControlsContainerClassName, scrollControlsButtonClassName, titles = [], selectedId = titles.length ? titles[0].id : undefined, scrollable = true, fullWidthScroll, onChange, dataTestId, platform, textStyle, inlineStyle, showSkeleton, skeletonProps, }: TabListProps & Styles & PlatformProps) => { const lineRef = useRef(null); const { selectedTab, focusedTab, getTabListItemProps } = useTabs({ titles, selectedId, onChange, }); // расчет размера и положения нижней полосы useEffect(() => { if (selectedTab) { const updateLineWidth = () => { if (lineRef.current) { lineRef.current.style.width = `${selectedTab.offsetWidth}px`; lineRef.current.style.transform = `translateX(${selectedTab.offsetLeft}px)`; } }; const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill; const observer = new ResizeObserver(updateLineWidth); observer.observe(selectedTab); return () => observer.disconnect(); } return fnUtils.noop; }, [selectedTab, titles]); const handleTitleResize = useCallback(() => { if (selectedTab && lineRef.current) { lineRef.current.style.width = `${selectedTab.offsetWidth}px`; lineRef.current.style.transform = `translateX(${selectedTab.offsetLeft}px)`; } }, [selectedTab]); const renderContent = () => (
{titles.map(({ dataTestId: _, toggleRef: __, ...restTitleProps }, index) => ( {(ref, focused) => ( )} </KeyboardFocusable> ))} <div className={styles.line} ref={lineRef} /> </div> ); const wrapperClassName = cn(textStyle && styles[textStyle], styles[platform]); return scrollable ? ( <ScrollableContainer containerWrapperClassName={wrapperClassName} activeChild={focusedTab || selectedTab} containerClassName={containerClassName} scrollControlsClassName={cn( textStyle && styles.scrollControls, scrollControlsContainerClassName, )} scrollControlsButtonClassName={scrollControlsButtonClassName} fullWidthScroll={fullWidthScroll} view='primary' size={textStyle ? undefined : size} platform={platform} inlineStyle={inlineStyle} showSkeleton={showSkeleton} > {renderContent()} </ScrollableContainer> ) : ( <div className={cn(styles.container, wrapperClassName, containerClassName)} style={inlineStyle} > {renderContent()} </div> ); };