You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

55 lines
1.8 KiB

import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["carousel", "marker"]
connect() {
this.boundUpdate = this.update.bind(this)
this.boundEqualizeHeights = this.equalizeHeights.bind(this)
this.carouselTarget.addEventListener("scroll", this.boundUpdate, { passive: true })
window.addEventListener("resize", this.boundEqualizeHeights)
this.equalizeHeights()
this.update()
}
disconnect() {
this.carouselTarget.removeEventListener("scroll", this.boundUpdate)
window.removeEventListener("resize", this.boundEqualizeHeights)
}
equalizeHeights() {
const articles = this.carouselTarget.querySelectorAll(":scope > li > article")
articles.forEach((article) => (article.style.height = "auto"))
const tallest = Array.from(articles).reduce((max, article) => Math.max(max, article.offsetHeight), 0)
articles.forEach((article) => (article.style.height = `${tallest}px`))
}
update() {
const slides = Array.from(this.carouselTarget.children)
const center = this.carouselTarget.scrollLeft + this.carouselTarget.clientWidth / 2
let activeIndex = 0
let closest = Infinity
slides.forEach((slide, i) => {
const slideCenter = slide.offsetLeft + slide.offsetWidth / 2
const distance = Math.abs(slideCenter - center)
if (distance < closest) {
closest = distance
activeIndex = i
}
})
this.markerTargets.forEach((marker, i) => {
marker.classList.toggle("current", i === activeIndex)
})
}
goto(event) {
const index = parseInt(event.currentTarget.dataset.index, 10)
const slide = this.carouselTarget.children[index]
if (slide) {
this.carouselTarget.scrollTo({ left: slide.offsetLeft, behavior: "smooth" })
}
}
}