refactor(frontend): extract types, API, helpers, and preview from +page.svelte
This commit is contained in:
91
frontend/src/lib/components/FileRow.svelte
Normal file
91
frontend/src/lib/components/FileRow.svelte
Normal file
@@ -0,0 +1,91 @@
|
||||
<script lang="ts">
|
||||
import type { FileRecord } from '$lib/types';
|
||||
import { formatName, formatSize } from '$lib/format';
|
||||
|
||||
let {
|
||||
file,
|
||||
selected,
|
||||
onselect,
|
||||
onpreview,
|
||||
ondownload,
|
||||
ondelete,
|
||||
}: {
|
||||
file: FileRecord;
|
||||
selected: boolean;
|
||||
onselect: () => void;
|
||||
onpreview: () => void;
|
||||
ondownload: () => void;
|
||||
ondelete: () => void;
|
||||
} = $props();
|
||||
|
||||
let confirming = $state(false);
|
||||
</script>
|
||||
|
||||
<div
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
onpreview();
|
||||
} else if (e.key === ' ') {
|
||||
e.preventDefault(); onselect();
|
||||
}
|
||||
}
|
||||
}
|
||||
onclick={onselect}
|
||||
ondblclick={onpreview}
|
||||
class="flex items-stretch border-l hover:bg-white/2 transition-all {selected ? 'border-sky-400/50 bg-white/2 ring-1 ring-inset ring-sky-400/50' : 'border-sky-200/20 border-l-transparent hover:border-l-sky-400/50'}"
|
||||
>
|
||||
<span class="font-medium text-white text-sm flex-1 truncate py-2 pl-6">{formatName(file.name)}</span>
|
||||
<span class="text-sm text-white/40 w-40 py-2">{formatSize(file.size)}</span>
|
||||
<span class="text-sm text-white/40 w-48 py-2">{new Date(file.uploadedAt).toLocaleString()}</span>
|
||||
<div class="w-px bg-sky-200/20 self-stretch"></div>
|
||||
<div class="flex items-center gap-4 w-32 justify-center relative">
|
||||
<!-- Download -->
|
||||
<button class="text-white/40 hover:text-emerald-400 hover:scale-110 transition-all cursor-pointer" title="Download" onclick={ondownload}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
||||
<polyline points="7 10 12 15 17 10"/>
|
||||
<line x1="12" y1="15" x2="12" y2="3"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- TODO: Copy -->
|
||||
<button class="text-white/40 hover:text-blue-400 hover:scale-110 transition-all cursor-pointer" title="Copy link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
|
||||
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Delete -->
|
||||
<div class="relative">
|
||||
<button class="text-white/40 hover:text-red-400 hover:scale-110 transition-all cursor-pointer" title="Delete" onclick={() => confirming = true}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="3 6 5 6 21 6"/>
|
||||
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
|
||||
<path d="M10 11v6"/>
|
||||
<path d="M14 11v6"/>
|
||||
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/>
|
||||
</svg>
|
||||
</button>
|
||||
{#if confirming}
|
||||
<div class="absolute left-6 top-1/2 -translate-y-1/2 flex items-center z-10">
|
||||
<div class="w-0 h-0 border-t-4 border-b-4 border-r-4 border-t-transparent border-b-transparent border-r-sky-200/20"></div>
|
||||
<div class="bg-[#0f1117] border border-sky-200/20 rounded px-3 py-2 flex items-center gap-2 whitespace-nowrap">
|
||||
<span class="text-white/40 text-xs">Confirm action</span>
|
||||
<button class="text-white/60 hover:text-white transition-colors cursor-pointer" title="Confirm" onclick={() => { ondelete(); confirming = false; }}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="20 6 9 17 4 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="text-white/60 hover:text-white transition-colors cursor-pointer" title="Cancel" onclick={() => confirming = false}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="18" y1="6" x2="6" y2="18"/>
|
||||
<line x1="6" y1="6" x2="18" y2="18"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user