* refactor to @base-ui/react

* fix all

* fixes to accordion

* more updates

* switch to chat/completions api from openai

* update version to v5.0.12
This commit is contained in:
Amruth Pillai
2026-03-17 23:38:06 +01:00
committed by GitHub
parent 89beb43ea2
commit 5cd16a62d9
192 changed files with 7333 additions and 9548 deletions
+31 -31
View File
@@ -90,9 +90,7 @@ const CreateApiKeyForm = ({ setApiKey }: CreateApiKeyFormProps) => {
<FormLabel>
<Trans>Name</Trans>
</FormLabel>
<FormControl>
<Input min={1} max={64} {...field} />
</FormControl>
<FormControl render={<Input min={1} max={64} {...field} />} />
<FormMessage />
<FormDescription>
<Trans>
@@ -112,34 +110,36 @@ const CreateApiKeyForm = ({ setApiKey }: CreateApiKeyFormProps) => {
<FormLabel>
<Trans>Expires in</Trans>
</FormLabel>
<FormControl>
<Combobox
value={field.value}
onValueChange={(value) => value && field.onChange(Number(value))}
options={[
{
// 1 month = 30 days
value: 3600 * 24 * 30,
label: t`1 month`,
},
{
// 3 months = 90 days
value: 3600 * 24 * 90,
label: t`3 months`,
},
{
// 6 months = 180 days
value: 3600 * 24 * 180,
label: t`6 months`,
},
{
// 1 year = 365 days
value: 3600 * 24 * 365,
label: t`1 year`,
},
]}
/>
</FormControl>
<FormControl
render={
<Combobox
value={field.value}
onValueChange={(value) => value && field.onChange(Number(value))}
options={[
{
// 1 month = 30 days
value: 3600 * 24 * 30,
label: t`1 month`,
},
{
// 3 months = 90 days
value: 3600 * 24 * 90,
label: t`3 months`,
},
{
// 6 months = 180 days
value: 3600 * 24 * 180,
label: t`6 months`,
},
{
// 1 year = 365 days
value: 3600 * 24 * 365,
label: t`1 year`,
},
]}
/>
}
/>
<FormMessage />
</FormItem>
)}
+22 -18
View File
@@ -85,15 +85,17 @@ export function ChangePasswordDialog(_: DialogProps<"auth.change-password">) {
<Trans>Current Password</Trans>
</FormLabel>
<div className="flex items-center gap-x-1.5">
<FormControl>
<Input
min={6}
max={64}
type={showCurrentPassword ? "text" : "password"}
autoComplete="current-password"
{...field}
/>
</FormControl>
<FormControl
render={
<Input
min={6}
max={64}
type={showCurrentPassword ? "text" : "password"}
autoComplete="current-password"
{...field}
/>
}
/>
<Button size="icon" variant="ghost" type="button" onClick={toggleShowCurrentPassword}>
{showCurrentPassword ? <EyeIcon /> : <EyeSlashIcon />}
@@ -113,15 +115,17 @@ export function ChangePasswordDialog(_: DialogProps<"auth.change-password">) {
<Trans>New Password</Trans>
</FormLabel>
<div className="flex items-center gap-x-1.5">
<FormControl>
<Input
min={6}
max={64}
type={showNewPassword ? "text" : "password"}
autoComplete="new-password"
{...field}
/>
</FormControl>
<FormControl
render={
<Input
min={6}
max={64}
type={showNewPassword ? "text" : "password"}
autoComplete="new-password"
{...field}
/>
}
/>
<Button size="icon" variant="ghost" type="button" onClick={toggleShowNewPassword}>
{showNewPassword ? <EyeIcon /> : <EyeSlashIcon />}
+11 -9
View File
@@ -77,15 +77,17 @@ export function DisableTwoFactorDialog(_: DialogProps<"auth.two-factor.disable">
<Trans>Password</Trans>
</FormLabel>
<div className="flex items-center gap-x-1.5">
<FormControl>
<Input
min={6}
max={64}
type={showPassword ? "text" : "password"}
autoComplete="current-password"
{...field}
/>
</FormControl>
<FormControl
render={
<Input
min={6}
max={64}
type={showPassword ? "text" : "password"}
autoComplete="current-password"
{...field}
/>
}
/>
<Button size="icon" variant="ghost" type="button" onClick={toggleShowPassword}>
{showPassword ? <EyeIcon /> : <EyeSlashIcon />}
+32 -28
View File
@@ -189,15 +189,17 @@ export function EnableTwoFactorDialog(_: DialogProps<"auth.two-factor.enable">)
<Trans>Password</Trans>
</FormLabel>
<div className="flex items-center gap-x-1.5">
<FormControl>
<Input
min={6}
max={64}
type={showPassword ? "text" : "password"}
autoComplete="current-password"
{...field}
/>
</FormControl>
<FormControl
render={
<Input
min={6}
max={64}
type={showPassword ? "text" : "password"}
autoComplete="current-password"
{...field}
/>
}
/>
<Button size="icon" variant="ghost" type="button" onClick={toggleShowPassword}>
{showPassword ? <EyeIcon /> : <EyeSlashIcon />}
@@ -244,25 +246,27 @@ export function EnableTwoFactorDialog(_: DialogProps<"auth.two-factor.enable">)
name="code"
render={({ field }) => (
<FormItem>
<FormControl>
<InputOTP
maxLength={6}
value={field.value}
onChange={field.onChange}
pattern={REGEXP_ONLY_DIGITS}
onComplete={verifyForm.handleSubmit(onVerifySubmit)}
pasteTransformer={(pasted) => pasted.replaceAll("-", "")}
>
<InputOTPGroup>
<InputOTPSlot index={0} className="size-12" />
<InputOTPSlot index={1} className="size-12" />
<InputOTPSlot index={2} className="size-12" />
<InputOTPSlot index={3} className="size-12" />
<InputOTPSlot index={4} className="size-12" />
<InputOTPSlot index={5} className="size-12" />
</InputOTPGroup>
</InputOTP>
</FormControl>
<FormControl
render={
<InputOTP
maxLength={6}
value={field.value}
onChange={field.onChange}
pattern={REGEXP_ONLY_DIGITS}
onComplete={verifyForm.handleSubmit(onVerifySubmit)}
pasteTransformer={(pasted) => pasted.replaceAll("-", "")}
>
<InputOTPGroup>
<InputOTPSlot index={0} className="size-12" />
<InputOTPSlot index={1} className="size-12" />
<InputOTPSlot index={2} className="size-12" />
<InputOTPSlot index={3} className="size-12" />
<InputOTPSlot index={4} className="size-12" />
<InputOTPSlot index={5} className="size-12" />
</InputOTPGroup>
</InputOTP>
}
/>
<FormMessage />
</FormItem>
)}
+2 -2
View File
@@ -27,7 +27,7 @@ import { useDialogStore } from "./store";
export function DialogManager() {
const { open, activeDialog, onOpenChange } = useDialogStore();
const dialogContent = match(activeDialog)
const DialogContent = match(activeDialog)
.with({ type: "auth.change-password" }, () => <ChangePasswordDialog />)
.with({ type: "auth.two-factor.enable" }, () => <EnableTwoFactorDialog />)
.with({ type: "auth.two-factor.disable" }, () => <DisableTwoFactorDialog />)
@@ -71,7 +71,7 @@ export function DialogManager() {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
{dialogContent}
{DialogContent}
</Dialog>
);
}
+48 -48
View File
@@ -226,34 +226,36 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
<FormLabel>
<Trans>Type</Trans>
</FormLabel>
<FormControl>
<Combobox
clearable={false}
value={field.value}
onValueChange={field.onChange}
options={[
{ value: "reactive-resume-json", label: "Reactive Resume (JSON)" },
{ value: "reactive-resume-v4-json", label: "Reactive Resume v4 (JSON)" },
{ value: "json-resume-json", label: "JSON Resume" },
{
value: "pdf",
label: (
<div className="flex items-center gap-x-2">
PDF <Badge>{t`AI`}</Badge>
</div>
),
},
{
value: "docx",
label: (
<div className="flex items-center gap-x-2">
Microsoft Word <Badge>{t`AI`}</Badge>
</div>
),
},
]}
/>
</FormControl>
<FormControl
render={
<Combobox
showClear={false}
value={field.value}
onValueChange={field.onChange}
options={[
{ value: "reactive-resume-json", label: "Reactive Resume (JSON)" },
{ value: "reactive-resume-v4-json", label: "Reactive Resume v4 (JSON)" },
{ value: "json-resume-json", label: "JSON Resume" },
{
value: "pdf",
label: (
<div className="flex items-center gap-x-2">
PDF <Badge>{t`AI`}</Badge>
</div>
),
},
{
value: "docx",
label: (
<div className="flex items-center gap-x-2">
Microsoft Word <Badge>{t`AI`}</Badge>
</div>
),
},
]}
/>
}
/>
<FormMessage />
</FormItem>
)}
@@ -266,27 +268,25 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
render={({ field }) => (
<FormItem className={cn(!type && "hidden")}>
<FormControl>
<div>
<Input type="file" className="hidden" ref={inputRef} onChange={onUploadFile} />
<Input type="file" className="hidden" ref={inputRef} onChange={onUploadFile} />
<Button
variant="outline"
className="h-auto w-full flex-col border-dashed py-8 font-normal"
onClick={onSelectFile}
>
{field.value ? (
<>
<FileIcon weight="thin" size={32} />
<p>{field.value.name}</p>
</>
) : (
<>
<UploadSimpleIcon weight="thin" size={32} />
<Trans>Click here to select a file to import</Trans>
</>
)}
</Button>
</div>
<Button
variant="outline"
className="h-auto w-full flex-col border-dashed py-8 font-normal"
onClick={onSelectFile}
>
{field.value ? (
<>
<FileIcon weight="thin" size={32} />
<p>{field.value.name}</p>
</>
) : (
<>
<UploadSimpleIcon weight="thin" size={32} />
<Trans>Click here to select a file to import</Trans>
</>
)}
</Button>
</FormControl>
<FormMessage />
</FormItem>
+20 -20
View File
@@ -125,14 +125,16 @@ export function CreateResumeDialog(_: DialogProps<"resume.create">) {
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="icon" disabled={isPending}>
<CaretDownIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuTrigger
render={
<Button size="icon" disabled={isPending}>
<CaretDownIcon />
</Button>
}
/>
<DropdownMenuContent align="end" className="w-fit">
<DropdownMenuItem onSelect={onCreateSampleResume}>
<DropdownMenuItem onClick={onCreateSampleResume}>
<TestTubeIcon />
<Trans>Create a Sample Resume</Trans>
</DropdownMenuItem>
@@ -309,9 +311,7 @@ function ResumeForm() {
<Trans>Name</Trans>
</FormLabel>
<div className="flex items-center gap-x-2">
<FormControl>
<Input min={1} max={64} {...field} />
</FormControl>
<FormControl render={<Input min={1} max={64} {...field} />} />
<Button size="icon" variant="outline" title={t`Generate a random name`} onClick={onGenerateName}>
<MagicWandIcon />
@@ -333,14 +333,16 @@ function ResumeForm() {
<FormLabel>
<Trans>Slug</Trans>
</FormLabel>
<FormControl>
<InputGroup>
<InputGroupAddon align="inline-start" className="hidden sm:flex">
<InputGroupText>{slugPrefix}</InputGroupText>
</InputGroupAddon>
<InputGroupInput min={1} max={64} className="ps-0!" {...field} />
</InputGroup>
</FormControl>
<FormControl
render={
<InputGroup>
<InputGroupAddon align="inline-start" className="hidden sm:flex">
<InputGroupText>{slugPrefix}</InputGroupText>
</InputGroupAddon>
<InputGroupInput min={1} max={64} className="ps-0!" {...field} />
</InputGroup>
}
/>
<FormMessage />
<FormDescription>
<Trans>This is a URL-friendly name for your resume.</Trans>
@@ -357,9 +359,7 @@ function ResumeForm() {
<FormLabel>
<Trans>Tags</Trans>
</FormLabel>
<FormControl>
<ChipInput {...field} />
</FormControl>
<FormControl render={<ChipInput {...field} />} />
<FormMessage />
<FormDescription>
<Trans>Tags can be used to categorize your resume by keywords.</Trans>
+12 -24
View File
@@ -159,9 +159,7 @@ function AwardForm() {
<FormLabel>
<Trans>Title</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -175,9 +173,7 @@ function AwardForm() {
<FormLabel>
<Trans context="(noun) person, organization, or entity that gives an award">Awarder</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -191,9 +187,7 @@ function AwardForm() {
<FormLabel>
<Trans>Date</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -207,14 +201,12 @@ function AwardForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -225,10 +217,8 @@ function AwardForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -243,9 +233,7 @@ function AwardForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+12 -24
View File
@@ -159,9 +159,7 @@ function CertificationForm() {
<FormLabel>
<Trans>Title</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -175,9 +173,7 @@ function CertificationForm() {
<FormLabel>
<Trans>Issuer</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -191,9 +187,7 @@ function CertificationForm() {
<FormLabel>
<Trans>Date</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -207,14 +201,12 @@ function CertificationForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -225,10 +217,8 @@ function CertificationForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -243,9 +233,7 @@ function CertificationForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+2 -6
View File
@@ -143,9 +143,7 @@ function CoverLetterForm() {
<FormLabel>
<Trans>Recipient</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
@@ -159,9 +157,7 @@ function CoverLetterForm() {
<FormLabel>
<Trans>Content</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+15 -15
View File
@@ -167,9 +167,7 @@ function CustomSectionForm({ isUpdate = false }: { isUpdate?: boolean }) {
<FormLabel>
<Trans>Title</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -183,18 +181,20 @@ function CustomSectionForm({ isUpdate = false }: { isUpdate?: boolean }) {
<FormLabel>
<Trans>Section Type</Trans>
</FormLabel>
<FormControl>
<Combobox
{...field}
value={field.value}
disabled={isUpdate}
onValueChange={field.onChange}
options={SECTION_TYPE_OPTIONS.map((option) => ({
value: option.value,
label: i18n.t(option.label),
}))}
/>
</FormControl>
<FormControl
render={
<Combobox
{...field}
value={field.value}
disabled={isUpdate}
onValueChange={field.onChange}
options={SECTION_TYPE_OPTIONS.map((option) => ({
value: option.value,
label: i18n.t(option.label),
}))}
/>
}
/>
<FormMessage />
</FormItem>
)}
+15 -33
View File
@@ -165,9 +165,7 @@ function EducationForm() {
<FormLabel>
<Trans>School</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -181,9 +179,7 @@ function EducationForm() {
<FormLabel>
<Trans>Degree</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -197,9 +193,7 @@ function EducationForm() {
<FormLabel>
<Trans>Area of Study</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -213,9 +207,7 @@ function EducationForm() {
<FormLabel>
<Trans>Grade</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -229,9 +221,7 @@ function EducationForm() {
<FormLabel>
<Trans>Location</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -245,9 +235,7 @@ function EducationForm() {
<FormLabel>
<Trans>Period</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -261,14 +249,12 @@ function EducationForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -279,10 +265,8 @@ function EducationForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2 sm:col-span-full">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -297,9 +281,7 @@ function EducationForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+17 -35
View File
@@ -204,9 +204,7 @@ function RoleFields({ role, index, onRemove }: RoleFieldsProps) {
<FormLabel>
<Trans>Position</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -220,9 +218,7 @@ function RoleFields({ role, index, onRemove }: RoleFieldsProps) {
<FormLabel>
<Trans>Period</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -236,9 +232,7 @@ function RoleFields({ role, index, onRemove }: RoleFieldsProps) {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
@@ -273,9 +267,7 @@ function ExperienceForm() {
<FormLabel>
<Trans>Company</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -287,9 +279,9 @@ function ExperienceForm() {
render={({ field }) => (
<FormItem>
<FormLabel>{hasRoles ? <Trans>Overall Title (optional)</Trans> : <Trans>Position</Trans>}</FormLabel>
<FormControl>
<Input {...field} placeholder={hasRoles ? "e.g. Software Engineer → Senior Engineer" : ""} />
</FormControl>
<FormControl
render={<Input {...field} placeholder={hasRoles ? "e.g. Software Engineer → Senior Engineer" : ""} />}
/>
<FormMessage />
</FormItem>
)}
@@ -303,9 +295,7 @@ function ExperienceForm() {
<FormLabel>
<Trans>Location</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -317,9 +307,7 @@ function ExperienceForm() {
render={({ field }) => (
<FormItem>
<FormLabel>{hasRoles ? <Trans>Overall Period</Trans> : <Trans>Period</Trans>}</FormLabel>
<FormControl>
<Input {...field} placeholder={hasRoles ? "e.g. 2018 Present" : ""} />
</FormControl>
<FormControl render={<Input {...field} placeholder={hasRoles ? "e.g. 2018 Present" : ""} />} />
<FormMessage />
</FormItem>
)}
@@ -333,14 +321,12 @@ function ExperienceForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -351,9 +337,7 @@ function ExperienceForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2 sm:col-span-full">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel>
<Trans>Show link in title</Trans>
</FormLabel>
@@ -408,9 +392,7 @@ function ExperienceForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+7 -9
View File
@@ -157,9 +157,11 @@ function InterestForm() {
name={"icon"}
render={({ field }) => (
<FormItem className="shrink-0">
<FormControl>
<IconPicker {...field} popoverProps={{ modal: true }} className="rounded-r-none! border-e-0!" />
</FormControl>
<FormControl
render={
<IconPicker {...field} popoverProps={{ modal: true }} className="rounded-r-none! border-e-0!" />
}
/>
</FormItem>
)}
/>
@@ -172,9 +174,7 @@ function InterestForm() {
<FormLabel>
<Trans>Name</Trans>
</FormLabel>
<FormControl>
<Input className="rounded-l-none!" {...field} />
</FormControl>
<FormControl render={<Input className="rounded-l-none!" {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -189,9 +189,7 @@ function InterestForm() {
<FormLabel>
<Trans>Keywords</Trans>
</FormLabel>
<FormControl>
<ChipInput {...field} />
</FormControl>
<FormControl render={<ChipInput {...field} />} />
<FormMessage />
</FormItem>
)}
+13 -15
View File
@@ -152,9 +152,7 @@ function LanguageForm() {
<FormLabel>
<Trans>Language</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -168,9 +166,7 @@ function LanguageForm() {
<FormLabel>
<Trans>Fluency</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -184,15 +180,17 @@ function LanguageForm() {
<FormLabel>
<Trans>Level</Trans>
</FormLabel>
<FormControl>
<Slider
min={0}
max={5}
step={1}
value={[field.value]}
onValueChange={(value) => field.onChange(value[0])}
/>
</FormControl>
<FormControl
render={
<Slider
min={0}
max={5}
step={1}
value={[field.value]}
onValueChange={(value) => field.onChange(Array.isArray(value) ? value[0] : value)}
/>
}
/>
<FormMessage />
<FormDescription>{Number(field.value) === 0 ? t`Hidden` : `${field.value} / 5`}</FormDescription>
</FormItem>
+15 -21
View File
@@ -162,9 +162,11 @@ function ProfileForm() {
name={"icon"}
render={({ field }) => (
<FormItem className="shrink-0">
<FormControl>
<IconPicker {...field} popoverProps={{ modal: true }} className="rounded-r-none! border-e-0!" />
</FormControl>
<FormControl
render={
<IconPicker {...field} popoverProps={{ modal: true }} className="rounded-r-none! border-e-0!" />
}
/>
</FormItem>
)}
/>
@@ -177,9 +179,7 @@ function ProfileForm() {
<FormLabel>
<Trans>Network</Trans>
</FormLabel>
<FormControl>
<Input className="rounded-l-none!" {...field} />
</FormControl>
<FormControl render={<Input className="rounded-l-none!" {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -201,9 +201,7 @@ function ProfileForm() {
</InputGroupText>
</InputGroupAddon>
<FormControl>
<InputGroupInput {...field} />
</FormControl>
<FormControl render={<InputGroupInput {...field} />} />
</InputGroup>
<FormMessage />
</FormItem>
@@ -218,14 +216,12 @@ function ProfileForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -236,10 +232,8 @@ function ProfileForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2 sm:col-span-full">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
+11 -21
View File
@@ -157,9 +157,7 @@ function ProjectForm() {
<FormLabel>
<Trans>Name</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -173,9 +171,7 @@ function ProjectForm() {
<FormLabel>
<Trans>Period</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -189,14 +185,12 @@ function ProjectForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -207,10 +201,8 @@ function ProjectForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2 sm:col-span-full">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -225,9 +217,7 @@ function ProjectForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+12 -24
View File
@@ -159,9 +159,7 @@ function PublicationForm() {
<FormLabel>
<Trans>Title</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -175,9 +173,7 @@ function PublicationForm() {
<FormLabel>
<Trans>Publisher</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -191,9 +187,7 @@ function PublicationForm() {
<FormLabel>
<Trans>Date</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -207,14 +201,12 @@ function PublicationForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -225,10 +217,8 @@ function PublicationForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -243,9 +233,7 @@ function PublicationForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+12 -24
View File
@@ -159,9 +159,7 @@ function ReferenceForm() {
<FormLabel>
<Trans>Name</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -175,9 +173,7 @@ function ReferenceForm() {
<FormLabel>
<Trans>Position</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -191,9 +187,7 @@ function ReferenceForm() {
<FormLabel>
<Trans>Phone</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -207,14 +201,12 @@ function ReferenceForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -225,10 +217,8 @@ function ReferenceForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -243,9 +233,7 @@ function ReferenceForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+19 -21
View File
@@ -163,9 +163,11 @@ function SkillForm() {
name={"icon"}
render={({ field }) => (
<FormItem className="shrink-0">
<FormControl>
<IconPicker {...field} popoverProps={{ modal: true }} className="rounded-r-none! border-e-0!" />
</FormControl>
<FormControl
render={
<IconPicker {...field} popoverProps={{ modal: true }} className="rounded-r-none! border-e-0!" />
}
/>
</FormItem>
)}
/>
@@ -178,9 +180,7 @@ function SkillForm() {
<FormLabel>
<Trans>Name</Trans>
</FormLabel>
<FormControl>
<Input className="rounded-l-none!" {...field} />
</FormControl>
<FormControl render={<Input className="rounded-l-none!" {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -195,9 +195,7 @@ function SkillForm() {
<FormLabel>
<Trans>Proficiency</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -211,15 +209,17 @@ function SkillForm() {
<FormLabel>
<Trans>Level</Trans>
</FormLabel>
<FormControl>
<Slider
min={0}
max={5}
step={1}
value={[field.value]}
onValueChange={(value) => field.onChange(value[0])}
/>
</FormControl>
<FormControl
render={
<Slider
min={0}
max={5}
step={1}
value={[field.value]}
onValueChange={(value) => field.onChange(Array.isArray(value) ? value[0] : value)}
/>
}
/>
<FormMessage />
<FormDescription>{Number(field.value) === 0 ? t`Hidden` : `${field.value} / 5`}</FormDescription>
</FormItem>
@@ -234,9 +234,7 @@ function SkillForm() {
<FormLabel>
<Trans>Keywords</Trans>
</FormLabel>
<FormControl>
<ChipInput {...field} />
</FormControl>
<FormControl render={<ChipInput {...field} />} />
<FormMessage />
</FormItem>
)}
+1 -3
View File
@@ -140,9 +140,7 @@ function SummaryItemForm() {
<FormLabel>
<Trans>Content</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+12 -24
View File
@@ -159,9 +159,7 @@ function VolunteerForm() {
<FormLabel>
<Trans>Organization</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -175,9 +173,7 @@ function VolunteerForm() {
<FormLabel>
<Trans>Location</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -191,9 +187,7 @@ function VolunteerForm() {
<FormLabel>
<Trans>Period</Trans>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormControl render={<Input {...field} />} />
<FormMessage />
</FormItem>
)}
@@ -207,14 +201,12 @@ function VolunteerForm() {
<FormLabel>
<Trans>Website</Trans>
</FormLabel>
<FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
</FormControl>
<URLInput
{...field}
value={field.value}
onChange={field.onChange}
hideLabelButton={form.watch("options.showLinkInTitle")}
/>
<FormMessage />
</FormItem>
)}
@@ -225,10 +217,8 @@ function VolunteerForm() {
name="options.showLinkInTitle"
render={({ field }) => (
<FormItem className="flex items-center gap-x-2">
<FormControl>
<Switch checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className="!mt-0">
<FormControl render={<Switch checked={field.value} onCheckedChange={field.onChange} />} />
<FormLabel className="mt-0!">
<Trans>Show link in title</Trans>
</FormLabel>
</FormItem>
@@ -243,9 +233,7 @@ function VolunteerForm() {
<FormLabel>
<Trans>Description</Trans>
</FormLabel>
<FormControl>
<RichInput {...field} value={field.value} onChange={field.onChange} />
</FormControl>
<FormControl render={<RichInput {...field} value={field.value} onChange={field.onChange} />} />
<FormMessage />
</FormItem>
)}
+17 -21
View File
@@ -1,7 +1,6 @@
import { useLingui } from "@lingui/react";
import { Trans } from "@lingui/react/macro";
import { SlideshowIcon } from "@phosphor-icons/react";
import { type RefObject, useRef } from "react";
import { CometCard } from "@/components/animation/comet-card";
import { useResumeStore } from "@/components/resume/store/resume";
import { Badge } from "@/components/ui/badge";
@@ -14,8 +13,6 @@ import { cn } from "@/utils/style";
import { type TemplateMetadata, templates } from "./data";
export function TemplateGalleryDialog(_: DialogProps<"resume.template.gallery">) {
const scrollAreaRef = useRef<HTMLDivElement | null>(null);
const closeDialog = useDialogStore((state) => state.closeDialog);
const selectedTemplate = useResumeStore((state) => state.resume.data.metadata.template);
const updateResumeData = useResumeStore((state) => state.updateResumeData);
@@ -44,14 +41,13 @@ export function TemplateGalleryDialog(_: DialogProps<"resume.template.gallery">)
</DialogDescription>
</DialogHeader>
<ScrollArea ref={scrollAreaRef} className="max-h-[80svh] pb-8">
<ScrollArea className="max-h-[80svh] pb-8">
<div className="grid grid-cols-2 gap-6 p-4 md:grid-cols-3 lg:grid-cols-4">
{Object.entries(templates).map(([template, metadata]) => (
<TemplateCard
key={template}
metadata={metadata}
id={template as Template}
collisionBoundary={scrollAreaRef}
isActive={template === selectedTemplate}
onSelect={onSelectTemplate}
/>
@@ -66,28 +62,29 @@ type TemplateCardProps = {
id: Template;
isActive?: boolean;
metadata: TemplateMetadata;
collisionBoundary: RefObject<HTMLDivElement | null>;
onSelect: (template: Template) => void;
};
function TemplateCard({ id, metadata, isActive, collisionBoundary, onSelect }: TemplateCardProps) {
function TemplateCard({ id, metadata, isActive, onSelect }: TemplateCardProps) {
const { i18n } = useLingui();
return (
<HoverCard openDelay={0} closeDelay={0}>
<HoverCard>
<CometCard translateDepth={3} rotateDepth={6} glareOpacity={0}>
<HoverCardTrigger asChild>
<button
tabIndex={-1}
onClick={() => onSelect(id)}
className={cn(
"relative block aspect-page size-full cursor-pointer overflow-hidden rounded-md bg-popover outline-none",
isActive && "ring-2 ring-ring ring-offset-4 ring-offset-background",
)}
>
<img src={metadata.imageUrl} alt={metadata.name} className="size-full object-cover" />
</button>
</HoverCardTrigger>
<HoverCardTrigger
render={
<button
tabIndex={-1}
onClick={() => onSelect(id)}
className={cn(
"relative block aspect-page size-full cursor-pointer overflow-hidden rounded-md bg-popover outline-none",
isActive && "ring-2 ring-ring ring-offset-4 ring-offset-background",
)}
>
<img src={metadata.imageUrl} alt={metadata.name} className="size-full object-cover" />
</button>
}
/>
<div className="flex items-center justify-center">
<span className="font-bold leading-loose tracking-tight">{metadata.name}</span>
@@ -98,7 +95,6 @@ function TemplateCard({ id, metadata, isActive, collisionBoundary, onSelect }: T
sideOffset={-32}
align="start"
alignOffset={32}
collisionBoundary={collisionBoundary.current}
className="pointer-events-none! flex w-80 flex-col justify-between space-y-6 rounded-md bg-background/80 p-4 pb-6"
>
<div className="space-y-1">