refactor(pdf): introduce createBaseTemplateStyles factory (~1,150 lines removed)

Move 14 identical style slots (text/heading/div/inline/link/small/bold/
richParagraph/richListItemRow/richListItemMarker/richListItemContent/
splitRow/alignEnd/picture) from all 15 template Page.tsx files into a
single createBaseTemplateStyles factory in templates/shared. Each template
now spreads …base and keeps only its real overrides. Resolved StyleSheet
values are identical to before. Update rtl-fixture and rich-text-template-
styles tests to guard the factory file rather than each template directly.

Claude-Session: https://claude.ai/code/session_012Bnvt1MghwHj4qQRxuQUGa
This commit is contained in:
Amruth Pillai
2026-07-04 20:13:42 +02:00
parent 0701f3b62a
commit f3a60432df
18 changed files with 207 additions and 1154 deletions
@@ -5,6 +5,7 @@ import { useMemo } from "react";
import { rgbaStringToHex } from "@reactive-resume/utils/color";
import { Image, Page, StyleSheet, View } from "#react-pdf-renderer";
import { useRender } from "../../context";
import { createBaseTemplateStyles } from "../shared/base-template-styles";
import { getPrimaryTint as getPrimaryAlpha } from "../shared/color-helpers";
import {
CustomFieldContactItem,
@@ -139,16 +140,10 @@ const useLeafishTemplate = (): LeafishTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const bodyText = {
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
fontWeight: metadata.typography.body.fontWeights[0] ?? "400",
lineHeight: metadata.typography.body.lineHeight,
color: foreground,
...r.text,
} satisfies Style;
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
@@ -157,62 +152,6 @@ const useLeafishTemplate = (): LeafishTemplate => {
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
text: bodyText,
heading: {
fontFamily: metadata.typography.heading.fontFamily,
fontSize: metadata.typography.heading.fontSize,
fontWeight: metadata.typography.heading.fontWeights.at(-1) ?? "600",
lineHeight: metadata.typography.heading.lineHeight,
color: foreground,
...r.text,
},
div: {
rowGap: metrics.gapY(0.125),
columnGap: metrics.gapX(1 / 3),
},
inline: {
flexDirection: r.row,
alignItems: "center",
columnGap: metrics.gapX(1 / 3),
},
link: {
textDecoration: "none",
color: foreground,
},
small: {
fontSize: metadata.typography.body.fontSize * 0.875,
},
bold: {
fontWeight: metadata.typography.body.fontWeights.at(-1) ?? "600",
},
richParagraph: {
margin: 0,
...bodyText,
},
richListItemRow: {
flexDirection: "row",
columnGap: metrics.gapX(1 / 3),
alignItems: "flex-start",
},
richListItemMarker: {
...bodyText,
width: metadata.typography.body.fontSize,
textAlign: r.listMarkerTextAlign,
},
richListItemContent: {
...bodyText,
flex: 1,
},
splitRow: {
flexDirection: r.row,
flexWrap: "wrap",
alignItems: "flex-start",
justifyContent: "space-between",
columnGap: metrics.gapX(2 / 3),
},
alignEnd: {
...r.alignEnd,
},
section: {
flexDirection: "column",
rowGap: metrics.gapY(0.25),
@@ -272,18 +211,6 @@ const useLeafishTemplate = (): LeafishTemplate => {
alignItems: "center",
columnGap: metrics.gapX(1 / 6),
},
picture: {
width: picture.size,
height: picture.size,
objectFit: "cover",
aspectRatio: picture.aspectRatio,
borderRadius: picture.borderRadius,
borderColor: rgbaStringToHex(picture.borderColor),
borderWidth: picture.borderWidth,
shadowColor: rgbaStringToHex(picture.shadowColor),
shadowWidth: picture.shadowWidth,
transform: `rotate(${picture.rotation}deg)`,
},
body: {
flexDirection: r.row,
columnGap: metrics.columnGap,