Add Ledger and Band template families with decor primitives

Crimson Grid, Tangerine Ledger, Slate Band and Teal Swoosh are rebuilt from
the Canva PDFs with grid and band tables that survive page breaks,
full-bleed fixed bands, pennant tabs, gradient corner swooshes with
keep-outs, Carbon icon circles, and the user's logo in the measured slot
(knockout or white chip on the dark Slate band). Adds static Poppins
500-700 and Inter fonts. Thumbnails regenerated for all eight templates;
the item-count sweeps run in their own test file.
This commit is contained in:
2026-10-04 08:34:18 +05:30
parent 04d92aa149
commit 06976df55c
57 changed files with 4078 additions and 217 deletions
+15 -4
View File
@@ -34,6 +34,12 @@ export interface PageChromeProps {
bandTop?: number;
/** Every-page decor in page space. */
decor?: DecorItem[];
/** Footer row offset from the page bottom; default: the bottom margin (padding minus the footer reserve). */
bottom?: number;
/** Colour of the continuation band's text; default `color`. */
bandColor?: string;
/** Page-space left edge and width of the continuation band; default: the frame's content box. */
bandBox?: { left: number; width: number };
}
/**
@@ -76,6 +82,9 @@ export function PageChrome({
band,
bandTop,
decor = [],
bottom,
bandBox,
bandColor,
}: PageChromeProps) {
const { pad } = frame;
const need = chromeHeight(role);
@@ -84,7 +93,9 @@ export function PageChrome({
throw new PlanError(`footerReserve ${frame.footerReserve} pt is under the ${need} pt a "${roleToken(role).size} pt" footer line needs`, "chrome-reserve");
}
const labelWidth = Math.ceil(measureToken(getMeasurer(), role, "Page 99 of 99")) + 2;
const marginBottom = pad.bottom - frame.footerReserve;
const marginBottom = bottom ?? pad.bottom - frame.footerReserve;
const bandLeftEdge = bandBox?.left ?? pad.left;
const bandWidth = bandBox?.width ?? frame.contentWidth;
const bandRightWidth = band?.right !== undefined ? Math.ceil(measureToken(getMeasurer(), role, band.right)) + 2 : 0;
const top = bandTop ?? Math.max(0, pad.top - frame.continuationReserve);
@@ -103,17 +114,17 @@ export function PageChrome({
{band && (band.left !== undefined || band.right !== undefined) && (
<View
style={{ position: "absolute", top, left: pad.left, width: frame.contentWidth, flexDirection: "row", justifyContent: "flex-end" }}
style={{ position: "absolute", top, left: bandLeftEdge, width: bandWidth, flexDirection: "row", justifyContent: "flex-end" }}
{...pdfFlags({ fixed: true })}
>
{band.left !== undefined && (
<RenderTxt id={BAND_ID} role={role} color={color} grow render={({ pageNumber }) => (pageNumber > 1 ? (band.left ?? "") : "")} />
<RenderTxt id={BAND_ID} role={role} color={bandColor ?? color} grow render={({ pageNumber }) => (pageNumber > 1 ? (band.left ?? "") : "")} />
)}
{band.right !== undefined && (
<RenderTxt
id={BAND_ID}
role={role}
color={color}
color={bandColor ?? color}
align="right"
width={bandRightWidth}
render={({ pageNumber }) => (pageNumber > 1 ? (band.right ?? "") : "")}