# slider-helpers (module-private) ## Purpose Shared pure functions for both `` and `` so that value resolution, detent snapping, and keyboard stepping are identical across the two orientations. The helpers live under `slider-v/` for a stable physical home, and `` reaches across with a single relative import. They are not re-exported from the package barrel — consumers of the package only see `` and ``. ## Features - `clamp` / `quantize` — primitive numeric helpers. - `applyDetents` — within-threshold snap to the nearest detent `at`. - `resolveSliderValue` — full pipeline: clamp → step quantize → detent snap. - `fractionForValue` — normalize value to 0..1 for thumb-position math. - `keyboardStep` — returns the next value for arrow / Home / End / PageUp / PageDown keys, orientation-aware, Shift-fine-mode aware. Returns `null` for unrecognised keys. ## Usage: Basic ```ts import { resolveSliderValue, fractionForValue, } from "./slider-helpers.js"; const next = resolveSliderValue({ raw: 0.42, min: 0, max: 1, step: 0.05, }); const pct = fractionForValue(next, 0, 1); // 0.4 ``` ## Usage: Advanced Keyboard-driven step with custom fine factor and detents: ```ts import { keyboardStep, resolveSliderValue, } from "./slider-helpers.js"; const proposed = keyboardStep({ key: event.key, value: current, min: -60, max: 12, step: 0.5, fineFactor: 0.1, shiftKey: event.shiftKey, orientation: "vertical", }); if (proposed !== null) { const snapped = resolveSliderValue({ raw: proposed, min: -60, max: 12, step: 0.5, detents: [{ at: 0, label: "0 dB" }], snapThreshold: 0.5, }); onChange(snapped); } ``` ## API Reference | Function | Signature | | -------------------- | ------------------------------------------------------------------------------ | | `clamp` | `(value, min, max) => number` | | `quantize` | `(value, step, min) => number` | | `applyDetents` | `(value, detents, threshold) => number` | | `resolveSliderValue` | `({ raw, min, max, step, detents?, snapThreshold? }) => number` | | `fractionForValue` | `(value, min, max) => number` (always clamped to 0..1) | | `keyboardStep` | `(args) => number \| null`; returns `null` for unrecognised keys. | ## Implementation Notes `applyDetents` greedily picks the closest detent within `threshold` distance; `threshold` defaults to 2% of the span when not supplied. `quantize` short-circuits when `step <= 0` so consumers can opt out of stepping with `step: 0`. `keyboardStep` derives a perceptible per-key delta of `max(step, span / 100)` so wide ranges still respond to a single arrow key even when `step` is tiny. The orientation flip between vertical / horizontal is encoded purely in the key mapping; all downstream math is direction-agnostic.