- new workspace package packages/chart (shadcn/ui Chart + Recharts, HM Theme tokens), examples entry with sample data - Storybook Chart group (src/chart), consumer example (examples/chart), build:chart / build:chart-example scripts - README rewritten as the AI usage guide (install, CSS wiring, chart selection, data rules, verification) - docs: package count/list, Submodule guide (chart workspace, React dedupe), shared AI_GUIDE row, MAINTAINING, story inventory
19 lines
816 B
TypeScript
19 lines
816 B
TypeScript
// 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 ""
|
|
}
|