{#if ambUrl} {#key ambUrl}
{/key}
{/if}
Playlists
{ e.stopPropagation(); menuFor = null; newMenuOpen = !newMenuOpen; }} >
Import
{#if newMenuOpen}
Playlist file…
M3U · XSPF · PLS · CSV · JSON
Folder of audio files…
tag or natural order
Paste a tracklist…
plain lines or timestamped setlist
YouTube DJ set…
tracks from chapters, description or comments
Playlist from a link…
YouTube · Spotify · Apple Music · TIDAL · Deezer
{/if}
New playlist
{#if playlistStore.playlists.length}
{playlistStore.playlists.length}
{playlistStore.playlists.length === 1 ? "playlist" : "playlists"}
{totals.tracks.toLocaleString()}
{totals.tracks === 1 ? "track" : "tracks"}
{#if totals.secs}
{fmtDuration(totals.secs)}
of music
{/if} {#if pinned.length}
{pinned.length}
pinned
{/if}
{/if}
{#if playlistStore.playlists.length === 0}
No playlists yet
Create one, or import an M3U/XSPF file or a pasted tracklist.
{:else} {#if pinned.length}
Pinned
{#each pinned as pl (pl.id)} {@render card(pl)} {/each}
{#if rest.length}
All playlists
{/if} {/if}
{#each rest as pl (pl.id)} {@render card(pl)} {/each}
{/if}
{#snippet card(pl)}
open(pl)}>
{#if playlistStore.covers[pl.id]}
{:else}
{/if} {#if pl.track_count > pl.unresolved_count}
{ e.stopPropagation(); playCard(pl); }} onkeydown={(e) => e.key === "Enter" && (e.stopPropagation(), playCard(pl))} >
{/if}
{pl.name}
{pl.track_count} {pl.track_count === 1 ? "track" : "tracks"} {#if pl.duration_secs} · {fmtDuration(pl.duration_secs)}{/if}
{#if pl.kind === "setlist" || pl.unresolved_count > 0}
{#if pl.kind === "setlist"}
Setlist
{/if} {#if pl.unresolved_count > 0}
{pl.unresolved_count} unresolved
{/if}
{/if}
{#if pl.pinned}
{/if}
toggleMenu(e, pl)}>
{#if menuFor === pl.id}
e.stopPropagation()}>
togglePin(pl)}>
{pl.pinned ? "Unpin" : "Pin"}
duplicate(pl)}>
Duplicate
(exportFor = pl.id)} onmouseleave={() => (exportFor = null)} >
(exportFor = exportFor === pl.id ? null : pl.id)} aria-haspopup="menu" aria-expanded={exportFor === pl.id} >
Export
{#if exportFor === pl.id}
exportAs(pl, "m3u8")}>M3U8
exportAs(pl, "xspf")}>XSPF
exportAs(pl, "pls")}>PLS
exportAs(pl, "csv")}>CSV
exportAs(pl, "json")}>Backup (JSON)
{/if}
remove(pl)}>
{confirmDelete === pl.id ? "Really delete?" : "Delete"}
{/if}
{/snippet}