Files
RenewCMS/web/src/components/MediaCardList.vue
T

78 lines
2.5 KiB
Vue

<script setup lang="ts">
import { t } from '@/i18n'
import MediaCardBadges from '@/components/MediaCardBadges.vue'
import MediaCheckbox from '@/components/MediaCheckbox.vue'
import MediaThumb from '@/components/MediaThumb.vue'
import type { MediaItem } from '@/composables/useMedia'
import { formatDimensions, formatMediaDate, formatSize, formatType } from '@/lib/mediaFormat'
defineProps<{
items: MediaItem[]
selected: number[]
}>()
const emit = defineEmits<{
open: [id: number, opener: HTMLElement]
toggle: [id: number]
}>()
</script>
<template>
<ul class="-mx-4 border-y border-default bg-default">
<li
v-for="item in items"
:key="item.id"
data-testid="media-card-row"
:data-selected="selected.includes(item.id) || undefined"
class="relative border-b border-default last:border-b-0"
:class="
selected.includes(item.id)
? 'bg-secondary-200 text-primary-900 dark:bg-secondary-300'
: 'bg-default'
"
>
<button
type="button"
data-media-card
:data-media-id="item.id"
class="flex min-h-20 w-full items-center py-2 pr-3 pl-11 text-start focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary"
:class="selected.includes(item.id) ? 'text-primary-600' : 'text-muted'"
@click="emit('open', item.id, $event.currentTarget as HTMLElement)"
>
<MediaThumb :item="item" size="md" class="size-14 border border-default" />
<span class="flex min-w-0 flex-1 flex-col gap-0.75 pl-3">
<span
class="truncate text-[0.9375rem] font-medium"
:class="
selected.includes(item.id) ? 'text-primary-900' : 'text-highlighted'
"
>{{ item.filename }}</span
>
<span class="text-xs/5"
>{{ formatSize(item.size) }} ·
{{ formatDimensions(item.width, item.height) }} ·
{{ formatType(item.content_type) }}</span
>
<span class="flex flex-wrap items-center gap-1 text-xs/5">
<MediaCardBadges :item="item" />
<span>{{ item.uploaded_by }} · {{ formatMediaDate(item.created_at) }}</span>
</span>
</span>
<UIcon name="i-lucide-chevron-right" class="ml-2 size-4 shrink-0" />
</button>
<div
class="absolute inset-y-0 left-0 flex w-11 items-center justify-center"
@click.self="emit('toggle', item.id)"
>
<MediaCheckbox
:state="selected.includes(item.id) ? 'checked' : 'unchecked'"
:label="t('Select {0}', [item.filename])"
:tabbable="false"
@toggle="emit('toggle', item.id)"
/>
</div>
</li>
</ul>
</template>