2025-01-19 05:24:56 +02:00
|
|
|
<script lang="ts">
|
2025-01-21 11:42:52 +02:00
|
|
|
import * as Card from '$lib/components/ui/card/index.js';
|
2025-01-19 05:24:56 +02:00
|
|
|
import { dndzone } from 'svelte-dnd-action';
|
|
|
|
import { flip } from 'svelte/animate';
|
2025-01-21 11:42:52 +02:00
|
|
|
import { expoOut } from 'svelte/easing';
|
|
|
|
import { truncate } from '$lib/utils';
|
2025-01-19 05:24:56 +02:00
|
|
|
|
|
|
|
let { items = $bindable(), image = false, type = 'default' } = $props();
|
|
|
|
|
|
|
|
const flipDurationMs = 300;
|
|
|
|
|
|
|
|
function handleDndConsider(e: CustomEvent<any>) {
|
|
|
|
items = e.detail.items;
|
|
|
|
}
|
|
|
|
function handleDndFinalize(e: CustomEvent<any>) {
|
|
|
|
items = e.detail.items;
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<section
|
2025-01-21 11:42:52 +02:00
|
|
|
use:dndzone={{
|
|
|
|
items,
|
|
|
|
flipDurationMs,
|
|
|
|
type: type,
|
|
|
|
dropTargetStyle: { outline: 'none' }
|
|
|
|
}}
|
2025-01-19 05:24:56 +02:00
|
|
|
onconsider={handleDndConsider}
|
|
|
|
onfinalize={handleDndFinalize}
|
2025-01-21 11:42:52 +02:00
|
|
|
class="grid grid-cols-3 items-center gap-16"
|
2025-01-19 05:24:56 +02:00
|
|
|
>
|
2025-01-21 11:42:52 +02:00
|
|
|
{#each items as item, i (item.id)}
|
|
|
|
<div animate:flip={{ duration: flipDurationMs, easing: expoOut }}>
|
|
|
|
<Card.Root
|
|
|
|
class="overflow-hidden rounded-xl border bg-card text-card-foreground shadow {type ===
|
|
|
|
'names'
|
|
|
|
? 'border-orange-300'
|
|
|
|
: type === 'artists'
|
|
|
|
? 'border-cyan-300'
|
2025-01-21 13:11:06 +02:00
|
|
|
: 'border-purple-300'}"
|
2025-01-21 11:42:52 +02:00
|
|
|
>
|
|
|
|
{#if image}
|
|
|
|
<Card.Content class="p-0">
|
|
|
|
<img class="aspect-square w-full object-cover" alt="Album Art" src={item.value} />
|
|
|
|
<input type="hidden" name="{type}_{i}" value={item.value} />
|
|
|
|
</Card.Content>
|
|
|
|
{:else}
|
|
|
|
<Card.Content>
|
|
|
|
<p class="text-center">
|
|
|
|
{#if type === 'artists'}
|
|
|
|
{truncate(item.value, 30)}
|
|
|
|
{:else}
|
|
|
|
{truncate(item.value, 45)}
|
|
|
|
{/if}
|
|
|
|
</p>
|
|
|
|
<input type="hidden" name="{type}_{i}" value={item.value} />
|
|
|
|
</Card.Content>
|
|
|
|
{/if}
|
|
|
|
</Card.Root>
|
|
|
|
</div>
|
|
|
|
{/each}
|
2025-01-19 05:24:56 +02:00
|
|
|
</section>
|