import { Controller } from "@hotwired/stimulus" export default class extends Controller { static values = { target: Number, decimal: Boolean, duration: { type: Number, default: 2000 } } connect() { this.observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { this.animate() this.observer.unobserve(this.element) } }) }, { threshold: 0.5 }) this.observer.observe(this.element) } disconnect() { if (this.observer) { this.observer.disconnect() } } animate() { const startValue = 0 const startTime = performance.now() const updateCounter = (currentTime) => { const elapsedTime = currentTime - startTime const progress = Math.min(elapsedTime / this.durationValue, 1) // Easing function for smooth animation const easeOutQuart = 1 - Math.pow(1 - progress, 4) let currentValue = startValue + (this.targetValue - startValue) * easeOutQuart if (this.decimalValue && this.targetValue < 10) { currentValue = currentValue.toFixed(1) } else { currentValue = Math.floor(currentValue) } this.element.textContent = currentValue if (progress < 1) { requestAnimationFrame(updateCounter) } else { this.element.textContent = this.decimalValue && this.targetValue < 10 ? this.targetValue.toFixed(1) : this.targetValue } } requestAnimationFrame(updateCounter) } }