feat(frontend): add raw HTML render + per-row actions to DashboardDataGrid

- Column.raw flag: render() output injected as HTML (for styled badges)
- Actions prop: per-row action buttons rendered as final column
  - Each action has label, handler, variant, condition, disabled
- Enables RepositoryDashboardGrid to delegate rendering to DataGrid
This commit is contained in:
2026-06-17 16:17:56 +03:00
parent 3ecf37e30a
commit 00dd83b88f

View File

@@ -42,6 +42,8 @@
class?: string; class?: string;
/** Custom cell render — returns display string */ /** Custom cell render — returns display string */
render?: (item: any) => string; render?: (item: any) => string;
/** If true, render() output is injected as HTML (for styled badges, etc.) */
raw?: boolean;
} }
// [SECTION: PROPS] // [SECTION: PROPS]
@@ -79,6 +81,15 @@
// Snippet for bulk actions bar (shown above table when items are selected) // Snippet for bulk actions bar (shown above table when items are selected)
children = undefined, children = undefined,
// Per-row action buttons (rendered as a final column)
actions = [] as Array<{
label: string;
handler: (item: any) => void;
variant?: string;
condition?: (item: any) => boolean;
disabled?: (item: any) => boolean;
}>,
} = $props(); } = $props();
// [SECTION: HELPERS] // [SECTION: HELPERS]
@@ -255,6 +266,11 @@
{/if} {/if}
</th> </th>
{/each} {/each}
{#if actions.length > 0}
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">
Actions
</th>
{/if}
</tr> </tr>
</thead> </thead>
<tbody class="bg-surface-card divide-y divide-border"> <tbody class="bg-surface-card divide-y divide-border">
@@ -275,9 +291,34 @@
class="px-6 py-4 whitespace-nowrap text-sm {col.class || ''}" class="px-6 py-4 whitespace-nowrap text-sm {col.class || ''}"
style={col.width ? `width:${col.width}` : ""} style={col.width ? `width:${col.width}` : ""}
> >
{col.render ? col.render(item) : item[col.key]} {#if col.render}
{#if col.raw}
{@html col.render(item)}
{:else}
{col.render(item)}
{/if}
{:else}
{item[col.key]}
{/if}
</td> </td>
{/each} {/each}
{#if actions.length > 0}
<td class="px-6 py-4 whitespace-nowrap text-sm">
{#each actions as action}
{#if !action.condition || action.condition(item)}
<Button
variant={action.variant || "ghost"}
size="sm"
onclick={() => action.handler(item)}
disabled={action.disabled ? action.disabled(item) : false}
class="mr-1"
>
{action.label}
</Button>
{/if}
{/each}
</td>
{/if}
</tr> </tr>
{/each} {/each}
</tbody> </tbody>