import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = ["container", "leftButton", "rightButton"] static values = { smooth: { type: Boolean, default: true } } connect() { // Optional: Hide arrows if content doesn't overflow this.checkOverflow() } scrollLeft() { this.scrollContainer(-this.getItemScrollDistance()) } scrollRight() { this.scrollContainer(this.getItemScrollDistance()) } scrollContainer(amount) { if (this.hasContainerTarget) { this.containerTarget.scrollBy({ left: amount, behavior: this.smoothValue ? 'smooth' : 'auto' }) } } getItemScrollDistance() { if (!this.hasContainerTarget) return 300 const container = this.containerTarget // Try multiple selectors to find items let items = container.querySelectorAll('[class*="flex-shrink-0"]') if (items.length === 0) { items = container.querySelectorAll('.flex-shrink-0') } if (items.length === 0) { items = container.querySelectorAll('> div') } if (items.length === 0) return 300 const firstItem = items[0] const itemWidth = firstItem.offsetWidth // Get computed styles to calculate margins/padding const computedStyle = window.getComputedStyle(firstItem) const marginLeft = parseFloat(computedStyle.marginLeft) || 0 const marginRight = parseFloat(computedStyle.marginRight) || 0 // Get container gap (if using CSS gap property) const containerGap = parseFloat(window.getComputedStyle(container).gap) || 0 // Calculate total distance: item width + margins + gap const scrollDistance = itemWidth + marginLeft + marginRight + containerGap return scrollDistance } checkOverflow() { if (this.hasContainerTarget) { const container = this.containerTarget const hasOverflow = container.scrollWidth> container.clientWidth // Hide/show buttons based on overflow if (this.hasLeftButtonTarget) { this.leftButtonTarget.style.display = hasOverflow ? 'block' : 'none' } if (this.hasRightButtonTarget) { this.rightButtonTarget.style.display = hasOverflow ? 'block' : 'none' } } } }