@hed-hog/core 0.0.329 → 0.0.331

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.
Files changed (66) hide show
  1. package/dist/core.module.d.ts.map +1 -1
  2. package/dist/core.module.js +7 -4
  3. package/dist/core.module.js.map +1 -1
  4. package/dist/index.d.ts +8 -6
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +8 -6
  7. package/dist/index.js.map +1 -1
  8. package/dist/oauth/oauth.service.js +1 -1
  9. package/dist/oauth/oauth.service.js.map +1 -1
  10. package/dist/pdf/components/index.d.ts +57 -0
  11. package/dist/pdf/components/index.d.ts.map +1 -0
  12. package/dist/pdf/components/index.js +258 -0
  13. package/dist/pdf/components/index.js.map +1 -0
  14. package/dist/pdf/dto/generate-pdf.dto.d.ts +5 -0
  15. package/dist/pdf/dto/generate-pdf.dto.d.ts.map +1 -0
  16. package/dist/pdf/dto/generate-pdf.dto.js +27 -0
  17. package/dist/pdf/dto/generate-pdf.dto.js.map +1 -0
  18. package/dist/pdf/interfaces/pdf-theme-config.interface.d.ts +10 -0
  19. package/dist/pdf/interfaces/pdf-theme-config.interface.d.ts.map +1 -0
  20. package/dist/pdf/interfaces/pdf-theme-config.interface.js +3 -0
  21. package/dist/pdf/interfaces/pdf-theme-config.interface.js.map +1 -0
  22. package/dist/pdf/pdf.controller.d.ts +16 -0
  23. package/dist/pdf/pdf.controller.d.ts.map +1 -0
  24. package/dist/pdf/pdf.controller.js +100 -0
  25. package/dist/pdf/pdf.controller.js.map +1 -0
  26. package/dist/pdf/pdf.module.d.ts +3 -0
  27. package/dist/pdf/pdf.module.d.ts.map +1 -0
  28. package/dist/pdf/pdf.module.js +29 -0
  29. package/dist/pdf/pdf.module.js.map +1 -0
  30. package/dist/pdf/pdf.service.d.ts +44 -0
  31. package/dist/pdf/pdf.service.d.ts.map +1 -0
  32. package/dist/pdf/pdf.service.js +185 -0
  33. package/dist/pdf/pdf.service.js.map +1 -0
  34. package/dist/pdf/templates/hcode-institutional.template.d.ts +36 -0
  35. package/dist/pdf/templates/hcode-institutional.template.d.ts.map +1 -0
  36. package/dist/pdf/templates/hcode-institutional.template.js +67 -0
  37. package/dist/pdf/templates/hcode-institutional.template.js.map +1 -0
  38. package/dist/pdf/themes/hcode.theme.d.ts +25 -0
  39. package/dist/pdf/themes/hcode.theme.d.ts.map +1 -0
  40. package/dist/pdf/themes/hcode.theme.js +504 -0
  41. package/dist/pdf/themes/hcode.theme.js.map +1 -0
  42. package/hedhog/data/route.yaml +8 -0
  43. package/hedhog/data/setting_group.yaml +60 -0
  44. package/hedhog/frontend/app/account/layout.tsx.ejs +1 -1
  45. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +27 -23
  46. package/hedhog/frontend/app/mail/template/page.tsx.ejs +5 -5
  47. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +574 -574
  48. package/hedhog/frontend/app/menu/page.tsx.ejs +7 -2
  49. package/hedhog/frontend/app/preferences/page.tsx.ejs +1 -1
  50. package/hedhog/frontend/app/roles/page.tsx.ejs +7 -2
  51. package/hedhog/frontend/app/users/page.tsx.ejs +1 -1
  52. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +5 -9
  53. package/hedhog/frontend/messages/en.json +36 -1
  54. package/hedhog/frontend/messages/pt.json +36 -1
  55. package/package.json +5 -5
  56. package/src/core.module.ts +7 -4
  57. package/src/index.ts +9 -6
  58. package/src/oauth/oauth.service.ts +12 -12
  59. package/src/pdf/components/index.ts +316 -0
  60. package/src/pdf/dto/generate-pdf.dto.ts +11 -0
  61. package/src/pdf/interfaces/pdf-theme-config.interface.ts +10 -0
  62. package/src/pdf/pdf.controller.ts +86 -0
  63. package/src/pdf/pdf.module.ts +17 -0
  64. package/src/pdf/pdf.service.ts +229 -0
  65. package/src/pdf/templates/hcode-institutional.template.ts +122 -0
  66. package/src/pdf/themes/hcode.theme.ts +515 -0
