refactor(font): inject font-load status as a prop, decoupling UI from the store

FontApplicator and FontSampler no longer read fontLifecycleManager. They take a
`status` prop (FontLoadStatus | undefined) supplied by the composing widget;
FontList and SampleList resolve status once per visible row and pass it down.

FSD+ dependency inversion: the entity/feature UI depends on a value, not the
lifecycle store. Removes FontApplicator's value-import of the store (one step
toward an inert ./ui barrel) and drops the duplicate getFontStatus read per row
in FontList. FontSampler is now status-decoupled and trivially relocatable to
entities/Font/ui.
This commit is contained in:
Ilia Mashkov
2026-06-01 12:06:30 +03:00
parent 28a8e49915
commit fcd61be4fa
6 changed files with 52 additions and 46 deletions
@@ -75,21 +75,6 @@ function handleSelect(font: UnifiedFont) {
comparisonStore.fontB = font;
}
}
/**
* Returns true once the font file is loaded (or errored) and safe to render.
* Called inside the template — Svelte 5 tracks the $state reads inside
* fontLifecycleManager.getFontStatus(), so each row re-renders reactively
* when its file arrives.
*/
function isFontReady(font: UnifiedFont): boolean {
const status = fontLifecycleManager.getFontStatus(
font.id,
DEFAULT_FONT_WEIGHT,
font.features?.isVariable,
);
return status === 'loaded' || status === 'error';
}
</script>
<div class="flex-1 min-h-0 h-full">
@@ -129,8 +114,15 @@ function isFontReady(font: UnifiedFont): boolean {
{/snippet}
{#snippet children({ item: font, index })}
<!--
Read load status once per row. Svelte 5 tracks the $state reads inside
fontLifecycleManager.getFontStatus(), so the row re-renders reactively
when its file arrives — and the same value drives both the skeleton gate
and FontApplicator below.
-->
{@const status = fontLifecycleManager.getFontStatus(font.id, DEFAULT_FONT_WEIGHT, font.features?.isVariable)}
<div class="relative h-11 w-full">
{#if !isFontReady(font)}
{#if status !== 'loaded' && status !== 'error'}
<div
class="absolute inset-0 px-3 md:px-4 flex items-center justify-between border border-transparent"
transition:fade={{ duration: 300 }}
@@ -155,7 +147,7 @@ function isFontReady(font: UnifiedFont): boolean {
class="h-full"
iconPosition="right"
>
<FontApplicator {font}>
<FontApplicator {font} {status}>
{font.name}
</FontApplicator>