import { getMeasurer, measureToken } from "../engine/measure"; import { resolveFace, roleToken } from "../fonts/roles"; import { useAvailableWidth } from "./AvailableWidth"; import { IdText } from "./IdText"; import { Txt, type TxtProps } from "./Txt"; export interface SafeTxtProps extends Omit { children: string; /** Width of the box; defaults to the available width of the enclosing cell. */ width?: number; } /** * Free text (addresses, names, notes) that cannot overflow: normal text wraps at spaces in a box of the * cell's width; a value with a single token wider than the cell (a long URL or an unbroken string) goes * through IdText, which shrinks it or splits it at "@ . / - _". textkit never breaks inside a word, * so without this such a token would run out of its box. */ export function SafeTxt({ children, width, align, ...rest }: SafeTxtProps) { const avail = useAvailableWidth(); const w = width ?? avail; const token = roleToken(rest.role); const m = getMeasurer(); const family = resolveFace(token.face, rest.faceOverrides); const widest = Math.max( 0, ...children.split(" ").map((word) => measureToken(m, token, word, { weight: rest.weight, italic: rest.italic, family })), ); if (widest > w + 1e-6) { return ( {children} ); } return ( {children} ); }