refactor: Centralize PDF styling with COLORS and FONT_SIZES and enhance module content and dynamic title generation.
This commit is contained in:
@@ -1,23 +1,51 @@
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Text as PDFText,
|
||||
View as PDFView,
|
||||
StyleSheet as PDFStyleSheet,
|
||||
Image as PDFImage
|
||||
} from '@react-pdf/renderer';
|
||||
import { View as PDFView, Text as PDFText, StyleSheet, Link as PDFLink, Image as PDFImage, Font } from '@react-pdf/renderer';
|
||||
|
||||
export const pdfStyles = PDFStyleSheet.create({
|
||||
// INDUSTRIAL DESIGN SYSTEM TOKENS
|
||||
export const COLORS = {
|
||||
CHARCOAL: '#0f172a', // Slate 900
|
||||
TEXT_MAIN: '#334155', // Slate 700
|
||||
TEXT_DIM: '#64748b', // Slate 500
|
||||
TEXT_LIGHT: '#94a3b8', // Slate 400
|
||||
DIVIDER: '#cbd5e1', // Slate 300
|
||||
GRID: '#f1f5f9', // Slate 100
|
||||
BLUEPRINT: '#e2e8f0', // Slate 200
|
||||
WHITE: '#ffffff'
|
||||
};
|
||||
|
||||
export const FONT_SIZES = {
|
||||
H1: 24,
|
||||
H2: 18,
|
||||
H3: 12,
|
||||
BODY: 9,
|
||||
TINY: 7,
|
||||
SUB: 8,
|
||||
BLUEPRINT: 5
|
||||
};
|
||||
|
||||
// Register a more technical font if possible, or use Helvetica with varying weights
|
||||
// Note: helvetica-bold is standard in react-pdf
|
||||
|
||||
export const pdfStyles = StyleSheet.create({
|
||||
page: {
|
||||
paddingTop: 45, // DIN 5008
|
||||
paddingLeft: 70, // ~25mm
|
||||
paddingRight: 57, // ~20mm
|
||||
paddingBottom: 80, // Safe buffer for absolute footer
|
||||
backgroundColor: '#ffffff',
|
||||
backgroundColor: COLORS.WHITE,
|
||||
fontFamily: 'Helvetica',
|
||||
fontSize: 10,
|
||||
color: '#000000',
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.CHARCOAL,
|
||||
},
|
||||
titlePage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: COLORS.WHITE,
|
||||
fontFamily: 'Helvetica',
|
||||
color: COLORS.CHARCOAL,
|
||||
padding: 0, // NO PADDING to prevent inner overflow page breaks
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
@@ -31,13 +59,13 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
marginTop: 45, // DIN 5008 positioning for window
|
||||
},
|
||||
senderLine: {
|
||||
fontSize: 7,
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
textDecoration: 'underline',
|
||||
color: '#666666',
|
||||
color: COLORS.TEXT_DIM,
|
||||
marginBottom: 8,
|
||||
},
|
||||
recipientAddress: {
|
||||
fontSize: 10,
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
lineHeight: 1.4,
|
||||
},
|
||||
brandLogoContainer: {
|
||||
@@ -47,14 +75,14 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
brandIconContainer: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
backgroundColor: '#000000',
|
||||
backgroundColor: '#0f172a',
|
||||
borderRadius: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 12,
|
||||
},
|
||||
brandIconText: {
|
||||
color: '#ffffff',
|
||||
color: COLORS.WHITE,
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
@@ -62,27 +90,27 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
marginBottom: 24,
|
||||
},
|
||||
mainTitle: {
|
||||
fontSize: 12,
|
||||
fontSize: FONT_SIZES.H3,
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 4,
|
||||
color: '#000000',
|
||||
color: COLORS.CHARCOAL,
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 1,
|
||||
},
|
||||
subTitle: {
|
||||
fontSize: 9,
|
||||
color: '#666666',
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_DIM,
|
||||
marginTop: 2,
|
||||
},
|
||||
section: {
|
||||
marginBottom: 32,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 8,
|
||||
fontSize: FONT_SIZES.SUB,
|
||||
fontWeight: 'bold',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 1,
|
||||
color: '#999999',
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
marginBottom: 8,
|
||||
},
|
||||
footer: {
|
||||
@@ -91,7 +119,7 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
left: 70,
|
||||
right: 57,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: '#f1f5f9',
|
||||
borderTopColor: COLORS.GRID,
|
||||
paddingTop: 16,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
@@ -108,17 +136,17 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
marginBottom: 8,
|
||||
},
|
||||
footerText: {
|
||||
fontSize: 7,
|
||||
color: '#94a3b8',
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
lineHeight: 1.5,
|
||||
},
|
||||
footerLabel: {
|
||||
fontWeight: 'bold',
|
||||
color: '#64748b',
|
||||
color: COLORS.TEXT_DIM,
|
||||
},
|
||||
pageNumber: {
|
||||
fontSize: 7,
|
||||
color: '#cbd5e1',
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
color: COLORS.DIVIDER,
|
||||
fontWeight: 'bold',
|
||||
marginTop: 8,
|
||||
textAlign: 'right',
|
||||
@@ -128,14 +156,41 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
left: 20,
|
||||
width: 10,
|
||||
borderTopWidth: 0.5,
|
||||
borderTopColor: '#cbd5e1',
|
||||
borderTopColor: COLORS.DIVIDER,
|
||||
},
|
||||
divider: {
|
||||
width: '100%',
|
||||
height: 1,
|
||||
backgroundColor: '#f1f5f9',
|
||||
backgroundColor: COLORS.DIVIDER,
|
||||
marginVertical: 12,
|
||||
},
|
||||
blueprintGrid: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
zIndex: -10,
|
||||
},
|
||||
gridLineH: {
|
||||
width: '100%',
|
||||
height: 0.5,
|
||||
backgroundColor: COLORS.GRID,
|
||||
position: 'absolute',
|
||||
},
|
||||
gridLineV: {
|
||||
width: 0.5,
|
||||
height: '100%',
|
||||
backgroundColor: COLORS.GRID,
|
||||
position: 'absolute',
|
||||
},
|
||||
technicalMarker: {
|
||||
position: 'absolute',
|
||||
fontSize: FONT_SIZES.BLUEPRINT,
|
||||
color: COLORS.BLUEPRINT,
|
||||
fontFamily: 'Helvetica',
|
||||
letterSpacing: 1,
|
||||
},
|
||||
// Atoms
|
||||
industrialListItem: {
|
||||
flexDirection: 'row',
|
||||
@@ -145,47 +200,47 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
industrialBulletBox: {
|
||||
width: 6,
|
||||
height: 6,
|
||||
backgroundColor: '#0f172a',
|
||||
backgroundColor: COLORS.CHARCOAL,
|
||||
marginRight: 8,
|
||||
marginTop: 5,
|
||||
},
|
||||
industrialTitle: {
|
||||
fontSize: 24,
|
||||
fontSize: FONT_SIZES.H1,
|
||||
fontWeight: 'bold',
|
||||
color: '#0f172a',
|
||||
color: COLORS.CHARCOAL,
|
||||
marginBottom: 6,
|
||||
letterSpacing: -0.5,
|
||||
letterSpacing: 0, // Reset for clarity
|
||||
},
|
||||
industrialSubtitle: {
|
||||
fontSize: 8,
|
||||
fontSize: FONT_SIZES.SUB,
|
||||
fontWeight: 'bold',
|
||||
color: '#94a3b8',
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
textTransform: 'uppercase',
|
||||
marginBottom: 16,
|
||||
letterSpacing: 2,
|
||||
},
|
||||
industrialTextLead: {
|
||||
fontSize: 10,
|
||||
color: '#334155',
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_MAIN,
|
||||
lineHeight: 1.6,
|
||||
marginBottom: 12,
|
||||
},
|
||||
industrialText: {
|
||||
fontSize: 9,
|
||||
color: '#64748b',
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_DIM,
|
||||
lineHeight: 1.6,
|
||||
marginBottom: 8,
|
||||
},
|
||||
industrialCard: {
|
||||
padding: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: '#e2e8f0',
|
||||
borderColor: COLORS.BLUEPRINT,
|
||||
marginBottom: 12,
|
||||
},
|
||||
industrialCardTitle: {
|
||||
fontSize: 10,
|
||||
fontSize: FONT_SIZES.BODY + 1, // 10
|
||||
fontWeight: 'bold',
|
||||
color: '#0f172a',
|
||||
color: COLORS.CHARCOAL,
|
||||
marginBottom: 4,
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 0.5,
|
||||
@@ -193,22 +248,30 @@ export const pdfStyles = PDFStyleSheet.create({
|
||||
darkBox: {
|
||||
marginTop: 32,
|
||||
padding: 24,
|
||||
backgroundColor: '#0f172a',
|
||||
color: '#ffffff',
|
||||
backgroundColor: COLORS.CHARCOAL,
|
||||
color: COLORS.WHITE,
|
||||
},
|
||||
darkTitle: {
|
||||
fontSize: 18,
|
||||
fontSize: FONT_SIZES.H2,
|
||||
fontWeight: 'bold',
|
||||
color: '#ffffff',
|
||||
color: COLORS.WHITE,
|
||||
marginBottom: 8,
|
||||
},
|
||||
darkText: {
|
||||
fontSize: 9,
|
||||
color: '#94a3b8',
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
lineHeight: 1.6,
|
||||
},
|
||||
});
|
||||
|
||||
const styles = pdfStyles;
|
||||
|
||||
export const BlueprintBackground = () => (
|
||||
<PDFView style={styles.blueprintGrid} fixed>
|
||||
{/* Clean background - grid lines removed per user request */}
|
||||
</PDFView>
|
||||
);
|
||||
|
||||
export const IndustrialListItem = ({ children }: { children: React.ReactNode }) => (
|
||||
<PDFView style={pdfStyles.industrialListItem}>
|
||||
<PDFView style={pdfStyles.industrialBulletBox} />
|
||||
@@ -238,5 +301,5 @@ export const Header = ({ sender, recipient, icon, showAddress = true }: { sender
|
||||
);
|
||||
|
||||
export const DocumentTitle = ({ title, subLines }: { title: string; subLines?: string[] }) => (
|
||||
<PDFView style={pdfStyles.titleInfo}><PDFText style={pdfStyles.mainTitle}>{title}</PDFText>{subLines?.map((line, i) => (<PDFText key={i} style={[pdfStyles.subTitle, i === 1 ? { fontWeight: 'bold', color: '#000000' } : {}]}>{line}</PDFText>))}</PDFView>
|
||||
<PDFView style={pdfStyles.titleInfo}><PDFText style={pdfStyles.mainTitle}>{title}</PDFText>{subLines?.map((line, i) => (<PDFText key={i} style={[pdfStyles.subTitle, i === 1 ? { fontWeight: 'bold', color: '#0f172a' } : {}]}>{line}</PDFText>))}</PDFView>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user