@gmoney2000/dygarn-pdf-kit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
1
+ import { B as BrandInput } from './types-CHgvU4U1.js';
2
+
3
+ /**
4
+ * Adapter: RepFirm TenantBranding shape -> BrandInput.
5
+ *
6
+ * RepFirm tenants store branding on the `tenants.branding` JSONB column with
7
+ * keys like primary_color, logo_url, logo_dark_url, etc. (snake_case). Pair
8
+ * with the tenant name from the parent row when calling.
9
+ */
10
+ interface TenantBrandingShape {
11
+ primary_color?: string;
12
+ logo_url?: string | null;
13
+ logo_wordmark_url?: string | null;
14
+ logo_mark_url?: string | null;
15
+ logo_dark_url?: string | null;
16
+ logo_light_url?: string | null;
17
+ pdf_header_theme?: "dark" | "light" | "auto";
18
+ theme_vars?: Record<string, string>;
19
+ tagline?: string | null;
20
+ company_address?: string | null;
21
+ company_phone?: string | null;
22
+ company_email?: string | null;
23
+ }
24
+ declare function brandFromTenantBranding(tenantName: string, branding: TenantBrandingShape | null | undefined, fallbackPrimary?: string): BrandInput;
25
+ /**
26
+ * Adapter: dygarn-dashboard prospect brand shape -> BrandInput.
27
+ *
28
+ * Dygarn-dashboard stores per-prospect brand kits in outreach_prospect_brands
29
+ * with simpler shape (camelCase or snake — be liberal in what we accept).
30
+ */
31
+ interface ProspectBrandShape {
32
+ agency_name?: string;
33
+ agencyName?: string;
34
+ legal_name?: string | null;
35
+ legalName?: string | null;
36
+ logo_url?: string | null;
37
+ logoUrl?: string | null;
38
+ primary_color?: string;
39
+ primaryColor?: string;
40
+ secondary_color?: string;
41
+ secondaryColor?: string;
42
+ address?: string | null;
43
+ phone?: string | null;
44
+ website?: string | null;
45
+ }
46
+ declare function brandFromProspectBrand(p: ProspectBrandShape): BrandInput;
47
+ /**
48
+ * Determine whether to use a dark or light header band for this brand.
49
+ *
50
+ * - Explicit override: respect pdfHeaderTheme if set to 'dark' or 'light'.
51
+ * - Auto (default): use dark theme only when a logoDarkUrl (white-on-dark
52
+ * variant) is available, OR when the logo filename hints at a white/dark
53
+ * variant. Otherwise default to LIGHT (safe for multi-color logos).
54
+ */
55
+ declare function resolveBandThemeMode(brand: BrandInput): "dark" | "light";
56
+ /**
57
+ * Pick the best logo URL for the resolved theme mode.
58
+ * Returns null if no logo available.
59
+ */
60
+ declare function resolveBestLogoUrl(brand: BrandInput, mode: "dark" | "light"): string | null;
61
+ /**
62
+ * Darken a hex color by a 0-1 amount. Used to derive a dark band color from
63
+ * a brand primary when no explicit dark variant exists.
64
+ */
65
+ declare function darkenHex(hex: string, amount: number): string;
66
+ /**
67
+ * Convert hex to {r,g,b} normalized 0-1. Used by both React-PDF (color objects)
68
+ * and pdf-lib (rgb() arguments).
69
+ */
70
+ declare function hexToRgb01(hex: string): [number, number, number];
71
+
72
+ /**
73
+ * PDF style contract. All branded paperwork (quotes, POs, packing slips,
74
+ * invoices) consumes a PdfStyle to render. Switching a tenant's style changes
75
+ * every PDF at once.
76
+ *
77
+ * Structure stays identical across styles - only colors, fonts, spacing, and
78
+ * visual accents vary.
79
+ */
80
+ type PdfStyleId = "classic" | "modern" | "minimal" | "bold";
81
+ interface PdfStyle {
82
+ id: PdfStyleId;
83
+ label: string;
84
+ description: string;
85
+ colors: {
86
+ text: string;
87
+ textMuted: string;
88
+ textInverse: string;
89
+ accent: string;
90
+ accentLight: string;
91
+ border: string;
92
+ rowAlt: string;
93
+ headerBg: string;
94
+ headerText: string;
95
+ tableHeaderBg: string;
96
+ tableHeaderText: string;
97
+ surface: string;
98
+ };
99
+ fonts: {
100
+ body: string;
101
+ heading: string;
102
+ mono: string;
103
+ sizeBase: number;
104
+ sizeLabel: number;
105
+ sizeHeading: number;
106
+ sizeHuge: number;
107
+ letterSpacingHeading: number;
108
+ };
109
+ layout: {
110
+ pagePaddingBottom: number;
111
+ sectionPaddingHorizontal: number;
112
+ headerPaddingVertical: number;
113
+ accentBarHeight: number;
114
+ tableRadius: number;
115
+ zebra: boolean;
116
+ showInfoSection: boolean;
117
+ infoSectionBg: "accent" | "surface" | "none";
118
+ };
119
+ header: {
120
+ variant: "band" | "hairline" | "minimal" | "bold-block";
121
+ logoWidth: number;
122
+ logoHeight: number;
123
+ agencyNameSize: number;
124
+ titleSize: number;
125
+ numberSize: number;
126
+ };
127
+ }
128
+
129
+ declare const boldStyle: PdfStyle;
130
+
131
+ declare const classicStyle: PdfStyle;
132
+
133
+ declare const minimalStyle: PdfStyle;
134
+
135
+ declare const modernStyle: PdfStyle;
136
+
137
+ declare const PDF_STYLES: Record<PdfStyleId, PdfStyle>;
138
+ declare const PDF_STYLE_LIST: PdfStyle[];
139
+ declare const DEFAULT_PDF_STYLE_ID: PdfStyleId;
140
+ declare function resolvePdfStyle(id: string | null | undefined): PdfStyle;
141
+
142
+ export { BrandInput, DEFAULT_PDF_STYLE_ID, PDF_STYLES, PDF_STYLE_LIST, type PdfStyle, type PdfStyleId, type ProspectBrandShape, type TenantBrandingShape, boldStyle, brandFromProspectBrand, brandFromTenantBranding, classicStyle, darkenHex, hexToRgb01, minimalStyle, modernStyle, resolveBandThemeMode, resolveBestLogoUrl, resolvePdfStyle };
package/dist/index.js ADDED
@@ -0,0 +1,292 @@
1
+ // src/brand.ts
2
+ function brandFromTenantBranding(tenantName, branding, fallbackPrimary = "#1e3a5f") {
3
+ const b = branding ?? {};
4
+ return {
5
+ agencyName: tenantName,
6
+ primaryColor: b.primary_color ?? fallbackPrimary,
7
+ logoUrl: b.logo_url ?? null,
8
+ logoDarkUrl: b.logo_dark_url ?? null,
9
+ logoLightUrl: b.logo_light_url ?? null,
10
+ logoWordmarkUrl: b.logo_wordmark_url ?? null,
11
+ logoMarkUrl: b.logo_mark_url ?? null,
12
+ pdfHeaderTheme: b.pdf_header_theme ?? "auto",
13
+ themeVars: b.theme_vars ?? {},
14
+ tagline: b.tagline ?? null,
15
+ address: b.company_address ?? null,
16
+ phone: b.company_phone ?? null,
17
+ email: b.company_email ?? null
18
+ };
19
+ }
20
+ function brandFromProspectBrand(p) {
21
+ const agency = p.agencyName ?? p.agency_name ?? "Agency";
22
+ return {
23
+ agencyName: agency,
24
+ legalName: p.legalName ?? p.legal_name ?? null,
25
+ logoUrl: p.logoUrl ?? p.logo_url ?? null,
26
+ primaryColor: p.primaryColor ?? p.primary_color ?? "#1a73e8",
27
+ address: p.address ?? null,
28
+ phone: p.phone ?? null,
29
+ website: p.website ?? null,
30
+ pdfHeaderTheme: "auto"
31
+ };
32
+ }
33
+ function resolveBandThemeMode(brand) {
34
+ if (brand.pdfHeaderTheme === "dark") return "dark";
35
+ if (brand.pdfHeaderTheme === "light") return "light";
36
+ if (brand.logoDarkUrl) return "dark";
37
+ const candidate = (brand.logoWordmarkUrl ?? brand.logoUrl ?? brand.logoMarkUrl ?? "").toLowerCase();
38
+ if (candidate.includes("white") || candidate.includes("-on-dark") || candidate.includes("_dark")) return "dark";
39
+ return "light";
40
+ }
41
+ function resolveBestLogoUrl(brand, mode) {
42
+ if (mode === "dark") {
43
+ return brand.logoDarkUrl ?? brand.logoUrl ?? brand.logoWordmarkUrl ?? brand.logoMarkUrl ?? null;
44
+ }
45
+ return brand.logoLightUrl ?? brand.logoUrl ?? brand.logoWordmarkUrl ?? brand.logoMarkUrl ?? brand.logoDarkUrl ?? null;
46
+ }
47
+ function darkenHex(hex, amount) {
48
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex);
49
+ if (!m) return hex;
50
+ const n = Number.parseInt(m[1], 16);
51
+ let r = n >> 16 & 255;
52
+ let g = n >> 8 & 255;
53
+ let b = n & 255;
54
+ r = Math.max(0, Math.round(r * (1 - amount)));
55
+ g = Math.max(0, Math.round(g * (1 - amount)));
56
+ b = Math.max(0, Math.round(b * (1 - amount)));
57
+ return `#${[r, g, b].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
58
+ }
59
+ function hexToRgb01(hex) {
60
+ const h = hex.replace("#", "").trim();
61
+ const r = Number.parseInt(h.slice(0, 2), 16) / 255;
62
+ const g = Number.parseInt(h.slice(2, 4), 16) / 255;
63
+ const b = Number.parseInt(h.slice(4, 6), 16) / 255;
64
+ return [Number.isFinite(r) ? r : 0.12, Number.isFinite(g) ? g : 0.23, Number.isFinite(b) ? b : 0.37];
65
+ }
66
+
67
+ // src/styles/bold.ts
68
+ var boldStyle = {
69
+ id: "bold",
70
+ label: "Bold",
71
+ description: "Heavy colored header and big typography. Brand-forward look.",
72
+ colors: {
73
+ text: "#0f1420",
74
+ textMuted: "#5a6378",
75
+ textInverse: "#ffffff",
76
+ accent: "#d97706",
77
+ accentLight: "#fff4e6",
78
+ border: "#e5d4bd",
79
+ rowAlt: "#fffaf2",
80
+ headerBg: "#0f1420",
81
+ headerText: "#ffffff",
82
+ tableHeaderBg: "#d97706",
83
+ tableHeaderText: "#ffffff",
84
+ surface: "#ffffff"
85
+ },
86
+ fonts: {
87
+ body: "Helvetica",
88
+ heading: "Helvetica-Bold",
89
+ mono: "Helvetica-Bold",
90
+ sizeBase: 9,
91
+ sizeLabel: 7,
92
+ sizeHeading: 14,
93
+ sizeHuge: 28,
94
+ letterSpacingHeading: 1
95
+ },
96
+ layout: {
97
+ pagePaddingBottom: 50,
98
+ sectionPaddingHorizontal: 40,
99
+ headerPaddingVertical: 36,
100
+ accentBarHeight: 6,
101
+ tableRadius: 2,
102
+ zebra: true,
103
+ showInfoSection: true,
104
+ infoSectionBg: "accent"
105
+ },
106
+ header: {
107
+ variant: "bold-block",
108
+ logoWidth: 90,
109
+ logoHeight: 54,
110
+ agencyNameSize: 24,
111
+ titleSize: 8,
112
+ numberSize: 32
113
+ }
114
+ };
115
+
116
+ // src/styles/classic.ts
117
+ var classicStyle = {
118
+ id: "classic",
119
+ label: "Classic",
120
+ description: "Dark navy header band with steel-blue accent. Professional and traditional.",
121
+ colors: {
122
+ text: "#1a2535",
123
+ textMuted: "#6b7a8a",
124
+ textInverse: "#ffffff",
125
+ accent: "#4a7aa0",
126
+ accentLight: "#e8f2ed",
127
+ border: "#d4dbe3",
128
+ rowAlt: "#f7f9f8",
129
+ headerBg: "#2c3e50",
130
+ headerText: "#ffffff",
131
+ tableHeaderBg: "#2c3e50",
132
+ tableHeaderText: "#a0b4c0",
133
+ surface: "#ffffff"
134
+ },
135
+ fonts: {
136
+ body: "Helvetica",
137
+ heading: "Helvetica-Bold",
138
+ mono: "Courier-Bold",
139
+ sizeBase: 9,
140
+ sizeLabel: 7,
141
+ sizeHeading: 12,
142
+ sizeHuge: 20,
143
+ letterSpacingHeading: 0.5
144
+ },
145
+ layout: {
146
+ pagePaddingBottom: 50,
147
+ sectionPaddingHorizontal: 40,
148
+ headerPaddingVertical: 28,
149
+ accentBarHeight: 3,
150
+ tableRadius: 4,
151
+ zebra: true,
152
+ showInfoSection: true,
153
+ infoSectionBg: "accent"
154
+ },
155
+ header: {
156
+ variant: "band",
157
+ logoWidth: 80,
158
+ logoHeight: 48,
159
+ agencyNameSize: 18,
160
+ titleSize: 7,
161
+ numberSize: 20
162
+ }
163
+ };
164
+
165
+ // src/styles/minimal.ts
166
+ var minimalStyle = {
167
+ id: "minimal",
168
+ label: "Minimal",
169
+ description: "Monochrome and typographic. Hairline rules, no color blocks.",
170
+ colors: {
171
+ text: "#111111",
172
+ textMuted: "#6b6b6b",
173
+ textInverse: "#ffffff",
174
+ accent: "#111111",
175
+ accentLight: "#f5f5f5",
176
+ border: "#d4d4d4",
177
+ rowAlt: "#fafafa",
178
+ headerBg: "#ffffff",
179
+ headerText: "#111111",
180
+ tableHeaderBg: "#ffffff",
181
+ tableHeaderText: "#6b6b6b",
182
+ surface: "#ffffff"
183
+ },
184
+ fonts: {
185
+ body: "Helvetica",
186
+ heading: "Helvetica-Bold",
187
+ mono: "Courier",
188
+ sizeBase: 9,
189
+ sizeLabel: 6.5,
190
+ sizeHeading: 11,
191
+ sizeHuge: 18,
192
+ letterSpacingHeading: 2
193
+ },
194
+ layout: {
195
+ pagePaddingBottom: 55,
196
+ sectionPaddingHorizontal: 54,
197
+ headerPaddingVertical: 36,
198
+ accentBarHeight: 1,
199
+ tableRadius: 2,
200
+ zebra: false,
201
+ showInfoSection: true,
202
+ infoSectionBg: "none"
203
+ },
204
+ header: {
205
+ variant: "minimal",
206
+ logoWidth: 70,
207
+ logoHeight: 42,
208
+ agencyNameSize: 16,
209
+ titleSize: 7,
210
+ numberSize: 16
211
+ }
212
+ };
213
+
214
+ // src/styles/modern.ts
215
+ var modernStyle = {
216
+ id: "modern",
217
+ label: "Modern",
218
+ description: "Light and airy with generous whitespace. Contemporary look.",
219
+ colors: {
220
+ text: "#18243a",
221
+ textMuted: "#5e7290",
222
+ textInverse: "#ffffff",
223
+ accent: "#5590b8",
224
+ accentLight: "#f4f8fb",
225
+ border: "#e5ecf3",
226
+ rowAlt: "#fafbfd",
227
+ headerBg: "#ffffff",
228
+ headerText: "#18243a",
229
+ tableHeaderBg: "#f4f8fb",
230
+ tableHeaderText: "#5e7290",
231
+ surface: "#ffffff"
232
+ },
233
+ fonts: {
234
+ body: "Helvetica",
235
+ heading: "Helvetica-Bold",
236
+ mono: "Courier-Bold",
237
+ sizeBase: 9.5,
238
+ sizeLabel: 7,
239
+ sizeHeading: 13,
240
+ sizeHuge: 22,
241
+ letterSpacingHeading: -0.3
242
+ },
243
+ layout: {
244
+ pagePaddingBottom: 60,
245
+ sectionPaddingHorizontal: 48,
246
+ headerPaddingVertical: 32,
247
+ accentBarHeight: 2,
248
+ tableRadius: 8,
249
+ zebra: true,
250
+ showInfoSection: true,
251
+ infoSectionBg: "surface"
252
+ },
253
+ header: {
254
+ variant: "hairline",
255
+ logoWidth: 90,
256
+ logoHeight: 54,
257
+ agencyNameSize: 22,
258
+ titleSize: 6.5,
259
+ numberSize: 24
260
+ }
261
+ };
262
+
263
+ // src/styles/index.ts
264
+ var PDF_STYLES = {
265
+ classic: classicStyle,
266
+ modern: modernStyle,
267
+ minimal: minimalStyle,
268
+ bold: boldStyle
269
+ };
270
+ var PDF_STYLE_LIST = [classicStyle, modernStyle, minimalStyle, boldStyle];
271
+ var DEFAULT_PDF_STYLE_ID = "classic";
272
+ function resolvePdfStyle(id) {
273
+ if (id && id in PDF_STYLES) return PDF_STYLES[id];
274
+ return PDF_STYLES[DEFAULT_PDF_STYLE_ID];
275
+ }
276
+ export {
277
+ DEFAULT_PDF_STYLE_ID,
278
+ PDF_STYLES,
279
+ PDF_STYLE_LIST,
280
+ boldStyle,
281
+ brandFromProspectBrand,
282
+ brandFromTenantBranding,
283
+ classicStyle,
284
+ darkenHex,
285
+ hexToRgb01,
286
+ minimalStyle,
287
+ modernStyle,
288
+ resolveBandThemeMode,
289
+ resolveBestLogoUrl,
290
+ resolvePdfStyle
291
+ };
292
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/brand.ts","../src/styles/bold.ts","../src/styles/classic.ts","../src/styles/minimal.ts","../src/styles/modern.ts","../src/styles/index.ts"],"sourcesContent":["import type { BrandInput } from \"./types\";\n\n/**\n * Adapter: RepFirm TenantBranding shape -> BrandInput.\n *\n * RepFirm tenants store branding on the `tenants.branding` JSONB column with\n * keys like primary_color, logo_url, logo_dark_url, etc. (snake_case). Pair\n * with the tenant name from the parent row when calling.\n */\nexport interface TenantBrandingShape {\n primary_color?: string;\n logo_url?: string | null;\n logo_wordmark_url?: string | null;\n logo_mark_url?: string | null;\n logo_dark_url?: string | null;\n logo_light_url?: string | null;\n pdf_header_theme?: \"dark\" | \"light\" | \"auto\";\n theme_vars?: Record<string, string>;\n tagline?: string | null;\n company_address?: string | null;\n company_phone?: string | null;\n company_email?: string | null;\n}\n\nexport function brandFromTenantBranding(\n tenantName: string,\n branding: TenantBrandingShape | null | undefined,\n fallbackPrimary = \"#1e3a5f\",\n): BrandInput {\n const b = branding ?? {};\n return {\n agencyName: tenantName,\n primaryColor: b.primary_color ?? fallbackPrimary,\n logoUrl: b.logo_url ?? null,\n logoDarkUrl: b.logo_dark_url ?? null,\n logoLightUrl: b.logo_light_url ?? null,\n logoWordmarkUrl: b.logo_wordmark_url ?? null,\n logoMarkUrl: b.logo_mark_url ?? null,\n pdfHeaderTheme: b.pdf_header_theme ?? \"auto\",\n themeVars: b.theme_vars ?? {},\n tagline: b.tagline ?? null,\n address: b.company_address ?? null,\n phone: b.company_phone ?? null,\n email: b.company_email ?? null,\n };\n}\n\n/**\n * Adapter: dygarn-dashboard prospect brand shape -> BrandInput.\n *\n * Dygarn-dashboard stores per-prospect brand kits in outreach_prospect_brands\n * with simpler shape (camelCase or snake — be liberal in what we accept).\n */\nexport interface ProspectBrandShape {\n agency_name?: string;\n agencyName?: string;\n legal_name?: string | null;\n legalName?: string | null;\n logo_url?: string | null;\n logoUrl?: string | null;\n primary_color?: string;\n primaryColor?: string;\n secondary_color?: string;\n secondaryColor?: string;\n address?: string | null;\n phone?: string | null;\n website?: string | null;\n}\n\nexport function brandFromProspectBrand(p: ProspectBrandShape): BrandInput {\n const agency = p.agencyName ?? p.agency_name ?? \"Agency\";\n return {\n agencyName: agency,\n legalName: p.legalName ?? p.legal_name ?? null,\n logoUrl: p.logoUrl ?? p.logo_url ?? null,\n primaryColor: p.primaryColor ?? p.primary_color ?? \"#1a73e8\",\n address: p.address ?? null,\n phone: p.phone ?? null,\n website: p.website ?? null,\n pdfHeaderTheme: \"auto\",\n };\n}\n\n/**\n * Determine whether to use a dark or light header band for this brand.\n *\n * - Explicit override: respect pdfHeaderTheme if set to 'dark' or 'light'.\n * - Auto (default): use dark theme only when a logoDarkUrl (white-on-dark\n * variant) is available, OR when the logo filename hints at a white/dark\n * variant. Otherwise default to LIGHT (safe for multi-color logos).\n */\nexport function resolveBandThemeMode(brand: BrandInput): \"dark\" | \"light\" {\n if (brand.pdfHeaderTheme === \"dark\") return \"dark\";\n if (brand.pdfHeaderTheme === \"light\") return \"light\";\n if (brand.logoDarkUrl) return \"dark\";\n const candidate = (brand.logoWordmarkUrl ?? brand.logoUrl ?? brand.logoMarkUrl ?? \"\").toLowerCase();\n if (candidate.includes(\"white\") || candidate.includes(\"-on-dark\") || candidate.includes(\"_dark\")) return \"dark\";\n return \"light\";\n}\n\n/**\n * Pick the best logo URL for the resolved theme mode.\n * Returns null if no logo available.\n */\nexport function resolveBestLogoUrl(brand: BrandInput, mode: \"dark\" | \"light\"): string | null {\n if (mode === \"dark\") {\n return brand.logoDarkUrl ?? brand.logoUrl ?? brand.logoWordmarkUrl ?? brand.logoMarkUrl ?? null;\n }\n return (\n brand.logoLightUrl ?? brand.logoUrl ?? brand.logoWordmarkUrl ?? brand.logoMarkUrl ?? brand.logoDarkUrl ?? null\n );\n}\n\n/**\n * Darken a hex color by a 0-1 amount. Used to derive a dark band color from\n * a brand primary when no explicit dark variant exists.\n */\nexport function darkenHex(hex: string, amount: number): string {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex);\n if (!m) return hex;\n const n = Number.parseInt(m[1], 16);\n let r = (n >> 16) & 0xff;\n let g = (n >> 8) & 0xff;\n let b = n & 0xff;\n r = Math.max(0, Math.round(r * (1 - amount)));\n g = Math.max(0, Math.round(g * (1 - amount)));\n b = Math.max(0, Math.round(b * (1 - amount)));\n return `#${[r, g, b].map((c) => c.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/**\n * Convert hex to {r,g,b} normalized 0-1. Used by both React-PDF (color objects)\n * and pdf-lib (rgb() arguments).\n */\nexport function hexToRgb01(hex: string): [number, number, number] {\n const h = hex.replace(\"#\", \"\").trim();\n const r = Number.parseInt(h.slice(0, 2), 16) / 255;\n const g = Number.parseInt(h.slice(2, 4), 16) / 255;\n const b = Number.parseInt(h.slice(4, 6), 16) / 255;\n return [Number.isFinite(r) ? r : 0.12, Number.isFinite(g) ? g : 0.23, Number.isFinite(b) ? b : 0.37];\n}\n","import type { PdfStyle } from \"./types\";\n\nexport const boldStyle: PdfStyle = {\n id: \"bold\",\n label: \"Bold\",\n description: \"Heavy colored header and big typography. Brand-forward look.\",\n\n colors: {\n text: \"#0f1420\",\n textMuted: \"#5a6378\",\n textInverse: \"#ffffff\",\n accent: \"#d97706\",\n accentLight: \"#fff4e6\",\n border: \"#e5d4bd\",\n rowAlt: \"#fffaf2\",\n headerBg: \"#0f1420\",\n headerText: \"#ffffff\",\n tableHeaderBg: \"#d97706\",\n tableHeaderText: \"#ffffff\",\n surface: \"#ffffff\",\n },\n\n fonts: {\n body: \"Helvetica\",\n heading: \"Helvetica-Bold\",\n mono: \"Helvetica-Bold\",\n sizeBase: 9,\n sizeLabel: 7,\n sizeHeading: 14,\n sizeHuge: 28,\n letterSpacingHeading: 1,\n },\n\n layout: {\n pagePaddingBottom: 50,\n sectionPaddingHorizontal: 40,\n headerPaddingVertical: 36,\n accentBarHeight: 6,\n tableRadius: 2,\n zebra: true,\n showInfoSection: true,\n infoSectionBg: \"accent\",\n },\n\n header: {\n variant: \"bold-block\",\n logoWidth: 90,\n logoHeight: 54,\n agencyNameSize: 24,\n titleSize: 8,\n numberSize: 32,\n },\n};\n","import type { PdfStyle } from \"./types\";\n\nexport const classicStyle: PdfStyle = {\n id: \"classic\",\n label: \"Classic\",\n description: \"Dark navy header band with steel-blue accent. Professional and traditional.\",\n\n colors: {\n text: \"#1a2535\",\n textMuted: \"#6b7a8a\",\n textInverse: \"#ffffff\",\n accent: \"#4a7aa0\",\n accentLight: \"#e8f2ed\",\n border: \"#d4dbe3\",\n rowAlt: \"#f7f9f8\",\n headerBg: \"#2c3e50\",\n headerText: \"#ffffff\",\n tableHeaderBg: \"#2c3e50\",\n tableHeaderText: \"#a0b4c0\",\n surface: \"#ffffff\",\n },\n\n fonts: {\n body: \"Helvetica\",\n heading: \"Helvetica-Bold\",\n mono: \"Courier-Bold\",\n sizeBase: 9,\n sizeLabel: 7,\n sizeHeading: 12,\n sizeHuge: 20,\n letterSpacingHeading: 0.5,\n },\n\n layout: {\n pagePaddingBottom: 50,\n sectionPaddingHorizontal: 40,\n headerPaddingVertical: 28,\n accentBarHeight: 3,\n tableRadius: 4,\n zebra: true,\n showInfoSection: true,\n infoSectionBg: \"accent\",\n },\n\n header: {\n variant: \"band\",\n logoWidth: 80,\n logoHeight: 48,\n agencyNameSize: 18,\n titleSize: 7,\n numberSize: 20,\n },\n};\n","import type { PdfStyle } from \"./types\";\n\nexport const minimalStyle: PdfStyle = {\n id: \"minimal\",\n label: \"Minimal\",\n description: \"Monochrome and typographic. Hairline rules, no color blocks.\",\n\n colors: {\n text: \"#111111\",\n textMuted: \"#6b6b6b\",\n textInverse: \"#ffffff\",\n accent: \"#111111\",\n accentLight: \"#f5f5f5\",\n border: \"#d4d4d4\",\n rowAlt: \"#fafafa\",\n headerBg: \"#ffffff\",\n headerText: \"#111111\",\n tableHeaderBg: \"#ffffff\",\n tableHeaderText: \"#6b6b6b\",\n surface: \"#ffffff\",\n },\n\n fonts: {\n body: \"Helvetica\",\n heading: \"Helvetica-Bold\",\n mono: \"Courier\",\n sizeBase: 9,\n sizeLabel: 6.5,\n sizeHeading: 11,\n sizeHuge: 18,\n letterSpacingHeading: 2,\n },\n\n layout: {\n pagePaddingBottom: 55,\n sectionPaddingHorizontal: 54,\n headerPaddingVertical: 36,\n accentBarHeight: 1,\n tableRadius: 2,\n zebra: false,\n showInfoSection: true,\n infoSectionBg: \"none\",\n },\n\n header: {\n variant: \"minimal\",\n logoWidth: 70,\n logoHeight: 42,\n agencyNameSize: 16,\n titleSize: 7,\n numberSize: 16,\n },\n};\n","import type { PdfStyle } from \"./types\";\n\nexport const modernStyle: PdfStyle = {\n id: \"modern\",\n label: \"Modern\",\n description: \"Light and airy with generous whitespace. Contemporary look.\",\n\n colors: {\n text: \"#18243a\",\n textMuted: \"#5e7290\",\n textInverse: \"#ffffff\",\n accent: \"#5590b8\",\n accentLight: \"#f4f8fb\",\n border: \"#e5ecf3\",\n rowAlt: \"#fafbfd\",\n headerBg: \"#ffffff\",\n headerText: \"#18243a\",\n tableHeaderBg: \"#f4f8fb\",\n tableHeaderText: \"#5e7290\",\n surface: \"#ffffff\",\n },\n\n fonts: {\n body: \"Helvetica\",\n heading: \"Helvetica-Bold\",\n mono: \"Courier-Bold\",\n sizeBase: 9.5,\n sizeLabel: 7,\n sizeHeading: 13,\n sizeHuge: 22,\n letterSpacingHeading: -0.3,\n },\n\n layout: {\n pagePaddingBottom: 60,\n sectionPaddingHorizontal: 48,\n headerPaddingVertical: 32,\n accentBarHeight: 2,\n tableRadius: 8,\n zebra: true,\n showInfoSection: true,\n infoSectionBg: \"surface\",\n },\n\n header: {\n variant: \"hairline\",\n logoWidth: 90,\n logoHeight: 54,\n agencyNameSize: 22,\n titleSize: 6.5,\n numberSize: 24,\n },\n};\n","import { boldStyle } from \"./bold\";\nimport { classicStyle } from \"./classic\";\nimport { minimalStyle } from \"./minimal\";\nimport { modernStyle } from \"./modern\";\nimport type { PdfStyle, PdfStyleId } from \"./types\";\n\nexport const PDF_STYLES: Record<PdfStyleId, PdfStyle> = {\n classic: classicStyle,\n modern: modernStyle,\n minimal: minimalStyle,\n bold: boldStyle,\n};\n\nexport const PDF_STYLE_LIST: PdfStyle[] = [classicStyle, modernStyle, minimalStyle, boldStyle];\n\nexport const DEFAULT_PDF_STYLE_ID: PdfStyleId = \"classic\";\n\nexport function resolvePdfStyle(id: string | null | undefined): PdfStyle {\n if (id && id in PDF_STYLES) return PDF_STYLES[id as PdfStyleId];\n return PDF_STYLES[DEFAULT_PDF_STYLE_ID];\n}\n\nexport { boldStyle, classicStyle, minimalStyle, modernStyle };\nexport type { PdfStyle, PdfStyleId } from \"./types\";\n"],"mappings":"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","names":[]}