46 lines
1.3 KiB
TypeScript
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)
|
|
}
|
|
}
|