HEX
Server: Apache
System: Linux webm013.cluster123.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: lesanew (165608)
PHP: 8.3.31
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/lesanew/anestetues2/web/app/themes/anes-tetues/resources/js/components/major-partners.ts
import Swiper from 'swiper';
import { Autoplay, FreeMode } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/free-mode';

export const initMajorPartnersSlider = () => {
  const container = document.querySelector<HTMLElement>('.major-partners__slider.swiper');
  if (!container) return;

  const wrapper = container.querySelector<HTMLElement>('.swiper-wrapper');
  if (!wrapper) return;

  // --- 1) Dupliquer suffisamment d'items pour un marquee en loop (évite freeze au loopFix) ---
  const initialSlides = Array.from(wrapper.querySelectorAll<HTMLElement>('.swiper-slide'));
  if (!initialSlides.length) return;

  // Ton max slidesPerView = 6 (breakpoint 1280). Pour un continu, prends large.
  const MAX_SLIDES_PER_VIEW = 6;
  const MIN_SLIDES = Math.max(24, MAX_SLIDES_PER_VIEW * 4); // 24 min

  const getSlideCount = () => wrapper.querySelectorAll('.swiper-slide').length;

  if (getSlideCount() < MIN_SLIDES) {
    let i = 0;
    while (getSlideCount() < MIN_SLIDES) {
      const clone = initialSlides[i % initialSlides.length].cloneNode(true) as HTMLElement;
      clone.setAttribute('data-duplicate', 'true');
      wrapper.appendChild(clone);
      i++;
    }
  }

  // --- 2) Précharger quelques logos (évite pop-in / placeholders) ---
  const imgs = Array.from(container.querySelectorAll<HTMLImageElement>('.swiper-slide img'));
  imgs.slice(0, 12).forEach((img) => {
    const src = img.currentSrc || img.src;
    if (!src) return;
    const pre = new Image();
    pre.decoding = 'async';
    pre.src = src;
  });

  // --- 3) Init Swiper ---
  const swiper = new Swiper(container, {
    modules: [Autoplay, FreeMode],
    loop: true,

    // Crucial en défilement continu
    loopAdditionalSlides: 12,
    watchSlidesProgress: true,

    slidesPerView: 3,
    spaceBetween: 20,

    speed: 6000,
    autoplay: {
      delay: 0,
      disableOnInteraction: false,
      pauseOnMouseEnter: true, // optionnel
    },

    freeMode: {
      enabled: true,
      momentum: false,
    },

    breakpoints: {
      780: { slidesPerView: 4 },
      1280: {
        slidesPerView: 6,
        spaceBetween: 40,
      },
    },
  });

  // --- 4) Safety net : en loop + marquee, on force la reprise si Swiper stoppe après un loopFix ---
  const restart = () => {
    // autoplay peut être undefined si module absent, mais ici il est présent
    if (swiper.autoplay && !swiper.autoplay.running) {
      swiper.autoplay.start();
    }
  };

  swiper.on('init', restart);
  swiper.on('loopFix', restart);
  swiper.on('reachEnd', restart);
  swiper.on('resize', restart);
  swiper.on('imagesReady', restart);

  // Important: certains events ne se déclenchent qu'après init
  restart();
};

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initMajorPartnersSlider);
} else {
  initMajorPartnersSlider();
}