feat(FontApplicator): switch from props to derived state from comparisonStore, apply the fonts

This commit is contained in:
Ilia Mashkov
2026-02-10 18:09:13 +03:00
parent 4734b1120a
commit 0a52bd6f6b

View File

@@ -6,30 +6,24 @@
- Adds smooth transition when font appears - Adds smooth transition when font appears
--> -->
<script lang="ts"> <script lang="ts">
import { getFontUrl } from '$entities/Font/lib';
import { cn } from '$shared/shadcn/utils/shadcn-utils'; import { cn } from '$shared/shadcn/utils/shadcn-utils';
import type { Snippet } from 'svelte'; import type { Snippet } from 'svelte';
import { prefersReducedMotion } from 'svelte/motion'; import { prefersReducedMotion } from 'svelte/motion';
import { appliedFontsManager } from '../../model'; import {
type UnifiedFont,
appliedFontsManager,
} from '../../model';
interface Props { interface Props {
/** /**
* Font name to set * Applied font
*/ */
name: string; font: UnifiedFont;
/**
* Font id to load
*/
id: string;
/** */
url: string;
/** /**
* Font weight * Font weight
*/ */
weight?: number; weight?: number;
/**
* Variable font flag
*/
isVariable?: boolean;
/** /**
* Additional classes * Additional classes
*/ */
@@ -40,12 +34,12 @@ interface Props {
children?: Snippet; children?: Snippet;
} }
let { name, id, url, weight = 400, isVariable = false, className, children }: Props = $props(); let { font, weight = 400, className, children }: Props = $props();
let element: Element; let element: Element;
// Track if the user has actually scrolled this into view // Track if the user has actually scrolled this into view
let hasEnteredViewport = $state(false); let hasEnteredViewport = $state(false);
const status = $derived(appliedFontsManager.getFontStatus(id, weight, isVariable)); const status = $derived(appliedFontsManager.getFontStatus(font.id, weight, font.features.isVariable));
$effect(() => { $effect(() => {
if (status === 'loaded' || status === 'error') { if (status === 'loaded' || status === 'error') {
@@ -56,17 +50,19 @@ $effect(() => {
const observer = new IntersectionObserver(entries => { const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) { if (entries[0].isIntersecting) {
hasEnteredViewport = true; hasEnteredViewport = true;
const url = getFontUrl(font, weight);
// Touch ensures it's in the queue. // Touch ensures it's in the queue.
// It's safe to call this even if VirtualList called it // It's safe to call this even if VirtualList called it
// (Manager dedupes based on key) // (Manager dedupes based on key)
if (url) {
appliedFontsManager.touch([{ appliedFontsManager.touch([{
id, id: font.id,
weight, weight,
name, name: font.name,
url, url,
isVariable, isVariable: font.features.isVariable,
}]); }]);
}
observer.unobserve(element); observer.unobserve(element);
} }
@@ -88,7 +84,7 @@ const transitionClasses = $derived(
<div <div
bind:this={element} bind:this={element}
style:font-family={shouldReveal ? `'${name}'` : 'system-ui, -apple-system, sans-serif'} style:font-family={shouldReveal ? `'${font.name}'` : 'system-ui, -apple-system, sans-serif'}
class={cn( class={cn(
transitionClasses, transitionClasses,
// If reduced motion is on, we skip the transform/blur entirely // If reduced motion is on, we skip the transform/blur entirely