fix issue with missing DialogTitle/DialogDescription, fix issue with hot reloads

This commit is contained in:
Amruth Pillai
2025-01-19 22:01:37 +01:00
parent 18cf814779
commit 460a40711e
27 changed files with 136 additions and 277 deletions

View File

@ -1,17 +1,24 @@
import { forwardRef } from "react";
type BrandIconProps = { type BrandIconProps = {
slug: string; slug: string;
}; };
export const BrandIcon = ({ slug }: BrandIconProps) => { export const BrandIcon = forwardRef<HTMLImageElement, BrandIconProps>(({ slug }, ref) => {
if (slug === "linkedin") { if (slug === "linkedin") {
return ( return (
<img <img
alt="linkedin" ref={ref}
alt="LinkedIn"
className="size-4" className="size-4"
src={`${window.location.origin}/support-logos/linkedin.svg`} src={`${window.location.origin}/support-logos/linkedin.svg`}
/> />
); );
} }
return <img alt={slug} className="size-4" src={`https://cdn.simpleicons.org/${slug}`} />; return (
}; <img ref={ref} alt={slug} className="size-4" src={`https://cdn.simpleicons.org/${slug}`} />
);
});
BrandIcon.displayName = "BrandIcon";

View File

@ -1,13 +1,23 @@
import { cn } from "@reactive-resume/utils"; import { forwardRef, useEffect } from "react";
import { useDebounceValue } from "usehooks-ts";
type BrandIconProps = { type BrandIconProps = {
slug: string; slug: string;
}; };
export const BrandIcon = ({ slug }: BrandIconProps) => { export const BrandIcon = forwardRef<HTMLImageElement, BrandIconProps>(({ slug }, ref) => {
if (slug === "linkedin") { const [debouncedSlug, setValue] = useDebounceValue(slug, 600);
useEffect(() => {
setValue(slug);
}, [slug]);
if (!slug) return null;
if (debouncedSlug === "linkedin") {
return ( return (
<img <img
ref={ref}
alt="LinkedIn" alt="LinkedIn"
className="size-5" className="size-5"
src={`${window.location.origin}/support-logos/linkedin.svg`} src={`${window.location.origin}/support-logos/linkedin.svg`}
@ -15,5 +25,14 @@ export const BrandIcon = ({ slug }: BrandIconProps) => {
); );
} }
return <i className={cn("si si--color text-[1.25rem]", `si-${slug}`)} />; return (
}; <img
ref={ref}
alt={debouncedSlug}
className="size-5"
src={`https://cdn.simpleicons.org/${debouncedSlug}`}
/>
);
});
BrandIcon.displayName = "BrandIcon";

View File

@ -1,5 +1,15 @@
import { useBreakpoint } from "@reactive-resume/hooks"; import { useBreakpoint } from "@reactive-resume/hooks";
import { Panel, PanelGroup, PanelResizeHandle, Sheet, SheetContent } from "@reactive-resume/ui"; import {
Panel,
PanelGroup,
PanelResizeHandle,
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
VisuallyHidden,
} from "@reactive-resume/ui";
import { cn } from "@reactive-resume/utils"; import { cn } from "@reactive-resume/utils";
import { Outlet } from "react-router"; import { Outlet } from "react-router";
@ -78,6 +88,13 @@ export const BuilderLayout = () => {
return ( return (
<div className="relative"> <div className="relative">
<Sheet open={sheet.left.open} onOpenChange={sheet.left.setOpen}> <Sheet open={sheet.left.open} onOpenChange={sheet.left.setOpen}>
<VisuallyHidden>
<SheetHeader>
<SheetTitle />
<SheetDescription />
</SheetHeader>
</VisuallyHidden>
<SheetContent <SheetContent
side="left" side="left"
showClose={false} showClose={false}
@ -97,6 +114,13 @@ export const BuilderLayout = () => {
className="top-16 p-0 sm:max-w-xl" className="top-16 p-0 sm:max-w-xl"
onOpenAutoFocus={onOpenAutoFocus} onOpenAutoFocus={onOpenAutoFocus}
> >
<VisuallyHidden>
<SheetHeader>
<SheetTitle />
<SheetDescription />
</SheetHeader>
</VisuallyHidden>
<RightSidebar /> <RightSidebar />
</SheetContent> </SheetContent>
</Sheet> </Sheet>

View File

@ -6,7 +6,7 @@ import { useResumeStore } from "@/client/stores/resume";
import { CustomFieldsSection } from "./custom/section"; import { CustomFieldsSection } from "./custom/section";
import { PictureSection } from "./picture/section"; import { PictureSection } from "./picture/section";
import { getSectionIcon } from "./shared/section-icon"; import { SectionIcon } from "./shared/section-icon";
import { URLInput } from "./shared/url-input"; import { URLInput } from "./shared/url-input";
export const BasicsSection = () => { export const BasicsSection = () => {
@ -17,7 +17,7 @@ export const BasicsSection = () => {
<section id="basics" className="grid gap-y-6"> <section id="basics" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("basics")} <SectionIcon id="basics" size={18} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Basics`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Basics`}</h2>
</div> </div>
</header> </header>

View File

@ -25,7 +25,7 @@ import get from "lodash.get";
import { useDialog } from "@/client/stores/dialog"; import { useDialog } from "@/client/stores/dialog";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "./section-icon"; import { SectionIcon } from "./section-icon";
import { SectionListItem } from "./section-list-item"; import { SectionListItem } from "./section-list-item";
import { SectionOptions } from "./section-options"; import { SectionOptions } from "./section-options";
@ -98,8 +98,7 @@ export const SectionBase = <T extends SectionItem>({ id, title, description }: P
> >
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon(id)} <SectionIcon id={id} size={18} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{section.name}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{section.name}</h2>
</div> </div>

View File

@ -23,7 +23,7 @@ import get from "lodash.get";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
export const getSectionIcon = (id: SectionKey, props: IconProps = {}) => { const getSectionIcon = (id: SectionKey, props: IconProps = {}) => {
switch (id) { switch (id) {
// Left Sidebar // Left Sidebar
case "basics": { case "basics": {
@ -75,13 +75,14 @@ export const getSectionIcon = (id: SectionKey, props: IconProps = {}) => {
} }
}; };
type SectionIconProps = ButtonProps & { type SectionIconProps = Omit<ButtonProps, "size"> & {
id: SectionKey; id: SectionKey;
name?: string; name?: string;
size?: number;
icon?: React.ReactNode; icon?: React.ReactNode;
}; };
export const SectionIcon = ({ id, name, icon, ...props }: SectionIconProps) => { export const SectionIcon = ({ id, name, icon, size = 14, ...props }: SectionIconProps) => {
const section = useResumeStore((state) => const section = useResumeStore((state) =>
get(state.resume.data.sections, id, defaultSection), get(state.resume.data.sections, id, defaultSection),
) as SectionWithItem; ) as SectionWithItem;
@ -89,7 +90,7 @@ export const SectionIcon = ({ id, name, icon, ...props }: SectionIconProps) => {
return ( return (
<Tooltip side="right" content={name ?? section.name}> <Tooltip side="right" content={name ?? section.name}>
<Button size="icon" variant="ghost" className="size-8 rounded-full" {...props}> <Button size="icon" variant="ghost" className="size-8 rounded-full" {...props}>
{icon ?? getSectionIcon(id, { size: 14 })} {icon ?? getSectionIcon(id, { size })}
</Button> </Button>
</Tooltip> </Tooltip>
); );

View File

@ -5,7 +5,7 @@ import { cn } from "@reactive-resume/utils";
import { AiActions } from "@/client/components/ai-actions"; import { AiActions } from "@/client/components/ai-actions";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "./shared/section-icon"; import { SectionIcon } from "./shared/section-icon";
import { SectionOptions } from "./shared/section-options"; import { SectionOptions } from "./shared/section-options";
export const SummarySection = () => { export const SummarySection = () => {
@ -19,7 +19,7 @@ export const SummarySection = () => {
<section id="summary" className="grid gap-y-6"> <section id="summary" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("summary")} <SectionIcon id="summary" size={18} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{section.name}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{section.name}</h2>
</div> </div>

View File

@ -7,7 +7,7 @@ import CodeEditor from "react-simple-code-editor";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const CssSection = () => { export const CssSection = () => {
const { isDarkMode } = useTheme(); const { isDarkMode } = useTheme();
@ -24,7 +24,7 @@ export const CssSection = () => {
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("css")} <SectionIcon id="css" size={18} name={t`Custom CSS`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Custom CSS`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Custom CSS`}</h2>
</div> </div>
</header> </header>

View File

@ -7,7 +7,7 @@ import { saveAs } from "file-saver";
import { usePrintResume } from "@/client/services/resume/print"; import { usePrintResume } from "@/client/services/resume/print";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
const onJsonExport = () => { const onJsonExport = () => {
const { resume } = useResumeStore.getState(); const { resume } = useResumeStore.getState();
@ -36,7 +36,7 @@ export const ExportSection = () => {
<section id="export" className="grid gap-y-6"> <section id="export" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("export")} <SectionIcon id="export" size={18} name={t`Export`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Export`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Export`}</h2>
</div> </div>
</header> </header>

View File

@ -10,7 +10,7 @@ import {
} from "@reactive-resume/ui"; } from "@reactive-resume/ui";
import { cn } from "@reactive-resume/utils"; import { cn } from "@reactive-resume/utils";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
const DonateCard = () => ( const DonateCard = () => (
<Card className="space-y-4 bg-info text-info-foreground"> <Card className="space-y-4 bg-info text-info-foreground">
@ -113,7 +113,7 @@ export const InformationSection = () => {
<section id="information" className="grid gap-y-6"> <section id="information" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("information")} <SectionIcon id="information" size={18} name={t`Information`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Information`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Information`}</h2>
</div> </div>
</header> </header>

View File

@ -27,7 +27,7 @@ import { useState } from "react";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
type ColumnProps = { type ColumnProps = {
id: string; id: string;
@ -194,7 +194,7 @@ export const LayoutSection = () => {
<section id="layout" className="grid gap-y-6"> <section id="layout" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("layout")} <SectionIcon id="layout" size={18} name={t`Layout`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Layout`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Layout`}</h2>
</div> </div>

View File

@ -3,7 +3,7 @@ import { RichInput } from "@reactive-resume/ui";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const NotesSection = () => { export const NotesSection = () => {
const setValue = useResumeStore((state) => state.setValue); const setValue = useResumeStore((state) => state.setValue);
@ -13,7 +13,7 @@ export const NotesSection = () => {
<section id="notes" className="grid gap-y-6"> <section id="notes" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("notes")} <SectionIcon id="notes" size={18} name={t`Notes`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Notes`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Notes`}</h2>
</div> </div>
</header> </header>

View File

@ -12,7 +12,7 @@ import {
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const PageSection = () => { export const PageSection = () => {
const setValue = useResumeStore((state) => state.setValue); const setValue = useResumeStore((state) => state.setValue);
@ -22,7 +22,7 @@ export const PageSection = () => {
<section id="page" className="grid gap-y-6"> <section id="page" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("page")} <SectionIcon id="page" size={18} name={t`Page`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Page`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Page`}</h2>
</div> </div>
</header> </header>

View File

@ -7,7 +7,7 @@ import { useToast } from "@/client/hooks/use-toast";
import { useUser } from "@/client/services/user"; import { useUser } from "@/client/services/user";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const SharingSection = () => { export const SharingSection = () => {
const { user } = useUser(); const { user } = useUser();
@ -35,7 +35,7 @@ export const SharingSection = () => {
<section id="sharing" className="grid gap-y-6"> <section id="sharing" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("sharing")} <SectionIcon id="sharing" size={18} name={t`Sharing`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Sharing`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Sharing`}</h2>
</div> </div>
</header> </header>

View File

@ -7,7 +7,7 @@ import { AnimatePresence, motion } from "framer-motion";
import { useResumeStatistics } from "@/client/services/resume"; import { useResumeStatistics } from "@/client/services/resume";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const StatisticsSection = () => { export const StatisticsSection = () => {
const id = useResumeStore((state) => state.resume.id); const id = useResumeStore((state) => state.resume.id);
@ -19,7 +19,7 @@ export const StatisticsSection = () => {
<section id="statistics" className="grid gap-y-6"> <section id="statistics" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("statistics")} <SectionIcon id="statistics" size={18} name={t`Statistics`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Statistics`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Statistics`}</h2>
</div> </div>
</header> </header>

View File

@ -5,7 +5,7 @@ import { motion } from "framer-motion";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const TemplateSection = () => { export const TemplateSection = () => {
const setValue = useResumeStore((state) => state.setValue); const setValue = useResumeStore((state) => state.setValue);
@ -15,7 +15,7 @@ export const TemplateSection = () => {
<section id="template" className="grid gap-y-6"> <section id="template" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("template")} <SectionIcon id="template" size={18} name={t`Template`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Template`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Template`}</h2>
</div> </div>
</header> </header>

View File

@ -6,7 +6,7 @@ import { HexColorPicker } from "react-colorful";
import { colors } from "@/client/constants/colors"; import { colors } from "@/client/constants/colors";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
export const ThemeSection = () => { export const ThemeSection = () => {
const setValue = useResumeStore((state) => state.setValue); const setValue = useResumeStore((state) => state.setValue);
@ -16,7 +16,7 @@ export const ThemeSection = () => {
<section id="theme" className="grid gap-y-6"> <section id="theme" className="grid gap-y-6">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("theme")} <SectionIcon id="theme" size={18} name={t`Theme`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Theme`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Theme`}</h2>
</div> </div>
</header> </header>

View File

@ -9,7 +9,7 @@ import webfontloader from "webfontloader";
import { useResumeStore } from "@/client/stores/resume"; import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon"; import { SectionIcon } from "../shared/section-icon";
const fontSuggestions = [ const fontSuggestions = [
"Open Sans", "Open Sans",
@ -62,7 +62,7 @@ export const TypographySection = () => {
<section id="typography" className="grid gap-y-8"> <section id="typography" className="grid gap-y-8">
<header className="flex items-center justify-between"> <header className="flex items-center justify-between">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
{getSectionIcon("typography")} <SectionIcon id="typography" size={18} name={t`Typography`} />
<h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Typography`}</h2> <h2 className="line-clamp-1 text-2xl font-bold lg:text-3xl">{t`Typography`}</h2>
</div> </div>
</header> </header>

View File

@ -16,7 +16,7 @@ import {
import type { ButtonProps } from "@reactive-resume/ui"; import type { ButtonProps } from "@reactive-resume/ui";
import { Button, Tooltip } from "@reactive-resume/ui"; import { Button, Tooltip } from "@reactive-resume/ui";
export type MetadataKey = type MetadataKey =
| "template" | "template"
| "layout" | "layout"
| "typography" | "typography"
@ -30,7 +30,7 @@ export type MetadataKey =
| "notes" | "notes"
| "information"; | "information";
export const getSectionIcon = (id: MetadataKey, props: IconProps = {}) => { const getSectionIcon = (id: MetadataKey, props: IconProps = {}) => {
switch (id) { switch (id) {
// Left Sidebar // Left Sidebar
case "notes": { case "notes": {
@ -76,16 +76,17 @@ export const getSectionIcon = (id: MetadataKey, props: IconProps = {}) => {
} }
}; };
type SectionIconProps = ButtonProps & { type SectionIconProps = Omit<ButtonProps, "size"> & {
id: MetadataKey; id: MetadataKey;
name: string; name: string;
size?: number;
icon?: React.ReactNode; icon?: React.ReactNode;
}; };
export const SectionIcon = ({ id, name, icon, ...props }: SectionIconProps) => ( export const SectionIcon = ({ id, name, icon, size = 14, ...props }: SectionIconProps) => (
<Tooltip side="left" content={name}> <Tooltip side="left" content={name}>
<Button size="icon" variant="ghost" className="size-8 rounded-full" {...props}> <Button size="icon" variant="ghost" className="size-8 rounded-full" {...props}>
{icon ?? getSectionIcon(id, { size: 14 })} {icon ?? getSectionIcon(id, { size })}
</Button> </Button>
</Tooltip> </Tooltip>
); );

View File

@ -1,113 +0,0 @@
/* eslint-disable lingui/no-unlocalized-strings */
import { t } from "@lingui/macro";
import { Helmet } from "react-helmet-async";
export const PrivacyPolicyPage = () => (
<main className="relative isolate bg-background">
<Helmet prioritizeSeoTags>
<title>
{t`Privacy Policy`} - {t`Reactive Resume`}
</title>
<meta
name="description"
content="A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume."
/>
</Helmet>
<section
id="privacy-policy"
className="container prose prose-zinc relative max-w-4xl py-32 dark:prose-invert"
>
<h1 className="mb-4">{t`Privacy Policy`}</h1>
<h6 className="text-sm">Last updated on 3rd May 2024</h6>
<hr className="my-6" />
<ol>
<li>
<h2 className="mb-2">Introduction</h2>
<p>
This privacy policy outlines how we collect, use, and protect the personal information
you provide when using our web application. By accessing or using Reactive Resume, you
agree to the collection and use of information in accordance with this policy.
</p>
</li>
<li>
<h2 className="mb-2">Information Collection and Use</h2>
<p>
For a better experience while using our Service, we may require you to provide us with
certain personally identifiable information, including but not limited to your name and
email address. The information that we collect will be used to contact or identify you
primarily for the following purposes:
</p>
<ul>
<li>
<strong>Account Creation:</strong> to allow you to create and manage your account.
</li>
<li>
<strong>Functionality:</strong> to enable the various features of the application that
you choose to utilize, such as building and saving resumes.
</li>
</ul>
</li>
<li>
<h2 className="mb-2">How We Collect Information</h2>
<p>
All personal data is provided directly by you. We collect information through our web
application when you voluntarily provide it to us as part of using our service.
</p>
</li>
<li>
<h2 className="mb-2">Data Security</h2>
<p>
Reactive Resume is committed to ensuring the security of your data. Our application and
database are hosted on a secure server from DigitalOcean, which has both SOC 2 and SOC 3
compliance, ensuring that your data is protected with industry-standard security
measures.
</p>
</li>
<li>
<h2 className="mb-2">Data Retention</h2>
<p>
We retain your personal data as long as your account is active or as needed to provide
you services. If you do not use your account for 6 months, your personal information is
automatically deleted from our servers. You may also delete your data at any time via
the user dashboard.
</p>
</li>
<li>
<h2 className="mb-2">Third-Party Disclosure</h2>
<p>
We do not share your personal information with third parties, ensuring your data is used
exclusively for the purposes stated in this privacy policy.
</p>
</li>
<li>
<h2 className="mb-2">Changes to This Privacy Policy</h2>
<p>
We may update our Privacy Policy from time to time. We will notify you of any changes by
posting the new Privacy Policy on this page. You are advised to review this Privacy
Policy periodically for any changes.
</p>
</li>
<li>
<h2 className="mb-2">Contact Us</h2>
<p>
If you have any questions or suggestions about our Privacy Policy, do not hesitate to
contact us at <code>hello[at]amruthpillai[dot]com</code>.
</p>
</li>
</ol>
</section>
</main>
);

View File

@ -77,7 +77,7 @@ export const PublicResumePage = () => {
<div <div
style={{ width: `${pageSizeMap[format].width}mm` }} style={{ width: `${pageSizeMap[format].width}mm` }}
className="mx-auto mb-6 mt-16 overflow-hidden rounded shadow-xl print:m-0 print:shadow-none" className="overflow-hidden rounded shadow-xl sm:mx-auto sm:mb-6 sm:mt-16 print:m-0 print:shadow-none"
> >
<iframe <iframe
ref={frameRef} ref={frameRef}
@ -87,7 +87,7 @@ export const PublicResumePage = () => {
/> />
</div> </div>
<div className="flex justify-center py-10 opacity-50 print:hidden"> <div className="hidden justify-center py-10 opacity-50 sm:flex print:hidden">
<Link to="/"> <Link to="/">
<Button size="sm" variant="ghost" className="space-x-1.5 text-xs font-normal"> <Button size="sm" variant="ghost" className="space-x-1.5 text-xs font-normal">
<span>{t`Built with`}</span> <span>{t`Built with`}</span>
@ -97,7 +97,7 @@ export const PublicResumePage = () => {
</Link> </Link>
</div> </div>
<div className="fixed bottom-5 right-5 print:hidden"> <div className="fixed bottom-5 right-5 hidden sm:block print:hidden">
<div className="flex items-center gap-x-4"> <div className="flex items-center gap-x-4">
<Button variant="outline" className="gap-x-2 rounded-full" onClick={onDownloadPdf}> <Button variant="outline" className="gap-x-2 rounded-full" onClick={onDownloadPdf}>
{loading ? <CircleNotch size={16} className="animate-spin" /> : <FilePdf size={16} />} {loading ? <CircleNotch size={16} className="animate-spin" /> : <FilePdf size={16} />}

View File

@ -14,7 +14,6 @@ import { DashboardLayout } from "../pages/dashboard/layout";
import { ResumesPage } from "../pages/dashboard/resumes/page"; import { ResumesPage } from "../pages/dashboard/resumes/page";
import { SettingsPage } from "../pages/dashboard/settings/page"; import { SettingsPage } from "../pages/dashboard/settings/page";
import { HomeLayout } from "../pages/home/layout"; import { HomeLayout } from "../pages/home/layout";
import { PrivacyPolicyPage } from "../pages/home/meta/privacy-policy/page";
import { HomePage } from "../pages/home/page"; import { HomePage } from "../pages/home/page";
import { publicLoader, PublicResumePage } from "../pages/public/page"; import { publicLoader, PublicResumePage } from "../pages/public/page";
import { Providers } from "../providers"; import { Providers } from "../providers";
@ -27,11 +26,6 @@ export const routes = createRoutesFromElements(
<Route element={<Providers />} hydrateFallbackElement={<div>Loading...</div>}> <Route element={<Providers />} hydrateFallbackElement={<div>Loading...</div>}>
<Route element={<HomeLayout />}> <Route element={<HomeLayout />}>
<Route path="/" element={<HomePage />} /> <Route path="/" element={<HomePage />} />
<Route path="meta">
<Route path="privacy-policy" element={<PrivacyPolicyPage />} />
<Route index element={<Navigate replace to="/" />} />
</Route>
</Route> </Route>
<Route path="auth"> <Route path="auth">

View File

@ -1,11 +1,8 @@
import { MagnifyingGlass } from "@phosphor-icons/react"; import { MagnifyingGlass } from "@phosphor-icons/react";
import type { DialogProps } from "@radix-ui/react-dialog";
import { cn } from "@reactive-resume/utils"; import { cn } from "@reactive-resume/utils";
import { Command as CommandPrimitive } from "cmdk"; import { Command as CommandPrimitive } from "cmdk";
import { forwardRef } from "react"; import { forwardRef } from "react";
import { Dialog, DialogContent } from "./dialog";
export const Command = forwardRef< export const Command = forwardRef<
React.ElementRef<typeof CommandPrimitive>, React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive> React.ComponentPropsWithoutRef<typeof CommandPrimitive>
@ -19,18 +16,6 @@ export const Command = forwardRef<
Command.displayName = CommandPrimitive.displayName; Command.displayName = CommandPrimitive.displayName;
type CommandDialogProps = DialogProps;
export const CommandDialog = ({ children, ...props }: CommandDialogProps) => (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0">
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-secondary [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:size-5">
{children}
</Command>
</DialogContent>
</Dialog>
);
export const CommandInput = forwardRef< export const CommandInput = forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>, React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>

View File

@ -34,3 +34,4 @@ export * from "./toast";
export * from "./toggle"; export * from "./toggle";
export * from "./toggle-group"; export * from "./toggle-group";
export * from "./tooltip"; export * from "./tooltip";
export * from "./visually-hidden";

View File

@ -0,0 +1,3 @@
import * as VisuallyHiddenPrimitive from "@radix-ui/react-visually-hidden";
export const VisuallyHidden = VisuallyHiddenPrimitive.Root;

View File

@ -1,7 +1,7 @@
{ {
"name": "@reactive-resume/source", "name": "@reactive-resume/source",
"description": "A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.", "description": "A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
"version": "4.3.9", "version": "4.3.10",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"author": { "author": {
@ -55,7 +55,7 @@
"@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@tanstack/eslint-plugin-query": "^5.62.16", "@tanstack/eslint-plugin-query": "^5.64.2",
"@testing-library/react": "^16.2.0", "@testing-library/react": "^16.2.0",
"@tiptap/core": "^2.11.2", "@tiptap/core": "^2.11.2",
"@types/async-retry": "^1.4.9", "@types/async-retry": "^1.4.9",
@ -96,7 +96,7 @@
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-lingui": "^0.9.0", "eslint-plugin-lingui": "^0.9.0",
"eslint-plugin-prettier": "^5.2.2", "eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-react": "^7.37.4", "eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-simple-import-sort": "^12.1.1",
@ -173,7 +173,7 @@
"@radix-ui/react-visually-hidden": "^1.1.1", "@radix-ui/react-visually-hidden": "^1.1.1",
"@sindresorhus/slugify": "^2.2.1", "@sindresorhus/slugify": "^2.2.1",
"@swc/helpers": "^0.5.15", "@swc/helpers": "^0.5.15",
"@tanstack/react-query": "^5.64.1", "@tanstack/react-query": "^5.64.2",
"@tiptap/extension-highlight": "^2.11.2", "@tiptap/extension-highlight": "^2.11.2",
"@tiptap/extension-image": "^2.11.2", "@tiptap/extension-image": "^2.11.2",
"@tiptap/extension-link": "^2.11.2", "@tiptap/extension-link": "^2.11.2",
@ -230,7 +230,7 @@
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-parallax-tilt": "^1.7.272", "react-parallax-tilt": "^1.7.272",
"react-resizable-panels": "^2.1.7", "react-resizable-panels": "^2.1.7",
"react-router": "^7.1.2", "react-router": "^7.1.3",
"react-simple-code-editor": "^0.14.1", "react-simple-code-editor": "^0.14.1",
"react-zoom-pan-pinch": "^3.6.1", "react-zoom-pan-pinch": "^3.6.1",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",

112
pnpm-lock.yaml generated
View File

@ -162,8 +162,8 @@ importers:
specifier: ^0.5.15 specifier: ^0.5.15
version: 0.5.15 version: 0.5.15
'@tanstack/react-query': '@tanstack/react-query':
specifier: ^5.64.1 specifier: ^5.64.2
version: 5.64.1(react@18.3.1) version: 5.64.2(react@18.3.1)
'@tiptap/extension-highlight': '@tiptap/extension-highlight':
specifier: ^2.11.2 specifier: ^2.11.2
version: 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2)) version: 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))
@ -333,8 +333,8 @@ importers:
specifier: ^2.1.7 specifier: ^2.1.7
version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-router: react-router:
specifier: ^7.1.2 specifier: ^7.1.3
version: 7.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 7.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-simple-code-editor: react-simple-code-editor:
specifier: ^0.14.1 specifier: ^0.14.1
version: 0.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 0.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -460,8 +460,8 @@ importers:
specifier: ^0.5.16 specifier: ^0.5.16
version: 0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@swc/core@1.10.7(@swc/helpers@0.5.15))(@types/node@22.10.7)(typescript@5.7.3))) version: 0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@swc/core@1.10.7(@swc/helpers@0.5.15))(@types/node@22.10.7)(typescript@5.7.3)))
'@tanstack/eslint-plugin-query': '@tanstack/eslint-plugin-query':
specifier: ^5.62.16 specifier: ^5.64.2
version: 5.62.16(eslint@8.57.0)(typescript@5.7.3) version: 5.64.2(eslint@8.57.0)(typescript@5.7.3)
'@testing-library/react': '@testing-library/react':
specifier: ^16.2.0 specifier: ^16.2.0
version: 16.2.0(@testing-library/dom@10.1.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 16.2.0(@testing-library/dom@10.1.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -583,8 +583,8 @@ importers:
specifier: ^0.9.0 specifier: ^0.9.0
version: 0.9.0(eslint@8.57.0)(typescript@5.7.3) version: 0.9.0(eslint@8.57.0)(typescript@5.7.3)
eslint-plugin-prettier: eslint-plugin-prettier:
specifier: ^5.2.2 specifier: ^5.2.3
version: 5.2.2(@types/eslint@8.56.5)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.4.2) version: 5.2.3(@types/eslint@8.56.5)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.4.2)
eslint-plugin-react: eslint-plugin-react:
specifier: ^7.37.4 specifier: ^7.37.4
version: 7.37.4(eslint@8.57.0) version: 7.37.4(eslint@8.57.0)
@ -3985,16 +3985,16 @@ packages:
peerDependencies: peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
'@tanstack/eslint-plugin-query@5.62.16': '@tanstack/eslint-plugin-query@5.64.2':
resolution: {integrity: sha512-VhnHSQ/hc62olLzGhlLJ4BJGWynwjs3cDMsByasKJ3zjW1YZ+6raxOv0gHHISm+VEnAY42pkMowmSWrXfL4NTw==} resolution: {integrity: sha512-Xq7jRYvNtGMHjQEGUZLHgEMNB59hgTlqdmKor6cdJ6CMZ/nwmBGpnlr/dcHden7W7BPCdBVN4PWMZBICWvCNQQ==}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
'@tanstack/query-core@5.64.1': '@tanstack/query-core@5.64.2':
resolution: {integrity: sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==} resolution: {integrity: sha512-hdO8SZpWXoADNTWXV9We8CwTkXU88OVWRBcsiFrk7xJQnhm6WRlweDzMD+uH+GnuieTBVSML6xFa17C2cNV8+g==}
'@tanstack/react-query@5.64.1': '@tanstack/react-query@5.64.2':
resolution: {integrity: sha512-vW5ggHpIO2Yjj44b4sB+Fd3cdnlMJppXRBJkEHvld6FXh3j5dwWJoQo7mGtKI2RbSFyiyu/PhGAy0+Vv5ev9Eg==} resolution: {integrity: sha512-3pakNscZNm8KJkxmovvtZ4RaXLyiYYobwleTMvpIGUoKRa8j8VlrQKNl5W8VUEfVfZKkikvXVddLuWMbcSCA1Q==}
peerDependencies: peerDependencies:
react: ^18 || ^19 react: ^18 || ^19
@ -4521,10 +4521,6 @@ packages:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0' typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/scope-manager@8.19.1':
resolution: {integrity: sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.20.0': '@typescript-eslint/scope-manager@8.20.0':
resolution: {integrity: sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==} resolution: {integrity: sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -4549,10 +4545,6 @@ packages:
typescript: typescript:
optional: true optional: true
'@typescript-eslint/types@8.19.1':
resolution: {integrity: sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/types@8.20.0': '@typescript-eslint/types@8.20.0':
resolution: {integrity: sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==} resolution: {integrity: sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -4561,12 +4553,6 @@ packages:
resolution: {integrity: sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==} resolution: {integrity: sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.19.1':
resolution: {integrity: sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/typescript-estree@8.20.0': '@typescript-eslint/typescript-estree@8.20.0':
resolution: {integrity: sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==} resolution: {integrity: sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -4582,13 +4568,6 @@ packages:
typescript: typescript:
optional: true optional: true
'@typescript-eslint/utils@8.19.1':
resolution: {integrity: sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/utils@8.20.0': '@typescript-eslint/utils@8.20.0':
resolution: {integrity: sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==} resolution: {integrity: sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -4602,10 +4581,6 @@ packages:
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
'@typescript-eslint/visitor-keys@8.19.1':
resolution: {integrity: sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.20.0': '@typescript-eslint/visitor-keys@8.20.0':
resolution: {integrity: sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==} resolution: {integrity: sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -6371,8 +6346,8 @@ packages:
peerDependencies: peerDependencies:
eslint: ^8.37.0 || ^9.0.0 eslint: ^8.37.0 || ^9.0.0
eslint-plugin-prettier@5.2.2: eslint-plugin-prettier@5.2.3:
resolution: {integrity: sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==} resolution: {integrity: sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies: peerDependencies:
'@types/eslint': '>=8.0.0' '@types/eslint': '>=8.0.0'
@ -9757,8 +9732,8 @@ packages:
react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
react-router@7.1.2: react-router@7.1.3:
resolution: {integrity: sha512-KeallSO30KLpIe/ZZqfk6pCJ1c+5JhMxl3SCS3Zx1LgaGuQbgLDmjuNi6KZ5LnAV9sWjbmBWGRw8Um/Pw6BExg==} resolution: {integrity: sha512-EezYymLY6Guk/zLQ2vRA8WvdUhWFEj5fcE3RfWihhxXBW7+cd1LsIiA3lmx+KCmneAGQuyBv820o44L2+TtkSA==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
peerDependencies: peerDependencies:
react: '>=18' react: '>=18'
@ -15711,19 +15686,19 @@ snapshots:
postcss-selector-parser: 6.0.10 postcss-selector-parser: 6.0.10
tailwindcss: 3.4.17(ts-node@10.9.2(@swc/core@1.10.7(@swc/helpers@0.5.15))(@types/node@22.10.7)(typescript@5.7.3)) tailwindcss: 3.4.17(ts-node@10.9.2(@swc/core@1.10.7(@swc/helpers@0.5.15))(@types/node@22.10.7)(typescript@5.7.3))
'@tanstack/eslint-plugin-query@5.62.16(eslint@8.57.0)(typescript@5.7.3)': '@tanstack/eslint-plugin-query@5.64.2(eslint@8.57.0)(typescript@5.7.3)':
dependencies: dependencies:
'@typescript-eslint/utils': 8.19.1(eslint@8.57.0)(typescript@5.7.3) '@typescript-eslint/utils': 8.20.0(eslint@8.57.0)(typescript@5.7.3)
eslint: 8.57.0 eslint: 8.57.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
- typescript - typescript
'@tanstack/query-core@5.64.1': {} '@tanstack/query-core@5.64.2': {}
'@tanstack/react-query@5.64.1(react@18.3.1)': '@tanstack/react-query@5.64.2(react@18.3.1)':
dependencies: dependencies:
'@tanstack/query-core': 5.64.1 '@tanstack/query-core': 5.64.2
react: 18.3.1 react: 18.3.1
'@testing-library/dom@10.1.0': '@testing-library/dom@10.1.0':
@ -16357,11 +16332,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.19.1':
dependencies:
'@typescript-eslint/types': 8.19.1
'@typescript-eslint/visitor-keys': 8.19.1
'@typescript-eslint/scope-manager@8.20.0': '@typescript-eslint/scope-manager@8.20.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.20.0 '@typescript-eslint/types': 8.20.0
@ -16395,26 +16365,10 @@ snapshots:
- eslint - eslint
- supports-color - supports-color
'@typescript-eslint/types@8.19.1': {}
'@typescript-eslint/types@8.20.0': {} '@typescript-eslint/types@8.20.0': {}
'@typescript-eslint/types@8.3.0': {} '@typescript-eslint/types@8.3.0': {}
'@typescript-eslint/typescript-estree@8.19.1(typescript@5.7.3)':
dependencies:
'@typescript-eslint/types': 8.19.1
'@typescript-eslint/visitor-keys': 8.19.1
debug: 4.4.0
fast-glob: 3.3.2
is-glob: 4.0.3
minimatch: 9.0.4
semver: 7.6.3
ts-api-utils: 2.0.0(typescript@5.7.3)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.20.0(typescript@5.7.3)': '@typescript-eslint/typescript-estree@8.20.0(typescript@5.7.3)':
dependencies: dependencies:
'@typescript-eslint/types': 8.20.0 '@typescript-eslint/types': 8.20.0
@ -16444,17 +16398,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.19.1(eslint@8.57.0)(typescript@5.7.3)':
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
'@typescript-eslint/scope-manager': 8.19.1
'@typescript-eslint/types': 8.19.1
'@typescript-eslint/typescript-estree': 8.19.1(typescript@5.7.3)
eslint: 8.57.0
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.20.0(eslint@8.57.0)(typescript@5.7.3)': '@typescript-eslint/utils@8.20.0(eslint@8.57.0)(typescript@5.7.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
@ -16477,11 +16420,6 @@ snapshots:
- supports-color - supports-color
- typescript - typescript
'@typescript-eslint/visitor-keys@8.19.1':
dependencies:
'@typescript-eslint/types': 8.19.1
eslint-visitor-keys: 4.2.0
'@typescript-eslint/visitor-keys@8.20.0': '@typescript-eslint/visitor-keys@8.20.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.20.0 '@typescript-eslint/types': 8.20.0
@ -18613,7 +18551,7 @@ snapshots:
- supports-color - supports-color
- typescript - typescript
eslint-plugin-prettier@5.2.2(@types/eslint@8.56.5)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.4.2): eslint-plugin-prettier@5.2.3(@types/eslint@8.56.5)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.4.2):
dependencies: dependencies:
eslint: 8.57.0 eslint: 8.57.0
prettier: 3.4.2 prettier: 3.4.2
@ -22855,7 +22793,7 @@ snapshots:
react: 18.3.1 react: 18.3.1
react-dom: 18.3.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1)
react-router@7.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): react-router@7.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies: dependencies:
'@types/cookie': 0.6.0 '@types/cookie': 0.6.0
cookie: 1.0.2 cookie: 1.0.2