feat: wire createFontRowSizeResolver into SampleList for pretext-backed row heights
This commit is contained in:
@@ -5,7 +5,12 @@
|
|||||||
- Provides a typography menu for font setup.
|
- Provides a typography menu for font setup.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { FontVirtualList } from '$entities/Font';
|
import {
|
||||||
|
FontVirtualList,
|
||||||
|
appliedFontsManager,
|
||||||
|
createFontRowSizeResolver,
|
||||||
|
fontStore,
|
||||||
|
} from '$entities/Font';
|
||||||
import { FontSampler } from '$features/DisplayFont';
|
import { FontSampler } from '$features/DisplayFont';
|
||||||
import {
|
import {
|
||||||
TypographyMenu,
|
TypographyMenu,
|
||||||
@@ -15,12 +20,30 @@ import { throttle } from '$shared/lib/utils';
|
|||||||
import { Skeleton } from '$shared/ui';
|
import { Skeleton } from '$shared/ui';
|
||||||
import { layoutManager } from '../../model';
|
import { layoutManager } from '../../model';
|
||||||
|
|
||||||
|
// FontSampler chrome heights — derived from Tailwind classes in FontSampler.svelte.
|
||||||
|
// Header: py-3 (12+12px padding) + ~32px content row ≈ 56px.
|
||||||
|
// Only the header is counted; the mobile footer (md:hidden) is excluded because
|
||||||
|
// on desktop, where container widths are wide and estimates matter most, it is invisible.
|
||||||
|
// Over-estimating chrome is safe (row is slightly taller than text needs, never cut off).
|
||||||
|
const SAMPLER_CHROME_HEIGHT = 56;
|
||||||
|
|
||||||
|
// p-4 = 16px per side = 32px total horizontal padding in FontSampler's content area.
|
||||||
|
// Using the smallest breakpoint (mobile) ensures contentWidth is never over-estimated:
|
||||||
|
// wider actual padding → more text wrapping → pretext height ≥ rendered height → safe.
|
||||||
|
const SAMPLER_CONTENT_PADDING_X = 32;
|
||||||
|
|
||||||
|
// Fallback row height used when the font has not loaded yet.
|
||||||
|
// Matches the previous hardcoded itemHeight={220} value to avoid regressions.
|
||||||
|
const SAMPLER_FALLBACK_HEIGHT = 220;
|
||||||
|
|
||||||
let text = $state('The quick brown fox jumps over the lazy dog...');
|
let text = $state('The quick brown fox jumps over the lazy dog...');
|
||||||
let wrapper = $state<HTMLDivElement | null>(null);
|
let wrapper = $state<HTMLDivElement | null>(null);
|
||||||
// Binds to the actual window height
|
// Binds to the actual window height
|
||||||
let innerHeight = $state(0);
|
let innerHeight = $state(0);
|
||||||
// Is the component above the middle of the viewport?
|
// Is the component above the middle of the viewport?
|
||||||
let isAboveMiddle = $state(false);
|
let isAboveMiddle = $state(false);
|
||||||
|
// Inner width of the wrapper div — updated by bind:clientWidth on mount and resize.
|
||||||
|
let containerWidth = $state(0);
|
||||||
|
|
||||||
const checkPosition = throttle(() => {
|
const checkPosition = throttle(() => {
|
||||||
if (!wrapper) return;
|
if (!wrapper) return;
|
||||||
@@ -30,6 +53,24 @@ const checkPosition = throttle(() => {
|
|||||||
|
|
||||||
isAboveMiddle = rect.top < viewportMiddle;
|
isAboveMiddle = rect.top < viewportMiddle;
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
// Resolver recreated when typography values change. The returned closure reads
|
||||||
|
// appliedFontsManager.statuses (a SvelteMap) on every call, so any font status
|
||||||
|
// change triggers a full offsets recompute in createVirtualizer — no DOM snap.
|
||||||
|
const fontRowHeight = $derived.by(() =>
|
||||||
|
createFontRowSizeResolver({
|
||||||
|
getFonts: () => fontStore.fonts,
|
||||||
|
getWeight: () => controlManager.weight,
|
||||||
|
getPreviewText: () => text,
|
||||||
|
getContainerWidth: () => containerWidth,
|
||||||
|
getFontSizePx: () => controlManager.renderedSize,
|
||||||
|
getLineHeightPx: () => controlManager.height * controlManager.renderedSize,
|
||||||
|
getStatus: key => appliedFontsManager.statuses.get(key),
|
||||||
|
contentHorizontalPadding: SAMPLER_CONTENT_PADDING_X,
|
||||||
|
chromeHeight: SAMPLER_CHROME_HEIGHT,
|
||||||
|
fallbackHeight: SAMPLER_FALLBACK_HEIGHT,
|
||||||
|
})
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#snippet skeleton()}
|
{#snippet skeleton()}
|
||||||
@@ -52,9 +93,9 @@ const checkPosition = throttle(() => {
|
|||||||
onresize={checkPosition}
|
onresize={checkPosition}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div bind:this={wrapper}>
|
<div bind:this={wrapper} bind:clientWidth={containerWidth}>
|
||||||
<FontVirtualList
|
<FontVirtualList
|
||||||
itemHeight={220}
|
itemHeight={fontRowHeight}
|
||||||
useWindowScroll={true}
|
useWindowScroll={true}
|
||||||
weight={controlManager.weight}
|
weight={controlManager.weight}
|
||||||
columns={layoutManager.columns}
|
columns={layoutManager.columns}
|
||||||
|
|||||||
Reference in New Issue
Block a user