// SVG text cannot ellipsize itself, so labels are measured by estimate (full-width glyphs 1em, others ~0.6em) and shortened here. export function textWidth(text: string, fontSize: number) { let width = 0 for (const char of text) width += (char.codePointAt(0) ?? 0) > 0x2e7f ? fontSize : fontSize * 0.6 return width } /** The longest start of `text` plus an ellipsis that fits `maxWidth`; "" when not even one character fits. */ export function fitText(text: string, maxWidth: number, fontSize: number) { if (textWidth(text, fontSize) <= maxWidth) return text const chars = [...text] for (let count = chars.length - 1; count > 0; count -= 1) { const candidate = `${chars.slice(0, count).join("").trimEnd()}…` if (textWidth(candidate, fontSize) <= maxWidth) return candidate } return "" }