first commit
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# `<TrackRow>`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`<TrackRow>` is the per-track row primitive consumed by `<TrackList>`.
|
||||
It subscribes to a single `Track` through the foundation `useTrack`
|
||||
hook and renders the canonical row controls: editable name, mute /
|
||||
solo toggles, volume + pan sliders, and a remove button. The row
|
||||
collapses to a tombstone marker when the referenced track is removed
|
||||
so the surrounding `<ul>` does not visually re-layout in the
|
||||
intervening render frame.
|
||||
|
||||
`<TrackRow>` can also be used standalone — anywhere you have a track
|
||||
id and a provider mounted you can drop it into a list to render
|
||||
exactly one row.
|
||||
|
||||
## Features
|
||||
|
||||
- Re-renders on `trackChange` for the bound track id via `useTrack`.
|
||||
- Mute / solo as `aria-pressed` toggles with live "Mute" / "Muted"
|
||||
labels (and analogous Solo).
|
||||
- Volume slider clamped `[0, 1]` and pan slider clamped `[-1, 1]`,
|
||||
both step `0.01`. Non-numeric input is ignored.
|
||||
- Name input writes through to `timeline.updateTrack({ name })`.
|
||||
- Remove button calls `useTrack().remove()` and the row immediately
|
||||
collapses to the tombstone.
|
||||
- `hideRemove` suppresses the remove button.
|
||||
- `data-muted` / `data-soloed` attributes for theming hooks.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```tsx
|
||||
import { TrackRow } from "@suaveplan/react-audio";
|
||||
|
||||
export function OneRow({ trackId }: { trackId: string }) {
|
||||
return (
|
||||
<ul>
|
||||
<TrackRow trackId={trackId} />
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```tsx
|
||||
import { TrackRow } from "@suaveplan/react-audio";
|
||||
|
||||
export function ReadOnlyRow({ trackId }: { trackId: string }) {
|
||||
return (
|
||||
<ul>
|
||||
<TrackRow trackId={trackId} hideRemove className="row-tight" />
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Prop | Type | Default | Notes |
|
||||
| ------------- | ------------------ | ------- | ------------------------------------------------------------ |
|
||||
| `trackId` | `string` | — | Required. The id of the track to render. |
|
||||
| `className` | `string \| undef` | — | Forwarded to the outer `<li>` (both active and tombstone). |
|
||||
| `hideRemove` | `boolean \| undef` | `false` | Suppresses the remove button when `true`. |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The active row is rendered by an inner `ActiveRow` sub-component so
|
||||
the mute / solo / volume / pan / name callbacks are only defined when
|
||||
the track exists. This keeps the hooks call sequence stable across
|
||||
the "track exists → tombstone" transition without violating the Rules
|
||||
of Hooks: the parent always calls `useTrack` first, then either
|
||||
returns the tombstone JSX (no further hooks) or renders `<ActiveRow>`
|
||||
(which calls its own bag of `useCallback`s). The tombstone collapses
|
||||
to a minimal `<li>` so list keying remains stable while the engine is
|
||||
mid-mutation.
|
||||
Reference in New Issue
Block a user