first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
# `hooks/use-preset`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`usePreset(plugin)` exposes plugin-level preset operations as
React-friendly callbacks: `get` reads the current preset, `apply`
writes one back, and `save` / `load` persist through the provider's
optional preset store. The hook gates `save`/`load` on the presence
of a store; if none is configured (or if the store throws), the hook
raises `ReactAudioError(REACT_AUDIO.PRESET_STORE_FAILED)` carrying
the offending id and the underlying cause.
## Features
- `get(): PresetSnapshot` — synchronous read.
- `apply(preset): void` — synchronous write.
- `save(id): Promise<void>` — async write through the preset store.
- `load(id): Promise<void>` — async read + apply.
- Structured errors: `PRESET_STORE_FAILED` for missing store, save
failure, load failure, and preset-not-found.
## Usage: Basic
```tsx
import { usePreset } from "@suaveplan/react-audio";
function PresetButtons({ plugin }: { plugin: AudioFxPlugin }) {
const { save, load } = usePreset(plugin);
return (
<>
<button type="button" onClick={() => save("default")}>Save</button>
<button type="button" onClick={() => load("default")}>Load</button>
</>
);
}
```
## Usage: Advanced
```tsx
import { usePreset } from "@suaveplan/react-audio";
function ExportPreset({ plugin }: { plugin: AudioFxPlugin }) {
const { get } = usePreset(plugin);
return (
<button
type="button"
onClick={() => {
const preset = get();
navigator.clipboard.writeText(JSON.stringify(preset));
}}
>
Copy JSON
</button>
);
}
```
## API Reference
- `usePreset(plugin): { get, apply, save, load }`.
## Implementation Notes
The hook wraps each store interaction in a try/catch that converts
underlying errors into `ReactAudioError(PRESET_STORE_FAILED)` with
the original `Error` set as `cause`. The store is allowed to be
undefined; consumers that don't need persistence omit it from
provider options and use `get` / `apply` only. Promise rejections are
deliberately wrapped (rather than re-thrown raw) so a single
`error instanceof ReactAudioError` branch handles every failure path.
The four failure modes — missing store, store-rejected save,
store-rejected load, preset-not-found — share one code
(`PRESET_STORE_FAILED`) but distinct `messageKey`s so an i18n layer
can branch on the message resolver instead of the code. Non-Error
values thrown by a store are narrowed to `undefined` causes so the
wrapper Error remains type-safe.