2026-05-12 20:45:28 +02:00
|
|
|
import { Image, StyleSheet, Text, View } from '@react-pdf/renderer';
|
|
|
|
|
|
|
|
|
|
import { PDF_TOKENS } from './tokens';
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
|
band: {
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
backgroundColor: PDF_TOKENS.colors.headerBand,
|
|
|
|
|
paddingHorizontal: PDF_TOKENS.spacing.pagePadding,
|
|
|
|
|
paddingVertical: 16,
|
|
|
|
|
minHeight: PDF_TOKENS.spacing.headerHeight,
|
|
|
|
|
},
|
|
|
|
|
logoSlot: {
|
|
|
|
|
width: PDF_TOKENS.spacing.logoMaxWidth,
|
|
|
|
|
height: PDF_TOKENS.spacing.logoMaxHeight,
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
},
|
|
|
|
|
logoImage: {
|
|
|
|
|
maxWidth: PDF_TOKENS.spacing.logoMaxWidth,
|
|
|
|
|
maxHeight: PDF_TOKENS.spacing.logoMaxHeight,
|
|
|
|
|
objectFit: 'contain',
|
|
|
|
|
objectPositionX: 0,
|
|
|
|
|
},
|
|
|
|
|
portNameFallback: {
|
|
|
|
|
fontFamily: PDF_TOKENS.fonts.sansBold,
|
|
|
|
|
fontSize: PDF_TOKENS.sizes.docTitle,
|
|
|
|
|
color: PDF_TOKENS.colors.headerText,
|
|
|
|
|
},
|
|
|
|
|
rightBlock: {
|
|
|
|
|
marginLeft: 'auto',
|
|
|
|
|
flexDirection: 'column',
|
|
|
|
|
alignItems: 'flex-end',
|
|
|
|
|
gap: 4,
|
|
|
|
|
},
|
|
|
|
|
docTitle: {
|
|
|
|
|
fontFamily: PDF_TOKENS.fonts.sansBold,
|
|
|
|
|
fontSize: PDF_TOKENS.sizes.docTitle,
|
|
|
|
|
color: PDF_TOKENS.colors.headerText,
|
|
|
|
|
},
|
|
|
|
|
meta: {
|
|
|
|
|
fontFamily: PDF_TOKENS.fonts.sans,
|
|
|
|
|
fontSize: PDF_TOKENS.sizes.small,
|
|
|
|
|
color: PDF_TOKENS.colors.headerText,
|
|
|
|
|
opacity: 0.85,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export interface HeaderProps {
|
|
|
|
|
portName: string;
|
|
|
|
|
docTitle: string;
|
|
|
|
|
meta?: string;
|
|
|
|
|
logoBuffer: Buffer | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function Header({ portName, docTitle, meta, logoBuffer }: HeaderProps) {
|
|
|
|
|
return (
|
|
|
|
|
<View style={styles.band} fixed>
|
|
|
|
|
<View style={styles.logoSlot}>
|
|
|
|
|
{logoBuffer ? (
|
2026-05-12 21:42:51 +02:00
|
|
|
// react-pdf's <Image> renders into PDF bytes; the jsx-a11y/alt-text
|
|
|
|
|
// rule is checking against the HTML <img> contract that doesn't
|
|
|
|
|
// apply here (PDFs use the document title for AT, not per-image alt).
|
|
|
|
|
// eslint-disable-next-line jsx-a11y/alt-text
|
2026-05-12 20:45:28 +02:00
|
|
|
<Image src={logoBuffer} style={styles.logoImage} />
|
|
|
|
|
) : (
|
|
|
|
|
<Text style={styles.portNameFallback}>{portName}</Text>
|
|
|
|
|
)}
|
|
|
|
|
</View>
|
|
|
|
|
<View style={styles.rightBlock}>
|
|
|
|
|
<Text style={styles.docTitle}>{docTitle}</Text>
|
|
|
|
|
{meta ? <Text style={styles.meta}>{meta}</Text> : null}
|
|
|
|
|
</View>
|
|
|
|
|
</View>
|
|
|
|
|
);
|
|
|
|
|
}
|