Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
# OpenSpec Change: enterprise-react-audio-midi
- **Change ID**: enterprise-react-audio-midi
- **Package**: `@suaveplan/react-audio`
- **Category**: react
- **Target path**: `packages/react/react-audio`
- **Status**: PROPOSED — Phase 3 of 3
- **Date**: 2026-05-19
- **Spec delta**: `./specs/react-audio/spec.md`
> Phase 3 of the decomposed `enterprise-react-audio` rollout. **Blocked** on Phases 1 and 2 landing first. Adds the MIDI learn-mode panel + `useMidiController` hook to the React surface.
## Summary
Ship `<MidiControllerSetup>` and `useMidiController(controllerId)`. The component reads connected controllers from the provider's `MidiControllerRegistry` (sourced via `@suaveplan/audio-controllers`) and exposes a learn-mode UI: user selects a target parameter, presses a control on the hardware, and the panel calls `bindParameter(plugin, paramId, capturedSource, { smoothingMs })`. Bindings persist via the provider's preset store and re-bind on next mount.
This is the smallest of the three phases (1 hook + 1 component + persistence wiring + a11y for the learn-flow). Spec delta has one requirement (MidiControllerSetup learn-mode panel).
## Out of scope
- Provider/hook foundation (Phase 1).
- Generic component library + presets + Storybook gate (Phase 2).
## Impact
After Phase 3 archives, the `@suaveplan/react-audio` package is **complete** — STATUS row flips from `–` to ✅ with the full description of all three phases.

View File

@@ -0,0 +1,34 @@
<!-- markdownlint-disable MD024 -->
# Capability Spec Delta: react-audio (enterprise-react-audio-midi)
**Package**: `@suaveplan/react-audio`
**Status**: PROPOSED — Phase 3 of 3 (MIDI learn-mode)
**Blocked on**: Phases 1 and 2 shipping first.
> Every requirement carries `**Verified by:**`.
## ADDED Requirements
### Requirement: MidiControllerSetup learn-mode panel
`<MidiControllerSetup>` SHALL render the connected controllers from the provider's `MidiControllerRegistry` (sourced via `@suaveplan/audio-controllers`) and expose a learn-mode UI: the user selects a target parameter on a plugin, presses a control on the hardware, and the panel calls `bindParameter(plugin, paramId, capturedSource, { smoothingMs })` from `@suaveplan/audio-controllers`. Captured bindings SHALL be persisted via the provider's preset store (the same store used by `<PresetManager>`) and re-bound on next mount. An `Unbind` button SHALL invoke the unsubscribe function returned by `bindParameter`. The package SHALL also export the `useMidiController(controllerId)` hook returning the controller instance + a `learn(target)` method.
#### Scenario: learn captures the next CC and binds it
- **WHEN** a user selects `eq.lowShelfGain` as the target and the fake-device fixture emits `CC 1/7 = 64`
- **THEN** `bindParameter(eq, 'lowShelfGain', { type: 'cc', channel: 1, number: 7 })` is called and the panel shows the binding
#### Scenario: unbind removes the binding
- **WHEN** a user clicks `Unbind` on an active binding
- **THEN** subsequent CC events for that source no longer call `setParameter` on the plugin
#### Scenario: useMidiController hook subscribes to connection-state changes
- **WHEN** the controller transitions `disconnected → connecting → connected`
- **THEN** the component using `useMidiController(controllerId)` re-renders once per transition with the new state
**Verified by:** `src/components/midi-controller-setup/midi-controller-setup.test.tsx::"learn captures the next CC and binds it"` AND `src/components/midi-controller-setup/midi-controller-setup.test.tsx::"unbind removes the binding"` AND `src/hooks/use-midi-controller/use-midi-controller.test.tsx::"re-renders on connection-state transitions"`
<!-- markdownlint-enable MD024 -->

View File

@@ -0,0 +1,12 @@
# Tasks: enterprise-react-audio-midi
**Phase**: 3 of 3
**Blocked on**: `enterprise-react-audio-foundation` AND `enterprise-react-audio-components` shipping green.
Outline (to flesh out at execution time):
1. `src/hooks/use-midi-controller/` — hook with `useSyncExternalStore` subscription against the controller's connection-state event surface.
2. `src/components/midi-controller-setup/` — `<MidiControllerSetup>` component with learn-mode UI, target picker, captured-source display, persistence via the foundation's preset store, unbind button.
3. Add the hook + component to `package.json` subpath exports (`./hooks/use-midi-controller`, `./components/midi-controller-setup`).
4. Tests + stories + sibling `.md` per CLAUDE.md.
5. 5-gate triple + archive + STATUS row flip: at end of Phase 3, description becomes the final post-migration description and status is ✅ (Migrated +1).