mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-24 07:12:18 +10:00
feat: add semantic CSS stylesheets (#3274)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor Agent
parent
4ac19f81b3
commit
d2ffbf9618
@@ -3,8 +3,10 @@ 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 { Image, Page, StyleSheet, View } from "#react-pdf-renderer";
|
||||
import { Page, StyleSheet, View } from "#react-pdf-renderer";
|
||||
import { useRender } from "../../context";
|
||||
import { useRenderedSectionIds, useResolvedNode } from "../../semantic/context";
|
||||
import { semanticNodeKeys } from "../../semantic/node-keys";
|
||||
import { createBaseTemplateStyles } from "../shared/base-template-styles";
|
||||
import { getPrimaryTint as getPrimaryAlpha } from "../shared/color-helpers";
|
||||
import {
|
||||
@@ -18,7 +20,15 @@ import { TemplateProvider } from "../shared/context";
|
||||
import { filterSections } from "../shared/filtering";
|
||||
import { getTemplateMetrics } from "../shared/metrics";
|
||||
import { hasTemplatePicture } from "../shared/picture";
|
||||
import { Heading, Text } from "../shared/primitives";
|
||||
import {
|
||||
Heading,
|
||||
SemanticContactListView,
|
||||
SemanticHeaderPicture,
|
||||
SemanticHeaderView,
|
||||
SemanticRegionView,
|
||||
SemanticTemplatePartView,
|
||||
Text,
|
||||
} from "../shared/primitives";
|
||||
import { createRtlStyleHelpers } from "../shared/rtl";
|
||||
import { Section } from "../shared/sections";
|
||||
import { composeStyles, headerNameLineHeight } from "../shared/styles";
|
||||
@@ -49,28 +59,41 @@ type LeafishHeaderProps = {
|
||||
styles: LeafishStyles;
|
||||
};
|
||||
|
||||
export const LeafishPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
|
||||
export const LeafishPage = ({ page, pageSize, pageMinHeightStyle, showHeader, pageNumber }: TemplatePageProps) => {
|
||||
const data = useRender();
|
||||
const pageNodeKey = semanticNodeKeys.page(pageNumber);
|
||||
const { style: semanticPageStyle, size: semanticPageSize, ...semanticPageProps } = useResolvedNode(pageNodeKey);
|
||||
const { metadata } = data;
|
||||
const { colors, styles } = useLeafishTemplate();
|
||||
const metrics = getTemplateMetrics(metadata.page);
|
||||
const mainSections = filterSections(page.main, data).filter((section) => section !== "summary");
|
||||
const sidebarSections = filterSections(page.sidebar, data).filter((section) => section !== "summary");
|
||||
const mainSections = useRenderedSectionIds(
|
||||
pageNodeKey,
|
||||
filterSections(page.main, data).filter((section) => section !== "summary"),
|
||||
);
|
||||
const sidebarSections = useRenderedSectionIds(
|
||||
pageNodeKey,
|
||||
filterSections(page.sidebar, data).filter((section) => section !== "summary"),
|
||||
);
|
||||
|
||||
return (
|
||||
<Page size={pageSize} style={composeStyles(styles.page, pageMinHeightStyle)}>
|
||||
<TemplateProvider styles={styles} colors={colors}>
|
||||
<Page
|
||||
{...semanticPageProps}
|
||||
size={semanticPageSize ?? pageSize}
|
||||
style={composeStyles(styles.page, pageMinHeightStyle, semanticPageStyle)}
|
||||
>
|
||||
<TemplateProvider pageNodeKey={pageNodeKey} styles={styles} colors={colors}>
|
||||
{showHeader && <Header styles={styles} />}
|
||||
|
||||
<View style={styles.body}>
|
||||
<View style={composeStyles(styles.mainColumn, { rowGap: metrics.sectionGap })}>
|
||||
<SemanticRegionView region="main" style={composeStyles(styles.mainColumn, { rowGap: metrics.sectionGap })}>
|
||||
{mainSections.map((section) => (
|
||||
<Section key={section} section={section} placement="main" />
|
||||
))}
|
||||
</View>
|
||||
</SemanticRegionView>
|
||||
|
||||
{!page.fullWidth && (
|
||||
<View
|
||||
<SemanticRegionView
|
||||
region="sidebar"
|
||||
style={composeStyles(styles.sidebarColumn, {
|
||||
width: `${metadata.layout.sidebarWidth}%`,
|
||||
rowGap: metrics.sectionGap,
|
||||
@@ -79,7 +102,7 @@ export const LeafishPage = ({ page, pageSize, pageMinHeightStyle, showHeader }:
|
||||
{sidebarSections.map((section) => (
|
||||
<Section key={section} section={section} placement="sidebar" />
|
||||
))}
|
||||
</View>
|
||||
</SemanticRegionView>
|
||||
)}
|
||||
</View>
|
||||
</TemplateProvider>
|
||||
@@ -92,10 +115,10 @@ const Header = ({ styles }: LeafishHeaderProps) => {
|
||||
const hasPicture = hasTemplatePicture(picture);
|
||||
|
||||
return (
|
||||
<View style={styles.header}>
|
||||
<View style={styles.headerIntro}>
|
||||
<View style={styles.headerBody}>
|
||||
{hasPicture && <Image src={picture.url} style={styles.picture} />}
|
||||
<SemanticHeaderView style={styles.header}>
|
||||
<SemanticTemplatePartView partKeys={["header-intro"]} style={styles.headerIntro}>
|
||||
<SemanticTemplatePartView partKeys={["header-intro", "header-body"]} style={styles.headerBody}>
|
||||
{hasPicture && <SemanticHeaderPicture src={picture.url} style={styles.picture} />}
|
||||
|
||||
<View style={styles.headerTitle}>
|
||||
<View style={styles.headerIdentity}>
|
||||
@@ -105,11 +128,11 @@ const Header = ({ styles }: LeafishHeaderProps) => {
|
||||
|
||||
<Section section="summary" placement="main" showHeading={false} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</SemanticTemplatePartView>
|
||||
</SemanticTemplatePartView>
|
||||
|
||||
<View style={styles.headerContactBand}>
|
||||
<View style={styles.contactList}>
|
||||
<SemanticTemplatePartView partKeys={["header-contact-band"]} style={styles.headerContactBand}>
|
||||
<SemanticContactListView style={styles.contactList}>
|
||||
<EmailContactItem email={basics.email} style={styles.contactItem} />
|
||||
<PhoneContactItem phone={basics.phone} style={styles.contactItem} />
|
||||
<LocationContactItem location={basics.location} style={styles.contactItem} />
|
||||
@@ -117,9 +140,9 @@ const Header = ({ styles }: LeafishHeaderProps) => {
|
||||
{basics.customFields.map((field) => (
|
||||
<CustomFieldContactItem key={field.id} field={field} style={styles.contactItem} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</SemanticContactListView>
|
||||
</SemanticTemplatePartView>
|
||||
</SemanticHeaderView>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { TemplateSemanticManifest } from "../../semantic/template-manifest";
|
||||
|
||||
export const leafishSemanticManifest = {
|
||||
template: "leafish",
|
||||
regions: [
|
||||
{ name: "header", placement: "main", origins: [] },
|
||||
{ name: "main", placement: "main", origins: ["main"] },
|
||||
{ name: "sidebar", placement: "sidebar", origins: ["sidebar"] },
|
||||
],
|
||||
header: { region: "header", placement: "main" },
|
||||
specialSummary: { region: "header", placement: "main", source: "always" },
|
||||
parts: [
|
||||
{
|
||||
name: "header-intro",
|
||||
key: "header-intro",
|
||||
owner: { kind: "header", key: "header" },
|
||||
binding: { type: "primitive", primitive: "View", source: "existing" },
|
||||
route: {
|
||||
parent: "owner",
|
||||
at: "start",
|
||||
take: [{ kind: "picture" }, { kind: "name" }, { kind: "headline" }, { kind: "section", name: "summary" }],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "header-body",
|
||||
key: "header-body",
|
||||
owner: { kind: "header", key: "header" },
|
||||
binding: { type: "primitive", primitive: "View", source: "existing" },
|
||||
route: { parent: "header-intro", at: "start", take: "all" },
|
||||
},
|
||||
{
|
||||
name: "header-contact-band",
|
||||
key: "header-contact-band",
|
||||
owner: { kind: "header", key: "header" },
|
||||
binding: { type: "primitive", primitive: "View", source: "existing" },
|
||||
route: { parent: "owner", at: "end", take: [{ kind: "contact-list" }] },
|
||||
},
|
||||
],
|
||||
} as const satisfies TemplateSemanticManifest;
|
||||
Reference in New Issue
Block a user