PageSourceSearch

https://tinylytics.app/assets/controllers/docs_carousel_controller-6bc04981.js

js tinylytics.app collected 2026-10-02 05:41:58 UTC 2,452 bytes, 85 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2
3export default class extends Controller {
4  static targets = [ "scroller", "slide", "status", "prev", "next" ]
5  static values = { index: { type: Number, default: 0 } }
6
7  connect() {
8    this.onScroll = this.onScroll.bind(this)
9    this.onSlideClick = this.selectSlide.bind(this)
10    this.scrollerTarget.addEventListener("scroll", this.onScroll, { passive: true })
11    this.slideTargets.forEach((slide) => slide.addEventListener("click", this.onSlideClick))
12    this.updatePager()
13  }
14
15  disconnect() {
16    this.scrollerTarget.removeEventListener("scroll", this.onScroll)
17    this.slideTargets.forEach((slide) => slide.removeEventListener("click", this.onSlideClick))
18  }
19
20  prev() {
21    if (this.indexValue <= 0) return
22    this.goTo(this.indexValue - 1)
23  }
24
25  next() {
26    if (this.indexValue >= this.slideTargets.length - 1) return
27    this.goTo(this.indexValue + 1)
28  }
29
30  selectSlide(event) {
31    const index = this.slideTargets.indexOf(event.currentTarget)
32    if (index === -1 || index === this.indexValue) return
33
34    event.preventDefault()
35    event.stopPropagation()
36    this.goTo(index)
37  }
38
39  goTo(index) {
40    const origin = this.slideTargets[0].offsetLeft
41    this.scrollerTarget.scrollLeft = this.slideTargets[index].offsetLeft - origin
42    this.indexValue = index
43    this.updatePager()
44  }
45
46  onScroll() {
47    const index = this.nearestIndex()
48    if (index === this.indexValue) return
49
50    this.indexValue = index
51    this.updatePager()
52  }
53
54  nearestIndex() {
55    const origin = this.slideTargets[0].offsetLeft
56    const left = this.scrollerTarget.scrollLeft
57    let best = 0
58    let bestDist = Infinity
59
60    this.slideTargets.forEach((slide, index) => {
61      const dist = Math.abs(slide.offsetLeft - origin - left)
62      if (dist < bestDist) {
63        bestDist = dist
64        best = index
65      }
66    })
67
68    return best
69  }
70
71  updatePager() {
72    if (this.hasStatusTarget) {
73      this.statusTarget.textContent = `${this.indexValue + 1} / ${this.slideTargets.length}`
74    }
75
76    if (this.hasPrevTarget) this.prevTarget.disabled = this.indexValue <= 0
77    if (this.hasNextTarget) this.nextTarget.disabled = this.indexValue >= this.slideTargets.length - 1
78
79    this.slideTargets.forEach((slide, index) => {
80      const current = index === this.indexValue
81      slide.classList.toggle("cursor-zoom-in", current)
82      slide.classList.toggle("cursor-pointer", !current)
83    })
84  }
85}

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.