Merges Renovate's kit 3 (PR #149) and adapter-static 4 (PR #148) bumps, plus the migration they need. The mechanical part is `sv migrate sveltekit-3`, run one task at a time and reviewed: - svelte.config.js is gone. Its options move into sveltekit() in vite.config.ts, exported as kitOptions so vitest.config.ts runs the same kit setup, including the $test-utils alias the tests import. - $lib becomes #lib through package.json "imports". There is no src/lib/index, so only the "#lib/*" entry is kept. - tsconfig extends $app/tsconfig. - Peer floors raised to kit 3's requirements: svelte ^5.57.1, vite ^8.0.12, svelte-check ^4.7.5. By hand, from the codemod's list of non-automated tasks: - goto's replaceState option is now replace; keepFocus becomes reset: false. For the search typeahead, reset: false also stops the scroll-to-top, which is wanted while typing. - The test setup mocks drop pushState/replaceState and $app/paths base/assets, which kit 3 removed, and mock refreshAll in place of invalidateAll. - The other flagged files only read page.url or goto internal routes, so they needed no change. TypeScript goes to ^6, not the ^7 Renovate offers: kit 3 declares typescript ^6 as a peer and svelte-check 4.7 accepts ^5 || ^6. Move to 7 once both accept it. With Tailwind 4 and kit 3 in, `npm audit` on the whole tree reports 0, so the web lane now audits every dependency rather than only what ships to browsers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.2 KiB
Svelte
67 lines
2.2 KiB
Svelte
<script lang="ts">
|
|
import { FALLBACK_COVER } from '#lib/media/covers.js';
|
|
import { Disc3 } from 'lucide-svelte';
|
|
|
|
// Shared cover-artwork renderer. The web counterpart of Android's
|
|
// CoverTile/ServerImage: one place that owns the loading placeholder and
|
|
// the error fallback so no card sits blank while art loads or 404s (the
|
|
// "You might like" row surfaces unplayed items whose art is often not yet
|
|
// backfilled). Replaces the three hand-rolled <img> tags that previously
|
|
// disagreed on fallback handling.
|
|
let {
|
|
src,
|
|
alt = '',
|
|
shape = 'square',
|
|
fallback = 'image',
|
|
class: klass = ''
|
|
}: {
|
|
src: string | undefined;
|
|
alt?: string;
|
|
// 'round' clips to a circle (artist avatars); 'square' leaves clipping
|
|
// to the parent so existing rounded-md / rounded corners still apply.
|
|
shape?: 'square' | 'round';
|
|
// 'artist' degrades to a Disc3 icon; 'image' to the static placeholder
|
|
// cover. A null/empty src is treated the same as a failed load.
|
|
fallback?: 'image' | 'artist';
|
|
class?: string;
|
|
} = $props();
|
|
|
|
// Per-image lifecycle. Reset when src changes so a reused card (virtualized
|
|
// list, client-side nav) never keeps a stale 'loaded'/'failed'.
|
|
let loaded = $state(false);
|
|
let failed = $state(false);
|
|
$effect(() => {
|
|
void src;
|
|
loaded = false;
|
|
failed = false;
|
|
});
|
|
|
|
const useIcon = $derived(fallback === 'artist' && (failed || !src));
|
|
// On failure for the image fallback, swap to the static placeholder asset.
|
|
// src doesn't change on the second error, so there's no reload loop.
|
|
const imgSrc = $derived(failed ? FALLBACK_COVER : src);
|
|
</script>
|
|
|
|
<div
|
|
class="relative h-full w-full overflow-hidden bg-surface-hover {shape === 'round'
|
|
? 'rounded-full'
|
|
: ''}"
|
|
>
|
|
{#if useIcon}
|
|
<div class="flex h-full w-full items-center justify-center">
|
|
<Disc3 strokeWidth={1} class="h-4/5 w-4/5 text-text-muted" />
|
|
</div>
|
|
{:else if imgSrc}
|
|
<img
|
|
src={imgSrc}
|
|
{alt}
|
|
class="h-full w-full object-cover transition-opacity duration-200 {loaded
|
|
? 'opacity-100'
|
|
: 'opacity-0'} {klass}"
|
|
loading="lazy"
|
|
onload={() => (loaded = true)}
|
|
onerror={() => (failed = true)}
|
|
/>
|
|
{/if}
|
|
</div>
|