refactor(web-player): let TrackTable declare its own columns
Every one of the seven tables repeated the same header markup and hand written grid templates, always in the same shape: an optional index, the title, optional desktop-only meta columns, the duration and an optional action. TrackTable now takes that shape as props and builds both grid templates and the headers itself.
This commit is contained in:
@@ -5,6 +5,11 @@
|
|||||||
readonly columns: string;
|
readonly columns: string;
|
||||||
readonly columnsMobile: string;
|
readonly columnsMobile: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TrackMetaColumn {
|
||||||
|
label: string;
|
||||||
|
width: string;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -12,23 +17,39 @@
|
|||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
columns: string;
|
index?: boolean;
|
||||||
columnsMobile?: string;
|
action?: boolean;
|
||||||
|
meta?: TrackMetaColumn[];
|
||||||
class?: string;
|
class?: string;
|
||||||
headers: Snippet;
|
|
||||||
children: Snippet;
|
children: Snippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { columns, columnsMobile, class: klass = '', headers, children }: Props = $props();
|
let { index = false, action = false, meta = [], class: klass = '', children }: Props = $props();
|
||||||
|
|
||||||
const mobile = $derived(columnsMobile ?? columns);
|
const columns = $derived(
|
||||||
|
[
|
||||||
|
index ? '32px' : '',
|
||||||
|
'1fr',
|
||||||
|
...meta.map((column) => column.width),
|
||||||
|
'64px',
|
||||||
|
action ? '36px' : ''
|
||||||
|
]
|
||||||
|
.filter((width) => width !== '')
|
||||||
|
.join(' ')
|
||||||
|
);
|
||||||
|
|
||||||
|
const columnsMobile = $derived(
|
||||||
|
[index ? '28px' : '', '1fr', '52px', action ? '32px' : '']
|
||||||
|
.filter((width) => width !== '')
|
||||||
|
.join(' ')
|
||||||
|
);
|
||||||
|
|
||||||
setContext<TrackTableContext>(trackTableKey, {
|
setContext<TrackTableContext>(trackTableKey, {
|
||||||
get columns() {
|
get columns() {
|
||||||
return columns;
|
return columns;
|
||||||
},
|
},
|
||||||
get columnsMobile() {
|
get columnsMobile() {
|
||||||
return mobile;
|
return columnsMobile;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -36,9 +57,19 @@
|
|||||||
<div class={klass}>
|
<div class={klass}>
|
||||||
<div
|
<div
|
||||||
class="grid track-grid items-center gap-3 border-b border-line px-2 pb-2 text-sm font-medium tracking-wide text-muted uppercase sm:gap-8 sm:px-3"
|
class="grid track-grid items-center gap-3 border-b border-line px-2 pb-2 text-sm font-medium tracking-wide text-muted uppercase sm:gap-8 sm:px-3"
|
||||||
style="--mf-track-cols:{columns}; --mf-track-cols-mobile:{mobile}"
|
style="--mf-track-cols:{columns}; --mf-track-cols-mobile:{columnsMobile}"
|
||||||
>
|
>
|
||||||
{@render headers()}
|
{#if index}
|
||||||
|
<span class="text-center">#</span>
|
||||||
|
{/if}
|
||||||
|
<span>Título</span>
|
||||||
|
{#each meta as column (column.label)}
|
||||||
|
<span class="hidden text-center sm:block">{column.label}</span>
|
||||||
|
{/each}
|
||||||
|
<span class="hidden text-center sm:block">Duración</span>
|
||||||
|
{#if action}
|
||||||
|
<span></span>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-1 flex flex-col">
|
<div class="mt-1 flex flex-col">
|
||||||
{@render children()}
|
{@render children()}
|
||||||
|
|||||||
@@ -30,19 +30,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TrackTable
|
<TrackTable index action={isOwner} class="mt-6 sm:mt-8">
|
||||||
columns={isOwner ? '32px 1fr 64px 36px' : '32px 1fr 64px'}
|
|
||||||
columnsMobile={isOwner ? '28px 1fr 52px 32px' : '28px 1fr 52px'}
|
|
||||||
class="mt-6 sm:mt-8"
|
|
||||||
>
|
|
||||||
{#snippet headers()}
|
|
||||||
<span class="text-center">#</span>
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
{#if isOwner}
|
|
||||||
<span></span>
|
|
||||||
{/if}
|
|
||||||
{/snippet}
|
|
||||||
{#each tracks as track, i (track.id)}
|
{#each tracks as track, i (track.id)}
|
||||||
<TrackRow>
|
<TrackRow>
|
||||||
<TrackIndexCell
|
<TrackIndexCell
|
||||||
|
|||||||
@@ -27,12 +27,7 @@
|
|||||||
|
|
||||||
<div class="mt-10 sm:mt-12">
|
<div class="mt-10 sm:mt-12">
|
||||||
<SectionHeading title="Tus canciones subidas" />
|
<SectionHeading title="Tus canciones subidas" />
|
||||||
<TrackTable columns="1fr 64px 36px" columnsMobile="1fr 52px 32px">
|
<TrackTable action>
|
||||||
{#snippet headers()}
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
<span></span>
|
|
||||||
{/snippet}
|
|
||||||
{#each library as track, i (track.id)}
|
{#each library as track, i (track.id)}
|
||||||
<TrackRow>
|
<TrackRow>
|
||||||
<TrackTitleCell
|
<TrackTitleCell
|
||||||
|
|||||||
@@ -140,12 +140,7 @@
|
|||||||
<p class="mt-6 text-sm text-fg-3">{data.album.description}</p>
|
<p class="mt-6 text-sm text-fg-3">{data.album.description}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<TrackTable columns="32px 1fr 64px" columnsMobile="28px 1fr 52px" class="mt-6 sm:mt-8">
|
<TrackTable index class="mt-6 sm:mt-8">
|
||||||
{#snippet headers()}
|
|
||||||
<span class="text-center">#</span>
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
{/snippet}
|
|
||||||
{#each tracks as track, i (track.videoId)}
|
{#each tracks as track, i (track.videoId)}
|
||||||
<TrackRow oncontextmenu={(e) => (contextMenu = contextMenuStateFor(e, targetFor(i)))}>
|
<TrackRow oncontextmenu={(e) => (contextMenu = contextMenuStateFor(e, targetFor(i)))}>
|
||||||
<TrackIndexCell
|
<TrackIndexCell
|
||||||
|
|||||||
@@ -49,18 +49,14 @@
|
|||||||
|
|
||||||
{#if items.length > 0}
|
{#if items.length > 0}
|
||||||
<TrackTable
|
<TrackTable
|
||||||
columns="32px 1fr 100px 100px 64px 36px"
|
index
|
||||||
columnsMobile="28px 1fr 52px 32px"
|
action
|
||||||
|
meta={[
|
||||||
|
{ label: 'Subida', width: '100px' },
|
||||||
|
{ label: 'Escuchas', width: '100px' }
|
||||||
|
]}
|
||||||
class="mt-6 sm:mt-8"
|
class="mt-6 sm:mt-8"
|
||||||
>
|
>
|
||||||
{#snippet headers()}
|
|
||||||
<span class="text-center">#</span>
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Subida</span>
|
|
||||||
<span class="hidden text-center sm:block">Escuchas</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
<span></span>
|
|
||||||
{/snippet}
|
|
||||||
{#each items as track, i (track.id)}
|
{#each items as track, i (track.id)}
|
||||||
<TrackRow>
|
<TrackRow>
|
||||||
<TrackIndexCell
|
<TrackIndexCell
|
||||||
|
|||||||
@@ -119,12 +119,7 @@
|
|||||||
<Alert tone="danger" class="mt-4">{form.message}</Alert>
|
<Alert tone="danger" class="mt-4">{form.message}</Alert>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<TrackTable columns="32px 1fr 64px" columnsMobile="28px 1fr 52px" class="mt-6 sm:mt-8">
|
<TrackTable index class="mt-6 sm:mt-8">
|
||||||
{#snippet headers()}
|
|
||||||
<span class="text-center">#</span>
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
{/snippet}
|
|
||||||
{#each items as item, i (mixItemKey(item))}
|
{#each items as item, i (mixItemKey(item))}
|
||||||
<TrackRow oncontextmenu={(e) => (contextMenu = contextMenuStateFor(e, targets[i]))}>
|
<TrackRow oncontextmenu={(e) => (contextMenu = contextMenuStateFor(e, targets[i]))}>
|
||||||
<TrackIndexCell
|
<TrackIndexCell
|
||||||
|
|||||||
@@ -32,18 +32,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TrackTable
|
<TrackTable index action meta={[{ label: 'Añadida', width: '140px' }]} class="mt-6 sm:mt-8">
|
||||||
columns="32px 1fr 140px 64px 36px"
|
|
||||||
columnsMobile="28px 1fr 52px 32px"
|
|
||||||
class="mt-6 sm:mt-8"
|
|
||||||
>
|
|
||||||
{#snippet headers()}
|
|
||||||
<span class="text-center">#</span>
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Añadida</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
<span></span>
|
|
||||||
{/snippet}
|
|
||||||
{#each tracks as track, i (track.id)}
|
{#each tracks as track, i (track.id)}
|
||||||
<TrackRow>
|
<TrackRow>
|
||||||
<TrackIndexCell
|
<TrackIndexCell
|
||||||
|
|||||||
@@ -84,12 +84,7 @@
|
|||||||
|
|
||||||
<div class="mt-10 sm:mt-12">
|
<div class="mt-10 sm:mt-12">
|
||||||
<SectionHeading title="Sugerencias" />
|
<SectionHeading title="Sugerencias" />
|
||||||
<TrackTable columns="1fr 64px 36px" columnsMobile="1fr 52px 32px">
|
<TrackTable action>
|
||||||
{#snippet headers()}
|
|
||||||
<span>Título</span>
|
|
||||||
<span class="hidden text-center sm:block">Duración</span>
|
|
||||||
<span></span>
|
|
||||||
{/snippet}
|
|
||||||
{#each suggestions as item, i (idFor(item))}
|
{#each suggestions as item, i (idFor(item))}
|
||||||
<TrackRow oncontextmenu={(e) => openContextMenu(e, item)}>
|
<TrackRow oncontextmenu={(e) => openContextMenu(e, item)}>
|
||||||
<TrackTitleCell
|
<TrackTitleCell
|
||||||
|
|||||||
Reference in New Issue
Block a user