From fcd61be4faaa1005d0aeee5b4830d26362bc9f54 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Mon, 1 Jun 2026 12:06:30 +0300 Subject: [PATCH] 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. --- .../FontApplicator.stories.svelte | 18 ++++++------ .../ui/FontApplicator/FontApplicator.svelte | 28 ++++++++----------- .../ui/FontSampler/FontSampler.stories.svelte | 7 +++++ .../ui/FontSampler/FontSampler.svelte | 11 ++++++-- .../ui/FontList/FontList.svelte | 26 ++++++----------- .../ui/SampleList/SampleList.svelte | 8 +++++- 6 files changed, 52 insertions(+), 46 deletions(-) diff --git a/src/entities/Font/ui/FontApplicator/FontApplicator.stories.svelte b/src/entities/Font/ui/FontApplicator/FontApplicator.stories.svelte index c2f412a..92bb034 100644 --- a/src/entities/Font/ui/FontApplicator/FontApplicator.stories.svelte +++ b/src/entities/Font/ui/FontApplicator/FontApplicator.stories.svelte @@ -10,14 +10,14 @@ const { Story } = defineMeta({ docs: { description: { component: - 'Loads a font and applies it to children. Shows blur/scale loading state until font is ready, then reveals with a smooth transition.', + 'Applies a font to its children based on the supplied load `status`. Renders the skeleton (or system font) until status is `loaded`/`error`, then reveals the font. The status is provided by the composing widget — the component does not read the lifecycle store itself.', }, story: { inline: false }, }, layout: 'centered', }, argTypes: { - weight: { control: 'number' }, + status: { control: 'select', options: ['loading', 'loaded', 'error'] }, }, }); @@ -39,11 +39,11 @@ const fontArialBold = mockUnifiedFont({ id: 'arial-bold', name: 'Arial' }); docs: { description: { story: - 'Font that has never been loaded by fontLifecycleManager. The component renders in its pending state: blurred, scaled down, and semi-transparent.', + 'Status is `loading`: the font file has not resolved yet, so children render in the skeleton (or system font) fallback rather than the target font.', }, }, }} - args={{ font: fontUnknown, weight: 400 }} + args={{ font: fontUnknown, status: 'loading' }} > {#snippet template(args: ComponentProps)} @@ -58,11 +58,11 @@ const fontArialBold = mockUnifiedFont({ id: 'arial-bold', name: 'Arial' }); docs: { description: { story: - 'Uses Arial, a system font available in all browsers. Because fontLifecycleManager has not loaded it via FontFace, the manager status may remain pending — meaning the blur/scale state may still show. In a real app the manager would load the font and transition to the revealed state.', + 'Status is `loaded`: the component reveals the font, applying it to its children (Arial here, available in all browsers).', }, }, }} - args={{ font: fontArial, weight: 400 }} + args={{ font: fontArial, status: 'loaded' }} > {#snippet template(args: ComponentProps)} @@ -72,16 +72,16 @@ const fontArialBold = mockUnifiedFont({ id: 'arial-bold', name: 'Arial' }); {#snippet template(args: ComponentProps)} diff --git a/src/entities/Font/ui/FontApplicator/FontApplicator.svelte b/src/entities/Font/ui/FontApplicator/FontApplicator.svelte index ae1e97c..8ead202 100644 --- a/src/entities/Font/ui/FontApplicator/FontApplicator.svelte +++ b/src/entities/Font/ui/FontApplicator/FontApplicator.svelte @@ -6,11 +6,10 @@ diff --git a/src/features/DisplayFont/ui/FontSampler/FontSampler.stories.svelte b/src/features/DisplayFont/ui/FontSampler/FontSampler.stories.svelte index ffc2a3f..0a5dadb 100644 --- a/src/features/DisplayFont/ui/FontSampler/FontSampler.stories.svelte +++ b/src/features/DisplayFont/ui/FontSampler/FontSampler.stories.svelte @@ -21,6 +21,11 @@ const { Story } = defineMeta({ control: 'object', description: 'Font information object', }, + status: { + control: 'select', + options: ['loading', 'loaded', 'error'], + description: 'Font-load status, supplied by the composing widget and forwarded to FontApplicator', + }, text: { control: 'text', description: 'Editable sample text (two-way bindable)', @@ -85,6 +90,7 @@ const mockGeorgia: UnifiedFont = { name="Default" args={{ font: mockArial, + status: 'loaded', text: 'The quick brown fox jumps over the lazy dog', index: 0, }} @@ -101,6 +107,7 @@ const mockGeorgia: UnifiedFont = { name="Long Text" args={{ font: mockGeorgia, + status: 'loaded', text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.', index: 1, diff --git a/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte b/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte index 614301b..b214ea1 100644 --- a/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte +++ b/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte @@ -6,6 +6,7 @@
@@ -129,8 +114,15 @@ function isFontReady(font: UnifiedFont): boolean { {/snippet} {#snippet children({ item: font, index })} + + {@const status = fontLifecycleManager.getFontStatus(font.id, DEFAULT_FONT_WEIGHT, font.features?.isVariable)}
- {#if !isFontReady(font)} + {#if status !== 'loaded' && status !== 'error'}
- + {font.name} diff --git a/src/widgets/SampleList/ui/SampleList/SampleList.svelte b/src/widgets/SampleList/ui/SampleList/SampleList.svelte index 22611e5..26f3347 100644 --- a/src/widgets/SampleList/ui/SampleList/SampleList.svelte +++ b/src/widgets/SampleList/ui/SampleList/SampleList.svelte @@ -113,7 +113,13 @@ const fontRowHeight = $derived.by(() => {skeleton} > {#snippet children({ item: font, index })} - + + {@const status = fontLifecycleManager.getFontStatus(font.id, typographySettingsStore.weight, font.features?.isVariable)} + {/snippet}