// Calcule combien d'onglets afficher pour qu'ils tiennent dans la largeur dispo, // en gardant la structure « flèches fixes aux bords » : le nombre est choisi pour // que les onglets visibles tiennent → pas de débordement sur les flèches, pas de // rognage, barre d'onglet actif intacte. // // On additionne les VRAIES largeurs d'onglets (pas la pire), donc le résultat // n'est pas sur-conservateur (évite de tomber à 1 onglet inutilement). // // Fonction pure → testable sans DOM. Sans layout (SSR / jsdom : largeurs à 0), // on retombe sur le plafond `maxVisibleTabs` (ou tous les onglets). export interface TabFitInput { count: number // nombre total d'onglets containerWidth: number // largeur dispo mesurée (0 si inconnue) tabWidths: number[] // largeur mesurée de chaque onglet (vide si inconnu) gap: number // espace entre onglets (px) chevronReserve: number // place des chevrons + marges quand fenêtré (px) maxVisibleTabs?: number // plafond optionnel imposé par le consommateur } export function computeVisibleCount(input: TabFitInput): number { const {count, containerWidth, tabWidths, gap, chevronReserve, maxVisibleTabs} = input // Pas d'info de layout : on respecte le plafond explicite, sinon tout afficher. if (containerWidth <= 0 || tabWidths.length === 0) { return maxVisibleTabs != null ? Math.min(maxVisibleTabs, count) : count } const fullAvail = containerWidth const total = tabWidths.reduce((s, w) => s + w, 0) + gap * Math.max(0, count - 1) let fit: number if (total <= fullAvail) { fit = count // tout tient, pas de chevrons } else { const avail = fullAvail - chevronReserve let used = 0 let n = 0 for (const w of tabWidths) { const add = w + (n > 0 ? gap : 0) if (used + add > avail) break used += add n++ } fit = Math.max(1, n) } return maxVisibleTabs != null ? Math.min(maxVisibleTabs, fit) : fit }