|
<script lang="ts"> |
|
import type { PicletInstance } from '$lib/db/schema'; |
|
import PicletCard from './PicletCard.svelte'; |
|
|
|
interface Props { |
|
instance: PicletInstance; |
|
size?: number; |
|
onDragStart?: (instance: PicletInstance) => void; |
|
onDragEnd?: () => void; |
|
onClick?: () => void; |
|
} |
|
|
|
let { instance, size = 100, onDragStart, onDragEnd, onClick }: Props = $props(); |
|
|
|
let isDragging = $state(false); |
|
|
|
function handleDragStart(e: DragEvent) { |
|
isDragging = true; |
|
|
|
|
|
e.dataTransfer!.effectAllowed = 'move'; |
|
e.dataTransfer!.setData('application/json', JSON.stringify({ |
|
instanceId: instance.id, |
|
fromRoster: instance.isInRoster, |
|
fromPosition: instance.rosterPosition |
|
})); |
|
|
|
|
|
const dragImage = e.currentTarget as HTMLElement; |
|
const clone = dragImage.cloneNode(true) as HTMLElement; |
|
clone.style.transform = 'scale(1.1)'; |
|
clone.style.opacity = '0.8'; |
|
document.body.appendChild(clone); |
|
e.dataTransfer!.setDragImage(clone, size / 2, size / 2); |
|
setTimeout(() => document.body.removeChild(clone), 0); |
|
|
|
onDragStart?.(instance); |
|
} |
|
|
|
function handleDragEnd() { |
|
isDragging = false; |
|
onDragEnd?.(); |
|
} |
|
</script> |
|
|
|
<div |
|
draggable="true" |
|
ondragstart={handleDragStart} |
|
ondragend={handleDragEnd} |
|
class="draggable-wrapper" |
|
class:dragging={isDragging} |
|
role="button" |
|
tabindex="0" |
|
> |
|
<PicletCard piclet={instance} {size} {onClick} /> |
|
</div> |
|
|
|
<style> |
|
.draggable-wrapper { |
|
cursor: move; |
|
} |
|
|
|
.draggable-wrapper.dragging { |
|
opacity: 0.5; |
|
} |
|
|
|
.draggable-wrapper.dragging :global(.piclet-card) { |
|
transform: scale(0.9); |
|
} |
|
</style> |