<!--
    Component: FontApplicator
    Loads fonts from fontshare with link tag
    - Loads font only if it's not already applied
    - Reacts to font load status to show/hide content
    - Adds smooth transition when font appears
-->
<script lang="ts">
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import type { Snippet } from 'svelte';
import { prefersReducedMotion } from 'svelte/motion';
import {
    DEFAULT_FONT_WEIGHT,
    type UnifiedFont,
    appliedFontsManager,
} from '../../model';

interface Props {
    /**
     * Font to apply
     */
    font: UnifiedFont;
    /**
     * Font weight
     * @default 400
     */
    weight?: number;
    /**
     * CSS classes
     */
    className?: string;
    /**
     * Content snippet
     */
    children?: Snippet;
}

let {
    font,
    weight = DEFAULT_FONT_WEIGHT,
    className,
    children,
}: Props = $props();

const status = $derived(
    appliedFontsManager.getFontStatus(
        font.id,
        weight,
        font.features?.isVariable,
    ),
);

// The "Show" condition: Font is loaded OR it errored out OR it's a noTouch preview (like in search)
const shouldReveal = $derived(status === 'loaded' || status === 'error');

const transitionClasses = $derived(
    prefersReducedMotion.current
        ? 'transition-none' // Disable CSS transitions if motion is reduced
        : 'transition-all duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]',
);
</script>

<div
    style:font-family={shouldReveal
    ? `'${font.name}'`
    : 'system-ui, -apple-system, sans-serif'}
    class={cn(
        transitionClasses,
        // If reduced motion is on, we skip the transform/blur entirely
        !shouldReveal
            && !prefersReducedMotion.current
            && 'opacity-50 scale-[0.95] blur-sm',
        !shouldReveal && prefersReducedMotion.current && 'opacity-0', // Still hide until font is ready, but no movement
        shouldReveal && 'opacity-100 scale-100 blur-0',
        className,
    )}
>
    {@render children?.()}
</div>
