refactor(web): converge PlaylistTrackRow drag-reorder onto @neodrag/svelte (B4)
This commit is contained in:
@@ -1,25 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { GripVertical, X } from 'lucide-svelte';
|
||||
import { draggable, type DragEventData } from '@neodrag/svelte';
|
||||
import LikeButton from './LikeButton.svelte';
|
||||
import TrackMenu from './TrackMenu.svelte';
|
||||
import type { PlaylistTrack, TrackRef } from '$lib/api/types';
|
||||
import { offsetToDelta } from './queue-row-math';
|
||||
|
||||
let {
|
||||
row,
|
||||
isOwner,
|
||||
onRemove,
|
||||
onPlay,
|
||||
onDragStart,
|
||||
onDragOver,
|
||||
onDrop
|
||||
onMove
|
||||
}: {
|
||||
row: PlaylistTrack;
|
||||
isOwner: boolean;
|
||||
onRemove: (position: number) => void;
|
||||
onPlay: (position: number) => void;
|
||||
onDragStart?: (position: number) => void;
|
||||
onDragOver?: (e: DragEvent, position: number) => void;
|
||||
onDrop?: (e: DragEvent, position: number) => void;
|
||||
onMove?: (fromPos: number, toPos: number) => void;
|
||||
} = $props();
|
||||
|
||||
const isUnavailable = $derived(row.track_id === null);
|
||||
@@ -41,21 +39,42 @@
|
||||
: null
|
||||
);
|
||||
|
||||
let measuredRowHeight = 56; // sensible default; replaced on dragStart
|
||||
|
||||
function handleDragStart(data: DragEventData) {
|
||||
const rect = data.rootNode.getBoundingClientRect();
|
||||
if (rect.height > 0) measuredRowHeight = rect.height;
|
||||
}
|
||||
|
||||
function handleDragEnd(data: DragEventData) {
|
||||
const delta = offsetToDelta(data.offsetY, measuredRowHeight);
|
||||
if (delta === 0) return;
|
||||
onMove?.(row.position, row.position + delta);
|
||||
}
|
||||
|
||||
function format(sec: number): string {
|
||||
const m = Math.floor(sec / 60);
|
||||
const s = sec % 60;
|
||||
return `${m}:${s.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
// Drag is gated on owner+available. When neither, the action runs but
|
||||
// the dragEnd handler skips by returning before onMove fires; visually
|
||||
// the user never sees the row move.
|
||||
const canDrag = $derived(isOwner && !isUnavailable);
|
||||
</script>
|
||||
|
||||
<div
|
||||
role="listitem"
|
||||
class="flex items-center gap-3 px-3 py-2 text-sm transition-colors hover:bg-surface-hover
|
||||
{isUnavailable ? 'text-text-muted' : 'text-text-primary'}"
|
||||
draggable={isOwner && !isUnavailable}
|
||||
ondragstart={() => onDragStart?.(row.position)}
|
||||
ondragover={(e) => { e.preventDefault(); onDragOver?.(e, row.position); }}
|
||||
ondrop={(e) => { e.preventDefault(); onDrop?.(e, row.position); }}
|
||||
use:draggable={{
|
||||
axis: 'y',
|
||||
bounds: 'parent',
|
||||
disabled: !canDrag,
|
||||
onDragStart: handleDragStart,
|
||||
onDragEnd: handleDragEnd
|
||||
}}
|
||||
>
|
||||
{#if isOwner}
|
||||
<span
|
||||
|
||||
Reference in New Issue
Block a user