Levels
4 partsA headless, accessible Photoshop-style levels control. The root owns a
LevelsValue — input black/white clipping points (0..255), a gamma
midtone factor (0.1..9.99), and an outputBlack/outputWhite range
(0..255) — controlled via v-model or uncontrolled via defaultValue. It
is a constrained multi-thumb slider: black is kept strictly below white
(by minStepsBetweenHandles * step) and the output handles keep their order,
with a value pushed past its neighbour pinning rather than swapping. The root
handles pointer drags and keyboard for the thumbs, exposes the 0..255 output
LUT via getOutputCurve, and can derive auto black/white from a histogram via
autoLevels. Provides context to LevelsTrack, LevelsThumb, and
LevelsHandleValue. Pair it with HistogramRoot for a full levels editor.
Demo
Anatomy
Import the parts and compose them. Each part forwards attributes to its underlying element.
import {
LevelsRoot,
LevelsTrack,
LevelsThumb,
LevelsHandleValue,
} from '@robonen/primitives/canvas/levels';
<LevelsRoot>
<LevelsTrack />
<LevelsThumb />
<LevelsHandleValue />
</LevelsRoot>API Reference
LevelsRoot
RootA headless, accessible Photoshop-style levels control. The root owns a `LevelsValue` — input `black`/`white` clipping points (`0..255`), a `gamma` midtone factor (`0.1..9.99`), and an `outputBlack`/`outputWhite` range (`0..255`) — controlled via `v-model` or uncontrolled via `defaultValue`. It is a constrained multi-thumb slider: `black` is kept strictly below `white` (by `minStepsBetweenHandles * step`) and the output handles keep their order, with a value pushed past its neighbour pinning rather than swapping. The root handles pointer drags and keyboard for the thumbs, exposes the `0..255` output LUT via `getOutputCurve`, and can derive auto black/white from a histogram via `autoLevels`. Provides context to `LevelsTrack`, `LevelsThumb`, and `LevelsHandleValue`. Pair it with `HistogramRoot` for a full levels editor.
| Prop | Type | Description |
|---|---|---|
defaultValue? | LevelsValue | Uncontrolled initial value. |
step? | number | Step for the 0..255 handles (black/white/output). |
gammaStep? | number | Step for the gamma handle. |
largeStep? | number | Large-step multiplier (Page keys / Shift+Arrow). |
minStepsBetweenHandles? | number | Minimum gap (in steps) the black handle keeps below white. |
disabled? | boolean | Disable all interaction. |
orientation? | LevelsOrientation | Orientation. |
dir? | LevelsDirection | Writing direction (inherited from ConfigProvider when omitted). |
inverted? | boolean | Invert the direction of interaction. |
modelValue? | LevelsValue | null | Two-way bound value (v-model). |
| Event | Payload |
|---|---|
update:modelValue | [value: LevelsValue | null] |
LevelsTrack
TrackThe `0..255` rail the levels thumbs travel along, rendered inside `LevelsRoot`. It registers itself as the geometry reference for the root's pointer math. Use it as the container for the histogram backdrop and the `LevelsThumb`s. (Drag is initiated on each thumb, so pressing a thumb does not also start a track-position drag.)
No props or events — renders its element and forwards attributes.
LevelsThumb
ThumbA draggable levels handle rendered as `role="slider"`, one per `kind` (`'black'` / `'gamma'` / `'white'` / `'outputBlack'` / `'outputWhite'`), placed inside `LevelsTrack`. It positions itself along the `0..255` track, exposes full per-kind ARIA (`aria-label`, `aria-valuemin/max/now`), and handles pointer drags and the keyboard (Arrow / Page / Home / End, neighbour-clamped). The gamma thumb is special: it sits at its effective midtone input level, its `aria-valuenow` carries the gamma FACTOR (`0.1..9.99`), and its `aria-valuetext` states the effective level (e.g. "Gamma 1.00, midtone at 128"). Keyboard nudges use `step` for the `0..255` handles and `gammaStep` for gamma.
| Prop | Type | Description |
|---|---|---|
kind | LevelsHandleKind | Which handle this thumb controls. |
LevelsHandleValue
HandleValueA visible, editable numeric entry box bound to one levels `kind` — the precise and screen-reader-friendly path for entering a handle value. It composes the `NumberField` family (`NumberFieldRoot` / `NumberFieldInput` / `NumberFieldIncrement` / `NumberFieldDecrement`) wired to the enclosing `LevelsRoot`: typing or stepping writes back through the same neighbour-clamped setter the thumb uses, so input black can never cross input white. The field's `min`/`max`/`step` track the handle's current legal range (gamma uses `gammaStep` and the `0.1..9.99` bounds). The default slot exposes the `NumberField` parts for full layout control; omit it for a stepper-free input.
| Prop | Type | Description |
|---|---|---|
kind | LevelsHandleKind | Which handle this entry box edits. |