mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-26 00:02:32 +10:00
feat(pdf): roll out shared RTL layout to all templates
Introduce createRtlStyleHelpers and a single rtl flag on RenderProvider, migrate every template page to mirrored layout styles, and rename alignRight to alignEnd. Fix plain rich text rendering via PdfText paragraph renderers and map legacy Times New Roman to Times-Roman. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,6 @@ import type { TemplatePageProps } from "../../document";
|
||||
import type { TemplateColorRoles, TemplateStyleContext, TemplateStyleSlots } from "../shared/types";
|
||||
import { useMemo } from "react";
|
||||
import { rgbaStringToHex } from "@reactive-resume/utils/color";
|
||||
import { isRTL } from "@reactive-resume/utils/locale";
|
||||
import { useRender } from "../../context";
|
||||
import { Image, Page, StyleSheet, View } from "../../renderer";
|
||||
import { CustomFieldContactItem, WebsiteContactItem } from "../shared/contact-item";
|
||||
@@ -14,6 +13,7 @@ import { getTemplateMetrics } from "../shared/metrics";
|
||||
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
|
||||
import { hasTemplatePicture } from "../shared/picture";
|
||||
import { Heading, Icon, Link, Text } from "../shared/primitives";
|
||||
import { createRtlStyleHelpers } from "../shared/rtl";
|
||||
import { Section } from "../shared/sections";
|
||||
import { composeStyles, headerNameLineHeight } from "../shared/styles";
|
||||
|
||||
@@ -154,15 +154,16 @@ const Header = ({ styles }: { styles: RhyhornStyles }) => {
|
||||
};
|
||||
|
||||
const useRhyhornTemplate = (): RhyhornTemplate => {
|
||||
const { picture, metadata } = useRender();
|
||||
const { picture, metadata, rtl } = useRender();
|
||||
|
||||
return useMemo(() => {
|
||||
const r = createRtlStyleHelpers(rtl);
|
||||
const foreground = rgbaStringToHex(metadata.design.colors.text);
|
||||
const background = rgbaStringToHex(metadata.design.colors.background);
|
||||
const primary = rgbaStringToHex(metadata.design.colors.primary);
|
||||
const colors: TemplateColorRoles = { foreground, background, primary };
|
||||
const metrics = getTemplateMetrics(metadata.page);
|
||||
const rtl = isRTL(metadata.page.locale);
|
||||
const contactGap = metrics.gapX(0.5);
|
||||
|
||||
const bodyText = {
|
||||
fontFamily: metadata.typography.body.fontFamily,
|
||||
@@ -170,7 +171,7 @@ const useRhyhornTemplate = (): RhyhornTemplate => {
|
||||
fontWeight: metadata.typography.body.fontWeights[0] ?? "400",
|
||||
lineHeight: metadata.typography.body.lineHeight,
|
||||
color: foreground,
|
||||
...(rtl ? { direction: "rtl" as const, textAlign: "right" as const } : {}),
|
||||
...r.text,
|
||||
} satisfies Style;
|
||||
|
||||
const baseStyles = StyleSheet.create({
|
||||
@@ -183,7 +184,7 @@ const useRhyhornTemplate = (): RhyhornTemplate => {
|
||||
fontFamily: metadata.typography.body.fontFamily,
|
||||
fontSize: metadata.typography.body.fontSize,
|
||||
lineHeight: metadata.typography.body.lineHeight,
|
||||
direction: rtl ? "rtl" : "ltr",
|
||||
direction: r.pageDirection,
|
||||
},
|
||||
text: bodyText,
|
||||
heading: {
|
||||
@@ -192,10 +193,10 @@ const useRhyhornTemplate = (): RhyhornTemplate => {
|
||||
fontWeight: metadata.typography.heading.fontWeights.at(-1) ?? "600",
|
||||
lineHeight: metadata.typography.heading.lineHeight,
|
||||
color: foreground,
|
||||
...(rtl ? { direction: "rtl" as const, textAlign: "right" as const } : {}),
|
||||
...r.text,
|
||||
},
|
||||
div: { rowGap: metrics.gapY(0.125), columnGap: metrics.gapX(1 / 3) },
|
||||
inline: { flexDirection: rtl ? "row-reverse" : "row", alignItems: "center", 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" },
|
||||
@@ -210,62 +211,47 @@ const useRhyhornTemplate = (): RhyhornTemplate => {
|
||||
// bodyText spread first so `textAlign` below isn't clobbered by bodyText.textAlign.
|
||||
...bodyText,
|
||||
width: metadata.typography.body.fontSize,
|
||||
textAlign: rtl ? "left" : "right",
|
||||
textAlign: r.listMarkerTextAlign,
|
||||
},
|
||||
richListItemContent: { flex: 1, ...bodyText },
|
||||
splitRow: {
|
||||
flexDirection: rtl ? "row-reverse" : "row",
|
||||
flexDirection: r.row,
|
||||
flexWrap: "wrap",
|
||||
alignItems: "flex-start",
|
||||
justifyContent: "space-between",
|
||||
columnGap: metrics.gapX(2 / 3),
|
||||
},
|
||||
alignRight: { textAlign: rtl ? "left" : "right", minWidth: 0, maxWidth: "100%", flexShrink: 1 },
|
||||
alignEnd: { ...r.alignEnd },
|
||||
section: { flexDirection: "column", rowGap: metrics.gapY(0.25) },
|
||||
sectionHeading: {
|
||||
color: primary,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: primary,
|
||||
textAlign: rtl ? "right" : "left",
|
||||
textAlign: r.sectionHeadingTextAlign,
|
||||
},
|
||||
item: { rowGap: metrics.gapY(0.125) },
|
||||
levelContainer: { width: "100%" },
|
||||
levelItem: { borderColor: primary },
|
||||
levelItemActive: { backgroundColor: primary },
|
||||
header: { flexDirection: rtl ? "row-reverse" : "row", alignItems: "center", columnGap: metrics.gapX(0.5) },
|
||||
header: { flexDirection: r.row, alignItems: "center", columnGap: metrics.gapX(0.5) },
|
||||
headerTitle: { flex: 1, rowGap: metrics.gapY(0.5) },
|
||||
headerIdentity: {
|
||||
textAlign: rtl ? "right" : "left",
|
||||
alignItems: rtl ? "flex-end" : "flex-start",
|
||||
...r.headerIdentity,
|
||||
rowGap: metrics.gapY(0.35),
|
||||
},
|
||||
headerName: { fontSize: metadata.typography.heading.fontSize * 1.5, lineHeight: headerNameLineHeight },
|
||||
contactList: { flexDirection: rtl ? "row-reverse" : "row", flexWrap: "wrap", rowGap: metrics.gapY(0.125) },
|
||||
contactList: { flexDirection: r.row, flexWrap: "wrap", rowGap: metrics.gapY(0.125) },
|
||||
contactItem: {
|
||||
flexDirection: rtl ? "row-reverse" : "row",
|
||||
flexDirection: r.row,
|
||||
alignItems: "center",
|
||||
...(rtl
|
||||
? {
|
||||
borderLeftWidth: 1,
|
||||
borderLeftColor: primary,
|
||||
paddingLeft: metrics.gapX(0.5),
|
||||
marginLeft: metrics.gapX(0.5),
|
||||
}
|
||||
: {
|
||||
borderRightWidth: 1,
|
||||
borderRightColor: primary,
|
||||
paddingRight: metrics.gapX(0.5),
|
||||
marginRight: metrics.gapX(0.5),
|
||||
}),
|
||||
...r.contactSeparator(primary, contactGap),
|
||||
},
|
||||
contactItemContent: {
|
||||
flexDirection: rtl ? "row-reverse" : "row",
|
||||
flexDirection: r.row,
|
||||
alignItems: "center",
|
||||
columnGap: metrics.gapX(1 / 6),
|
||||
},
|
||||
contactItemLast: rtl
|
||||
? { borderLeftWidth: 0, paddingLeft: 0, marginLeft: 0 }
|
||||
: { borderRightWidth: 0, paddingRight: 0, marginRight: 0 },
|
||||
contactItemLast: r.contactSeparatorClear,
|
||||
picture: {
|
||||
width: picture.size,
|
||||
height: picture.size,
|
||||
@@ -297,5 +283,5 @@ const useRhyhornTemplate = (): RhyhornTemplate => {
|
||||
}),
|
||||
} satisfies RhyhornStyles,
|
||||
};
|
||||
}, [picture, metadata]);
|
||||
}, [picture, metadata, rtl]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user