@@ -0,0 +1,515 @@
1
+ import { PdfAreaType, PdfThemeConfig } from '../interfaces/pdf-theme-config.interface';
2
+
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ // Design System v1.0 – April 2026 – hardcoded defaults
5
+ // Overrides loaded from SettingService at runtime (see PdfService.loadThemeConfig)
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+
8
+ export interface AreaDefaults {
9
+ primary: string;
10
+ dark: string;
11
+ light: string;
12
+ }
13
+
14
+ /** Per-area color tokens — Design System v1.0 */
15
+ export const HCODE_DEFAULTS: Record<PdfAreaType, AreaDefaults> = {
16
+ // Blue 600 / Blue 800 / Blue 50
17
+ consulting: { primary: '#2D669E', dark: '#1F4A75', light: '#EAF1F8' },
18
+ // Orange 500 / Orange 700 / Orange 50
19
+ training: { primary: '#FF760C', dark: '#C45400', light: '#FFF0E2' },
20
+ // Violet 600 / Violet 800 / Violet 50
21
+ research: { primary: '#9400B5', dark: '#6A0083', light: '#F6E6FB' },
22
+ };
23
+
24
+ /** Neutral tokens — shared across all areas */
25
+ export const HCODE_NEUTRALS = {
26
+ ink1: '#101010', // body text
27
+ ink2: '#5D5D5D',
28
+ ink3: '#79756C',
29
+ line: '#ECECEC',
30
+ surface: '#FFFFFF',
31
+ surface2: '#F8F8F8',
32
+ } as const;
33
+
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+ // CSS builders
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+
38
+ /** Google Fonts import for Inter, Roboto and JetBrains Mono */
39
+ export function buildFontImport(): string {
40
+ return `<link rel="preconnect" href="https://fonts.googleapis.com">
41
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
42
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;600;700&family=Roboto:wght@400;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">`;
43
+ }
44
+
45
+ /**
46
+ * Generates the <style> block with all Design System CSS variables and rules.
47
+ * Typography scale is calibrated for A4 PDF (794 px viewport).
48
+ */
49
+ export function buildThemeCss(config: PdfThemeConfig): string {
50
+ return `<style>
51
+ /* ── CSS Variables ─────────────────────────────────────── */
52
+ :root {
53
+ /* Area accent */
54
+ --primary: ${config.primaryColor};
55
+ --dark: ${config.darkColor};
56
+ --light: ${config.lightColor};
57
+
58
+ /* Neutrals */
59
+ --ink-1: ${HCODE_NEUTRALS.ink1};
60
+ --ink-2: ${HCODE_NEUTRALS.ink2};
61
+ --ink-3: ${HCODE_NEUTRALS.ink3};
62
+ --line: ${HCODE_NEUTRALS.line};
63
+ --surface: ${HCODE_NEUTRALS.surface};
64
+ --surface-2:${HCODE_NEUTRALS.surface2};
65
+
66
+ /* Fonts */
67
+ --font-main: 'Inter', sans-serif;
68
+ --font-micro: 'Roboto', sans-serif;
69
+ --font-meta: 'JetBrains Mono', monospace;
70
+ }
71
+
72
+ /* ── Reset ─────────────────────────────────────────────── */
73
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
74
+
75
+ html, body {
76
+ font-family: var(--font-main);
77
+ font-size: 13px;
78
+ color: var(--ink-1);
79
+ background: var(--surface);
80
+ -webkit-print-color-adjust: exact;
81
+ print-color-adjust: exact;
82
+ }
83
+
84
+ /* ── Type Scale (A4-calibrated, DS v1.0 proportions) ───── */
85
+ /* Display / 80 → Inter 200, tracking -0.03em */
86
+ .t-display {
87
+ font-family: var(--font-main);
88
+ font-weight: 200;
89
+ font-size: 52px;
90
+ line-height: 1.05;
91
+ letter-spacing: -0.03em;
92
+ color: var(--ink-1);
93
+ }
94
+ /* H1 / 56 → Inter 300, tracking -0.02em */
95
+ .t-h1 {
96
+ font-family: var(--font-main);
97
+ font-weight: 300;
98
+ font-size: 36px;
99
+ line-height: 1.1;
100
+ letter-spacing: -0.02em;
101
+ color: var(--ink-1);
102
+ }
103
+ /* H2 / 36 → Inter 400 */
104
+ .t-h2 {
105
+ font-family: var(--font-main);
106
+ font-weight: 400;
107
+ font-size: 24px;
108
+ line-height: 1.15;
109
+ color: var(--ink-1);
110
+ }
111
+ /* H3 / 26 → Inter 600 */
112
+ .t-h3 {
113
+ font-family: var(--font-main);
114
+ font-weight: 600;
115
+ font-size: 17px;
116
+ line-height: 1.2;
117
+ color: var(--ink-1);
118
+ }
119
+ /* Eyebrow / 22 → Inter 400, tracking 0.36em, uppercase */
120
+ .t-eyebrow {
121
+ font-family: var(--font-main);
122
+ font-weight: 400;
123
+ font-size: 9px;
124
+ line-height: 1.4;
125
+ letter-spacing: 0.36em;
126
+ text-transform: uppercase;
127
+ color: var(--ink-3);
128
+ }
129
+ /* Body / 22 → Inter 300 */
130
+ .t-body {
131
+ font-family: var(--font-main);
132
+ font-weight: 300;
133
+ font-size: 13px;
134
+ line-height: 1.65;
135
+ color: var(--ink-2);
136
+ }
137
+ /* Meta / 14 → JetBrains Mono 500, tracking 0.18em */
138
+ .t-meta {
139
+ font-family: var(--font-meta);
140
+ font-weight: 500;
141
+ font-size: 8px;
142
+ line-height: 1.4;
143
+ letter-spacing: 0.18em;
144
+ text-transform: uppercase;
145
+ color: var(--ink-3);
146
+ }
147
+ /* Micro → Roboto 400 (rodapés, créditos) */
148
+ .t-micro {
149
+ font-family: var(--font-micro);
150
+ font-weight: 400;
151
+ font-size: 8px;
152
+ line-height: 1.4;
153
+ color: var(--ink-3);
154
+ }
155
+
156
+ /* ── Color utilities ────────────────────────────────────── */
157
+ .color-primary { color: var(--primary) !important; }
158
+ .bg-primary { background-color: var(--primary) !important; }
159
+ .bg-light { background-color: var(--light) !important; }
160
+ .bg-surface2 { background-color: var(--surface-2) !important; }
161
+
162
+ /* ── Page layout ────────────────────────────────────────── */
163
+ @page { size: A4; margin: 0; }
164
+
165
+ .page-content {
166
+ padding: 32px 48px 80px;
167
+ }
168
+
169
+ /* Page break utilities */
170
+ .break-before { page-break-before: always; break-before: page; }
171
+ .break-after { page-break-after: always; break-after: page; }
172
+ .no-break { page-break-inside: avoid; break-inside: avoid; }
173
+
174
+ /* ── Cover page ─────────────────────────────────────────── */
175
+ /* Two-column grid: left=white 55%, right=primary 45% */
176
+ .cover {
177
+ display: grid;
178
+ grid-template-columns: 55% 45%;
179
+ min-height: 297mm;
180
+ page-break-after: always;
181
+ break-after: page;
182
+ }
183
+ .cover-left {
184
+ background: var(--surface);
185
+ padding: 56px 40px 40px;
186
+ display: flex;
187
+ flex-direction: column;
188
+ justify-content: space-between;
189
+ }
190
+ .cover-right {
191
+ background: var(--primary);
192
+ padding: 40px 32px;
193
+ display: flex;
194
+ flex-direction: column;
195
+ align-items: flex-start;
196
+ justify-content: flex-end;
197
+ position: relative;
198
+ overflow: hidden;
199
+ }
200
+ .cover-right-glyph {
201
+ position: absolute;
202
+ top: -40px;
203
+ right: -20px;
204
+ font-family: var(--font-main);
205
+ font-weight: 300;
206
+ font-size: 280px;
207
+ color: rgba(255,255,255,0.10);
208
+ line-height: 1;
209
+ letter-spacing: -0.01em;
210
+ user-select: none;
211
+ pointer-events: none;
212
+ }
213
+ .cover-right-areas {
214
+ list-style: none;
215
+ width: 100%;
216
+ border-top: 1px solid rgba(255,255,255,0.25);
217
+ position: relative;
218
+ z-index: 1;
219
+ }
220
+ .cover-right-areas li {
221
+ font-family: var(--font-main);
222
+ font-weight: 400;
223
+ font-size: 9px;
224
+ letter-spacing: 0.30em;
225
+ text-transform: uppercase;
226
+ color: rgba(255,255,255,0.90);
227
+ padding: 10px 0;
228
+ border-bottom: 1px solid rgba(255,255,255,0.15);
229
+ display: flex;
230
+ align-items: center;
231
+ gap: 10px;
232
+ }
233
+ .cover-right-areas li .num {
234
+ font-family: var(--font-meta);
235
+ font-size: 7px;
236
+ opacity: 0.55;
237
+ }
238
+ .cover-system-label {
239
+ font-family: var(--font-meta);
240
+ font-size: 7px;
241
+ letter-spacing: 0.18em;
242
+ color: rgba(255,255,255,0.55);
243
+ position: absolute;
244
+ top: 16px;
245
+ left: 32px;
246
+ }
247
+ .cover-release-label {
248
+ font-family: var(--font-meta);
249
+ font-size: 7px;
250
+ letter-spacing: 0.18em;
251
+ color: rgba(255,255,255,0.55);
252
+ position: absolute;
253
+ top: 16px;
254
+ right: 32px;
255
+ display: flex;
256
+ align-items: center;
257
+ gap: 6px;
258
+ }
259
+ .cover-release-label::before {
260
+ content: '';
261
+ width: 6px;
262
+ height: 6px;
263
+ border-radius: 50%;
264
+ background: rgba(255,255,255,0.70);
265
+ }
266
+
267
+ /* ── Wordmark lockup ────────────────────────────────────── */
268
+ .lockup { display: flex; flex-direction: column; gap: 3px; }
269
+ .lockup-wordmark {
270
+ font-family: var(--font-main);
271
+ font-weight: 300;
272
+ font-size: 32px;
273
+ letter-spacing: -0.01em;
274
+ line-height: 1;
275
+ }
276
+ .lockup-wordmark .glyph { color: var(--primary); }
277
+ .lockup-wordmark .wordmark { color: var(--ink-3); }
278
+ .lockup-area {
279
+ font-family: var(--font-main);
280
+ font-weight: 400;
281
+ font-size: 9px;
282
+ letter-spacing: 0.30em;
283
+ text-transform: uppercase;
284
+ color: var(--primary);
285
+ }
286
+
287
+ /* ── Accent bar — fixed at top of EVERY page (cover included) ── */
288
+ .page-accent-bar {
289
+ position: fixed;
290
+ top: 0;
291
+ left: 0;
292
+ right: 0;
293
+ height: 6px;
294
+ background: var(--primary);
295
+ z-index: 999;
296
+ }
297
+
298
+ /* ── Page header (logo + page title) ───────────────────── */
299
+ .page-header {
300
+ display: flex;
301
+ align-items: center;
302
+ justify-content: space-between;
303
+ padding: 18px 48px 14px;
304
+ border-bottom: 1px solid var(--line);
305
+ }
306
+
307
+ /* ── Section header: eyebrow + title + left accent bar ─── */
308
+ .section-header {
309
+ display: flex;
310
+ flex-direction: column;
311
+ gap: 6px;
312
+ margin-bottom: 24px;
313
+ padding-left: 14px;
314
+ border-left: 3.5px solid var(--primary);
315
+ }
316
+
317
+ /* ── Purpose block (colored background) ─────────────────── */
318
+ .purpose-block {
319
+ background: var(--primary);
320
+ border-radius: 14px;
321
+ padding: 28px 32px;
322
+ margin-bottom: 28px;
323
+ page-break-inside: avoid;
324
+ break-inside: avoid;
325
+ }
326
+ .purpose-block .t-eyebrow { color: rgba(255,255,255,0.65); margin-bottom: 8px; }
327
+ .purpose-block .t-h3 { color: #ffffff; margin-bottom: 12px; font-size: 18px; font-weight: 600; }
328
+ .purpose-block .t-body { color: rgba(255,255,255,0.85); font-size: 12px; }
329
+
330
+ /* ── Feature cards (3-column grid) ─────────────────────── */
331
+ .feature-cards {
332
+ display: grid;
333
+ grid-template-columns: repeat(3, 1fr);
334
+ gap: 14px;
335
+ margin-bottom: 28px;
336
+ }
337
+ .feature-card {
338
+ border: 1px solid var(--line);
339
+ border-radius: 12px;
340
+ padding: 18px 14px;
341
+ background: var(--surface);
342
+ page-break-inside: avoid;
343
+ break-inside: avoid;
344
+ }
345
+ .feature-card-icon {
346
+ width: 38px;
347
+ height: 32px;
348
+ border: 1.5px solid var(--line);
349
+ border-radius: 8px;
350
+ display: flex;
351
+ align-items: center;
352
+ justify-content: center;
353
+ margin-bottom: 10px;
354
+ color: var(--primary);
355
+ }
356
+ .feature-card-title {
357
+ font-family: var(--font-main);
358
+ font-weight: 600;
359
+ font-size: 12px;
360
+ color: var(--primary);
361
+ margin-bottom: 5px;
362
+ letter-spacing: -0.01em;
363
+ }
364
+ .feature-card-desc {
365
+ font-family: var(--font-main);
366
+ font-weight: 300;
367
+ font-size: 10px;
368
+ line-height: 1.55;
369
+ color: var(--ink-2);
370
+ }
371
+
372
+ /* ── Chip ─────────────────────────────────────────────── */
373
+ .chip {
374
+ display: inline-flex;
375
+ align-items: center;
376
+ gap: 5px;
377
+ padding: 3px 10px;
378
+ border-radius: 999px;
379
+ background: var(--light);
380
+ font-family: var(--font-main);
381
+ font-weight: 400;
382
+ font-size: 9px;
383
+ color: var(--primary);
384
+ letter-spacing: 0.01em;
385
+ }
386
+ .chip::before {
387
+ content: '';
388
+ width: 5px;
389
+ height: 5px;
390
+ border-radius: 50%;
391
+ background: var(--primary);
392
+ flex-shrink: 0;
393
+ }
394
+
395
+ /* ── Data table ──────────────────────────────────────── */
396
+ .data-table {
397
+ width: 100%;
398
+ border-collapse: collapse;
399
+ margin-bottom: 28px;
400
+ }
401
+ .data-table thead tr { background: var(--light); }
402
+ .data-table th {
403
+ font-family: var(--font-meta);
404
+ font-weight: 500;
405
+ font-size: 8px;
406
+ letter-spacing: 0.18em;
407
+ text-transform: uppercase;
408
+ color: var(--primary);
409
+ padding: 9px 13px;
410
+ text-align: left;
411
+ border-bottom: 1.5px solid var(--primary);
412
+ }
413
+ .data-table td {
414
+ font-family: var(--font-main);
415
+ font-weight: 300;
416
+ font-size: 10px;
417
+ color: var(--ink-2);
418
+ padding: 9px 13px;
419
+ border-bottom: 1px solid var(--line);
420
+ }
421
+ .data-table tbody tr { page-break-inside: avoid; break-inside: avoid; }
422
+ .data-table tbody tr:nth-child(even) td { background: var(--surface-2); }
423
+
424
+ /* ── Metadata block ──────────────────────────────────── */
425
+ .metadata-block {
426
+ display: grid;
427
+ grid-template-columns: repeat(4, 1fr);
428
+ gap: 0;
429
+ border: 1px solid var(--line);
430
+ border-radius: 12px;
431
+ overflow: hidden;
432
+ margin-bottom: 28px;
433
+ page-break-inside: avoid;
434
+ break-inside: avoid;
435
+ }
436
+ .metadata-item {
437
+ padding: 14px 16px;
438
+ border-right: 1px solid var(--line);
439
+ background: var(--surface);
440
+ }
441
+ .metadata-item:nth-child(4n) { border-right: none; }
442
+ .metadata-item:nth-child(4n+4) { border-right: none; }
443
+ .metadata-item:nth-child(n+5) { border-top: 1px solid var(--line); }
444
+ .metadata-label {
445
+ font-family: var(--font-meta);
446
+ font-weight: 500;
447
+ font-size: 7px;
448
+ letter-spacing: 0.18em;
449
+ text-transform: uppercase;
450
+ color: var(--ink-3);
451
+ margin-bottom: 4px;
452
+ }
453
+ .metadata-value {
454
+ font-family: var(--font-main);
455
+ font-weight: 400;
456
+ font-size: 11px;
457
+ color: var(--ink-1);
458
+ }
459
+
460
+ /* ── Signature area ──────────────────────────────────── */
461
+ .signature-area {
462
+ display: grid;
463
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
464
+ gap: 24px;
465
+ margin-top: 28px;
466
+ page-break-inside: avoid;
467
+ break-inside: avoid;
468
+ }
469
+ .signature-item { display: flex; flex-direction: column; gap: 6px; }
470
+ .signature-line {
471
+ width: 100%;
472
+ height: 1px;
473
+ background: var(--ink-1);
474
+ margin-bottom: 5px;
475
+ }
476
+ .signature-label {
477
+ font-family: var(--font-micro);
478
+ font-size: 8px;
479
+ color: var(--ink-3);
480
+ }
481
+ .signature-name {
482
+ font-family: var(--font-main);
483
+ font-weight: 400;
484
+ font-size: 10px;
485
+ color: var(--ink-2);
486
+ }
487
+
488
+ /* ── Fixed footer (repeats on every page) ───────────── */
489
+ .pdf-footer {
490
+ position: fixed;
491
+ bottom: 0;
492
+ left: 0;
493
+ right: 0;
494
+ height: 40px;
495
+ display: flex;
496
+ align-items: center;
497
+ justify-content: space-between;
498
+ padding: 0 48px;
499
+ border-top: 1px solid var(--line);
500
+ background: var(--surface);
501
+ }
502
+ /* CSS counter for page numbering */
503
+ @page { counter-increment: page; }
504
+ .pdf-footer-page::after {
505
+ content: counter(page);
506
+ font-family: var(--font-meta);
507
+ font-size: 8px;
508
+ letter-spacing: 0.18em;
509
+ color: var(--ink-3);
510
+ }
511
+
512
+ /* Padding to avoid content overlapping the fixed header bar and footer */
513
+ body { padding-top: 6px; padding-bottom: 48px; }
514
+ </style>`;
515
+ }