@@ -29,7 +31,12 @@ export const PublicResumePage = () => {
{resume.metadata.layout.map((columns, pageIndex) => (
-
+ {template !== null && (
+
+ )}
))}
diff --git a/libs/hooks/src/hooks/use-template.ts b/libs/hooks/src/hooks/use-template.ts
new file mode 100644
index 00000000..3bfe95c3
--- /dev/null
+++ b/libs/hooks/src/hooks/use-template.ts
@@ -0,0 +1,12 @@
+import { templatesList } from "@reactive-resume/templates";
+import { useMemo } from "react";
+
+export const useTemplate = (templateId?: string) => {
+ const template = useMemo(() => {
+ return templatesList.find((template) => template.id === templateId);
+ }, [templateId]);
+
+ if (!template || !template.Component) return null;
+
+ return template;
+};
diff --git a/libs/hooks/src/index.ts b/libs/hooks/src/index.ts
index 9e33af74..615d124b 100644
--- a/libs/hooks/src/index.ts
+++ b/libs/hooks/src/index.ts
@@ -1,4 +1,5 @@
export * from "./hooks/use-breakpoint";
export * from "./hooks/use-form-field";
export * from "./hooks/use-password-toggle";
+export * from "./hooks/use-template";
export * from "./hooks/use-theme";
diff --git a/libs/schema/src/basics/custom.ts b/libs/schema/src/basics/custom.ts
index 23cd251f..4b95f613 100644
--- a/libs/schema/src/basics/custom.ts
+++ b/libs/schema/src/basics/custom.ts
@@ -2,6 +2,7 @@ import { z } from "zod";
export const customFieldSchema = z.object({
id: z.string().cuid2(),
+ icon: z.string(),
name: z.string(),
value: z.string(),
});
diff --git a/libs/schema/src/sections/custom-section.ts b/libs/schema/src/sections/custom-section.ts
index 30c062ef..d62dca53 100644
--- a/libs/schema/src/sections/custom-section.ts
+++ b/libs/schema/src/sections/custom-section.ts
@@ -7,7 +7,7 @@ export const customSectionSchema = itemSchema.extend({
name: z.string(),
description: z.string(),
date: z.string(),
- level: z.number().min(0).max(5).default(0),
+ location: z.string(),
summary: z.string(),
keywords: z.array(z.string()).default([]),
url: urlSchema,
@@ -22,7 +22,7 @@ export const defaultCustomSection: CustomSection = {
name: "",
description: "",
date: "",
- level: 0,
+ location: "",
summary: "",
keywords: [],
url: defaultUrl,
diff --git a/libs/templates/src/shared/frame.tsx b/libs/templates/src/shared/frame.tsx
index 50ae0526..aa983dde 100644
--- a/libs/templates/src/shared/frame.tsx
+++ b/libs/templates/src/shared/frame.tsx
@@ -33,34 +33,48 @@ export const FrameWrapper = ({ children, style }: Props) => {
setHeight(`${height}px`);
}, []);
+ const loadFonts = useCallback(
+ (frame: HTMLIFrameElement) => {
+ if (font.family === "CMU Serif") {
+ return webfontloader.load({
+ classes: false,
+ custom: {
+ families: ["CMU Serif"],
+ urls: ["https://cdn.jsdelivr.net/npm/computer-modern/cmu-serif.min.css"],
+ },
+ context: frame.contentWindow!,
+ fontactive: () => handleResize(frame!),
+ });
+ }
+
+ webfontloader.load({
+ classes: false,
+ google: { families: [fontString] },
+ context: frame.contentWindow!,
+ fontactive: () => handleResize(frame!),
+ });
+ },
+ [font, fontString, handleResize],
+ );
+
+ const loadIconFonts = useCallback((frame: HTMLIFrameElement) => {
+ const document = frame.contentDocument!;
+
+ const link = document.createElement("link");
+ link.type = "text/css";
+ link.rel = "stylesheet";
+ link.href = "https://unpkg.com/@phosphor-icons/web@2.0.3/src/regular/style.css";
+
+ document.head.appendChild(link);
+ }, []);
+
const onLoad = useCallback(() => {
if (!frameRef.current) return;
handleResize(frameRef.current);
-
- if (font.family === "CMU Serif") {
- return webfontloader.load({
- classes: false,
- custom: {
- families: ["CMU Serif"],
- urls: ["https://cdn.jsdelivr.net/npm/computer-modern/cmu-serif.min.css"],
- },
- context: frameRef.current.contentWindow!,
- fontactive: () => {
- handleResize(frameRef.current!);
- },
- });
- }
-
- webfontloader.load({
- classes: false,
- google: { families: [fontString] },
- context: frameRef.current.contentWindow!,
- fontactive: () => {
- handleResize(frameRef.current!);
- },
- });
- }, [frameRef, font, fontString, handleResize]);
+ loadFonts(frameRef.current);
+ loadIconFonts(frameRef.current);
+ }, [frameRef, handleResize, loadFonts, loadIconFonts]);
useEffect(() => {
onLoad();
diff --git a/libs/templates/src/styles/shared.ts b/libs/templates/src/styles/shared.ts
index 497c71db..a2940835 100644
--- a/libs/templates/src/styles/shared.ts
+++ b/libs/templates/src/styles/shared.ts
@@ -41,17 +41,14 @@ export const Shared = css
`
h1 {
font-size: 2rem;
- line-height: calc(var(--line-height) + 1.5rem);
}
h2 {
font-size: 1.5rem;
- line-height: calc(var(--line-height) + 1rem);
}
h3 {
font-size: 1rem;
- line-height: calc(var(--line-height) + 0rem);
}
/* Paragraphs */
@@ -67,7 +64,7 @@ export const Shared = css`
small {
font-size: calc(var(--font-size) - 2px);
- line-height: calc(var(--line-height) - 0.5rem);
+ line-height: calc(var(--line-height) - 2px);
}
i,
diff --git a/libs/templates/src/templates/index.ts b/libs/templates/src/templates/index.ts
index ebcd2175..9ef61b7f 100644
--- a/libs/templates/src/templates/index.ts
+++ b/libs/templates/src/templates/index.ts
@@ -1 +1,16 @@
-export * from "./rhyhorn";
+import { TemplateProps } from "../shared";
+import { Rhyhorn } from "./rhyhorn";
+
+type Template = {
+ id: string;
+ name: string;
+ Component: (props: TemplateProps) => JSX.Element;
+};
+
+export const templatesList: Template[] = [
+ {
+ id: "rhyhorn",
+ name: "Rhyhorn",
+ Component: Rhyhorn,
+ },
+];
diff --git a/libs/templates/src/templates/rhyhorn/index.tsx b/libs/templates/src/templates/rhyhorn/index.tsx
index d68b235e..acfd764f 100644
--- a/libs/templates/src/templates/rhyhorn/index.tsx
+++ b/libs/templates/src/templates/rhyhorn/index.tsx
@@ -16,7 +16,7 @@ import { References } from "./sections/references";
import { Skills } from "./sections/skills";
import { Summary } from "./sections/summary";
import { Volunteer } from "./sections/volunteer";
-import { RhyhornStyles } from "./style";
+import { RhyhornWrapper } from "./style";
const sectionMap: Partial React.ReactNode>> = {
summary: Summary,
@@ -44,7 +44,7 @@ const getSection = (id: SectionKey) => {
};
export const Rhyhorn = ({ isFirstPage, columns }: TemplateProps) => (
-
+
{isFirstPage && }
{/* Main */}
@@ -52,5 +52,5 @@ export const Rhyhorn = ({ isFirstPage, columns }: TemplateProps) => (
{/* Sidebar */}
{columns[1].map(getSection)}
-
+
);
diff --git a/libs/templates/src/templates/rhyhorn/sections/awards.tsx b/libs/templates/src/templates/rhyhorn/sections/awards.tsx
index 0a858bf1..521f7a2e 100644
--- a/libs/templates/src/templates/rhyhorn/sections/awards.tsx
+++ b/libs/templates/src/templates/rhyhorn/sections/awards.tsx
@@ -1,7 +1,6 @@
import { Award as IAward } from "@reactive-resume/schema";
import { useStore } from "@reactive-resume/templates";
import { isUrl } from "@reactive-resume/utils";
-import { Fragment } from "react";
import { SectionBase } from "../shared/section-base";
@@ -12,24 +11,27 @@ export const Awards = () => {
section={section}
header={(item) => (
-
+ <>
- {isUrl(item.url.href) ? (
-
- {item.title}
-
- ) : (
-
{item.title}
- )}
+
{item.title}
{item.awarder}
{item.date}
-
+ >
)}
main={(item) => }
+ footer={(item) => (
+
+ )}
/>
);
};
diff --git a/libs/templates/src/templates/rhyhorn/sections/certifications.tsx b/libs/templates/src/templates/rhyhorn/sections/certifications.tsx
index 04274b2f..ef5f26f8 100644
--- a/libs/templates/src/templates/rhyhorn/sections/certifications.tsx
+++ b/libs/templates/src/templates/rhyhorn/sections/certifications.tsx
@@ -1,7 +1,6 @@
import { Certification as ICertification } from "@reactive-resume/schema";
import { useStore } from "@reactive-resume/templates";
import { isUrl } from "@reactive-resume/utils";
-import { Fragment } from "react";
import { SectionBase } from "../shared/section-base";
@@ -12,24 +11,27 @@ export const Certifications = () => {
section={section}
header={(item) => (
-
+ <>
- {isUrl(item.url.href) ? (
-
- {item.name}
-
- ) : (
-
{item.name}
- )}
+
{item.name}
{item.issuer}
{item.date}
-
+ >
)}
main={(item) => }
+ footer={(item) => (
+
+ )}
/>
);
};
diff --git a/libs/templates/src/templates/rhyhorn/sections/custom.tsx b/libs/templates/src/templates/rhyhorn/sections/custom.tsx
index 4af9f601..70012015 100644
--- a/libs/templates/src/templates/rhyhorn/sections/custom.tsx
+++ b/libs/templates/src/templates/rhyhorn/sections/custom.tsx
@@ -6,7 +6,6 @@ import {
import { useStore } from "@reactive-resume/templates";
import { isUrl } from "@reactive-resume/utils";
import get from "lodash.get";
-import { Fragment } from "react";
import { SectionBase } from "../shared/section-base";
@@ -24,30 +23,32 @@ export const CustomSection = ({ id }: Props) => {
section={section}
header={(item: CustomSectionItem) => (
-
+ <>
- {isUrl(item.url.href) ? (
-
- {item.name}
-
- ) : (
-
{item.name}
- )}
+
{item.name}
{item.description}
{item.date}
-
- {Array.from({ length: item.level }).map((_, i) => (
-
- ))}
-
+
{item.location}
-
+ >
)}
main={(item: CustomSectionItem) => }
- footer={(item: CustomSectionItem) => {item.keywords.join(", ")}}
+ footer={(item: CustomSectionItem) => (
+ <>
+ {item.keywords.join(", ")}
+
+
+ >
+ )}
/>
);
};
diff --git a/libs/templates/src/templates/rhyhorn/sections/education.tsx b/libs/templates/src/templates/rhyhorn/sections/education.tsx
index 7df5ca96..05902286 100644
--- a/libs/templates/src/templates/rhyhorn/sections/education.tsx
+++ b/libs/templates/src/templates/rhyhorn/sections/education.tsx
@@ -1,7 +1,6 @@
import { Education as IEducation } from "@reactive-resume/schema";
import { useStore } from "@reactive-resume/templates";
import { isUrl } from "@reactive-resume/utils";
-import { Fragment } from "react";
import { SectionBase } from "../shared/section-base";
@@ -12,15 +11,9 @@ export const Education = () => {
section={section}
header={(item) => (
-
+ <>
- {isUrl(item.url.href) ? (
-
- {item.institution}
-
- ) : (
-
{item.institution}
- )}
+
{item.institution}
{item.area}
@@ -31,9 +24,18 @@ export const Education = () => {
{item.score ? ` | ${item.score}` : ""}
-
+ >
)}
main={(item) =>