import type { ViewHook } from "phoenix_live_view" interface RoverSliderHook extends ViewHook { labelEl: HTMLElement | null formatter: (v: number) => string format: string inputHandler: () => void } const AVG_SPEED_KMH = 65.0 const formatters: Record string> = { forecast: (v) => `+${v}h`, drive: (v) => { const hours = Math.round((v / 60) * 10) / 10 return `${hours}h` } } export const RoverSlider: Partial = { mounted(this: RoverSliderHook) { const labelId = this.el.dataset.labelId || "" this.format = this.el.dataset.format || "forecast" this.formatter = formatters[this.format] || formatters.forecast this.labelEl = document.getElementById(labelId) this.inputHandler = () => { const value = Number((this.el as HTMLInputElement).value) if (this.labelEl) this.labelEl.textContent = this.formatter(value) if (this.format === "drive") { const km = (value * AVG_SPEED_KMH) / 60.0 window.dispatchEvent(new CustomEvent("rover:drive-radius", { detail: { km } })) } } this.el.addEventListener("input", this.inputHandler) this.inputHandler() }, updated(this: RoverSliderHook) { if (this.inputHandler) this.inputHandler() }, destroyed(this: RoverSliderHook) { if (this.inputHandler) this.el.removeEventListener("input", this.inputHandler) } }