Swap the eagerly-constructed fontCatalogStore singleton for a lazy
getFontCatalog() accessor (plus __resetFontCatalog for tests), so the
InfiniteQueryObserver is created on first use rather than at module load.
Update the model barrels and all consumers (FontVirtualList, SampleList,
SampleListSection) to the accessor.
Also extract createFontLoadRequestConfig from FontVirtualList: it resolves a
font's URL for a weight and returns a 0-or-1 element array, letting callers
flatMap over a list to build load requests and drop unresolvable fonts in one
pass.
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.
Re-exporting the store singletons (fontCatalogStore, fontLifecycleManager,
FontsByIdsStore) through entities/Font/index.ts meant every consumer of the
barrel eager-instantiated stores and pulled @tanstack/query-core — in dev,
test, and as retained code. Drop the store re-export from the top barrel;
keep the pure surface (types, constants, domain, lib, ui) there for
convenience. Consumers that need stores import $entities/Font/model.
Aligns with the BaseQueryStore carve-out: barrel by default, segment path
when it would drag a heavy or side-effectful dependency.
Breadcrumb is not a business aggregate — it is a scroll-tracking navigation
capability (NavigationWrapper registers page sections into a store), so it
belongs in the features layer, not entities. Move the whole slice and
repoint its three widget consumers. entities/ now holds only Font, a true
aggregate.
Replace inline class clusters with the design-system utilities and
tokens established in the prior two commits. No behavior changes
intended beyond two real bug fixes.
Bug fixes:
- SampleList.svelte: 'border-border-subtle bg-background-40' was a
silent no-op (both classes mis-spelled). Now 'border-subtle
bg-background/40' applies as intended.
- FontList.svelte: 'h-[44px]' → 'h-11' (44px = 2.75rem = spacing-11,
no need for arbitrary value).
Sweeps:
- TypographyMenu: popover + floating bar now use surface-popover /
surface-floating + shadow-popover.
- FontList + FilterGroup: tertiary list buttons use the new
Button layout="block-list-row" variant; skeleton fills use
the skeleton-fill utility.
- Footer / BreadcrumbHeader: surface-floating absorbs the
bg-surface/blur/border cluster. Footer bumped to z-20 with a
comment explaining the stacking against SidebarContainer (z-40/50).
- FontSampler: surface-card + hover shadow-stamp-card token.
- SliderArea: surface-canvas, flex-center, shadow-floating-panel
tokens (light + dark variants).
- Sidebar / Header / ButtonGroup / Layout / SidebarContainer:
bg-surface dark:bg-dark-bg → surface-canvas (8 sites);
SidebarContainer mobile panel uses shadow-overlay.
- Loader / Thumb: flex items-center justify-center → flex-center;
Thumb durations → duration-fast.
- ComboControl: trigger uses surface-card-elevated when open,
popover uses surface-card-elevated, label cluster → text-label-mono,
flex-center for the trigger interior.
- Slider: shadow-sm → shadow-rest, duration-150 → duration-fast.
- text-secondary → text-subtle across Input, Slider, ComboControl
(matches the rename in the styles commit).
- Link: reverted earlier surface-floating attempt — Link's original
bg-surface/80 backdrop-blur pattern was thinner than surface-floating
(no border, smaller blur), and the Footer was overlaying its own
border-subtle on top, fighting the utility. Kept the original style.
- Use existing MULTIPLIER_S/M/L from \$entities/Font in SliderArea instead
of inlining the 0.5/0.75/1 literals (constants already existed but were
duplicated at the call site).
- Centralize API base URL in \$shared/api/endpoints.ts (was duplicated
between proxyFonts and FilterAndSortFonts filters api).
- Promote every 'glyphdiff:...' localStorage key to a named module-level
STORAGE_KEY constant. Test files now import the source constant rather
than redeclaring it (eliminates silent-typo divergence risk).
Both names were vague or overloaded:
- fontStore / FontStore -> fontCatalogStore / FontCatalogStore
Three font-related stores live in this slice; the new name names the
paginated catalog specifically.
- appliedFontsManager / AppliedFontsManager -> fontLifecycleManager /
FontLifecycleManager
"Applied" collided with the filter-side appliedFilterStore (different
meaning). The class actually orchestrates a load-use-evict lifecycle
with FontBufferCache + FontEvictionPolicy + FontLoadQueue
collaborators, so "Manager" is justified. Companion types file moved
alongside (appliedFonts.ts -> fontLifecycle.ts).
Directories, file basenames, factory (createFontStore ->
createFontCatalogStore), and the AppliedFontsManagerDeps interface all
renamed. All consumers (ComparisonView, SampleList, FontList,
FontApplicator, FontVirtualList, FilterAndSortFonts bindings,
createFontRowSizeResolver, mocks) updated.
Structural:
- Merge factory + singleton from lib/settingsManager and model/state into
one model/store/typographySettingsStore/ slice
- Drop now-empty lib/ and model/state/ directories
Semantic:
- Rename feature SetupFont -> AdjustTypography (the feature owns
continuous typography adjustment, not one-time font setup)
- Drop "Manager" from TypographySettingsManager -> TypographySettingsStore
(class + factory); singleton typographySettingsStore unchanged
All consumers (Character, Line, SampleList, SliderArea, FontSampler,
comparisonStore) updated. Public barrel signature changed: now exports
createTypographySettingsStore and type TypographySettingsStore.