prop/assets/js/rover_slider_hook.ts

46 lines
1.3 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 KM_PER_MI = 1.609344
const formatters: Record<string, (v: number) => string> = {
forecast: (v) => `+${v}h`,
distance: (v) => `${v} mi`
}
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 === "distance") {
const km = value * KM_PER_MI
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)
}
}