Categorize components/ui into primitives, overlay, media, forms and layout
Splits the flat 38-component ui/ folder into primitives/ (generic controls), overlay/ (menus/modals), media/ (music-domain display components), forms/ (composite entity forms) and layout/ (page scaffolding), and updates every import path accordingly.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from 'svelte';
|
||||
import Disc3 from '@lucide/svelte/icons/disc-3';
|
||||
import CoverForm from './CoverForm.svelte';
|
||||
import Field from '../primitives/Field.svelte';
|
||||
import Input from '../primitives/Input.svelte';
|
||||
import Textarea from '../primitives/Textarea.svelte';
|
||||
import { ALBUM_EARLIEST_YEAR } from '$lib/config';
|
||||
|
||||
interface Props {
|
||||
action: string;
|
||||
initialTitle?: string;
|
||||
initialDescription?: string;
|
||||
initialReleaseYear?: number;
|
||||
titlePlaceholder?: string;
|
||||
coverFallbackUrl?: string;
|
||||
requireCover?: boolean;
|
||||
formMessage?: string;
|
||||
submitLabel: string;
|
||||
submittingLabel: string;
|
||||
onCancel: () => void;
|
||||
onSuccess?: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
action,
|
||||
initialTitle = '',
|
||||
initialDescription = '',
|
||||
initialReleaseYear,
|
||||
titlePlaceholder = '',
|
||||
coverFallbackUrl,
|
||||
requireCover = false,
|
||||
formMessage,
|
||||
submitLabel,
|
||||
submittingLabel,
|
||||
onCancel,
|
||||
onSuccess
|
||||
}: Props = $props();
|
||||
|
||||
let title = $state(untrack(() => initialTitle));
|
||||
let description = $state(untrack(() => initialDescription));
|
||||
let releaseYear = $state(untrack(() => (initialReleaseYear ? String(initialReleaseYear) : '')));
|
||||
|
||||
const latestYear = new Date().getFullYear() + 1;
|
||||
</script>
|
||||
|
||||
<CoverForm
|
||||
{action}
|
||||
{coverFallbackUrl}
|
||||
{requireCover}
|
||||
coverIcon={Disc3}
|
||||
{formMessage}
|
||||
{submitLabel}
|
||||
{submittingLabel}
|
||||
canSubmit={title.trim() !== ''}
|
||||
{onCancel}
|
||||
{onSuccess}
|
||||
>
|
||||
{#snippet fields()}
|
||||
<Field label="Título" for="album-title">
|
||||
<Input
|
||||
id="album-title"
|
||||
name="title"
|
||||
maxlength={200}
|
||||
required
|
||||
bind:value={title}
|
||||
placeholder={titlePlaceholder}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field label="Año de publicación" for="album-year">
|
||||
<Input
|
||||
id="album-year"
|
||||
name="releaseYear"
|
||||
type="number"
|
||||
min={ALBUM_EARLIEST_YEAR}
|
||||
max={latestYear}
|
||||
bind:value={releaseYear}
|
||||
placeholder={String(new Date().getFullYear())}
|
||||
/>
|
||||
</Field>
|
||||
{/snippet}
|
||||
{#snippet extra()}
|
||||
<Field label="Descripción" for="album-description">
|
||||
<Textarea
|
||||
id="album-description"
|
||||
name="description"
|
||||
maxlength={256}
|
||||
bind:value={description}
|
||||
placeholder="¿De qué va este álbum?"
|
||||
/>
|
||||
</Field>
|
||||
{/snippet}
|
||||
</CoverForm>
|
||||
Reference in New Issue
Block a user