feat(index): ajouter hero carousel avec images et script dedie

This commit is contained in:
2026-05-28 17:48:45 +02:00
parent 4c958b448a
commit ba31d6447a
7 changed files with 342 additions and 12 deletions
+155
View File
@@ -0,0 +1,155 @@
(() => {
"use strict";
const existingCleanup = window.__heroCarouselCleanup;
if (typeof existingCleanup === "function") {
existingCleanup();
}
const hero = document.querySelector(".hero-carousel");
if (!hero) {
return;
}
const slides = Array.from(hero.querySelectorAll("[data-hero-slide]"));
const prevButton = hero.querySelector("[data-hero-prev]");
const nextButton = hero.querySelector("[data-hero-next]");
const dotsContainer = hero.querySelector("[data-hero-dots]");
if (!slides.length || !prevButton || !nextButton || !dotsContainer) {
return;
}
let currentIndex = Math.max(
0,
slides.findIndex((slide) => slide.classList.contains("is-active"))
);
let autoRotateTimer = null;
const rotateDelay = 5500;
const abortController = new AbortController();
const { signal } = abortController;
const dots = slides.map((_, index) => {
const dot = document.createElement("button");
dot.type = "button";
dot.className = "hero-dot";
dot.setAttribute("role", "tab");
dot.setAttribute("aria-label", `Aller a l'image ${index + 1}`);
dot.dataset.index = index.toString();
dotsContainer.appendChild(dot);
return dot;
});
function updateUI() {
slides.forEach((slide, index) => {
const isActive = index === currentIndex;
slide.classList.toggle("is-active", isActive);
slide.setAttribute("aria-hidden", String(!isActive));
});
dots.forEach((dot, index) => {
const isActive = index === currentIndex;
dot.classList.toggle("is-active", isActive);
dot.setAttribute("aria-selected", String(isActive));
dot.tabIndex = isActive ? 0 : -1;
});
}
function goTo(index) {
if (index < 0) {
currentIndex = slides.length - 1;
} else if (index >= slides.length) {
currentIndex = 0;
} else {
currentIndex = index;
}
updateUI();
}
function stopAutoRotate() {
if (autoRotateTimer !== null) {
window.clearInterval(autoRotateTimer);
autoRotateTimer = null;
}
}
function startAutoRotate() {
stopAutoRotate();
autoRotateTimer = window.setInterval(() => {
goTo(currentIndex + 1);
}, rotateDelay);
}
prevButton.addEventListener(
"click",
() => {
goTo(currentIndex - 1);
startAutoRotate();
},
{ signal }
);
nextButton.addEventListener(
"click",
() => {
goTo(currentIndex + 1);
startAutoRotate();
},
{ signal }
);
dotsContainer.addEventListener(
"click",
(event) => {
const button = event.target.closest(".hero-dot");
if (!button) {
return;
}
const targetIndex = Number.parseInt(button.dataset.index || "0", 10);
goTo(targetIndex);
startAutoRotate();
},
{ signal }
);
hero.addEventListener(
"mouseenter",
() => {
stopAutoRotate();
},
{ signal }
);
hero.addEventListener(
"mouseleave",
() => {
startAutoRotate();
},
{ signal }
);
document.addEventListener(
"visibilitychange",
() => {
if (document.hidden) {
stopAutoRotate();
} else {
startAutoRotate();
}
},
{ signal }
);
updateUI();
startAutoRotate();
window.__heroCarouselCleanup = () => {
stopAutoRotate();
abortController.abort();
};
document.addEventListener("page:before-route-change", window.__heroCarouselCleanup, {
once: true,
});
})();