first commit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# `parameter-keyboard`
|
||||
|
||||
Internal helper consumed by `<PluginParameterKnob>` and
|
||||
`<PluginParameterSlider>` to translate a `KeyboardEvent` into a clamped
|
||||
next parameter value. The helper is a pure function — no React, no DOM
|
||||
— so it is fully unit-testable without rendering a tree.
|
||||
|
||||
## Purpose
|
||||
|
||||
The `<PluginSlot>` accessibility requirement mandates an identical
|
||||
keyboard contract on every parameter control: arrow keys for fine /
|
||||
coarse adjustments, `PageUp`/`PageDown` for ×10 coarse, `Home`/`End` for
|
||||
range endpoints, `Enter` for type-edit, plus `Shift` ×10 and `Alt` ÷10
|
||||
modifiers. Reimplementing this contract in two component files would
|
||||
double the surface area subject to drift. The shared helper guarantees
|
||||
both primitives interpret the keymap identically.
|
||||
|
||||
## Features
|
||||
|
||||
- 1 % step base ×1, ×10, ×100 binding factors (from `PARAMETER_KEY_BINDINGS`).
|
||||
- `Shift` multiplier ×10, `Alt` multiplier ÷10.
|
||||
- Clamping to `[min, max]` on every increment, decrement, and `Home`/`End` jump.
|
||||
- Returns the matching `KeyBinding` so the caller can detect the special
|
||||
`Enter` action and open a type-edit affordance.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { resolveParameterKeyboardChange } from "./parameter-keyboard.js";
|
||||
|
||||
const result = resolveParameterKeyboardChange(
|
||||
{ key: "ArrowRight", shiftKey: false, altKey: false },
|
||||
0,
|
||||
-24,
|
||||
24
|
||||
);
|
||||
// result.handled === true; result.next === 0.48 (1 % of 48)
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
// Compose with the React keyboard handler in <PluginParameterKnob>:
|
||||
function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||
const out = resolveParameterKeyboardChange(event, value, min, max);
|
||||
if (!out.handled) return;
|
||||
event.preventDefault();
|
||||
if (out.binding?.action === "enter-value") {
|
||||
setEditing(true);
|
||||
return;
|
||||
}
|
||||
onChange(out.next);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `resolveParameterKeyboardChange(event, current, min, max) → ParameterKeyboardResult`
|
||||
- `event` — `{ key, shiftKey, altKey }`; matches the shape of `KeyboardEvent`.
|
||||
- `current` — current numeric value.
|
||||
- `min` / `max` — declared parameter range.
|
||||
- `ParameterKeyboardResult` — `{ handled, next, binding }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The function iterates `PARAMETER_KEY_BINDINGS` in declaration order.
|
||||
Adding new bindings is purely declarative — the helper picks them up
|
||||
for free.
|
||||
- `Home`/`End` deliberately ignore the modifier multipliers; they are
|
||||
endpoint jumps, not stepped moves.
|
||||
- The function never throws; an unrecognised key returns
|
||||
`{ handled: false, next: current, binding: undefined }` so the caller
|
||||
can fall through to other listeners.
|
||||
Reference in New Issue
Block a user