Linea (the vendor's original format.pdf design), Monogram and Serenity are rebuilt from the Canva PDFs as one parametric family on the engine, with the user's logo in the measured slot, a home for every GST field and A4/Letter support. Adds static Montserrat, Open Sans and Poppins fonts and a generated Ms Madi outline for Serenity's vertical word. Text-only logo placeholders (Monolith, Tangerine) use a doc-derived allowance box. A Carbon TemplatePicker with committed thumbnails opens from the page setup controls.
94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
import { defineRoles } from "../../fonts/roles";
|
|
import { scriptWordBounds, scriptWordDecor } from "../../decor/ScriptWord";
|
|
import { FOOTER_RESERVE } from "./constants";
|
|
import { catalogEntry } from "../catalog";
|
|
import type { TemplateDefinition } from "../contract";
|
|
import { slotFor } from "../slots.optin";
|
|
import { NeutralLayoutFor } from "./layoutFor";
|
|
import { MONOGRAM_ROLES } from "./monogram";
|
|
import type { NeutralRoles, NeutralVariant } from "./variant";
|
|
|
|
const INK = "#3D3B3A";
|
|
/** The paper colour measured from Canva's texture (its average); the texture itself is stock and is not bundled. */
|
|
const PAPER = "#ECE8E1";
|
|
|
|
/** Serenity shares Monogram's Open Sans type system (docs/templates/06-serenity.md); its own object so it can drift. */
|
|
export const SERENITY_ROLES = defineRoles({
|
|
...MONOGRAM_ROLES,
|
|
} satisfies NeutralRoles);
|
|
|
|
/** Letter keeps the band's top and takes this share of the page-height deficit off its position (docs: shift up about 32 pt). */
|
|
const BAND_SHIFT_SHARE = 0.64;
|
|
|
|
/**
|
|
* Canva A4 numbers: the rules start on the 162.91 pt left margin (the band occupies x 55-155), the
|
|
* stamp slot is 82 x 82 at y 131.75 on the right.
|
|
*/
|
|
export const SERENITY_VARIANT: NeutralVariant = {
|
|
id: "serenity",
|
|
roles: SERENITY_ROLES,
|
|
ink: INK,
|
|
margins: { top: 56, right: 64.1, bottom: 60, left: 162.91 },
|
|
// The left margin never goes under the band's right edge plus 8 pt, whatever the preset.
|
|
marginFloor: { top: 36, right: 36, bottom: 36, left: 162.91 },
|
|
ruleInset: 0,
|
|
padX: 8.9,
|
|
textInset: { left: 8.9, right: 6.7 },
|
|
rule: 0.75,
|
|
topGap: { nominal: 75.75, min: 40 },
|
|
fromGap: 12,
|
|
bandToInfo: 156.85,
|
|
infoMinGap: 14,
|
|
tableGap: { nominal: 61, min: 28 },
|
|
headTail: { before: 3.47, after: 6.98 },
|
|
padY: 5.8,
|
|
closeGap: 7.9,
|
|
subtotalPad: 8.06,
|
|
totalsRowGap: 5.1,
|
|
labelGap: 8,
|
|
hsnMode: "subline",
|
|
cols: { hsn: 0, rate: 90, qty: 36, amount: 80, descMin: 60 },
|
|
totalsW: 210,
|
|
amountW: 90,
|
|
wordsPlacement: "below",
|
|
notesGap: { nominal: 14, min: 8 },
|
|
fromW: 250,
|
|
payTo: { where: "closing", label: "Bank details", inset: 10.9 },
|
|
signatureW: 150,
|
|
payGap: 0,
|
|
chromeInset: 8.9,
|
|
footerLeftW: 130,
|
|
signatureImageH: 44,
|
|
};
|
|
|
|
export const serenity: TemplateDefinition = {
|
|
...catalogEntry("serenity"),
|
|
version: 1,
|
|
roles: SERENITY_ROLES,
|
|
margins: SERENITY_VARIANT.margins,
|
|
marginFloor: SERENITY_VARIANT.marginFloor,
|
|
decor: {
|
|
ink: INK,
|
|
background: PAPER,
|
|
everyPage: (frame) => scriptWordDecor(INK, frame.heightDeficit * BAND_SHIFT_SHARE),
|
|
keepOuts: (frame) => [scriptWordBounds(frame.heightDeficit * BAND_SHIFT_SHARE)],
|
|
},
|
|
chrome: {
|
|
color: INK,
|
|
rule: null,
|
|
role: SERENITY_ROLES.footer,
|
|
inset: { left: SERENITY_VARIANT.chromeInset, right: SERENITY_VARIANT.chromeInset },
|
|
reserve: FOOTER_RESERVE,
|
|
leftWidth: SERENITY_VARIANT.footerLeftW,
|
|
},
|
|
logo: {
|
|
box: { w: 82, h: 81.75 },
|
|
stackBelowTextWidth: 0,
|
|
defaultOn: true,
|
|
slotWidth: () => 82,
|
|
slot: slotFor("serenity"),
|
|
available: () => ({ w: 82, h: 81.75 }),
|
|
},
|
|
Layout: NeutralLayoutFor(SERENITY_VARIANT),
|
|
};
|