Linea (the vendor's original format.pdf design), Monogram and Serenity are rebuilt from the reference 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.
56 lines
2.1 KiB
TypeScript
56 lines
2.1 KiB
TypeScript
import type { MarginPreset, PageId } from "../engine/geometry";
|
|
|
|
/** Page and template choices frozen with an invoice at issue (stored as JSON). */
|
|
export interface RenderPrefsV1 {
|
|
version: 1;
|
|
templateId: string;
|
|
pageSize: PageId;
|
|
margins: MarginPreset;
|
|
logo?: {
|
|
/** The logo already contains the business name, so a template drops its own name lockup. */
|
|
useWordmark?: boolean;
|
|
/** Templates without a reference logo placeholder (Linea, ...) show the logo only when this is true. */
|
|
show?: boolean;
|
|
};
|
|
}
|
|
|
|
export const DEFAULT_PREFS: RenderPrefsV1 = {
|
|
version: 1,
|
|
templateId: "classic",
|
|
pageSize: "A4",
|
|
margins: "template",
|
|
};
|
|
|
|
const PAGE_SIZE_IDS: readonly PageId[] = ["A4", "LETTER"];
|
|
const MARGIN_IDS: readonly MarginPreset[] = ["template", "narrow", "normal"];
|
|
|
|
/** Tolerant: anything unreadable or out of range falls back to the default for that field. */
|
|
export function parsePrefs(json: string | null | undefined): RenderPrefsV1 {
|
|
if (!json) return { ...DEFAULT_PREFS };
|
|
let raw: unknown;
|
|
try {
|
|
raw = JSON.parse(json);
|
|
} catch {
|
|
return { ...DEFAULT_PREFS };
|
|
}
|
|
if (typeof raw !== "object" || raw === null) return { ...DEFAULT_PREFS };
|
|
const o = raw as Record<string, unknown>;
|
|
const prefs: RenderPrefsV1 = {
|
|
version: 1,
|
|
templateId: typeof o.templateId === "string" && o.templateId ? o.templateId : DEFAULT_PREFS.templateId,
|
|
pageSize: PAGE_SIZE_IDS.includes(o.pageSize as PageId) ? (o.pageSize as PageId) : DEFAULT_PREFS.pageSize,
|
|
margins: MARGIN_IDS.includes(o.margins as MarginPreset) ? (o.margins as MarginPreset) : DEFAULT_PREFS.margins,
|
|
};
|
|
const logo = o.logo;
|
|
if (typeof logo === "object" && logo !== null) {
|
|
const { useWordmark, show } = logo as { useWordmark?: unknown; show?: unknown };
|
|
const out: NonNullable<RenderPrefsV1["logo"]> = {};
|
|
if (typeof useWordmark === "boolean") out.useWordmark = useWordmark;
|
|
if (typeof show === "boolean") out.show = show;
|
|
if (Object.keys(out).length > 0) prefs.logo = out;
|
|
}
|
|
return prefs;
|
|
}
|
|
|
|
export const prefsToJson = (prefs: RenderPrefsV1): string => JSON.stringify(prefs);
|