import { useCallback, useEffect, useRef, useState } from "react"; import classes from "./classes.module.scss"; import HorizontalTab, { ITab } from "./HorizontalTab"; import VerticalTabs from "./VerticalTabs"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import { useWindowSize } from "@uidotdev/usehooks"; import useOpenable from "@Front/Hooks/useOpenable"; export type ITabValue = T & { id: unknown; } type ITabInternal = ITab & { key?: string; value: ITabValue; }; type IProps = { tabs: ITabInternal[]; onSelect: (value: T) => void; }; export default function Tabs({ onSelect, tabs: propsTabs }: IProps) { const tabs = useRef(propsTabs); const shadowElementRef = useRef(null); const [visibleElements, setVisibleElements] = useState[]>([]); const [overflowedElements, setOverflowedElements] = useState[]>([]); const [selectedTab, setSelectedTab] = useState>(tabs.current[0]!.value); const { close, isOpen, toggle } = useOpenable(); const windowSize = useWindowSize(); const calculateVisibleElements = useCallback(() => { const shadowElement = shadowElementRef.current; if (!shadowElement) return; const shadowElementWidth = shadowElement.offsetWidth; // The first element is the show more element, it needs to be ignored in the calculation let totalWidth = (shadowElement.children[0]! as HTMLElement).offsetWidth; let visibleCount = 0; for (let i = 1; i < shadowElement.children.length; i++) { totalWidth += (shadowElement.children[i]! as HTMLElement).offsetWidth; if (totalWidth > shadowElementWidth) { break; } visibleCount++; } setVisibleElements(tabs.current.slice(0, visibleCount)); setOverflowedElements(tabs.current.slice(visibleCount)); }, []); useEffect(() => { tabs.current = propsTabs; }, [propsTabs]); useEffect(() => { calculateVisibleElements(); }, [calculateVisibleElements, windowSize]); const handleSelect = useCallback( (value: ITabValue) => { setSelectedTab(value); onSelect(value); close(); calculateVisibleElements(); }, [close, onSelect, calculateVisibleElements], ); const handleVerticalSelect = useCallback( (value: ITabValue) => { const index = tabs.current.findIndex((tab) => tab.value.id === value.id); const newTabs = [...tabs.current]; newTabs.splice(index, 1); newTabs.unshift(tabs.current[index]!); tabs.current = newTabs; console.log("Updated values ; ", tabs.current); handleSelect(value); }, [handleSelect], ); return (
{overflowedElements.length} de plus...
{tabs.current.map((element, index) => ( label={element.label} key={element.key ?? index} value={element.value} onSelect={handleSelect} isSelected={element.value.id === selectedTab.id} /> ))}
{visibleElements.map((element, index) => ( label={element.label} key={element.key ?? index} value={element.value} onSelect={handleSelect} isSelected={element.value.id === selectedTab.id} /> ))}
{overflowedElements.length > 0 && (
{overflowedElements.length} de plus...
{overflowedElements.length > 0 && overflowedElements.map((element, index) => ( label={element.label} key={element.key ?? index} value={element.value} onSelect={handleVerticalSelect} isSelected={selectedTab === element.value} /> ))}
)}
); }