mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-14 14:57:00 +10:00
fixes #2530
This commit is contained in:
@@ -113,7 +113,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -92,7 +92,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -104,7 +104,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -101,7 +101,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -113,7 +113,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -87,7 +87,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -106,7 +106,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -100,7 +100,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -84,7 +84,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -102,7 +102,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -85,7 +85,7 @@ function Header() {
|
||||
{basics.customFields.map((field) => (
|
||||
<div key={field.id} className="basics-item-custom">
|
||||
<PageIcon icon={field.icon} />
|
||||
<span>{field.text}</span>
|
||||
{field.link ? <PageLink url={field.link} label={field.text} /> : <span>{field.text}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -422,6 +422,7 @@ export class ReactiveResumeV4JSONImporter {
|
||||
id: field.id ?? generateId(),
|
||||
icon: field.icon ?? "",
|
||||
text: field.text ?? "",
|
||||
link: "",
|
||||
})),
|
||||
},
|
||||
summary: {
|
||||
|
||||
@@ -27,6 +27,7 @@ export function Hero() {
|
||||
muted
|
||||
autoPlay
|
||||
playsInline
|
||||
// @ts-expect-error - typescript doesn't know about fetchpriority for video elements
|
||||
fetchpriority="high"
|
||||
src="/videos/timelapse.webm"
|
||||
aria-label={t`Timelapse demonstration of building a resume with Reactive Resume`}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
import { DotsSixVerticalIcon, ListPlusIcon, XIcon } from "@phosphor-icons/react";
|
||||
import { DotsSixVerticalIcon, LinkIcon, ListPlusIcon, XIcon } from "@phosphor-icons/react";
|
||||
import { Reorder, useDragControls } from "motion/react";
|
||||
import { useFieldArray, useFormContext, useWatch } from "react-hook-form";
|
||||
import { Controller, useFieldArray, useFormContext, useWatch } from "react-hook-form";
|
||||
import type z from "zod";
|
||||
import { Button } from "@/components/animate-ui/components/buttons/button";
|
||||
import { IconPicker } from "@/components/input/icon-picker";
|
||||
import { FormControl, FormField, FormItem } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import type { basicsSchema } from "@/schema/resume/data";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
@@ -41,7 +42,7 @@ export function CustomFieldsSection({ onSubmit }: Props) {
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
customFieldsArray.append({ id: generateId(), icon: "acorn", text: "" });
|
||||
customFieldsArray.append({ id: generateId(), icon: "acorn", text: "", link: "" });
|
||||
form.handleSubmit(onSubmit)();
|
||||
}
|
||||
|
||||
@@ -87,7 +88,39 @@ export function CustomFieldsSection({ onSubmit }: Props) {
|
||||
)}
|
||||
/>
|
||||
|
||||
<Button size="icon" variant="ghost" className="ml-2" onClick={() => handleRemove(index)}>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button size="icon" variant="ghost" className="ml-1">
|
||||
<LinkIcon />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
||||
<PopoverContent align="center">
|
||||
<div className="flex flex-col gap-y-1.5">
|
||||
<span className="text-muted-foreground text-xs">
|
||||
<Trans>Enter the URL to link to</Trans>
|
||||
</span>
|
||||
|
||||
<Controller
|
||||
control={form.control}
|
||||
name={`customFields.${index}.link`}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
type="url"
|
||||
value={field.value}
|
||||
placeholder="Must start with https://"
|
||||
onChange={(e) => {
|
||||
field.onChange(e.target.value);
|
||||
form.handleSubmit(onSubmit)();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
<Button size="icon" variant="ghost" onClick={() => handleRemove(index)}>
|
||||
<XIcon />
|
||||
</Button>
|
||||
</CustomFieldItem>
|
||||
|
||||
+11
-60
@@ -7,65 +7,6 @@ export const iconSchema = z
|
||||
"The icon to display for the custom field. Must be a valid icon name from @phosphor-icons/web icon set, or an empty string to hide. Default to '' (empty string) when unsure which icons are available.",
|
||||
);
|
||||
|
||||
export const localeSchema = z
|
||||
.union([
|
||||
z.literal("af-ZA"),
|
||||
z.literal("am-ET"),
|
||||
z.literal("ar-SA"),
|
||||
z.literal("az-AZ"),
|
||||
z.literal("bg-BG"),
|
||||
z.literal("bn-BD"),
|
||||
z.literal("ca-ES"),
|
||||
z.literal("cs-CZ"),
|
||||
z.literal("da-DK"),
|
||||
z.literal("de-DE"),
|
||||
z.literal("el-GR"),
|
||||
z.literal("en-US"),
|
||||
z.literal("es-ES"),
|
||||
z.literal("fa-IR"),
|
||||
z.literal("fi-FI"),
|
||||
z.literal("fr-FR"),
|
||||
z.literal("he-IL"),
|
||||
z.literal("hi-IN"),
|
||||
z.literal("hu-HU"),
|
||||
z.literal("id-ID"),
|
||||
z.literal("it-IT"),
|
||||
z.literal("ja-JP"),
|
||||
z.literal("km-KH"),
|
||||
z.literal("kn-IN"),
|
||||
z.literal("ko-KR"),
|
||||
z.literal("lt-LT"),
|
||||
z.literal("lv-LV"),
|
||||
z.literal("ml-IN"),
|
||||
z.literal("mr-IN"),
|
||||
z.literal("ms-MY"),
|
||||
z.literal("ne-NP"),
|
||||
z.literal("nl-NL"),
|
||||
z.literal("no-NO"),
|
||||
z.literal("or-IN"),
|
||||
z.literal("pl-PL"),
|
||||
z.literal("pt-BR"),
|
||||
z.literal("pt-PT"),
|
||||
z.literal("ro-RO"),
|
||||
z.literal("ru-RU"),
|
||||
z.literal("sk-SK"),
|
||||
z.literal("sq-AL"),
|
||||
z.literal("sr-SP"),
|
||||
z.literal("sv-SE"),
|
||||
z.literal("ta-IN"),
|
||||
z.literal("te-IN"),
|
||||
z.literal("th-TH"),
|
||||
z.literal("tr-TR"),
|
||||
z.literal("uk-UA"),
|
||||
z.literal("uz-UZ"),
|
||||
z.literal("vi-VN"),
|
||||
z.literal("zh-CN"),
|
||||
z.literal("zh-TW"),
|
||||
z.literal("zu-ZA"),
|
||||
])
|
||||
.describe("The language used in the resume, used for displaying pre-translated section headings, if not overridden.")
|
||||
.catch("en-US");
|
||||
|
||||
export const urlSchema = z.object({
|
||||
url: z
|
||||
.string()
|
||||
@@ -124,6 +65,11 @@ export const customFieldSchema = z.object({
|
||||
id: z.string().describe("The unique identifier for the custom field. Usually generated as a UUID."),
|
||||
icon: iconSchema,
|
||||
text: z.string().describe("The text to display for the custom field."),
|
||||
link: z
|
||||
.url()
|
||||
.or(z.literal(""))
|
||||
.describe("If the custom field should be a link, the URL to link to. Leave blank to hide.")
|
||||
.catch(""),
|
||||
});
|
||||
|
||||
export const basicsSchema = z.object({
|
||||
@@ -431,7 +377,10 @@ export const pageSchema = z.object({
|
||||
marginX: z.number().min(0).describe("The horizontal margin of the page, defined in points (pt)."),
|
||||
marginY: z.number().min(0).describe("The vertical margin of the page, defined in points (pt)."),
|
||||
format: z.enum(["a4", "letter"]).describe("The format of the page. Can be 'a4' or 'letter'."),
|
||||
locale: localeSchema,
|
||||
locale: z
|
||||
.string()
|
||||
.describe("The locale of the page. Used for displaying pre-translated section headings, if not overridden.")
|
||||
.catch("en-US"),
|
||||
hideIcons: z.boolean().describe("Whether to hide the icons of the sections.").catch(false),
|
||||
});
|
||||
|
||||
@@ -683,11 +632,13 @@ export const sampleResumeData: ResumeData = {
|
||||
id: "cf1",
|
||||
icon: "github-logo",
|
||||
text: "github.com/dkowalski-dev",
|
||||
link: "https://github.com/dkowalski-dev",
|
||||
},
|
||||
{
|
||||
id: "cf2",
|
||||
icon: "game-controller",
|
||||
text: "itch.io/dkowalski",
|
||||
link: "https://itch.io/dkowalski",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
Vendored
-8
@@ -1,19 +1,11 @@
|
||||
/// <reference types="vite-plugin-pwa/client" />
|
||||
|
||||
import type { AriaAttributes, DOMAttributes } from "react";
|
||||
|
||||
declare const __APP_VERSION__: string;
|
||||
|
||||
declare module "*.css";
|
||||
declare module "@fontsource/*" {}
|
||||
declare module "@fontsource-variable/*" {}
|
||||
|
||||
declare module "react" {
|
||||
interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
|
||||
fetchpriority?: "high" | "low" | "auto";
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
// Basics
|
||||
|
||||
Reference in New Issue
Block a user