Txt always sets an absolute line height; RenderTxt never does. Row pins every cell and stacks when the fill column would be too narrow. IdText and FitText shrink then chunk or truncate. The fontkit measurer matches react-pdf text widths exactly. A TypeScript-AST lint test enforces the layout rules (no lineHeight outside Txt, no non-literal fixed/wrap/minPresenceAhead, flexGrow needs flexBasis, no stray absolute positioning).
26 lines
1.0 KiB
TypeScript
26 lines
1.0 KiB
TypeScript
import { roleToken } from "../fonts/roles";
|
|
import { Txt, type TxtProps } from "./Txt";
|
|
|
|
export interface TrackedProps extends Omit<TxtProps, "align"> {
|
|
align: "right" | "center";
|
|
}
|
|
|
|
/**
|
|
* textkit adds letterSpacing after every glyph, the last one included, so right- and centre-aligned
|
|
* tracked text sits one tracking step too far left. This cancels it with a negative margin: the full
|
|
* step on the right edge for `right`, half a step each side for `center` (shifting the box right by
|
|
* half a step).
|
|
*
|
|
* HAZARD: the Text box now overhangs its parent by up to one tracking step. Overflow and safe-zone
|
|
* audits must measure ink (glyph extents), not boxes, or they flag it.
|
|
*/
|
|
export function Tracked({ align, style, ...rest }: TrackedProps) {
|
|
const token = roleToken(rest.role);
|
|
const step = (token.tracking ?? 0) * token.size;
|
|
const margin =
|
|
align === "right"
|
|
? { marginRight: -step }
|
|
: { marginLeft: step / 2, marginRight: -step / 2 };
|
|
return <Txt {...rest} align={align} style={{ ...margin, ...style }} />;
|
|
}
|