1import { Controller } from "@hotwired/stimulus" 2 3// Generic horizontal scroll controller with arrow buttons and fade indicators. 4// Works for tabs, tables, and any scrollable container. 5// 6// Targets: 7// - scrollable: the overflow-x-auto container 8// - leftArrow: clickable left scroll button (optional) 9// - rightArrow: clickable right scroll button (optional) 10// 11// The arrows are shown/hidden based on scroll position using the "hidden" class. 12export default class extends Controller { 13 static targets = ["scrollable", "leftArrow", "rightArrow"] 14 15 connect() { 16 if (!this.hasScrollableTarget) return 17 18 requestAnimationFrame(() => this.update()) 19 this.scrollableTarget.addEventListener("scroll", this.update) 20 this.resizeObserver = new ResizeObserver(this.update) 21 this.resizeObserver.observe(this.scrollableTarget) 22 } 23 24 disconnect() { 25 this.scrollableTarget?.removeEventListener("scroll", this.update) 26 this.resizeObserver?.disconnect() 27 } 28 29 scrollLeft() { 30 this.scrollableTarget.scrollBy({ left: -150, behavior: "smooth" }) 31 } 32 33 scrollRight() { 34 this.scrollableTarget.scrollBy({ left: 150, behavior: "smooth" }) 35 } 36 37 update = () => { 38 if (!this.hasScrollableTarget) return 39 40 const { scrollLeft, scrollWidth, clientWidth } = this.scrollableTarget 41 const canScrollLeft = scrollLeft > 1 42 const canScrollRight = scrollLeft + clientWidth < scrollWidth - 1 43 44 if (this.hasLeftArrowTarget) { 45 this.leftArrowTarget.classList.toggle("hidden", !canScrollLeft) 46 } 47 if (this.hasRightArrowTarget) { 48 this.rightArrowTarget.classList.toggle("hidden", !canScrollRight) 49 } 50 } 51};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.