diff --git a/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts b/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts index 06b75b8..fc88cbc 100644 --- a/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts +++ b/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts @@ -15,16 +15,22 @@ export interface LineData { * @param fontB - The second font definition * @returns Object with reactive state (lines, containerWidth) and methods (breakIntoLines, getCharState) */ -export function createCharacterComparison( +export function createCharacterComparison< + T extends { name: string; id: string } | undefined = undefined, +>( text: () => string, - fontA: () => { name: string; id: string }, - fontB: () => { name: string; id: string }, + fontA: () => T, + fontB: () => T, weight: () => number, size: () => number, ) { let lines = $state([]); let containerWidth = $state(0); + function fontDefined(font: T | undefined): font is T { + return font !== undefined; + } + /** * Measures text width using a canvas context. * @param ctx - Canvas rendering context @@ -36,10 +42,11 @@ export function createCharacterComparison( function measureText( ctx: CanvasRenderingContext2D, text: string, - fontFamily: string, fontSize: number, fontWeight: number, + fontFamily?: string, ): number { + if (!fontFamily) return 0; ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`; return ctx.measureText(text).width; } @@ -73,7 +80,7 @@ export function createCharacterComparison( container: HTMLElement | undefined, measureCanvas: HTMLCanvasElement | undefined, ) { - if (!container || !measureCanvas) return; + if (!container || !measureCanvas || !fontA() || !fontB()) return; const rect = container.getBoundingClientRect(); containerWidth = rect.width; @@ -92,22 +99,24 @@ export function createCharacterComparison( let currentLineWords: string[] = []; function pushLine(words: string[]) { - if (words.length === 0) return; + if (words.length === 0 || !fontDefined(fontA()) || !fontDefined(fontB())) { + return; + } const lineText = words.join(' '); // Measure both fonts at the CURRENT weight const widthA = measureText( ctx!, lineText, - fontA().name, Math.min(fontSize, controlledFontSize), currentWeight, + fontA()?.name, ); const widthB = measureText( ctx!, lineText, - fontB().name, Math.min(fontSize, controlledFontSize), currentWeight, + fontB()?.name, ); const maxWidth = Math.max(widthA, widthB); newLines.push({ text: lineText, width: maxWidth }); @@ -121,16 +130,16 @@ export function createCharacterComparison( const widthA = measureText( ctx, testLine, - fontA().name, Math.min(fontSize, controlledFontSize), currentWeight, + fontA()?.name, ); const widthB = measureText( ctx, testLine, - fontB().name, Math.min(fontSize, controlledFontSize), currentWeight, + fontB()?.name, ); const maxWidth = Math.max(widthA, widthB); const isContainerOverflown = maxWidth > availableWidth; @@ -155,16 +164,16 @@ export function createCharacterComparison( const wA = measureText( ctx, testFragment, - fontA().name, fontSize, currentWeight, + fontA()?.name, ); const wB = measureText( ctx, testFragment, - fontB().name, fontSize, currentWeight, + fontB()?.name, ); if (Math.max(wA, wB) <= availableWidth) {