Add typography roles, text primitives, fontkit measurer and layout lint
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).
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { Text } from "@react-pdf/renderer";
|
||||
import { FILL, pinned } from "../engine/columns";
|
||||
import { roleToken, type RoleName, type TypeToken } from "../fonts/roles";
|
||||
import { pdfFlags, type PdfFlagsInput } from "./pdfProps";
|
||||
import { assertNoLineHeight, baseTextStyle, type TxtStyleProps } from "./Txt";
|
||||
|
||||
export interface RenderTxtProps extends TxtStyleProps, PdfFlagsInput {
|
||||
/** Receives { pageNumber, totalPages, subPageNumber, ... } from react-pdf. */
|
||||
render: (info: { pageNumber: number; totalPages: number; subPageNumber: number; subPageTotalPages: number }) => string;
|
||||
role: RoleName | TypeToken;
|
||||
width?: number;
|
||||
grow?: boolean;
|
||||
style?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Text drawn from a render prop (page numbers, continuation band). It sets NO lineHeight, and no
|
||||
* ancestor may set one either: react-pdf multiplies a render-prop lineHeight again on every relayout
|
||||
* ('10pt' ends up as 5120 and nothing draws). The box is auto-height; reserve its space from font
|
||||
* metrics, never a fixed height. No maxLines: a clamped render-prop Text draws nothing.
|
||||
* `totalPages` is undefined on the first layout pass, so the render function must cope with that.
|
||||
*/
|
||||
export function RenderTxt({ role, render, color, align, weight, italic, width, grow, style, faceOverrides, fixed, wrap, minPresenceAhead }: RenderTxtProps) {
|
||||
const token = roleToken(role);
|
||||
assertNoLineHeight(style, "RenderTxt");
|
||||
const merged = {
|
||||
...baseTextStyle(token, { color, align, weight, italic, faceOverrides }),
|
||||
...(width !== undefined ? pinned(width) : {}),
|
||||
...(grow ? FILL : {}),
|
||||
...style,
|
||||
};
|
||||
return <Text style={merged as never} render={render as never} {...pdfFlags({ fixed, wrap, minPresenceAhead })} />;
|
||||
}
|
||||
Reference in New Issue
Block a user