<!-- source-hash: 9a66a790bb4e14efee7ac5e9ffc0cfb8 -->
A generic, reusable React component for managing arrays of objects with inline add, edit, remove, and multi-line paste support. Supports both immediate and deferred (save-gated) change modes.

## Key Components

### `ArrayEntryManager<T>`
A generic client component that renders a labeled list of editable input entries backed by a typed array.

**Props:**

| Prop | Type | Description |
|------|------|-------------|
| `title` | `ReactNode` | Section label; supports strings or badge components |
| `items` | `T[]` | Array of objects to manage |
| `onChange` | `(items: T[]) => void` | Called on change (immediate) or save (deferred) |
| `fieldKey` | `keyof T` | Object key to bind each input to |
| `requireSave` | `boolean` | When `true`, buffers edits locally until "Save" is clicked |
| `onDirtyChange` | `(isDirty: boolean) => void` | Notifies parent of unsaved changes |
| `renderLabel` | `(item: T, index: number) => ReactNode` | Custom renderer above each input |
| `isSaving` | `boolean` | Shows spinner on the save button during async operations |

**Behaviors:**
- **Draft mode** (`requireSave=true`): edits are buffered in local state; `onChange` fires only on explicit save
- **Immediate mode** (`requireSave=false`): every edit calls `onChange` directly
- **Multi-line paste**: pasting newline-separated values auto-creates multiple entries
- **Add at top**: new items are prepended for better UX

## Usage Example

```typescript
<ArrayEntryManager<{ github_release_url: string }>
  title="Release URLs"
  items={releaseUrls}
  onChange={setReleaseUrls}
  fieldKey="github_release_url"
  placeholder="https://github.com/org/repo/releases/tag/v1.0.0"
  emptyMessage="No release URLs configured."
  addButtonText="Add URL"
  saveButtonText="Save URLs"
  requireSave={true}
  onDirtyChange={(dirty) => setHasUnsavedChanges(dirty)}
  isSaving={isSaving}
/>
```