summaryrefslogtreecommitdiff
path: root/web/frontend/ride-filters.ts
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-08-18 21:32:28 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-08-18 21:32:28 +0200
commit992c36c6c7ce7e1e732866b3cd4fb8269a905875 (patch)
tree15b7ae06b14341929e555ebc126f07d963213104 /web/frontend/ride-filters.ts
parent51613971c1e25dedbc808c66b79d15111d250160 (diff)
feat(web): add ride library filtersHEADmain
Diffstat (limited to 'web/frontend/ride-filters.ts')
-rw-r--r--web/frontend/ride-filters.ts49
1 files changed, 49 insertions, 0 deletions
diff --git a/web/frontend/ride-filters.ts b/web/frontend/ride-filters.ts
new file mode 100644
index 0000000..24c23e8
--- /dev/null
+++ b/web/frontend/ride-filters.ts
@@ -0,0 +1,49 @@
+import { requireElement } from "./dom.js";
+import {
+ formatRideFilterValue,
+ normalizeRideFilterRange,
+ type RideFilterRangeFormat,
+ type RideFilterRangeHandle,
+} from "./ride-filters-logic.js";
+
+const mountRangeFilter = (container: HTMLElement): void => {
+ const format = container.dataset.rangeFormat as RideFilterRangeFormat | undefined;
+ if (!format) throw new Error("Missing ride filter range format");
+ const minInput = requireElement(container.querySelector<HTMLInputElement>("[data-range-min]"), "ride filter minimum input");
+ const maxInput = requireElement(container.querySelector<HTMLInputElement>("[data-range-max]"), "ride filter maximum input");
+ const track = requireElement(container.querySelector<HTMLElement>("[data-range-track]"), "ride filter range track");
+ const group = requireElement(container.parentElement, "ride filter group");
+ const minOutput = requireElement(group.querySelector<HTMLOutputElement>('[data-range-value="min"]'), "ride filter minimum output");
+ const maxOutput = requireElement(group.querySelector<HTMLOutputElement>('[data-range-value="max"]'), "ride filter maximum output");
+ const lowerBound = Number(minInput.min);
+ const upperBound = Number(minInput.max);
+
+ const update = (changed?: RideFilterRangeHandle): void => {
+ const range = normalizeRideFilterRange(Number(minInput.value), Number(maxInput.value), changed ?? "min");
+ minInput.value = String(range.min);
+ maxInput.value = String(range.max);
+ const span = Math.max(upperBound - lowerBound, 1);
+ const start = ((range.min - lowerBound) / span) * 100;
+ const end = ((range.max - lowerBound) / span) * 100;
+ track.style.setProperty("--range-start", `${start}%`);
+ track.style.setProperty("--range-end", `${end}%`);
+ const minLabel = formatRideFilterValue(format, range.min);
+ const maxLabel = formatRideFilterValue(format, range.max);
+ minOutput.value = minLabel;
+ maxOutput.value = maxLabel;
+ minOutput.textContent = minLabel;
+ maxOutput.textContent = maxLabel;
+ minInput.setAttribute("aria-valuetext", minLabel);
+ maxInput.setAttribute("aria-valuetext", maxLabel);
+ };
+
+ minInput.addEventListener("input", () => update("min"));
+ maxInput.addEventListener("input", () => update("max"));
+ update();
+};
+
+export const mountRideFilters = (): void => {
+ document.querySelectorAll<HTMLElement>("[data-range-filter]").forEach(mountRangeFilter);
+};
+
+mountRideFilters();