prop/assets/js/rover_slider_hook.ts

49 lines
1.4 KiB
TypeScript

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, (v: number) => string> = {
forecast: (v) => `+${v}h`,
drive: (v) => {
const hours = Math.round((v / 60) * 10) / 10
return `${hours}h`
}
}
export const RoverSlider: Partial<RoverSliderHook> = {
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)
}
}