import { motion } from 'framer-motion'
import { Eye, EyeOff, Heart, X, Disc3 } from '../../lib/icons'
import { getBestImage } from '../../api/jellyfin'
import type { BaseItemDto } from '../../api/types'
/**
* Floating ghost that follows the pointer while a drag is in progress.
* Shows the moving item count and a label so multi-row drags read clearly.
*/
export function DragGhost({ count, pointerY, label }: { count: number; pointerY: number; label: string }) {
return (
{count > 1 ? `Moving ${count} items` : label || 'Moving item'}
)
}
interface SelectionToolbarProps {
count: number
onClear: () => void
onRemove: () => void
onMarkPlayed: () => void
onMarkUnplayed: () => void
onToggleFavorite: () => void
}
/**
* Bottom-floating toolbar that appears whenever the user has rows
* selected. Bundles the bulk actions (mark watched / unwatched, favorite,
* remove) plus a Done button to clear the selection.
*/
export function SelectionToolbar({
count,
onClear,
onRemove,
onMarkPlayed,
onMarkUnplayed,
onToggleFavorite,
}: SelectionToolbarProps) {
return (
{count} selected
} label="Mark watched" />
} label="Mark unwatched" />
} label="Favorite" />
}
label="Remove"
tone="danger"
/>
Done
)
}
function ToolbarButton({
onClick,
icon,
label,
tone,
}: {
onClick: () => void
icon: React.ReactNode
label: string
tone?: 'danger'
}) {
return (
{icon}
{label}
)
}
/**
* 2x2 poster mosaic fallback for playlists that don't have a primary
* image. Shows the first 4 item posters in a grid - if fewer than 4 are
* available, blanks fill the gaps. Empty state shows a music disc icon.
*/
export function PosterMosaic({ items, serverUrl }: { items: BaseItemDto[]; serverUrl: string }) {
const tiles = items
.slice(0, 4)
.map(it => getBestImage(serverUrl, it, 'primary', 300))
.filter(Boolean) as string[]
return (
{tiles.length > 0 ? (
Array.from({ length: 4 }).map((_, i) => (
{tiles[i] ? (
) : (
)}
))
) : (
)}
)
}