<!-- source-hash: 567153c4bee0ea823c8dcb3ad142df21 -->
A React client component for managing media attachments (images, videos, screenshots, demos) on release entries, supporting file upload, drag-to-reorder, and inline editing.

## Key Components

### `ReleaseMediaItem` (interface)
Represents a single media entry with the following fields:

| Field | Type | Description |
|-------|------|-------------|
| `media_type` | `'image' \| 'video' \| 'screenshot' \| 'demo'` | Category of media |
| `media_url` | `string` | Public URL after upload |
| `title` | `string?` | Optional display title |
| `description` | `string?` | Optional description |
| `display_order` | `number?` | Sort position in gallery |
| `_file` | `File?` | Temporary pre-upload file reference |
| `_uploading` | `boolean?` | Upload in-progress flag |

### `ReleaseMediaManager` (component)

**Props:**

| Prop | Type | Description |
|------|------|-------------|
| `media` | `ReleaseMediaItem[]` | Controlled media list |
| `onChange` | `(media: ReleaseMediaItem[]) => void` | Called on any list mutation |
| `onUpload` | `(file, mediaType) => Promise<string>` | Handles actual file upload, returns URL |
| `className` | `string?` | Optional wrapper class |

**Internal behaviors:**
- `handleFileSelect` — detects file MIME type, auto-assigns `media_type`, triggers `onUpload`, rolls back on failure
- `removeMedia` — removes item by index
- `updateMedia` — updates a single field on an existing item
- `handleDragStart` / `handleDragOver` / `handleDrop` — native HTML5 drag-and-drop reordering, updates `display_order` on drop

## Usage Example

```typescript
import { ReleaseMediaManager, ReleaseMediaItem } from './release-media-manager';

const [media, setMedia] = useState<ReleaseMediaItem[]>([]);

async function uploadToStorage(file: File, mediaType: string): Promise<string> {
  const formData = new FormData();
  formData.append('file', file);
  const res = await fetch('/api/upload', { method: 'POST', body: formData });
  const { url } = await res.json();
  return url;
}

<ReleaseMediaManager
  media={media}
  onChange={setMedia}
  onUpload={uploadToStorage}
/>
```

> **Note:** The component is fully controlled — the parent owns the `media` array. Failed uploads automatically roll back to the previous state without manual intervention.