This commit is contained in:
2026-03-23 19:10:55 -03:00
parent 3df9ed5ada
commit 95246c5452
23 changed files with 1361 additions and 107 deletions

View File

@@ -0,0 +1,119 @@
<script setup lang="ts">
import { computed } from 'vue'
export interface TableColumn {
key: string
label: string
width?: string
}
const props = defineProps<{
columns: TableColumn[]
rows: Record<string, unknown>[]
sortKey?: string
sortDir?: 'asc' | 'desc'
}>()
const emits = defineEmits<{
sort: [key: string]
}>()
const sorted = computed(() => {
if (!props.sortKey) return props.rows
const key = props.sortKey
const dir = props.sortDir === 'desc' ? -1 : 1
return [...props.rows].sort((a, b) => {
const av = a[key] as number | string
const bv = b[key] as number | string
if (av < bv) return -1 * dir
if (av > bv) return 1 * dir
return 0
})
})
</script>
<template>
<div class="table-renderer">
<table>
<thead>
<tr>
<th
v-for="col in columns"
:key="col.key"
:style="{ width: col.width }"
@click="emits('sort', col.key)"
class="sortable"
>
{{ col.label }}
<span v-if="sortKey === col.key" class="sort-indicator">
{{ sortDir === 'desc' ? '' : '' }}
</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in sorted" :key="i">
<td v-for="col in columns" :key="col.key">
{{ row[col.key] }}
</td>
</tr>
<tr v-if="rows.length === 0">
<td :colspan="columns.length" class="empty">No detections yet</td>
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
.table-renderer {
overflow: auto;
height: 100%;
font-family: var(--font-mono);
font-size: var(--font-size-sm);
}
table {
width: 100%;
border-collapse: collapse;
}
th {
position: sticky;
top: 0;
background: var(--surface-2);
color: var(--text-secondary);
font-weight: 600;
text-align: left;
padding: var(--space-2) var(--space-3);
border-bottom: var(--panel-border);
cursor: pointer;
user-select: none;
white-space: nowrap;
}
th:hover {
color: var(--text-primary);
}
.sort-indicator {
font-size: 9px;
margin-left: 4px;
}
td {
padding: var(--space-1) var(--space-3);
border-bottom: 1px solid var(--surface-3);
white-space: nowrap;
}
tr:hover td {
background: var(--surface-3);
}
.empty {
color: var(--text-dim);
text-align: center;
padding: var(--space-6);
}
</style>