style: style the code according to Prettier rules
This commit is contained in:
parent
fe3ab6cdf1
commit
7bb89ce202
125 changed files with 5263 additions and 5263 deletions
|
@ -1,7 +1,7 @@
|
|||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Admin // Changelogs",
|
||||
title: "Admin // Changelogs"
|
||||
};
|
||||
|
||||
export default function logPages({ children }: { children: React.ReactNode }) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
FormMessage
|
||||
} from "@/components/ui/form";
|
||||
import {
|
||||
Table,
|
||||
|
@ -19,7 +19,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { logsSchema } from "@/lib/validations/validation";
|
||||
|
@ -46,13 +46,13 @@ const AdminLogPage = () => {
|
|||
defaultValues: {
|
||||
version: "",
|
||||
date: "",
|
||||
bullets: [{ point: "" }],
|
||||
},
|
||||
bullets: [{ point: "" }]
|
||||
}
|
||||
});
|
||||
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
control: form.control,
|
||||
name: "bullets",
|
||||
name: "bullets"
|
||||
});
|
||||
|
||||
const fetchLogs = async () => {
|
||||
|
@ -74,7 +74,7 @@ const AdminLogPage = () => {
|
|||
const response = await fetch("/api/uploadlogs", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
@ -91,7 +91,7 @@ const AdminLogPage = () => {
|
|||
const deleteLog = async (id: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/delete/logs/${id}`, {
|
||||
method: "DELETE",
|
||||
method: "DELETE"
|
||||
});
|
||||
if (response.ok) {
|
||||
fetchLogs();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Admin // Downloads",
|
||||
title: "Admin // Downloads"
|
||||
};
|
||||
|
||||
export default function logPages({ children }: { children: React.ReactNode }) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
FormMessage
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { UploadButton } from "@/lib/uploadthing";
|
||||
|
@ -23,7 +23,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
|
||||
interface DownloadEntry {
|
||||
|
@ -46,14 +46,14 @@ const DownloadsPage = () => {
|
|||
fileName: "",
|
||||
version: "",
|
||||
downloadLink: "",
|
||||
fileSize: "",
|
||||
},
|
||||
fileSize: ""
|
||||
}
|
||||
});
|
||||
|
||||
const fetchDownloads = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/downloads", {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: DownloadEntry[] = await response.json();
|
||||
|
@ -82,9 +82,9 @@ const DownloadsPage = () => {
|
|||
const response = await fetch("/api/upload", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
@ -102,7 +102,7 @@ const DownloadsPage = () => {
|
|||
const deleteDownload = async (id: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/delete/downloads/${id}`, {
|
||||
method: "DELETE",
|
||||
method: "DELETE"
|
||||
});
|
||||
if (response.ok) {
|
||||
fetchDownloads();
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import {
|
||||
Pagination,
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
PaginationItem,
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
PaginationPrevious
|
||||
} from "@/components/ui/pagination";
|
||||
import Link from "next/link";
|
||||
|
||||
|
@ -45,7 +45,7 @@ const EmailPage = () => {
|
|||
} catch (error) {
|
||||
toast({
|
||||
title: "Error fetching subscribers",
|
||||
description: `${error}`,
|
||||
description: `${error}`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import MobileNav from "../_components/Mobilenav";
|
|||
import Sidebar from "../_components/Sidebar";
|
||||
|
||||
export default function PageLayout({
|
||||
children,
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Admin // Mods",
|
||||
title: "Admin // Mods"
|
||||
};
|
||||
|
||||
export default function logPages({ children }: { children: React.ReactNode }) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
FormMessage
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { UploadButton } from "@/lib/uploadthing";
|
||||
|
@ -23,13 +23,13 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
DialogTrigger
|
||||
} from "@/components/ui/dialog";
|
||||
|
||||
interface ModEntry {
|
||||
|
@ -54,8 +54,8 @@ const SvrjsModsAdminPage = () => {
|
|||
fileName: "",
|
||||
version: "",
|
||||
downloadLink: "",
|
||||
fileSize: "",
|
||||
},
|
||||
fileSize: ""
|
||||
}
|
||||
});
|
||||
|
||||
const dialogForm = useForm<z.infer<typeof modsSchema>>({
|
||||
|
@ -64,8 +64,8 @@ const SvrjsModsAdminPage = () => {
|
|||
fileName: "",
|
||||
version: "",
|
||||
downloadLink: "",
|
||||
fileSize: "",
|
||||
},
|
||||
fileSize: ""
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -83,7 +83,7 @@ const SvrjsModsAdminPage = () => {
|
|||
fileName: editMod.fileName,
|
||||
version: editMod.version,
|
||||
downloadLink: editMod.downloadLink,
|
||||
fileSize: editMod.fileSize,
|
||||
fileSize: editMod.fileSize
|
||||
});
|
||||
setDialogOpen(true); // Open dialog when a mod is being edited
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ const SvrjsModsAdminPage = () => {
|
|||
const fetchMods = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/mods", {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: ModEntry[] = await response.json();
|
||||
|
@ -112,16 +112,16 @@ const SvrjsModsAdminPage = () => {
|
|||
? await fetch(`/api/update/mods/${editMod._id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
: await fetch("/api/uploadmods", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
@ -132,14 +132,14 @@ const SvrjsModsAdminPage = () => {
|
|||
setEditMod(null);
|
||||
setDialogOpen(false); // Close dialog on successful submission
|
||||
toast({
|
||||
description: "Successfully Saved Changes",
|
||||
description: "Successfully Saved Changes"
|
||||
});
|
||||
} else {
|
||||
console.error("Save failed");
|
||||
setLoading(false);
|
||||
toast({
|
||||
description: "Save failed",
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -147,7 +147,7 @@ const SvrjsModsAdminPage = () => {
|
|||
setLoading(false);
|
||||
toast({
|
||||
description: "Save failed",
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -155,7 +155,7 @@ const SvrjsModsAdminPage = () => {
|
|||
const deleteMod = async (id: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/delete/mods/${id}`, {
|
||||
method: "DELETE",
|
||||
method: "DELETE"
|
||||
});
|
||||
if (response.ok) {
|
||||
fetchMods();
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Button } from "@/components/ui/button";
|
|||
import { useToast } from "@/components/ui/use-toast";
|
||||
|
||||
const MarkdownEditor = dynamic(() => import("@uiw/react-md-editor"), {
|
||||
ssr: false,
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const EditPage = ({ params }: { params: { slug: string } }) => {
|
||||
|
@ -37,7 +37,7 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
|
|||
const response = await fetch(`/api/mdx/pages/${slug}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ title, content, vulnerabilities }),
|
||||
body: JSON.stringify({ title, content, vulnerabilities })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Admin // MultiLogs",
|
||||
title: "Admin // MultiLogs"
|
||||
};
|
||||
|
||||
export default function logPages({ children }: { children: React.ReactNode }) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogTitle
|
||||
} from "@/components/ui/dialog";
|
||||
|
||||
interface PageEntry {
|
||||
|
@ -47,7 +47,7 @@ const MultiLogs = () => {
|
|||
const response = await fetch("/api/mdx/pages", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ title: pageTitle, slug, content: "" }),
|
||||
body: JSON.stringify({ title: pageTitle, slug, content: "" })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
@ -68,7 +68,7 @@ const MultiLogs = () => {
|
|||
const deletePage = async (slug: string) => {
|
||||
setLoading(true);
|
||||
const response = await fetch(`/api/mdx/pages/${slug}`, {
|
||||
method: "DELETE",
|
||||
method: "DELETE"
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Admin // Vulnerabilities",
|
||||
title: "Admin // Vulnerabilities"
|
||||
};
|
||||
|
||||
export default function logPages({ children }: { children: React.ReactNode }) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
FormMessage
|
||||
} from "@/components/ui/form";
|
||||
import {
|
||||
Table,
|
||||
|
@ -19,7 +19,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { z } from "zod";
|
||||
|
@ -29,7 +29,7 @@ import {
|
|||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectTrigger
|
||||
} from "@/components/ui/select";
|
||||
|
||||
interface VulnerabiltyEntry {
|
||||
|
@ -50,13 +50,13 @@ const AdminLogPage = () => {
|
|||
resolver: zodResolver(vulnerabilitiesSchema),
|
||||
defaultValues: {
|
||||
version: "",
|
||||
bullets: [{ point: "" }],
|
||||
},
|
||||
bullets: [{ point: "" }]
|
||||
}
|
||||
});
|
||||
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
control: form.control,
|
||||
name: "bullets",
|
||||
name: "bullets"
|
||||
});
|
||||
|
||||
const fetchLogs = async () => {
|
||||
|
@ -78,7 +78,7 @@ const AdminLogPage = () => {
|
|||
const response = await fetch("/api/uploadvulnerabilities", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
@ -95,7 +95,7 @@ const AdminLogPage = () => {
|
|||
const deleteLog = async (id: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/delete/vulnerability/${id}`, {
|
||||
method: "DELETE",
|
||||
method: "DELETE"
|
||||
});
|
||||
if (response.ok) {
|
||||
fetchLogs();
|
||||
|
|
|
@ -18,7 +18,7 @@ const EmailEditor = () => {
|
|||
toast({
|
||||
title: "Validation Error",
|
||||
description: "Subject and content cannot be empty.",
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
@ -33,12 +33,12 @@ const EmailEditor = () => {
|
|||
const response = await fetch("/api/newsletter/send", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subject: subject,
|
||||
html: previewContent,
|
||||
}),
|
||||
html: previewContent
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
@ -48,14 +48,14 @@ const EmailEditor = () => {
|
|||
const result = await response.json();
|
||||
toast({
|
||||
title: "Success!",
|
||||
description: result.message || "Emails sent successfully",
|
||||
description: result.message || "Emails sent successfully"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
toast({
|
||||
title: "Uh oh!",
|
||||
description: `Failed to send emails: ${error}`,
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
@ -70,12 +70,12 @@ const EmailEditor = () => {
|
|||
const response = await fetch("/api/newsletter/test", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subject: subject,
|
||||
html: previewContent,
|
||||
}),
|
||||
html: previewContent
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
@ -85,14 +85,14 @@ const EmailEditor = () => {
|
|||
const result = await response.json();
|
||||
toast({
|
||||
title: "Success!",
|
||||
description: result.message || "Test email sent successfully",
|
||||
description: result.message || "Test email sent successfully"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
toast({
|
||||
title: "Uh oh!",
|
||||
description: `Failed to send test email: ${error}`,
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
|
|
@ -2,13 +2,9 @@ import React from "react";
|
|||
import AuthProvider from "../../components/shared/providers/AuthProvider";
|
||||
|
||||
export default function AdminLayout({
|
||||
children,
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<AuthProvider>
|
||||
{children}
|
||||
</AuthProvider>
|
||||
);
|
||||
return <AuthProvider>{children}</AuthProvider>;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ interface BlogSlugArticle {
|
|||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
params
|
||||
}: {
|
||||
params: { slug: string };
|
||||
}): Promise<Metadata> {
|
||||
|
@ -50,7 +50,7 @@ export async function generateMetadata({
|
|||
if (!data) {
|
||||
return {
|
||||
title: "Not Found",
|
||||
description: "Blog post not found",
|
||||
description: "Blog post not found"
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -67,9 +67,9 @@ export async function generateMetadata({
|
|||
url: urlFor(data.titleImage).url(),
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: `${data.title} - SVRJS`,
|
||||
},
|
||||
],
|
||||
alt: `${data.title} - SVRJS`
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -77,8 +77,8 @@ export async function generateMetadata({
|
|||
title: `${data.title} - SVRJS`,
|
||||
description: data.smallDescription,
|
||||
images: [urlFor(data.titleImage).url()],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -126,12 +126,12 @@ const customPortableTextComponents: PortableTextComponents = {
|
|||
<CopyButton code={value.code} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default async function BlogSlugArticle({
|
||||
params,
|
||||
params
|
||||
}: {
|
||||
params: { slug: string };
|
||||
}) {
|
||||
|
|
|
@ -20,9 +20,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Blog - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Blog - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -31,12 +31,12 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Welcome to the SVR.JS Blog! Explore our latest blog posts featuring web development, web application security, and web server administration tips. Stay tuned for the latest SVR.JS updates.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
|
||||
const BlogPage = async ({
|
||||
searchParams,
|
||||
searchParams
|
||||
}: {
|
||||
searchParams: { page?: string };
|
||||
}) => {
|
||||
|
|
|
@ -16,9 +16,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "ChangeLogs - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "ChangeLogs - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -27,8 +27,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Stay up-to-date with the latest improvements and updates to SVR.JS web server. Our change log page provides a comprehensive list of new features, bug fixes, and enhancements for each release.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
const ContactLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <main>{children}</main>;
|
||||
|
|
|
@ -27,7 +27,7 @@ const LogsPage: React.FC = () => {
|
|||
const fetchDownloads = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/logs", {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: LOGS[] = await response.json();
|
||||
|
|
|
@ -16,9 +16,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Contact Us - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Contact Us - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -27,8 +27,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Have questions about SVR.JS? Need technical support? Visit our Contact Us page to find various ways to get in touch with our team, including email, forums, and our official support channel.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
const ContactLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <main>{children}</main>;
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
FormMessage
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
@ -33,8 +33,8 @@ const ContactUs = () => {
|
|||
defaultValues: {
|
||||
name: "",
|
||||
email: "",
|
||||
message: "",
|
||||
},
|
||||
message: ""
|
||||
}
|
||||
});
|
||||
|
||||
async function onSubmit(values: z.infer<typeof contactFormSchema>) {
|
||||
|
@ -50,27 +50,27 @@ const ContactUs = () => {
|
|||
body: JSON.stringify({ ...values, captchaToken }),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
Accept: "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
form.reset();
|
||||
setCaptchaToken(null); // Reset captcha token after successful submission
|
||||
toast({
|
||||
description: "Your message has been sent.",
|
||||
description: "Your message has been sent."
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: "Uh oh! Something went wrong.",
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast({
|
||||
title: "Uh oh! Something went wrong.",
|
||||
variant: "destructive",
|
||||
variant: "destructive"
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
|
|
@ -18,9 +18,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Contribute - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Contribute - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -29,8 +29,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Contribute to SVR.JS and be part of an exciting open-source project. Follow the step-by-step guidelines to make your code contributions.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
const Contribute = () => {
|
||||
return (
|
||||
|
|
|
@ -16,9 +16,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Downloads - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Downloads - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -27,12 +27,12 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Ready to get started with SVR.JS? Visit our downloads page to access the latest stable releases, nightly builds, and archived versions. Find the right fit for your needs today!",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
|
||||
export default function DownloadLayout({
|
||||
children,
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import { Download } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
@ -31,7 +31,7 @@ const DownloadPage: React.FC = () => {
|
|||
const fetchDownloads = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/downloads", {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: Download[] = await response.json();
|
||||
|
|
|
@ -3,7 +3,7 @@ import React from "react";
|
|||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Forum - SVRJS",
|
||||
title: "Forum - SVRJS"
|
||||
};
|
||||
|
||||
const Forum = () => {
|
||||
|
|
|
@ -20,9 +20,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "SVRJS - A Web Server running on Node.js",
|
||||
},
|
||||
],
|
||||
alt: "SVRJS - A Web Server running on Node.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -31,12 +31,12 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Experience unparalleled flexibility with SVR.JS - the ultimate web server for Node.js. Host web pages, run server-side JavaScript, utilize mods for extended functionality, and more. Integrated log viewer and user management tools included. Also supports Bun (experimental).",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
|
||||
export default function PageLayout({
|
||||
children,
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
|
|
|
@ -16,9 +16,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Mods - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Mods - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -27,8 +27,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Expand the functionality of SVR.JS with our collection of mods! Visit the mod downloads page to explore, download, and install a wide range of mods tailored to enhance your web server experience.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
const ModLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <main>{children}</main>;
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRow
|
||||
} from "@/components/ui/table";
|
||||
import { Download } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
@ -30,7 +30,7 @@ const ModsPage: React.FC = () => {
|
|||
const fetchDownloads = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/mods", {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: Mods[] = await response.json();
|
||||
|
|
|
@ -20,9 +20,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Privacy Policy - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Privacy Policy - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -31,8 +31,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Learn how we collect, use, and protect your data. Our Privacy Policy outlines our commitment to your privacy and the measures we take to safeguard your information when visiting our website.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
|
||||
const PrivacyPolicy = () => {
|
||||
|
|
|
@ -18,9 +18,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Terms of Service - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Terms of Service - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -29,8 +29,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Understand your rights and responsibilities when using SVR.JS. Our Terms of Service page outlines the conditions for visiting our website, ensuring a transparent and fair experience for all users.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
|
||||
const TermsOfService = () => {
|
||||
|
|
|
@ -16,9 +16,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "Vulnerabilities - SVRJS",
|
||||
},
|
||||
],
|
||||
alt: "Vulnerabilities - SVRJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -27,8 +27,8 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Learn about potential security risks associated with outdated SVR.JS web server versions. Stay informed and safeguard your web applications from potential threats with timely updates.",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
const ModLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <main>{children}</main>;
|
||||
|
|
|
@ -32,7 +32,7 @@ const Vulnerabilities = () => {
|
|||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/vulnerabilities", {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: Vulnerabilities[] = await response.json();
|
||||
|
@ -51,7 +51,7 @@ const Vulnerabilities = () => {
|
|||
const fetchMods = async () => {
|
||||
try {
|
||||
const response = await fetch(`/api/mdx/pages`, {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: ModsVulnerability[] = await response.json();
|
||||
|
|
|
@ -9,7 +9,7 @@ export const authOptions: NextAuthOptions = {
|
|||
name: "Credentials",
|
||||
credentials: {
|
||||
username: { label: "Username", type: "text" },
|
||||
password: { label: "Password", type: "password" },
|
||||
password: { label: "Password", type: "password" }
|
||||
},
|
||||
async authorize(credentials: any): Promise<any> {
|
||||
const adminUsername = process.env.ADMIN_USERNAME;
|
||||
|
@ -34,8 +34,8 @@ export const authOptions: NextAuthOptions = {
|
|||
}
|
||||
// If you return null then an error will be displayed that the user to check their details.
|
||||
return null;
|
||||
},
|
||||
}),
|
||||
}
|
||||
})
|
||||
],
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
|
@ -51,13 +51,13 @@ export const authOptions: NextAuthOptions = {
|
|||
// session.user.id = token.id;
|
||||
// session.user.name = token.name;
|
||||
return session;
|
||||
},
|
||||
}
|
||||
},
|
||||
pages: {
|
||||
signIn: "/login",
|
||||
signIn: "/login"
|
||||
},
|
||||
session: {
|
||||
strategy: "jwt",
|
||||
strategy: "jwt"
|
||||
},
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
secret: process.env.NEXTAUTH_SECRET
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import { NextRequest, NextResponse } from "next/server";
|
|||
const CONTACT_MESSAGE_FIELDS: Record<string, string> = {
|
||||
name: "Name",
|
||||
email: "Email",
|
||||
message: "Message",
|
||||
message: "Message"
|
||||
};
|
||||
|
||||
const escapeHtml = (text: string) => {
|
||||
|
@ -90,7 +90,7 @@ const generateEmailContent = (data: Record<string, string>) => {
|
|||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>`,
|
||||
</html>`
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -109,7 +109,7 @@ export async function POST(req: NextRequest) {
|
|||
await transporter.sendMail({
|
||||
...mailOptions,
|
||||
...generateEmailContent(data),
|
||||
subject: "Contact Email",
|
||||
subject: "Contact Email"
|
||||
});
|
||||
|
||||
return NextResponse.json(
|
||||
|
|
|
@ -14,21 +14,21 @@ export async function POST(request: NextRequest) {
|
|||
const cookie = serialize("auth", "authenticated", {
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
maxAge: 60 * 60 * 24, // 1 day
|
||||
maxAge: 60 * 60 * 24 // 1 day
|
||||
});
|
||||
|
||||
return new NextResponse(JSON.stringify({ message: "Login successful" }), {
|
||||
headers: {
|
||||
"Set-Cookie": cookie,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new NextResponse(JSON.stringify({ message: "Invalid credentials" }), {
|
||||
status: 401,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export const PUT = async (
|
|||
if (result?.value) {
|
||||
const serializedResult = {
|
||||
...result.value,
|
||||
_id: result.value._id.toString(), // Convert ObjectId to string
|
||||
_id: result.value._id.toString() // Convert ObjectId to string
|
||||
};
|
||||
return NextResponse.json(serializedResult, { status: 200 });
|
||||
} else {
|
||||
|
|
|
@ -8,8 +8,8 @@ const transporter = nodemailer.createTransport({
|
|||
port: 587,
|
||||
auth: {
|
||||
user: process.env.EMAIL,
|
||||
pass: process.env.EMAIL_PASS,
|
||||
},
|
||||
pass: process.env.EMAIL_PASS
|
||||
}
|
||||
});
|
||||
|
||||
const sendEmail = async (to: string[], subject: string, html: string) => {
|
||||
|
@ -18,7 +18,7 @@ const sendEmail = async (to: string[], subject: string, html: string) => {
|
|||
from: process.env.EMAIL_USER,
|
||||
to: to.join(", "),
|
||||
subject: subject,
|
||||
html: html,
|
||||
html: html
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error sending email:", error);
|
||||
|
|
|
@ -27,7 +27,7 @@ export async function GET(req: Request) {
|
|||
subscribedAt:
|
||||
doc.subscribedAt instanceof Date
|
||||
? doc.subscribedAt
|
||||
: new Date(doc.subscribedAt),
|
||||
: new Date(doc.subscribedAt)
|
||||
}));
|
||||
|
||||
const totalSubscribers = await collection.countDocuments();
|
||||
|
@ -35,7 +35,7 @@ export async function GET(req: Request) {
|
|||
return NextResponse.json({
|
||||
subscribers,
|
||||
totalSubscribers,
|
||||
totalPages: Math.ceil(totalSubscribers / limit),
|
||||
totalPages: Math.ceil(totalSubscribers / limit)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching subscribers:", error);
|
||||
|
|
|
@ -7,8 +7,8 @@ const transporter = nodemailer.createTransport({
|
|||
port: 587,
|
||||
auth: {
|
||||
user: process.env.EMAIL,
|
||||
pass: process.env.EMAIL_PASS,
|
||||
},
|
||||
pass: process.env.EMAIL_PASS
|
||||
}
|
||||
});
|
||||
|
||||
const sendEmail = async (to: string[], subject: string, html: string) => {
|
||||
|
@ -17,7 +17,7 @@ const sendEmail = async (to: string[], subject: string, html: string) => {
|
|||
from: process.env.EMAIL_USER,
|
||||
to: to.join(", "),
|
||||
subject: subject,
|
||||
html: html,
|
||||
html: html
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error sending email:", error);
|
||||
|
@ -32,7 +32,7 @@ export async function POST(req: NextRequest) {
|
|||
// add ur email here
|
||||
const testEmails = [
|
||||
"abhijitbhattacharjee333@gmail.com",
|
||||
"test2@example.com",
|
||||
"test2@example.com"
|
||||
];
|
||||
|
||||
if (testEmails.length === 0) {
|
||||
|
|
|
@ -18,9 +18,9 @@ export async function POST(req: NextRequest) {
|
|||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: `secret=${process.env.HCAPTCHA_SECRET}&response=${captchaToken}`,
|
||||
body: `secret=${process.env.HCAPTCHA_SECRET}&response=${captchaToken}`
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ export async function PUT(
|
|||
fileName,
|
||||
version,
|
||||
downloadLink,
|
||||
fileSize,
|
||||
},
|
||||
fileSize
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -33,14 +33,14 @@ export async function PUT(
|
|||
} else {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: "No document updated",
|
||||
message: "No document updated"
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Update failed", error);
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: "Failed to update mod",
|
||||
message: "Failed to update mod"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export async function POST(request: Request) {
|
|||
fileName,
|
||||
version,
|
||||
downloadLink,
|
||||
fileSize,
|
||||
fileSize
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, id: result.insertedId });
|
||||
|
|
|
@ -14,7 +14,7 @@ export async function POST(request: Request) {
|
|||
const result = await db.collection("logs").insertOne({
|
||||
version,
|
||||
date,
|
||||
bullets,
|
||||
bullets
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, id: result.insertedId });
|
||||
|
|
|
@ -16,7 +16,7 @@ export async function POST(request: Request) {
|
|||
fileName,
|
||||
version,
|
||||
downloadLink,
|
||||
fileSize,
|
||||
fileSize
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, id: result.insertedId });
|
||||
|
|
|
@ -7,10 +7,10 @@ const f = createUploadthing();
|
|||
|
||||
export const ourFileRouter = {
|
||||
imageUploader: f({
|
||||
"application/zip": { maxFileSize: "8MB" },
|
||||
"application/zip": { maxFileSize: "8MB" }
|
||||
}).onUploadComplete(async ({ metadata, file }) => {
|
||||
console.log("file url", file.url);
|
||||
}),
|
||||
})
|
||||
} satisfies FileRouter;
|
||||
|
||||
export type OurFileRouter = typeof ourFileRouter;
|
||||
|
|
|
@ -4,5 +4,5 @@ import { ourFileRouter } from "./core";
|
|||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const { GET, POST } = createRouteHandler({
|
||||
router: ourFileRouter,
|
||||
router: ourFileRouter
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ export async function POST(request: Request) {
|
|||
|
||||
const result = await db.collection("vulnerabilities").insertOne({
|
||||
version,
|
||||
bullets,
|
||||
bullets
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, id: result.insertedId });
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Analytics } from "@vercel/analytics/react";
|
|||
|
||||
const poppins = Poppins({
|
||||
weight: ["400", "600", "700", "900"],
|
||||
subsets: ["latin"],
|
||||
subsets: ["latin"]
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
|
@ -25,9 +25,9 @@ export const metadata: Metadata = {
|
|||
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
|
||||
width: 800,
|
||||
height: 600,
|
||||
alt: "SVRJS - A Web Server running on Node.js",
|
||||
},
|
||||
],
|
||||
alt: "SVRJS - A Web Server running on Node.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
|
@ -36,12 +36,12 @@ export const metadata: Metadata = {
|
|||
description:
|
||||
"Experience unparalleled flexibility with SVR.JS - the ultimate web server for Node.js. Host web pages, run server-side JavaScript, utilize mods for extended functionality, and more. Integrated log viewer and user management tools included. Also supports Bun (experimental).",
|
||||
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
|
||||
creator: "@SVR_JS",
|
||||
},
|
||||
creator: "@SVR_JS"
|
||||
}
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
children
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
|
@ -54,7 +54,6 @@ export default function RootLayout({
|
|||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
|
||||
{children}
|
||||
<Toaster />
|
||||
<Analytics />
|
||||
|
|
|
@ -30,7 +30,7 @@ const LoginPage = () => {
|
|||
const res = await signIn("credentials", {
|
||||
redirect: false,
|
||||
username,
|
||||
password,
|
||||
password
|
||||
});
|
||||
|
||||
if (res?.ok) {
|
||||
|
|
|
@ -27,7 +27,7 @@ export async function GET() {
|
|||
site_url: `${SITE_URL}`,
|
||||
image_url: `${SITE_URL}/metadata/svrjs-cover.png`,
|
||||
language: "en-US",
|
||||
pubDate: new Date().toUTCString(),
|
||||
pubDate: new Date().toUTCString()
|
||||
});
|
||||
|
||||
posts.forEach((post: any) => {
|
||||
|
@ -35,7 +35,7 @@ export async function GET() {
|
|||
title: post.title,
|
||||
description: toHTML(post.content),
|
||||
url: `${SITE_URL}/blog/${post.slug}`,
|
||||
date: new Date(post._createdAt).toUTCString(),
|
||||
date: new Date(post._createdAt).toUTCString()
|
||||
// uncomment this if u want to
|
||||
// enclosure: { url: urlFor(post.titleImage).url() },
|
||||
// author: "SVRJS",
|
||||
|
@ -44,7 +44,7 @@ export async function GET() {
|
|||
|
||||
return new NextResponse(feed.xml({ indent: true }), {
|
||||
headers: {
|
||||
"Content-Type": "application/xml",
|
||||
},
|
||||
"Content-Type": "application/xml"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,15 +15,15 @@ export default async function sitemap() {
|
|||
"/privacy-policy",
|
||||
"/tos",
|
||||
"/vulnerabilities",
|
||||
"/newsletter",
|
||||
"/newsletter"
|
||||
].map((route) => ({
|
||||
url: `https://svrjs.vercel.app${route}`,
|
||||
lastModified: new Date().toISOString().split("T")[0],
|
||||
lastModified: new Date().toISOString().split("T")[0]
|
||||
}));
|
||||
|
||||
const blogRoutes = blogPostSlugs.map((slug) => ({
|
||||
url: `https://svrjs.vercel.app/blog/${slug.slug}`,
|
||||
lastModified: new Date().toISOString().split("T")[0],
|
||||
lastModified: new Date().toISOString().split("T")[0]
|
||||
}));
|
||||
|
||||
return [...baseRoutes, ...blogRoutes];
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
PaginationItem,
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
PaginationPrevious
|
||||
} from "@/components/ui/pagination";
|
||||
import { format } from "date-fns";
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ const CodeEditor = ({ onChange }: CodeEditorProps) => {
|
|||
<Editor
|
||||
options={{
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
enabled: false
|
||||
}
|
||||
}}
|
||||
height="75vh"
|
||||
theme="vs-dark"
|
||||
|
|
|
@ -14,7 +14,7 @@ const TestimonialCard = ({
|
|||
name,
|
||||
role,
|
||||
testimonial,
|
||||
rating,
|
||||
rating
|
||||
}: TestimonialCard) => {
|
||||
return (
|
||||
<li className="inline-block w-full">
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
AccordionTrigger
|
||||
} from "../ui/accordion";
|
||||
|
||||
const Faq = () => {
|
||||
|
|
|
@ -13,7 +13,7 @@ import Image from "next/image";
|
|||
const happyMonkey = Happy_Monkey({
|
||||
preload: true,
|
||||
weight: ["400"],
|
||||
subsets: ["latin"],
|
||||
subsets: ["latin"]
|
||||
});
|
||||
|
||||
const Hero = () => {
|
||||
|
@ -29,7 +29,7 @@ const Hero = () => {
|
|||
linux:
|
||||
"curl -fsSL https://downloads.svrjs.org/installer/svr.js.installer.linux.20240509.sh > /tmp/installer.sh && sudo bash /tmp/installer.sh",
|
||||
docker:
|
||||
"docker pull svrjs/svrjs && docker run --name mysvrjs -d -p 80:80 --restart=always svrjs/svrjs",
|
||||
"docker pull svrjs/svrjs && docker run --name mysvrjs -d -p 80:80 --restart=always svrjs/svrjs"
|
||||
};
|
||||
|
||||
const copyToClipboard = () => {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardTitle
|
||||
} from "@/components/ui/card";
|
||||
import Image from "next/image";
|
||||
import { Happy_Monkey } from "next/font/google";
|
||||
|
@ -21,7 +21,7 @@ import { useRouter } from "next/navigation";
|
|||
const happyMonkey = Happy_Monkey({
|
||||
preload: true,
|
||||
weight: ["400"],
|
||||
subsets: ["latin"],
|
||||
subsets: ["latin"]
|
||||
});
|
||||
|
||||
const HeroCards = () => {
|
||||
|
@ -34,8 +34,8 @@ const HeroCards = () => {
|
|||
x: "https://x.com/SVR_JS",
|
||||
Mastodon: "https://mastodon.social/@svrjs",
|
||||
Bluesky: "https://bsky.app/profile/svrjs.org",
|
||||
Odysee: "https://odysee.com/@SVRJS",
|
||||
},
|
||||
Odysee: "https://odysee.com/@SVRJS"
|
||||
}
|
||||
},
|
||||
pricingCard: {
|
||||
planName: "Pro Plan",
|
||||
|
@ -48,26 +48,26 @@ const HeroCards = () => {
|
|||
features: [
|
||||
{
|
||||
title: "Unlimited Projects",
|
||||
icons: <Infinity className="rounded-full" width={25} height={25} />,
|
||||
icons: <Infinity className="rounded-full" width={25} height={25} />
|
||||
},
|
||||
{
|
||||
title: "Priority Support",
|
||||
icons: (
|
||||
<ArchiveRestore className="rounded-full" width={25} height={25} />
|
||||
),
|
||||
)
|
||||
},
|
||||
{
|
||||
title: "Free Updates",
|
||||
icons: <Headset className="rounded-full" width={25} height={25} />,
|
||||
},
|
||||
icons: <Headset className="rounded-full" width={25} height={25} />
|
||||
}
|
||||
],
|
||||
curlyText: "Best Value!",
|
||||
curlyText: "Best Value!"
|
||||
},
|
||||
serviceCard: {
|
||||
title: "Our Services",
|
||||
description:
|
||||
"We offer a variety of services to cater to your needs, including web development, SEO, and more.",
|
||||
},
|
||||
"We offer a variety of services to cater to your needs, including web development, SEO, and more."
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
SheetTrigger
|
||||
} from "../ui/sheet";
|
||||
import { Menu } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
|
@ -48,7 +48,7 @@ const MobileNav = () => {
|
|||
href={href}
|
||||
target={target}
|
||||
className={`w-[110px] gap-2 ${buttonVariants({
|
||||
variant: "secondary",
|
||||
variant: "secondary"
|
||||
})}`}
|
||||
>
|
||||
<svg
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import {
|
||||
NavigationMenu,
|
||||
NavigationMenuItem,
|
||||
NavigationMenuList,
|
||||
NavigationMenuList
|
||||
} from "@radix-ui/react-navigation-menu";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
@ -44,7 +44,7 @@ const Navbar = () => {
|
|||
className={`text-[17px] tracking-tight ${
|
||||
pathname == href ? "bg-muted-foreground/20" : ""
|
||||
} ${buttonVariants({
|
||||
variant: "ghost",
|
||||
variant: "ghost"
|
||||
})}`}
|
||||
>
|
||||
{label}
|
||||
|
@ -61,7 +61,7 @@ const Navbar = () => {
|
|||
target={target}
|
||||
className={`border ${buttonVariants({
|
||||
variant: "ghost",
|
||||
size: "icon",
|
||||
size: "icon"
|
||||
})}`}
|
||||
>
|
||||
<span className="sr-only">Git</span>
|
||||
|
|
|
@ -11,7 +11,7 @@ import HCaptcha from "@hcaptcha/react-hcaptcha";
|
|||
const happyMonkey = Happy_Monkey({
|
||||
preload: true,
|
||||
weight: "400",
|
||||
subsets: ["latin"],
|
||||
subsets: ["latin"]
|
||||
});
|
||||
|
||||
const Newsletter = () => {
|
||||
|
@ -41,9 +41,9 @@ const Newsletter = () => {
|
|||
const response = await fetch("/api/subscribe", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({ email: input, captchaToken: token }),
|
||||
body: JSON.stringify({ email: input, captchaToken: token })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
|
|
|
@ -8,7 +8,7 @@ const testimonials = [
|
|||
avatar: "avatar1",
|
||||
testimonial:
|
||||
"Working with this team was a fantastic experience. They developed our website exactly to our specifications, and everything was seamless and well-integrated.",
|
||||
rating: 5,
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Jane Smith",
|
||||
|
@ -16,7 +16,7 @@ const testimonials = [
|
|||
avatar: "avatar2",
|
||||
testimonial:
|
||||
"We're thrilled with the website. It's simple, clean, and has significantly boosted our sales. The developers did an excellent job.",
|
||||
rating: 4,
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
name: "Sam Green",
|
||||
|
@ -24,7 +24,7 @@ const testimonials = [
|
|||
avatar: "avatar3",
|
||||
testimonial:
|
||||
"Collaborating with this team to build a SaaS-integrated website was a perfect experience. I look forward to working with them again.",
|
||||
rating: 5,
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Chris Brown",
|
||||
|
@ -32,14 +32,14 @@ const testimonials = [
|
|||
avatar: "avatar4",
|
||||
testimonial:
|
||||
"The team's understanding of our needs and their ability to provide fitting solutions was impressive. Their support and guidance were invaluable.",
|
||||
rating: 4,
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
name: "Alex Johnson",
|
||||
avatar: "avatar5",
|
||||
testimonial:
|
||||
"Exceptional service and outstanding results. They consistently deliver on time and within budget, making them our go-to partner for all our projects.",
|
||||
rating: 5,
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Patricia Taylor",
|
||||
|
@ -47,7 +47,7 @@ const testimonials = [
|
|||
avatar: "avatar6",
|
||||
testimonial:
|
||||
"It was great to work with them. I needed a design for a SaaS project, and it was delivered within 2 days.",
|
||||
rating: 4,
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
name: "Emily Davis",
|
||||
|
@ -55,22 +55,22 @@ const testimonials = [
|
|||
avatar: "avatar7",
|
||||
testimonial:
|
||||
"Collaborating with them has been a pleasure. Their creativity and user-centric approach have significantly enhanced our product's usability.",
|
||||
rating: 5,
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Michael Lee",
|
||||
avatar: "avatar8",
|
||||
testimonial:
|
||||
"They have a keen understanding of our business needs and consistently deliver top-notch solutions. Their reliability and efficiency are commendable.",
|
||||
rating: 5,
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Sarah Wilson",
|
||||
avatar: "avatar9",
|
||||
testimonial:
|
||||
"Their dedication to client satisfaction is evident in everything they do. We've seen remarkable improvements in our processes thanks to their expertise.",
|
||||
rating: 4,
|
||||
},
|
||||
rating: 4
|
||||
}
|
||||
];
|
||||
|
||||
const Testimonials = () => {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { SessionProvider } from "next-auth/react";
|
||||
|
||||
export default function AuthProvider({
|
||||
children,
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
|
|
|
@ -5,7 +5,7 @@ interface ChangelogLayoutProps {
|
|||
}
|
||||
|
||||
export const ChangelogLayout: React.FC<ChangelogLayoutProps> = ({
|
||||
children,
|
||||
children
|
||||
}) => {
|
||||
return (
|
||||
<div className="wrapper container py-24 md:py-28 gap-4 flex flex-col">
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import { ThemeProvider as NextThemesProvider } from "next-themes"
|
||||
import { type ThemeProviderProps } from "next-themes/dist/types"
|
||||
import * as React from "react";
|
||||
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
||||
import { type ThemeProviderProps } from "next-themes/dist/types";
|
||||
|
||||
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
|
||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ReactNode } from "react";
|
|||
|
||||
export default function AnimatedGradientText({
|
||||
children,
|
||||
className,
|
||||
className
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
|
@ -12,7 +12,7 @@ export default function AnimatedGradientText({
|
|||
<div
|
||||
className={cn(
|
||||
"group relative mx-auto flex max-w-fit flex-row items-center justify-center rounded-2xl bg-white/40 px-4 py-1.5 text-sm font-medium shadow-[inset_0_-8px_10px_#8fdfff1f] backdrop-blur-sm transition-shadow duration-500 ease-out [--bg-size:300%] hover:shadow-[inset_0_-5px_10px_#8fdfff3f] dark:bg-black/40",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -10,13 +10,13 @@ interface AnimatedShinyTextProps {
|
|||
const AnimatedShinyText: FC<AnimatedShinyTextProps> = ({
|
||||
children,
|
||||
className,
|
||||
shimmerWidth = 100,
|
||||
shimmerWidth = 100
|
||||
}) => {
|
||||
return (
|
||||
<p
|
||||
style={
|
||||
{
|
||||
"--shimmer-width": `${shimmerWidth}px`,
|
||||
"--shimmer-width": `${shimmerWidth}px`
|
||||
} as CSSProperties
|
||||
}
|
||||
className={cn(
|
||||
|
@ -28,7 +28,7 @@ const AnimatedShinyText: FC<AnimatedShinyTextProps> = ({
|
|||
// Shimmer gradient
|
||||
"bg-gradient-to-r from-transparent via-black/80 via-50% to-transparent dark:via-white/80",
|
||||
|
||||
className,
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -13,7 +13,7 @@ const Avatar = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
@ -40,7 +40,7 @@ const AvatarFallback = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
@ -14,13 +14,13 @@ const badgeVariants = cva(
|
|||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
||||
outline: "text-foreground",
|
||||
},
|
||||
outline: "text-foreground"
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
variant: "default"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
|
|
|
@ -19,7 +19,7 @@ export const BorderBeam = ({
|
|||
borderWidth = 1.5,
|
||||
colorFrom = "#8803AF",
|
||||
colorTo = "#61DAFB",
|
||||
delay = 0,
|
||||
delay = 0
|
||||
}: BorderBeamProps) => {
|
||||
return (
|
||||
<div
|
||||
|
@ -31,7 +31,7 @@ export const BorderBeam = ({
|
|||
"--border-width": borderWidth,
|
||||
"--color-from": colorFrom,
|
||||
"--color-to": colorTo,
|
||||
"--delay": `-${delay}s`,
|
||||
"--delay": `-${delay}s`
|
||||
} as React.CSSProperties
|
||||
}
|
||||
className={cn(
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import * as React from "react";
|
||||
import { Slot } from "@radix-ui/react-slot";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
|
@ -17,40 +17,40 @@ const buttonVariants = cva(
|
|||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
link: "text-primary underline-offset-4 hover:underline"
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
icon: "h-10 w-10"
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
size: "default"
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
const Comp = asChild ? Slot : "button";
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
);
|
||||
Button.displayName = "Button";
|
||||
|
||||
export { Button, buttonVariants }
|
||||
export { Button, buttonVariants };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
|
@ -14,8 +14,8 @@ const Card = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
));
|
||||
Card.displayName = "Card";
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
|
@ -26,8 +26,8 @@ const CardHeader = React.forwardRef<
|
|||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
));
|
||||
CardHeader.displayName = "CardHeader";
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
|
@ -41,8 +41,8 @@ const CardTitle = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
));
|
||||
CardTitle.displayName = "CardTitle";
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
|
@ -53,16 +53,16 @@ const CardDescription = React.forwardRef<
|
|||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
));
|
||||
CardDescription.displayName = "CardDescription";
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
));
|
||||
CardContent.displayName = "CardContent";
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
|
@ -73,7 +73,14 @@ const CardFooter = React.forwardRef<
|
|||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
));
|
||||
CardFooter.displayName = "CardFooter";
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent
|
||||
};
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||
import { X } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Dialog = DialogPrimitive.Root
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger
|
||||
const DialogTrigger = DialogPrimitive.Trigger;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
|
||||
const DialogClose = DialogPrimitive.Close
|
||||
const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
|
@ -26,8 +26,8 @@ const DialogOverlay = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
||||
));
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
|
@ -50,8 +50,8 @@ const DialogContent = React.forwardRef<
|
|||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
))
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName
|
||||
));
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
const DialogHeader = ({
|
||||
className,
|
||||
|
@ -64,8 +64,8 @@ const DialogHeader = ({
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogHeader.displayName = "DialogHeader"
|
||||
);
|
||||
DialogHeader.displayName = "DialogHeader";
|
||||
|
||||
const DialogFooter = ({
|
||||
className,
|
||||
|
@ -78,8 +78,8 @@ const DialogFooter = ({
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogFooter.displayName = "DialogFooter"
|
||||
);
|
||||
DialogFooter.displayName = "DialogFooter";
|
||||
|
||||
const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
|
@ -93,8 +93,8 @@ const DialogTitle = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
||||
));
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
|
@ -105,8 +105,8 @@ const DialogDescription = React.forwardRef<
|
|||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
||||
));
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
|
@ -118,5 +118,5 @@ export {
|
|||
DialogHeader,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
}
|
||||
DialogDescription
|
||||
};
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
||||
import { Check, ChevronRight, Circle } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||
|
||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
||||
|
||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
||||
|
||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
||||
|
||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
||||
|
||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||
|
||||
const DropdownMenuSubTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, children, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
|
@ -36,9 +36,9 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
|||
{children}
|
||||
<ChevronRight className="ml-auto h-4 w-4" />
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
))
|
||||
));
|
||||
DropdownMenuSubTrigger.displayName =
|
||||
DropdownMenuPrimitive.SubTrigger.displayName
|
||||
DropdownMenuPrimitive.SubTrigger.displayName;
|
||||
|
||||
const DropdownMenuSubContent = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||
|
@ -52,9 +52,9 @@ const DropdownMenuSubContent = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
));
|
||||
DropdownMenuSubContent.displayName =
|
||||
DropdownMenuPrimitive.SubContent.displayName
|
||||
DropdownMenuPrimitive.SubContent.displayName;
|
||||
|
||||
const DropdownMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||
|
@ -71,13 +71,13 @@ const DropdownMenuContent = React.forwardRef<
|
|||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
))
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
||||
));
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
||||
|
||||
const DropdownMenuItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Item
|
||||
|
@ -89,8 +89,8 @@ const DropdownMenuItem = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
||||
));
|
||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
||||
|
||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||
|
@ -112,9 +112,9 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
|||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
))
|
||||
));
|
||||
DropdownMenuCheckboxItem.displayName =
|
||||
DropdownMenuPrimitive.CheckboxItem.displayName
|
||||
DropdownMenuPrimitive.CheckboxItem.displayName;
|
||||
|
||||
const DropdownMenuRadioItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||
|
@ -135,13 +135,13 @@ const DropdownMenuRadioItem = React.forwardRef<
|
|||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
))
|
||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
||||
));
|
||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
||||
|
||||
const DropdownMenuLabel = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
||||
inset?: boolean
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Label
|
||||
|
@ -153,8 +153,8 @@ const DropdownMenuLabel = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
||||
));
|
||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
||||
|
||||
const DropdownMenuSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||
|
@ -165,8 +165,8 @@ const DropdownMenuSeparator = React.forwardRef<
|
|||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
||||
));
|
||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
||||
|
||||
const DropdownMenuShortcut = ({
|
||||
className,
|
||||
|
@ -177,9 +177,9 @@ const DropdownMenuShortcut = ({
|
|||
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
||||
);
|
||||
};
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
|
@ -196,5 +196,5 @@ export {
|
|||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuRadioGroup,
|
||||
}
|
||||
DropdownMenuRadioGroup
|
||||
};
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import * as React from "react"
|
||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import * as React from "react";
|
||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||
import { Slot } from "@radix-ui/react-slot";
|
||||
import {
|
||||
Controller,
|
||||
ControllerProps,
|
||||
FieldPath,
|
||||
FieldValues,
|
||||
FormProvider,
|
||||
useFormContext,
|
||||
} from "react-hook-form"
|
||||
useFormContext
|
||||
} from "react-hook-form";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
||||
const Form = FormProvider
|
||||
const Form = FormProvider;
|
||||
|
||||
type FormFieldContextValue<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||
> = {
|
||||
name: TName
|
||||
}
|
||||
name: TName;
|
||||
};
|
||||
|
||||
const FormFieldContext = React.createContext<FormFieldContextValue>(
|
||||
{} as FormFieldContextValue
|
||||
)
|
||||
);
|
||||
|
||||
const FormField = <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
|
@ -36,21 +36,21 @@ const FormField = <
|
|||
<FormFieldContext.Provider value={{ name: props.name }}>
|
||||
<Controller {...props} />
|
||||
</FormFieldContext.Provider>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const useFormField = () => {
|
||||
const fieldContext = React.useContext(FormFieldContext)
|
||||
const itemContext = React.useContext(FormItemContext)
|
||||
const { getFieldState, formState } = useFormContext()
|
||||
const fieldContext = React.useContext(FormFieldContext);
|
||||
const itemContext = React.useContext(FormItemContext);
|
||||
const { getFieldState, formState } = useFormContext();
|
||||
|
||||
const fieldState = getFieldState(fieldContext.name, formState)
|
||||
const fieldState = getFieldState(fieldContext.name, formState);
|
||||
|
||||
if (!fieldContext) {
|
||||
throw new Error("useFormField should be used within <FormField>")
|
||||
throw new Error("useFormField should be used within <FormField>");
|
||||
}
|
||||
|
||||
const { id } = itemContext
|
||||
const { id } = itemContext;
|
||||
|
||||
return {
|
||||
id,
|
||||
|
@ -58,37 +58,37 @@ const useFormField = () => {
|
|||
formItemId: `${id}-form-item`,
|
||||
formDescriptionId: `${id}-form-item-description`,
|
||||
formMessageId: `${id}-form-item-message`,
|
||||
...fieldState,
|
||||
}
|
||||
}
|
||||
...fieldState
|
||||
};
|
||||
};
|
||||
|
||||
type FormItemContextValue = {
|
||||
id: string
|
||||
}
|
||||
id: string;
|
||||
};
|
||||
|
||||
const FormItemContext = React.createContext<FormItemContextValue>(
|
||||
{} as FormItemContextValue
|
||||
)
|
||||
);
|
||||
|
||||
const FormItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const id = React.useId()
|
||||
const id = React.useId();
|
||||
|
||||
return (
|
||||
<FormItemContext.Provider value={{ id }}>
|
||||
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
||||
</FormItemContext.Provider>
|
||||
)
|
||||
})
|
||||
FormItem.displayName = "FormItem"
|
||||
);
|
||||
});
|
||||
FormItem.displayName = "FormItem";
|
||||
|
||||
const FormLabel = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { error, formItemId } = useFormField()
|
||||
const { error, formItemId } = useFormField();
|
||||
|
||||
return (
|
||||
<Label
|
||||
|
@ -97,15 +97,16 @@ const FormLabel = React.forwardRef<
|
|||
htmlFor={formItemId}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
FormLabel.displayName = "FormLabel"
|
||||
);
|
||||
});
|
||||
FormLabel.displayName = "FormLabel";
|
||||
|
||||
const FormControl = React.forwardRef<
|
||||
React.ElementRef<typeof Slot>,
|
||||
React.ComponentPropsWithoutRef<typeof Slot>
|
||||
>(({ ...props }, ref) => {
|
||||
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
|
||||
const { error, formItemId, formDescriptionId, formMessageId } =
|
||||
useFormField();
|
||||
|
||||
return (
|
||||
<Slot
|
||||
|
@ -119,15 +120,15 @@ const FormControl = React.forwardRef<
|
|||
aria-invalid={!!error}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
FormControl.displayName = "FormControl"
|
||||
);
|
||||
});
|
||||
FormControl.displayName = "FormControl";
|
||||
|
||||
const FormDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { formDescriptionId } = useFormField()
|
||||
const { formDescriptionId } = useFormField();
|
||||
|
||||
return (
|
||||
<p
|
||||
|
@ -136,19 +137,19 @@ const FormDescription = React.forwardRef<
|
|||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
FormDescription.displayName = "FormDescription"
|
||||
);
|
||||
});
|
||||
FormDescription.displayName = "FormDescription";
|
||||
|
||||
const FormMessage = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, children, ...props }, ref) => {
|
||||
const { error, formMessageId } = useFormField()
|
||||
const body = error ? String(error?.message) : children
|
||||
const { error, formMessageId } = useFormField();
|
||||
const body = error ? String(error?.message) : children;
|
||||
|
||||
if (!body) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -160,9 +161,9 @@ const FormMessage = React.forwardRef<
|
|||
>
|
||||
{body}
|
||||
</p>
|
||||
)
|
||||
})
|
||||
FormMessage.displayName = "FormMessage"
|
||||
);
|
||||
});
|
||||
FormMessage.displayName = "FormMessage";
|
||||
|
||||
export {
|
||||
useFormField,
|
||||
|
@ -172,5 +173,5 @@ export {
|
|||
FormControl,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
FormField,
|
||||
}
|
||||
FormField
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ export function GridPattern({
|
|||
aria-hidden="true"
|
||||
className={cn(
|
||||
"pointer-events-none absolute inset-0 h-full w-full fill-gray-400/35 stroke-gray-400/35",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
@ -26,50 +26,50 @@ const animationVariants = {
|
|||
"from-bottom": {
|
||||
initial: { y: "100%", opacity: 0 },
|
||||
animate: { y: 0, opacity: 1 },
|
||||
exit: { y: "100%", opacity: 0 },
|
||||
exit: { y: "100%", opacity: 0 }
|
||||
},
|
||||
"from-center": {
|
||||
initial: { scale: 0.5, opacity: 0 },
|
||||
animate: { scale: 1, opacity: 1 },
|
||||
exit: { scale: 0.5, opacity: 0 },
|
||||
exit: { scale: 0.5, opacity: 0 }
|
||||
},
|
||||
"from-top": {
|
||||
initial: { y: "-100%", opacity: 0 },
|
||||
animate: { y: 0, opacity: 1 },
|
||||
exit: { y: "-100%", opacity: 0 },
|
||||
exit: { y: "-100%", opacity: 0 }
|
||||
},
|
||||
"from-left": {
|
||||
initial: { x: "-100%", opacity: 0 },
|
||||
animate: { x: 0, opacity: 1 },
|
||||
exit: { x: "-100%", opacity: 0 },
|
||||
exit: { x: "-100%", opacity: 0 }
|
||||
},
|
||||
"from-right": {
|
||||
initial: { x: "100%", opacity: 0 },
|
||||
animate: { x: 0, opacity: 1 },
|
||||
exit: { x: "100%", opacity: 0 },
|
||||
exit: { x: "100%", opacity: 0 }
|
||||
},
|
||||
fade: {
|
||||
initial: { opacity: 0 },
|
||||
animate: { opacity: 1 },
|
||||
exit: { opacity: 0 },
|
||||
exit: { opacity: 0 }
|
||||
},
|
||||
"top-in-bottom-out": {
|
||||
initial: { y: "-100%", opacity: 0 },
|
||||
animate: { y: 0, opacity: 1 },
|
||||
exit: { y: "100%", opacity: 0 },
|
||||
exit: { y: "100%", opacity: 0 }
|
||||
},
|
||||
"left-in-right-out": {
|
||||
initial: { x: "-100%", opacity: 0 },
|
||||
animate: { x: 0, opacity: 1 },
|
||||
exit: { x: "100%", opacity: 0 },
|
||||
},
|
||||
exit: { x: "100%", opacity: 0 }
|
||||
}
|
||||
};
|
||||
|
||||
export default function HeroVideoDialog({
|
||||
animationStyle = "from-center",
|
||||
videoSrc,
|
||||
thumbnailSrc,
|
||||
thumbnailAlt = "Video thumbnail",
|
||||
thumbnailAlt = "Video thumbnail"
|
||||
}: HeroVideoProps) {
|
||||
const [isVideoOpen, setIsVideoOpen] = useState(false);
|
||||
const [isCloseHovered, setIsCloseHovered] = useState(false);
|
||||
|
@ -105,7 +105,7 @@ export default function HeroVideoDialog({
|
|||
className="size-8 text-white"
|
||||
style={{
|
||||
transform: isPlayHovered ? "scale(1.1)" : "scale(1)",
|
||||
transition: "transform 0.3s ease",
|
||||
transition: "transform 0.3s ease"
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -10,9 +10,9 @@ const Iconss = () => {
|
|||
x: "https://x.com/SVR_JS",
|
||||
Mastodon: "https://mastodon.social/@svrjs",
|
||||
Bluesky: "https://bsky.app/profile/svrjs.org",
|
||||
Odysee: "https://odysee.com/@SVRJS",
|
||||
},
|
||||
},
|
||||
Odysee: "https://odysee.com/@SVRJS"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -22,7 +22,7 @@ const Iconss = () => {
|
|||
target="_blank"
|
||||
className={buttonVariants({
|
||||
variant: "ghost",
|
||||
size: "sm",
|
||||
size: "sm"
|
||||
})}
|
||||
>
|
||||
<span className="sr-only">X icon</span>
|
||||
|
@ -44,7 +44,7 @@ const Iconss = () => {
|
|||
target="_blank"
|
||||
className={buttonVariants({
|
||||
variant: "ghost",
|
||||
size: "sm",
|
||||
size: "sm"
|
||||
})}
|
||||
>
|
||||
<span className="sr-only">Mastodon icon</span>
|
||||
|
@ -68,7 +68,7 @@ const Iconss = () => {
|
|||
target="_blank"
|
||||
className={buttonVariants({
|
||||
variant: "ghost",
|
||||
size: "sm",
|
||||
size: "sm"
|
||||
})}
|
||||
>
|
||||
<span className="sr-only">Bluesky icon</span>
|
||||
|
@ -92,7 +92,7 @@ const Iconss = () => {
|
|||
target="_blank"
|
||||
className={buttonVariants({
|
||||
variant: "ghost",
|
||||
size: "sm",
|
||||
size: "sm"
|
||||
})}
|
||||
>
|
||||
<span className="sr-only">Odysee icon</span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
@ -17,9 +17,9 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
Input.displayName = "Input"
|
||||
);
|
||||
Input.displayName = "Input";
|
||||
|
||||
export { Input }
|
||||
export { Input };
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import * as React from "react";
|
||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
)
|
||||
);
|
||||
|
||||
const Label = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
|
@ -20,7 +20,7 @@ const Label = React.forwardRef<
|
|||
className={cn(labelVariants(), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Label.displayName = LabelPrimitive.Root.displayName
|
||||
));
|
||||
Label.displayName = LabelPrimitive.Root.displayName;
|
||||
|
||||
export { Label }
|
||||
export { Label };
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as React from "react"
|
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
||||
import { cva } from "class-variance-authority"
|
||||
import { ChevronDown } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const NavigationMenu = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
|
||||
|
@ -20,8 +20,8 @@ const NavigationMenu = React.forwardRef<
|
|||
{children}
|
||||
<NavigationMenuViewport />
|
||||
</NavigationMenuPrimitive.Root>
|
||||
))
|
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
|
||||
));
|
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
|
||||
|
||||
const NavigationMenuList = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.List>,
|
||||
|
@ -35,14 +35,14 @@ const NavigationMenuList = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
|
||||
));
|
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
|
||||
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item;
|
||||
|
||||
const navigationMenuTriggerStyle = cva(
|
||||
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50"
|
||||
)
|
||||
);
|
||||
|
||||
const NavigationMenuTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
|
||||
|
@ -59,8 +59,8 @@ const NavigationMenuTrigger = React.forwardRef<
|
|||
aria-hidden="true"
|
||||
/>
|
||||
</NavigationMenuPrimitive.Trigger>
|
||||
))
|
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
|
||||
));
|
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
|
||||
|
||||
const NavigationMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
|
||||
|
@ -74,10 +74,10 @@ const NavigationMenuContent = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
|
||||
));
|
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
|
||||
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link;
|
||||
|
||||
const NavigationMenuViewport = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
||||
|
@ -93,9 +93,9 @@ const NavigationMenuViewport = React.forwardRef<
|
|||
{...props}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
));
|
||||
NavigationMenuViewport.displayName =
|
||||
NavigationMenuPrimitive.Viewport.displayName
|
||||
NavigationMenuPrimitive.Viewport.displayName;
|
||||
|
||||
const NavigationMenuIndicator = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
|
||||
|
@ -111,9 +111,9 @@ const NavigationMenuIndicator = React.forwardRef<
|
|||
>
|
||||
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
||||
</NavigationMenuPrimitive.Indicator>
|
||||
))
|
||||
));
|
||||
NavigationMenuIndicator.displayName =
|
||||
NavigationMenuPrimitive.Indicator.displayName
|
||||
NavigationMenuPrimitive.Indicator.displayName;
|
||||
|
||||
export {
|
||||
navigationMenuTriggerStyle,
|
||||
|
@ -124,5 +124,5 @@ export {
|
|||
NavigationMenuTrigger,
|
||||
NavigationMenuLink,
|
||||
NavigationMenuIndicator,
|
||||
NavigationMenuViewport,
|
||||
}
|
||||
NavigationMenuViewport
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import * as React from "react"
|
||||
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { ButtonProps, buttonVariants } from "@/components/ui/button"
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ButtonProps, buttonVariants } from "@/components/ui/button";
|
||||
|
||||
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
||||
<nav
|
||||
|
@ -11,8 +11,8 @@ const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
|||
className={cn("mx-auto flex w-full justify-center", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
Pagination.displayName = "Pagination"
|
||||
);
|
||||
Pagination.displayName = "Pagination";
|
||||
|
||||
const PaginationContent = React.forwardRef<
|
||||
HTMLUListElement,
|
||||
|
@ -23,21 +23,21 @@ const PaginationContent = React.forwardRef<
|
|||
className={cn("flex flex-row items-center gap-1", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
PaginationContent.displayName = "PaginationContent"
|
||||
));
|
||||
PaginationContent.displayName = "PaginationContent";
|
||||
|
||||
const PaginationItem = React.forwardRef<
|
||||
HTMLLIElement,
|
||||
React.ComponentProps<"li">
|
||||
>(({ className, ...props }, ref) => (
|
||||
<li ref={ref} className={cn("", className)} {...props} />
|
||||
))
|
||||
PaginationItem.displayName = "PaginationItem"
|
||||
));
|
||||
PaginationItem.displayName = "PaginationItem";
|
||||
|
||||
type PaginationLinkProps = {
|
||||
isActive?: boolean
|
||||
isActive?: boolean;
|
||||
} & Pick<ButtonProps, "size"> &
|
||||
React.ComponentProps<"a">
|
||||
React.ComponentProps<"a">;
|
||||
|
||||
const PaginationLink = ({
|
||||
className,
|
||||
|
@ -50,14 +50,14 @@ const PaginationLink = ({
|
|||
className={cn(
|
||||
buttonVariants({
|
||||
variant: isActive ? "outline" : "ghost",
|
||||
size,
|
||||
size
|
||||
}),
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
PaginationLink.displayName = "PaginationLink"
|
||||
);
|
||||
PaginationLink.displayName = "PaginationLink";
|
||||
|
||||
const PaginationPrevious = ({
|
||||
className,
|
||||
|
@ -72,8 +72,8 @@ const PaginationPrevious = ({
|
|||
<ChevronLeft className="h-4 w-4" />
|
||||
<span>Previous</span>
|
||||
</PaginationLink>
|
||||
)
|
||||
PaginationPrevious.displayName = "PaginationPrevious"
|
||||
);
|
||||
PaginationPrevious.displayName = "PaginationPrevious";
|
||||
|
||||
const PaginationNext = ({
|
||||
className,
|
||||
|
@ -88,8 +88,8 @@ const PaginationNext = ({
|
|||
<span>Next</span>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</PaginationLink>
|
||||
)
|
||||
PaginationNext.displayName = "PaginationNext"
|
||||
);
|
||||
PaginationNext.displayName = "PaginationNext";
|
||||
|
||||
const PaginationEllipsis = ({
|
||||
className,
|
||||
|
@ -103,8 +103,8 @@ const PaginationEllipsis = ({
|
|||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">More pages</span>
|
||||
</span>
|
||||
)
|
||||
PaginationEllipsis.displayName = "PaginationEllipsis"
|
||||
);
|
||||
PaginationEllipsis.displayName = "PaginationEllipsis";
|
||||
|
||||
export {
|
||||
Pagination,
|
||||
|
@ -113,5 +113,5 @@ export {
|
|||
PaginationItem,
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
}
|
||||
PaginationPrevious
|
||||
};
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as SelectPrimitive from "@radix-ui/react-select"
|
||||
import { Check, ChevronDown, ChevronUp } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as SelectPrimitive from "@radix-ui/react-select";
|
||||
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Select = SelectPrimitive.Root
|
||||
const Select = SelectPrimitive.Root;
|
||||
|
||||
const SelectGroup = SelectPrimitive.Group
|
||||
const SelectGroup = SelectPrimitive.Group;
|
||||
|
||||
const SelectValue = SelectPrimitive.Value
|
||||
const SelectValue = SelectPrimitive.Value;
|
||||
|
||||
const SelectTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||
|
@ -29,8 +29,8 @@ const SelectTrigger = React.forwardRef<
|
|||
<ChevronDown className="h-4 w-4 opacity-50" />
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
))
|
||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
|
||||
));
|
||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
||||
|
||||
const SelectScrollUpButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
||||
|
@ -46,8 +46,8 @@ const SelectScrollUpButton = React.forwardRef<
|
|||
>
|
||||
<ChevronUp className="h-4 w-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
))
|
||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
|
||||
));
|
||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
||||
|
||||
const SelectScrollDownButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
||||
|
@ -63,9 +63,9 @@ const SelectScrollDownButton = React.forwardRef<
|
|||
>
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
))
|
||||
));
|
||||
SelectScrollDownButton.displayName =
|
||||
SelectPrimitive.ScrollDownButton.displayName
|
||||
SelectPrimitive.ScrollDownButton.displayName;
|
||||
|
||||
const SelectContent = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
||||
|
@ -96,8 +96,8 @@ const SelectContent = React.forwardRef<
|
|||
<SelectScrollDownButton />
|
||||
</SelectPrimitive.Content>
|
||||
</SelectPrimitive.Portal>
|
||||
))
|
||||
SelectContent.displayName = SelectPrimitive.Content.displayName
|
||||
));
|
||||
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
||||
|
||||
const SelectLabel = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Label>,
|
||||
|
@ -108,8 +108,8 @@ const SelectLabel = React.forwardRef<
|
|||
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
SelectLabel.displayName = SelectPrimitive.Label.displayName
|
||||
));
|
||||
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
||||
|
||||
const SelectItem = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
||||
|
@ -131,8 +131,8 @@ const SelectItem = React.forwardRef<
|
|||
|
||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||
</SelectPrimitive.Item>
|
||||
))
|
||||
SelectItem.displayName = SelectPrimitive.Item.displayName
|
||||
));
|
||||
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
||||
|
||||
const SelectSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
||||
|
@ -143,8 +143,8 @@ const SelectSeparator = React.forwardRef<
|
|||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
|
||||
));
|
||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
||||
|
||||
export {
|
||||
Select,
|
||||
|
@ -156,5 +156,5 @@ export {
|
|||
SelectItem,
|
||||
SelectSeparator,
|
||||
SelectScrollUpButton,
|
||||
SelectScrollDownButton,
|
||||
}
|
||||
SelectScrollDownButton
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
||||
import * as React from "react";
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
|
@ -25,7 +25,7 @@ const Separator = React.forwardRef<
|
|||
{...props}
|
||||
/>
|
||||
)
|
||||
)
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName
|
||||
);
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||
|
||||
export { Separator }
|
||||
export { Separator };
|
||||
|
|
|
@ -40,12 +40,12 @@ const sheetVariants = cva(
|
|||
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
||||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
||||
right:
|
||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
||||
},
|
||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm"
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
side: "right"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -136,5 +136,5 @@ export {
|
|||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
SheetDescription
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Skeleton({
|
||||
className,
|
||||
|
@ -9,7 +9,7 @@ function Skeleton({
|
|||
className={cn("animate-pulse rounded-md bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { Skeleton }
|
||||
export { Skeleton };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Table = React.forwardRef<
|
||||
HTMLTableElement,
|
||||
|
@ -13,16 +13,16 @@ const Table = React.forwardRef<
|
|||
{...props}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
Table.displayName = "Table"
|
||||
));
|
||||
Table.displayName = "Table";
|
||||
|
||||
const TableHeader = React.forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
React.HTMLAttributes<HTMLTableSectionElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
||||
))
|
||||
TableHeader.displayName = "TableHeader"
|
||||
));
|
||||
TableHeader.displayName = "TableHeader";
|
||||
|
||||
const TableBody = React.forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
|
@ -33,8 +33,8 @@ const TableBody = React.forwardRef<
|
|||
className={cn("[&_tr:last-child]:border-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableBody.displayName = "TableBody"
|
||||
));
|
||||
TableBody.displayName = "TableBody";
|
||||
|
||||
const TableFooter = React.forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
|
@ -48,8 +48,8 @@ const TableFooter = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableFooter.displayName = "TableFooter"
|
||||
));
|
||||
TableFooter.displayName = "TableFooter";
|
||||
|
||||
const TableRow = React.forwardRef<
|
||||
HTMLTableRowElement,
|
||||
|
@ -63,8 +63,8 @@ const TableRow = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableRow.displayName = "TableRow"
|
||||
));
|
||||
TableRow.displayName = "TableRow";
|
||||
|
||||
const TableHead = React.forwardRef<
|
||||
HTMLTableCellElement,
|
||||
|
@ -78,8 +78,8 @@ const TableHead = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableHead.displayName = "TableHead"
|
||||
));
|
||||
TableHead.displayName = "TableHead";
|
||||
|
||||
const TableCell = React.forwardRef<
|
||||
HTMLTableCellElement,
|
||||
|
@ -90,8 +90,8 @@ const TableCell = React.forwardRef<
|
|||
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableCell.displayName = "TableCell"
|
||||
));
|
||||
TableCell.displayName = "TableCell";
|
||||
|
||||
const TableCaption = React.forwardRef<
|
||||
HTMLTableCaptionElement,
|
||||
|
@ -102,8 +102,8 @@ const TableCaption = React.forwardRef<
|
|||
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableCaption.displayName = "TableCaption"
|
||||
));
|
||||
TableCaption.displayName = "TableCaption";
|
||||
|
||||
export {
|
||||
Table,
|
||||
|
@ -113,5 +113,5 @@ export {
|
|||
TableHead,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableCaption,
|
||||
}
|
||||
TableCaption
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface TextareaProps
|
||||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
|
@ -16,9 +16,9 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
Textarea.displayName = "Textarea"
|
||||
);
|
||||
Textarea.displayName = "Textarea";
|
||||
|
||||
export { Textarea }
|
||||
export { Textarea };
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuTrigger
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Moon, Sun } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as ToastPrimitives from "@radix-ui/react-toast"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { X } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as ToastPrimitives from "@radix-ui/react-toast";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ToastProvider = ToastPrimitives.Provider
|
||||
const ToastProvider = ToastPrimitives.Provider;
|
||||
|
||||
const ToastViewport = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
||||
|
@ -21,8 +21,8 @@ const ToastViewport = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
|
||||
));
|
||||
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
||||
|
||||
const toastVariants = cva(
|
||||
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
||||
|
@ -31,14 +31,14 @@ const toastVariants = cva(
|
|||
variant: {
|
||||
default: "border bg-background text-foreground",
|
||||
destructive:
|
||||
"destructive group border-destructive bg-destructive text-destructive-foreground",
|
||||
},
|
||||
"destructive group border-destructive bg-destructive text-destructive-foreground"
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
variant: "default"
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
const Toast = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Root>,
|
||||
|
@ -51,9 +51,9 @@ const Toast = React.forwardRef<
|
|||
className={cn(toastVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
Toast.displayName = ToastPrimitives.Root.displayName
|
||||
);
|
||||
});
|
||||
Toast.displayName = ToastPrimitives.Root.displayName;
|
||||
|
||||
const ToastAction = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Action>,
|
||||
|
@ -67,8 +67,8 @@ const ToastAction = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
ToastAction.displayName = ToastPrimitives.Action.displayName
|
||||
));
|
||||
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
||||
|
||||
const ToastClose = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Close>,
|
||||
|
@ -85,8 +85,8 @@ const ToastClose = React.forwardRef<
|
|||
>
|
||||
<X className="h-4 w-4" />
|
||||
</ToastPrimitives.Close>
|
||||
))
|
||||
ToastClose.displayName = ToastPrimitives.Close.displayName
|
||||
));
|
||||
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
||||
|
||||
const ToastTitle = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Title>,
|
||||
|
@ -97,8 +97,8 @@ const ToastTitle = React.forwardRef<
|
|||
className={cn("text-sm font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
ToastTitle.displayName = ToastPrimitives.Title.displayName
|
||||
));
|
||||
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
||||
|
||||
const ToastDescription = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Description>,
|
||||
|
@ -109,12 +109,12 @@ const ToastDescription = React.forwardRef<
|
|||
className={cn("text-sm opacity-90", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
ToastDescription.displayName = ToastPrimitives.Description.displayName
|
||||
));
|
||||
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
||||
|
||||
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
|
||||
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
||||
|
||||
type ToastActionElement = React.ReactElement<typeof ToastAction>
|
||||
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
||||
|
||||
export {
|
||||
type ToastProps,
|
||||
|
@ -125,5 +125,5 @@ export {
|
|||
ToastTitle,
|
||||
ToastDescription,
|
||||
ToastClose,
|
||||
ToastAction,
|
||||
}
|
||||
ToastAction
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Toast,
|
||||
|
@ -6,12 +6,12 @@ import {
|
|||
ToastDescription,
|
||||
ToastProvider,
|
||||
ToastTitle,
|
||||
ToastViewport,
|
||||
} from "@/components/ui/toast"
|
||||
import { useToast } from "@/components/ui/use-toast"
|
||||
ToastViewport
|
||||
} from "@/components/ui/toast";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
|
||||
export function Toaster() {
|
||||
const { toasts } = useToast()
|
||||
const { toasts } = useToast();
|
||||
|
||||
return (
|
||||
<ToastProvider>
|
||||
|
@ -27,9 +27,9 @@ export function Toaster() {
|
|||
{action}
|
||||
<ToastClose />
|
||||
</Toast>
|
||||
)
|
||||
);
|
||||
})}
|
||||
<ToastViewport />
|
||||
</ToastProvider>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,106 +1,103 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
// Inspired by react-hot-toast library
|
||||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import type {
|
||||
ToastActionElement,
|
||||
ToastProps,
|
||||
} from "@/components/ui/toast"
|
||||
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
|
||||
|
||||
const TOAST_LIMIT = 1
|
||||
const TOAST_REMOVE_DELAY = 1000000
|
||||
const TOAST_LIMIT = 1;
|
||||
const TOAST_REMOVE_DELAY = 1000000;
|
||||
|
||||
type ToasterToast = ToastProps & {
|
||||
id: string
|
||||
title?: React.ReactNode
|
||||
description?: React.ReactNode
|
||||
action?: ToastActionElement
|
||||
}
|
||||
id: string;
|
||||
title?: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
action?: ToastActionElement;
|
||||
};
|
||||
|
||||
const actionTypes = {
|
||||
ADD_TOAST: "ADD_TOAST",
|
||||
UPDATE_TOAST: "UPDATE_TOAST",
|
||||
DISMISS_TOAST: "DISMISS_TOAST",
|
||||
REMOVE_TOAST: "REMOVE_TOAST",
|
||||
} as const
|
||||
REMOVE_TOAST: "REMOVE_TOAST"
|
||||
} as const;
|
||||
|
||||
let count = 0
|
||||
let count = 0;
|
||||
|
||||
function genId() {
|
||||
count = (count + 1) % Number.MAX_SAFE_INTEGER
|
||||
return count.toString()
|
||||
count = (count + 1) % Number.MAX_SAFE_INTEGER;
|
||||
return count.toString();
|
||||
}
|
||||
|
||||
type ActionType = typeof actionTypes
|
||||
type ActionType = typeof actionTypes;
|
||||
|
||||
type Action =
|
||||
| {
|
||||
type: ActionType["ADD_TOAST"]
|
||||
toast: ToasterToast
|
||||
type: ActionType["ADD_TOAST"];
|
||||
toast: ToasterToast;
|
||||
}
|
||||
| {
|
||||
type: ActionType["UPDATE_TOAST"]
|
||||
toast: Partial<ToasterToast>
|
||||
type: ActionType["UPDATE_TOAST"];
|
||||
toast: Partial<ToasterToast>;
|
||||
}
|
||||
| {
|
||||
type: ActionType["DISMISS_TOAST"]
|
||||
toastId?: ToasterToast["id"]
|
||||
type: ActionType["DISMISS_TOAST"];
|
||||
toastId?: ToasterToast["id"];
|
||||
}
|
||||
| {
|
||||
type: ActionType["REMOVE_TOAST"]
|
||||
toastId?: ToasterToast["id"]
|
||||
}
|
||||
type: ActionType["REMOVE_TOAST"];
|
||||
toastId?: ToasterToast["id"];
|
||||
};
|
||||
|
||||
interface State {
|
||||
toasts: ToasterToast[]
|
||||
toasts: ToasterToast[];
|
||||
}
|
||||
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
||||
|
||||
const addToRemoveQueue = (toastId: string) => {
|
||||
if (toastTimeouts.has(toastId)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
toastTimeouts.delete(toastId)
|
||||
toastTimeouts.delete(toastId);
|
||||
dispatch({
|
||||
type: "REMOVE_TOAST",
|
||||
toastId: toastId,
|
||||
})
|
||||
}, TOAST_REMOVE_DELAY)
|
||||
toastId: toastId
|
||||
});
|
||||
}, TOAST_REMOVE_DELAY);
|
||||
|
||||
toastTimeouts.set(toastId, timeout)
|
||||
}
|
||||
toastTimeouts.set(toastId, timeout);
|
||||
};
|
||||
|
||||
export const reducer = (state: State, action: Action): State => {
|
||||
switch (action.type) {
|
||||
case "ADD_TOAST":
|
||||
return {
|
||||
...state,
|
||||
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
||||
}
|
||||
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
|
||||
};
|
||||
|
||||
case "UPDATE_TOAST":
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.map((t) =>
|
||||
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
||||
),
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
case "DISMISS_TOAST": {
|
||||
const { toastId } = action
|
||||
const { toastId } = action;
|
||||
|
||||
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
||||
// but I'll keep it here for simplicity
|
||||
if (toastId) {
|
||||
addToRemoveQueue(toastId)
|
||||
addToRemoveQueue(toastId);
|
||||
} else {
|
||||
state.toasts.forEach((toast) => {
|
||||
addToRemoveQueue(toast.id)
|
||||
})
|
||||
addToRemoveQueue(toast.id);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -109,48 +106,48 @@ export const reducer = (state: State, action: Action): State => {
|
|||
t.id === toastId || toastId === undefined
|
||||
? {
|
||||
...t,
|
||||
open: false,
|
||||
open: false
|
||||
}
|
||||
: t
|
||||
),
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
case "REMOVE_TOAST":
|
||||
if (action.toastId === undefined) {
|
||||
return {
|
||||
...state,
|
||||
toasts: [],
|
||||
}
|
||||
toasts: []
|
||||
};
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
||||
toasts: state.toasts.filter((t) => t.id !== action.toastId)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const listeners: Array<(state: State) => void> = []
|
||||
const listeners: Array<(state: State) => void> = [];
|
||||
|
||||
let memoryState: State = { toasts: [] }
|
||||
let memoryState: State = { toasts: [] };
|
||||
|
||||
function dispatch(action: Action) {
|
||||
memoryState = reducer(memoryState, action)
|
||||
memoryState = reducer(memoryState, action);
|
||||
listeners.forEach((listener) => {
|
||||
listener(memoryState)
|
||||
})
|
||||
listener(memoryState);
|
||||
});
|
||||
}
|
||||
|
||||
type Toast = Omit<ToasterToast, "id">
|
||||
type Toast = Omit<ToasterToast, "id">;
|
||||
|
||||
function toast({ ...props }: Toast) {
|
||||
const id = genId()
|
||||
const id = genId();
|
||||
|
||||
const update = (props: ToasterToast) =>
|
||||
dispatch({
|
||||
type: "UPDATE_TOAST",
|
||||
toast: { ...props, id },
|
||||
})
|
||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
|
||||
toast: { ...props, id }
|
||||
});
|
||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
|
||||
|
||||
dispatch({
|
||||
type: "ADD_TOAST",
|
||||
|
@ -159,36 +156,36 @@ function toast({ ...props }: Toast) {
|
|||
id,
|
||||
open: true,
|
||||
onOpenChange: (open) => {
|
||||
if (!open) dismiss()
|
||||
},
|
||||
},
|
||||
})
|
||||
if (!open) dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
id: id,
|
||||
dismiss,
|
||||
update,
|
||||
}
|
||||
update
|
||||
};
|
||||
}
|
||||
|
||||
function useToast() {
|
||||
const [state, setState] = React.useState<State>(memoryState)
|
||||
const [state, setState] = React.useState<State>(memoryState);
|
||||
|
||||
React.useEffect(() => {
|
||||
listeners.push(setState)
|
||||
listeners.push(setState);
|
||||
return () => {
|
||||
const index = listeners.indexOf(setState)
|
||||
const index = listeners.indexOf(setState);
|
||||
if (index > -1) {
|
||||
listeners.splice(index, 1)
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}, [state])
|
||||
};
|
||||
}, [state]);
|
||||
|
||||
return {
|
||||
...state,
|
||||
toast,
|
||||
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
||||
}
|
||||
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId })
|
||||
};
|
||||
}
|
||||
|
||||
export { useToast, toast }
|
||||
export { useToast, toast };
|
||||
|
|
|
@ -20,7 +20,7 @@ export default function Banner({
|
|||
link,
|
||||
buttonText = "Learn More",
|
||||
closeButton = true,
|
||||
icon,
|
||||
icon
|
||||
}: BannerProps) {
|
||||
const [isBannerVisible, setIsBannerVisible] = useState(true);
|
||||
|
||||
|
@ -43,7 +43,7 @@ export default function Banner({
|
|||
<div
|
||||
style={{
|
||||
clipPath:
|
||||
"polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)",
|
||||
"polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)"
|
||||
}}
|
||||
className="aspect-[577/310] w-[36.0625rem] bg-gradient-to-r from-primary to-yellow-200 opacity-30"
|
||||
/>
|
||||
|
@ -55,7 +55,7 @@ export default function Banner({
|
|||
<div
|
||||
style={{
|
||||
clipPath:
|
||||
"polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)",
|
||||
"polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)"
|
||||
}}
|
||||
className="aspect-[577/310] w-[36.0625rem] bg-gradient-to-r from-primary to-[#9089fc] opacity-30"
|
||||
/>
|
||||
|
|
|
@ -9,7 +9,7 @@ export default function NumberTicker({
|
|||
value,
|
||||
direction = "up",
|
||||
delay = 0,
|
||||
className,
|
||||
className
|
||||
}: {
|
||||
value: number;
|
||||
direction?: "up" | "down";
|
||||
|
@ -20,7 +20,7 @@ export default function NumberTicker({
|
|||
const motionValue = useMotionValue(direction === "down" ? value : 0);
|
||||
const springValue = useSpring(motionValue, {
|
||||
damping: 60,
|
||||
stiffness: 100,
|
||||
stiffness: 100
|
||||
});
|
||||
const isInView = useInView(ref, { once: true, margin: "0px" });
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ export const transporter = nodemailer.createTransport({
|
|||
port: 587,
|
||||
auth: {
|
||||
user: process.env.EMAIL,
|
||||
pass: process.env.EMAIL_PASS,
|
||||
},
|
||||
pass: process.env.EMAIL_PASS
|
||||
}
|
||||
});
|
||||
|
||||
export const mailOptions = {
|
||||
|
@ -33,5 +33,5 @@ export const mailOptions = {
|
|||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
`,
|
||||
`
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ const config = {
|
|||
apiVersion: "2023-08-08",
|
||||
dataset: "production",
|
||||
projectId: `${process.env.SANITY_PROJECT_ID}`,
|
||||
useCdn: false, // ensure fresh data
|
||||
useCdn: false // ensure fresh data
|
||||
};
|
||||
|
||||
export const client = createClient(config);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {
|
||||
generateUploadButton,
|
||||
generateUploadDropzone,
|
||||
generateUploadDropzone
|
||||
} from "@uploadthing/react";
|
||||
|
||||
import type { OurFileRouter } from "@/app/api/uploadthing/core";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ export const downloadSchema = z.object({
|
|||
fileName: z.string().nonempty(),
|
||||
version: z.string().nonempty(),
|
||||
downloadLink: z.string().url().nonempty(),
|
||||
fileSize: z.string().nonempty(),
|
||||
fileSize: z.string().nonempty()
|
||||
});
|
||||
|
||||
export const modsSchema = z.object({
|
||||
fileName: z.string().nonempty(),
|
||||
version: z.string().nonempty(),
|
||||
downloadLink: z.string().url().nonempty(),
|
||||
fileSize: z.string().nonempty(),
|
||||
fileSize: z.string().nonempty()
|
||||
});
|
||||
|
||||
export const logsSchema = z.object({
|
||||
|
@ -19,18 +19,18 @@ export const logsSchema = z.object({
|
|||
date: z.string(),
|
||||
bullets: z.array(
|
||||
z.object({
|
||||
point: z.string(),
|
||||
point: z.string()
|
||||
})
|
||||
),
|
||||
)
|
||||
});
|
||||
|
||||
export const vulnerabilitiesSchema = z.object({
|
||||
version: z.string(),
|
||||
bullets: z.array(
|
||||
z.object({
|
||||
point: z.string(),
|
||||
point: z.string()
|
||||
})
|
||||
),
|
||||
)
|
||||
});
|
||||
|
||||
export const ModsVulnerabilities = z.object({
|
||||
|
@ -38,9 +38,9 @@ export const ModsVulnerabilities = z.object({
|
|||
category: z.string(),
|
||||
bullets: z.array(
|
||||
z.object({
|
||||
point: z.string(),
|
||||
point: z.string()
|
||||
})
|
||||
),
|
||||
)
|
||||
});
|
||||
|
||||
export type LogsFormValues = z.infer<typeof logsSchema>;
|
||||
|
@ -51,12 +51,12 @@ export type ModsVulnerability = z.infer<typeof ModsVulnerabilities>;
|
|||
|
||||
export const contactFormSchema = z.object({
|
||||
name: z.string().min(2, {
|
||||
message: "Name must be at least 2 characters.",
|
||||
message: "Name must be at least 2 characters."
|
||||
}),
|
||||
email: z.string().email({
|
||||
message: "Invalid email address.",
|
||||
message: "Invalid email address."
|
||||
}),
|
||||
message: z.string().min(10, {
|
||||
message: "Message must be at least 10 characters.",
|
||||
}),
|
||||
message: "Message must be at least 10 characters."
|
||||
})
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import { AppProps } from "next/app";
|
|||
|
||||
const poppins = Poppins({
|
||||
weight: ["400", "600", "700", "900"],
|
||||
subsets: ["latin"],
|
||||
subsets: ["latin"]
|
||||
});
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
|
|
Loading…
Reference in a new issue