chore(website): make biome happy

This commit is contained in:
JiPai
2024-09-06 15:42:50 +08:00
parent 7acb86a83e
commit c482230995
23 changed files with 396 additions and 472 deletions

View File

@@ -1,5 +1,5 @@
import { notFound } from 'next/navigation' import { notFound } from "next/navigation";
export default function CatchAll() { export default function CatchAll() {
notFound() notFound();
} }

View File

@@ -1,94 +1,90 @@
import clsx from 'clsx' import clsx from "clsx";
import { Inter, Lexend } from 'next/font/google' import { Inter, Lexend } from "next/font/google";
import '@/styles/tailwind.css' import "@/styles/tailwind.css";
import GoogleAnalytics from '@/components/analitycs/google' import GoogleAnalytics from "@/components/analitycs/google";
import { NextIntlClientProvider } from 'next-intl' import { NextIntlClientProvider } from "next-intl";
import { getMessages } from 'next-intl/server' import { getMessages } from "next-intl/server";
import type { Metadata } from 'next' import type { Metadata } from "next";
export const metadata: Metadata = { export const metadata: Metadata = {
title: { title: {
default: 'Dokploy - Effortless Deployment Solutions', default: "Dokploy - Effortless Deployment Solutions",
template: '%s | Simplify Your DevOps', template: "%s | Simplify Your DevOps",
}, },
alternates: { alternates: {
canonical: 'https://dokploy.com', canonical: "https://dokploy.com",
languages: { languages: {
en: 'https://dokploy.com', en: "https://dokploy.com",
}, },
}, },
description: description:
'Streamline your deployment process with Dokploy. Effortlessly manage applications and databases on any VPS using Docker and Traefik for improved performance and security.', "Streamline your deployment process with Dokploy. Effortlessly manage applications and databases on any VPS using Docker and Traefik for improved performance and security.",
applicationName: 'Dokploy', applicationName: "Dokploy",
keywords: [ keywords: [
'Dokploy', "Dokploy",
'Docker', "Docker",
'Traefik', "Traefik",
'deployment', "deployment",
'VPS', "VPS",
'application management', "application management",
'database management', "database management",
'DevOps', "DevOps",
'cloud infrastructure', "cloud infrastructure",
'UI Self hosted', "UI Self hosted",
], ],
referrer: 'origin', referrer: "origin",
robots: 'index, follow', robots: "index, follow",
openGraph: { openGraph: {
type: 'website', type: "website",
url: 'https://dokploy.com', url: "https://dokploy.com",
title: 'Dokploy - Effortless Deployment Solutions', title: "Dokploy - Effortless Deployment Solutions",
description: description:
'Simplify your DevOps with Dokploy. Deploy applications and manage databases efficiently on any VPS.', "Simplify your DevOps with Dokploy. Deploy applications and manage databases efficiently on any VPS.",
siteName: 'Dokploy', siteName: "Dokploy",
images: [ images: [
{ {
url: 'http://dokploy.com/og.png', url: "http://dokploy.com/og.png",
}, },
], ],
}, },
twitter: { twitter: {
card: 'summary_large_image', card: "summary_large_image",
site: '@Dokploy', site: "@Dokploy",
creator: '@Dokploy', creator: "@Dokploy",
title: 'Dokploy - Simplify Your DevOps', title: "Dokploy - Simplify Your DevOps",
description: description:
'Deploy applications and manage databases with ease using Dokploy. Learn how our platform can elevate your infrastructure management.', "Deploy applications and manage databases with ease using Dokploy. Learn how our platform can elevate your infrastructure management.",
images: 'https://dokploy.com/og.png', images: "https://dokploy.com/og.png",
}, },
} };
const inter = Inter({ const inter = Inter({
subsets: ['latin'], subsets: ["latin"],
display: 'swap', display: "swap",
variable: '--font-inter', variable: "--font-inter",
}) });
const lexend = Lexend({ const lexend = Lexend({
subsets: ['latin'], subsets: ["latin"],
display: 'swap', display: "swap",
variable: '--font-lexend', variable: "--font-lexend",
}) });
export default async function RootLayout({ export default async function RootLayout({
children, children,
params, params,
}: { }: {
children: React.ReactNode children: React.ReactNode;
params: { locale: string } params: { locale: string };
}) { }) {
const { locale } = params const { locale } = params;
const messages = await getMessages() const messages = await getMessages();
return ( return (
<html <html
lang={locale} lang={locale}
className={clsx( className={clsx("h-full scroll-smooth", inter.variable, lexend.variable)}
'h-full scroll-smooth',
inter.variable,
lexend.variable,
)}
> >
<GoogleAnalytics /> <GoogleAnalytics />
<body className="flex h-full flex-col"> <body className="flex h-full flex-col">
@@ -97,5 +93,5 @@ export default async function RootLayout({
</NextIntlClientProvider> </NextIntlClientProvider>
</body> </body>
</html> </html>
) );
} }

View File

@@ -1,5 +1,5 @@
import { SlimLayout } from '@/components/SlimLayout' import { SlimLayout } from "@/components/SlimLayout";
export default function NotFound() { export default function NotFound() {
return <SlimLayout /> return <SlimLayout />;
} }

View File

@@ -1,11 +1,11 @@
import { CallToAction } from '@/components/CallToAction' import { CallToAction } from "@/components/CallToAction";
import { Faqs } from '@/components/Faqs' import { Faqs } from "@/components/Faqs";
import { Footer } from '@/components/Footer' import { Footer } from "@/components/Footer";
import { Header } from '@/components/Header' import { Header } from "@/components/Header";
import { Hero } from '@/components/Hero' import { Hero } from "@/components/Hero";
import { PrimaryFeatures } from '@/components/PrimaryFeatures' import { PrimaryFeatures } from "@/components/PrimaryFeatures";
import { SecondaryFeatures } from '@/components/SecondaryFeatures' import { SecondaryFeatures } from "@/components/SecondaryFeatures";
import { Testimonials } from '../../components/Testimonials' import { Testimonials } from "../../components/Testimonials";
export default function Home() { export default function Home() {
return ( return (
@@ -21,5 +21,5 @@ export default function Home() {
<Footer /> <Footer />
</main> </main>
</div> </div>
) );
} }

View File

@@ -1,11 +1,11 @@
import { ReactNode } from 'react' import type { ReactNode } from "react";
type Props = { type Props = {
children: ReactNode children: ReactNode;
} };
// Since we have a `not-found.tsx` page on the root, a layout file // Since we have a `not-found.tsx` page on the root, a layout file
// is required, even if it's just passing children through. // is required, even if it's just passing children through.
export default function RootLayout({ children }: Props) { export default function RootLayout({ children }: Props) {
return children return children;
} }

View File

@@ -1,13 +1,13 @@
'use client' "use client";
import Error from 'next/error' import NextError from "next/error";
export default function NotFound() { export default function NotFound() {
return ( return (
<html lang="en"> <html lang="en">
<body> <body>
<Error statusCode={404} /> <NextError statusCode={404} />
</body> </body>
</html> </html>
) );
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,58 +1,57 @@
import { useTranslations } from 'next-intl' import { useTranslations } from "next-intl";
import { Container } from './Container' import { Container } from "./Container";
const faqs = [ const faqs = [
[ [
{ {
question: 'faq.q1', question: "faq.q1",
answer: 'faq.a1', answer: "faq.a1",
}, },
{ {
question: 'faq.q2', question: "faq.q2",
answer: 'faq.a2', answer: "faq.a2",
}, },
{ {
question: 'faq.q3', question: "faq.q3",
answer: 'faq.a3', answer: "faq.a3",
}, },
{ {
question: 'faq.q4', question: "faq.q4",
answer: 'faq.a4', answer: "faq.a4",
}, },
], ],
[ [
{ {
question: 'faq.q5', question: "faq.q5",
answer: 'faq.a5', answer: "faq.a5",
}, },
{ {
question: 'faq.q6', question: "faq.q6",
answer: 'faq.a6', answer: "faq.a6",
}, },
{ {
question: 'faq.q7', question: "faq.q7",
answer: "faq.a7", answer: "faq.a7",
}, },
], ],
[ [
{ {
question: question: "faq.q8",
'faq.q8', answer: "faq.a8",
answer: 'faq.a8',
}, },
{ {
question: 'faq.q9', question: "faq.q9",
answer: 'faq.a9', answer: "faq.a9",
}, },
{ {
question: 'faq.q10', question: "faq.q10",
answer: 'faq.a10', answer: "faq.a10",
}, },
], ],
] ];
export function Faqs() { export function Faqs() {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
return ( return (
<section <section
id="faqs" id="faqs"
@@ -65,10 +64,10 @@ export function Faqs() {
id="faq-title" id="faq-title"
className="font-display text-3xl tracking-tight text-primary sm:text-4xl" className="font-display text-3xl tracking-tight text-primary sm:text-4xl"
> >
{t('faq.title')} {t("faq.title")}
</h2> </h2>
<p className="mt-4 text-lg tracking-tight text-muted-foreground"> <p className="mt-4 text-lg tracking-tight text-muted-foreground">
{t('faq.des')} {t("faq.des")}
</p> </p>
</div> </div>
<ul className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-8 lg:max-w-none lg:grid-cols-3"> <ul className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-8 lg:max-w-none lg:grid-cols-3">
@@ -91,5 +90,5 @@ export function Faqs() {
</ul> </ul>
</Container> </Container>
</section> </section>
) );
} }

View File

@@ -1,13 +1,13 @@
import Link from 'next/link' import Link from "next/link";
import { Container } from './Container' import { useTranslations } from "next-intl";
import { NavLink } from './NavLink' import { Container } from "./Container";
import { Logo } from './shared/Logo' import { NavLink } from "./NavLink";
import { useTranslations } from 'next-intl' import { Logo } from "./shared/Logo";
export function Footer() { export function Footer() {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
const linkT = useTranslations('Link') const linkT = useTranslations("Link");
return ( return (
<footer className="bg-black"> <footer className="bg-black">
@@ -22,14 +22,10 @@ export function Footer() {
<nav className="mt-10 text-sm" aria-label="quick links"> <nav className="mt-10 text-sm" aria-label="quick links">
<div className="-my-1 flex flex-wrap justify-center gap-6"> <div className="-my-1 flex flex-wrap justify-center gap-6">
<NavLink href="/#features"> <NavLink href="/#features">{t("navigation.features")}</NavLink>
{t('navigation.features')} <NavLink href="/#faqs">{t("navigation.faqs")}</NavLink>
</NavLink> <NavLink href={linkT("docs.intro")} target="_blank">
<NavLink href="/#faqs"> {t("navigation.docs")}
{t('navigation.faqs')}
</NavLink>
<NavLink href={linkT('docs.intro')} target="_blank">
{t('navigation.docs')}
</NavLink> </NavLink>
</div> </div>
</nav> </nav>
@@ -62,12 +58,12 @@ export function Footer() {
</Link> </Link>
</div> </div>
<p className="mt-6 text-sm text-muted-foreground sm:mt-0"> <p className="mt-6 text-sm text-muted-foreground sm:mt-0">
{t('footer.copyright', { {t("footer.copyright", {
year: new Date().getFullYear(), year: new Date().getFullYear(),
})} })}
</p> </p>
</div> </div>
</Container> </Container>
</footer> </footer>
) );
} }

View File

@@ -1,40 +1,40 @@
'use client' "use client";
import { cn } from '@/lib/utils'
import { Popover, Transition } from '@headlessui/react'
import { HeartIcon } from 'lucide-react'
import { Fragment, JSX, SVGProps } from 'react'
import { Container } from './Container'
import { NavLink } from './NavLink'
import { trackGAEvent } from './analitycs'
import { Logo } from './shared/Logo'
import { Button, buttonVariants } from './ui/button'
import { useLocale, useTranslations } from 'next-intl'
import { Link, useRouter } from '@/i18n/routing'
import { import {
Select, Select,
SelectContent, SelectContent,
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
} from '@/components/ui/select' } from "@/components/ui/select";
import { Link, useRouter } from "@/i18n/routing";
import { cn } from "@/lib/utils";
import { Popover, Transition } from "@headlessui/react";
import { HeartIcon } from "lucide-react";
import { useLocale, useTranslations } from "next-intl";
import { Fragment, type JSX, type SVGProps } from "react";
import { Container } from "./Container";
import { NavLink } from "./NavLink";
import { trackGAEvent } from "./analitycs";
import { Logo } from "./shared/Logo";
import { Button, buttonVariants } from "./ui/button";
function MobileNavLink({ function MobileNavLink({
href, href,
children, children,
target, target,
}: { }: {
href: string href: string;
children: React.ReactNode children: React.ReactNode;
target?: string target?: string;
}) { }) {
return ( return (
<Popover.Button <Popover.Button
onClick={() => { onClick={() => {
trackGAEvent({ trackGAEvent({
action: 'Nav Link Clicked', action: "Nav Link Clicked",
category: 'Navigation', category: "Navigation",
label: href, label: href,
}) });
}} }}
as={Link} as={Link}
href={href} href={href}
@@ -43,7 +43,7 @@ function MobileNavLink({
> >
{children} {children}
</Popover.Button> </Popover.Button>
) );
} }
function MobileNavIcon({ open }: { open: boolean }) { function MobileNavIcon({ open }: { open: boolean }) {
@@ -57,20 +57,17 @@ function MobileNavIcon({ open }: { open: boolean }) {
> >
<path <path
d="M0 1H14M0 7H14M0 13H14" d="M0 1H14M0 7H14M0 13H14"
className={cn( className={cn("origin-center transition", open && "scale-90 opacity-0")}
'origin-center transition',
open && 'scale-90 opacity-0',
)}
/> />
<path <path
d="M2 2L12 12M12 2L2 12" d="M2 2L12 12M12 2L2 12"
className={cn( className={cn(
'origin-center transition', "origin-center transition",
!open && 'scale-90 opacity-0', !open && "scale-90 opacity-0",
)} )}
/> />
</svg> </svg>
) );
} }
const I18nIcon = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => ( const I18nIcon = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
@@ -89,11 +86,11 @@ const I18nIcon = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
d="m478.33 433.6-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362 368 281.65 401.17 362zm-66.99-19.08a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73 39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93.92 1.19 1.83 2.35 2.74 3.51-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59 22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z" d="m478.33 433.6-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362 368 281.65 401.17 362zm-66.99-19.08a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73 39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93.92 1.19 1.83 2.35 2.74 3.51-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59 22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z"
/> />
</svg> </svg>
) );
function MobileNavigation() { function MobileNavigation() {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
const linkT = useTranslations('Link') const linkT = useTranslations("Link");
return ( return (
<Popover> <Popover>
<Popover.Button <Popover.Button
@@ -129,30 +126,25 @@ function MobileNavigation() {
className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5" className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5"
> >
<MobileNavLink href="/#features"> <MobileNavLink href="/#features">
{t('navigation.features')} {t("navigation.features")}
</MobileNavLink> </MobileNavLink>
{/* <MobileNavLink href="/#testimonials">Testimonials</MobileNavLink> */} {/* <MobileNavLink href="/#testimonials">Testimonials</MobileNavLink> */}
<MobileNavLink href="/#faqs"> <MobileNavLink href="/#faqs">{t("navigation.faqs")}</MobileNavLink>
{t('navigation.faqs')} <MobileNavLink href={linkT("docs.intro")} target="_blank">
</MobileNavLink> {t("navigation.docs")}
<MobileNavLink
href={linkT('docs.intro')}
target="_blank"
>
{t('navigation.docs')}
</MobileNavLink> </MobileNavLink>
</Popover.Panel> </Popover.Panel>
</Transition.Child> </Transition.Child>
</Transition.Root> </Transition.Root>
</Popover> </Popover>
) );
} }
export function Header() { export function Header() {
const router = useRouter() const router = useRouter();
const locale = useLocale() const locale = useLocale();
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
const linkT = useTranslations('Link') const linkT = useTranslations("Link");
return ( return (
<header className="bg-background py-10"> <header className="bg-background py-10">
@@ -163,57 +155,50 @@ export function Header() {
<Logo className="h-10 w-auto" /> <Logo className="h-10 w-auto" />
</Link> </Link>
<div className="hidden md:flex md:gap-x-6"> <div className="hidden md:flex md:gap-x-6">
<NavLink href="/#features"> <NavLink href="/#features">{t("navigation.features")}</NavLink>
{t('navigation.features')}
</NavLink>
{/* <NavLink href="/#testimonials">Testimonials</NavLink> */} {/* <NavLink href="/#testimonials">Testimonials</NavLink> */}
<NavLink href="/#faqs"> <NavLink href="/#faqs">{t("navigation.faqs")}</NavLink>
{t('navigation.faqs')} <NavLink href={linkT("docs.intro")} target="_blank">
</NavLink> {t("navigation.docs")}
<NavLink href={linkT('docs.intro')} target="_blank">
{t('navigation.docs')}
</NavLink> </NavLink>
</div> </div>
</div> </div>
<div className="flex items-center gap-x-2 md:gap-x-5"> <div className="flex items-center gap-x-2 md:gap-x-5">
<Select <Select
onValueChange={(locale) => { onValueChange={(locale) => {
router.replace('/', { router.replace("/", {
locale: locale as 'en' | 'zh-Hans', locale: locale as "en" | "zh-Hans",
}) });
}} }}
value={locale} value={locale}
> >
<SelectTrigger <SelectTrigger
className={buttonVariants({ className={buttonVariants({
variant: 'outline', variant: "outline",
className: className:
' flex items-center gap-2 !rounded-full visited:outline-none focus-within:outline-none focus:outline-none', " flex items-center gap-2 !rounded-full visited:outline-none focus-within:outline-none focus:outline-none",
})} })}
> >
<I18nIcon width={20} height={20} /> <I18nIcon width={20} height={20} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="en"> <SelectItem value="en">{t("navigation.i18nEn")}</SelectItem>
{t('navigation.i18nEn')}
</SelectItem>
<SelectItem value="zh-Hans"> <SelectItem value="zh-Hans">
{t('navigation.i18nZh-Hans')} {t("navigation.i18nZh-Hans")}
</SelectItem> </SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<Link <Link
className={buttonVariants({ className={buttonVariants({
variant: 'outline', variant: "outline",
className: className: " flex items-center gap-2 !rounded-full",
' flex items-center gap-2 !rounded-full',
})} })}
href="https://opencollective.com/dokploy" href="https://opencollective.com/dokploy"
target="_blank" target="_blank"
> >
<span className="text-sm font-semibold"> <span className="text-sm font-semibold">
{t('navigation.support')}{' '} {t("navigation.support")}{" "}
</span> </span>
<HeartIcon className="animate-heartbeat size-4 fill-red-600 text-red-500 " /> <HeartIcon className="animate-heartbeat size-4 fill-red-600 text-red-500 " />
</Link> </Link>
@@ -236,7 +221,7 @@ export function Header() {
> >
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" /> <path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" />
</svg> </svg>
{t('navigation.discord')} {t("navigation.discord")}
</Link> </Link>
</Button> </Button>
<div className="-mr-1 md:hidden"> <div className="-mr-1 md:hidden">
@@ -246,5 +231,5 @@ export function Header() {
</nav> </nav>
</Container> </Container>
</header> </header>
) );
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import { Link } from "@/i18n/routing";
import { trackGAEvent } from "./analitycs"; import { trackGAEvent } from "./analitycs";
import { Link } from '@/i18n/routing'
export function NavLink({ export function NavLink({
href, href,

View File

@@ -1,73 +1,73 @@
'use client' "use client";
import { Tab } from '@headlessui/react' import { Tab } from "@headlessui/react";
import { AnimatePresence, motion } from 'framer-motion' import { AnimatePresence, motion } from "framer-motion";
import { useEffect, useState } from 'react' import { useEffect, useState } from "react";
import { cn } from '@/lib/utils' import { cn } from "@/lib/utils";
import { Container } from './Container' import { useTranslations } from "next-intl";
import { useTranslations } from 'next-intl' import { Container } from "./Container";
const features = [ const features = [
{ {
title: 'primaryFeatures.projects', title: "primaryFeatures.projects",
description: 'primaryFeatures.projectsDes', description: "primaryFeatures.projectsDes",
image: '/primary/projects.png', image: "/primary/projects.png",
}, },
{ {
title: 'primaryFeatures.applications', title: "primaryFeatures.applications",
description: 'primaryFeatures.applicationsDes', description: "primaryFeatures.applicationsDes",
image: '/primary/applications.png', image: "/primary/applications.png",
}, },
{ {
title: 'primaryFeatures.compose', title: "primaryFeatures.compose",
description: 'primaryFeatures.composeDes', description: "primaryFeatures.composeDes",
image: '/primary/compose.png', image: "/primary/compose.png",
}, },
{ {
title: 'primaryFeatures.multinode', title: "primaryFeatures.multinode",
description: 'primaryFeatures.multinodeDes', description: "primaryFeatures.multinodeDes",
image: '/primary/multinode.png', image: "/primary/multinode.png",
}, },
{ {
title: 'primaryFeatures.monitoring', title: "primaryFeatures.monitoring",
description: 'primaryFeatures.monitoringDes', description: "primaryFeatures.monitoringDes",
image: '/primary/monitoring.png', image: "/primary/monitoring.png",
}, },
{ {
title: 'primaryFeatures.backups', title: "primaryFeatures.backups",
description: 'primaryFeatures.backupsDes', description: "primaryFeatures.backupsDes",
image: '/primary/backups.png', image: "/primary/backups.png",
}, },
] ];
export function PrimaryFeatures() { export function PrimaryFeatures() {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
const [tabOrientation, setTabOrientation] = useState< const [tabOrientation, setTabOrientation] = useState<
'horizontal' | 'vertical' "horizontal" | "vertical"
>('horizontal') >("horizontal");
useEffect(() => { useEffect(() => {
const lgMediaQuery = window.matchMedia('(min-width: 1024px)') const lgMediaQuery = window.matchMedia("(min-width: 1024px)");
function onMediaQueryChange({ matches }: { matches: boolean }) { function onMediaQueryChange({ matches }: { matches: boolean }) {
setTabOrientation(matches ? 'vertical' : 'horizontal') setTabOrientation(matches ? "vertical" : "horizontal");
} }
onMediaQueryChange(lgMediaQuery) onMediaQueryChange(lgMediaQuery);
lgMediaQuery.addEventListener('change', onMediaQueryChange) lgMediaQuery.addEventListener("change", onMediaQueryChange);
return () => { return () => {
lgMediaQuery.removeEventListener('change', onMediaQueryChange) lgMediaQuery.removeEventListener("change", onMediaQueryChange);
} };
}, []) }, []);
const [isMounted, setIsMounted] = useState(false) const [isMounted, setIsMounted] = useState(false);
// Cambiar isMounted a true después del primer render // Cambiar isMounted a true después del primer render
useEffect(() => { useEffect(() => {
setIsMounted(true) setIsMounted(true);
}, []) }, []);
return ( return (
<section <section
@@ -88,16 +88,16 @@ export function PrimaryFeatures() {
<Container className="relative"> <Container className="relative">
<div className="max-w-2xl md:mx-auto md:text-center xl:max-w-none"> <div className="max-w-2xl md:mx-auto md:text-center xl:max-w-none">
<h2 className="font-display text-3xl tracking-tight text-white sm:text-4xl md:text-5xl"> <h2 className="font-display text-3xl tracking-tight text-white sm:text-4xl md:text-5xl">
{t('primaryFeatures.title')} {t("primaryFeatures.title")}
</h2> </h2>
<p className="mt-6 text-lg tracking-tight text-muted-foreground"> <p className="mt-6 text-lg tracking-tight text-muted-foreground">
{t('primaryFeatures.des')} {t("primaryFeatures.des")}
</p> </p>
</div> </div>
<Tab.Group <Tab.Group
as="div" as="div"
className="mt-16 grid grid-cols-1 items-center gap-y-2 pt-10 sm:gap-y-6 md:mt-20 lg:grid-cols-12 lg:pt-0" className="mt-16 grid grid-cols-1 items-center gap-y-2 pt-10 sm:gap-y-6 md:mt-20 lg:grid-cols-12 lg:pt-0"
vertical={tabOrientation === 'vertical'} vertical={tabOrientation === "vertical"}
> >
{({ selectedIndex }) => ( {({ selectedIndex }) => (
<> <>
@@ -113,12 +113,11 @@ export function PrimaryFeatures() {
initial={false} initial={false}
key={`feature-${featureIndex}`} key={`feature-${featureIndex}`}
className={cn( className={cn(
'group relative rounded-full px-4 py-1 transition-colors lg:rounded-l-xl lg:rounded-r-none lg:p-6 ', "group relative rounded-full px-4 py-1 transition-colors lg:rounded-l-xl lg:rounded-r-none lg:p-6 ",
)} )}
> >
<AnimatePresence> <AnimatePresence>
{selectedIndex === {selectedIndex === featureIndex && (
featureIndex && (
<motion.span <motion.span
layoutId="tab" layoutId="tab"
className="absolute inset-0 z-10 rounded-full bg-white/5 mix-blend-difference lg:rounded-l-xl lg:rounded-r-none" className="absolute inset-0 z-10 rounded-full bg-white/5 mix-blend-difference lg:rounded-l-xl lg:rounded-r-none"
@@ -126,7 +125,7 @@ export function PrimaryFeatures() {
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ transition={{
type: 'spring', type: "spring",
bounce: 0.2, bounce: 0.2,
duration: 0.5, duration: 0.5,
}} }}
@@ -136,7 +135,7 @@ export function PrimaryFeatures() {
<h3> <h3>
<Tab <Tab
className={cn( className={cn(
'font-display text-lg text-primary ui-not-focus-visible:outline-none', "font-display text-lg text-primary ui-not-focus-visible:outline-none",
)} )}
> >
<span className="absolute inset-0 rounded-full lg:rounded-l-xl lg:rounded-r-none" /> <span className="absolute inset-0 rounded-full lg:rounded-l-xl lg:rounded-r-none" />
@@ -145,7 +144,7 @@ export function PrimaryFeatures() {
</h3> </h3>
<p <p
className={cn( className={cn(
'mt-2 hidden text-sm text-muted-foreground lg:block', "mt-2 hidden text-sm text-muted-foreground lg:block",
)} )}
> >
{t(feature.description)} {t(feature.description)}
@@ -166,19 +165,11 @@ export function PrimaryFeatures() {
<motion.div <motion.div
key={feature.title} key={feature.title}
initial={ initial={isMounted ? { opacity: 0.8, x: 50 } : {}}
isMounted animate={isMounted ? { opacity: 1, x: 0 } : {}}
? { opacity: 0.8, x: 50 }
: {}
}
animate={
isMounted
? { opacity: 1, x: 0 }
: {}
}
exit={{ opacity: 0, x: -50 }} exit={{ opacity: 0, x: -50 }}
transition={{ transition={{
type: 'spring', type: "spring",
bounce: 0.2, bounce: 0.2,
duration: 0.6, duration: 0.6,
}} }}
@@ -199,5 +190,5 @@ export function PrimaryFeatures() {
</Tab.Group> </Tab.Group>
</Container> </Container>
</section> </section>
) );
} }

View File

@@ -1,38 +1,38 @@
'use client' "use client";
import { cn } from '@/lib/utils' import { cn } from "@/lib/utils";
import { Tab } from '@headlessui/react' import { Tab } from "@headlessui/react";
import { motion } from 'framer-motion' import { motion } from "framer-motion";
import { Layers, Terminal, Users } from 'lucide-react' import { Layers, Terminal, Users } from "lucide-react";
import { Container } from './Container' import { useTranslations } from "next-intl";
import { useTranslations } from 'next-intl' import { Container } from "./Container";
interface Feature { interface Feature {
name: React.ReactNode name: React.ReactNode;
summary: string summary: string;
description: string description: string;
image: string image: string;
icon: React.ComponentType icon: React.ComponentType;
} }
const features: Array<Feature> = [ const features: Array<Feature> = [
{ {
name: 'secondaryFeatures.templates', name: "secondaryFeatures.templates",
summary: 'secondaryFeatures.templatesSummary', summary: "secondaryFeatures.templatesSummary",
description: 'secondaryFeatures.templatesDes', description: "secondaryFeatures.templatesDes",
image: '/secondary/templates.png', image: "/secondary/templates.png",
icon: function ReportingIcon() { icon: function ReportingIcon() {
return ( return (
<> <>
<Layers className="size-5 text-primary" /> <Layers className="size-5 text-primary" />
</> </>
) );
}, },
}, },
{ {
name: 'secondaryFeatures.traefik', name: "secondaryFeatures.traefik",
summary: 'secondaryFeatures.traefikSummary', summary: "secondaryFeatures.traefikSummary",
description: 'secondaryFeatures.traefikDes', description: "secondaryFeatures.traefikDes",
image: '/secondary/traefik.png', image: "/secondary/traefik.png",
icon: function ReportingIcon() { icon: function ReportingIcon() {
return ( return (
<> <>
@@ -82,12 +82,7 @@ const features: Array<Feature> = [
d="M299.847 285.567c10.027 58.288 105.304 42.877 91.619-15.91-12.271-52.716-94.951-38.124-91.619 15.91m-113.855 9.427c12.996 50.745 94.24 37.753 91.178-13.149-3.669-60.964-103.603-49.2-91.178 13.149m132.351 58.517c.044 7.79 1.843 15.403.289 24.148-1.935 3.656-5.729 4.043-9.001 5.52-4.524-.71-8.328-3.68-10.143-7.912-1.161-9.202.433-18.111.726-27.316l18.129 5.56z" d="M299.847 285.567c10.027 58.288 105.304 42.877 91.619-15.91-12.271-52.716-94.951-38.124-91.619 15.91m-113.855 9.427c12.996 50.745 94.24 37.753 91.178-13.149-3.669-60.964-103.603-49.2-91.178 13.149m132.351 58.517c.044 7.79 1.843 15.403.289 24.148-1.935 3.656-5.729 4.043-9.001 5.52-4.524-.71-8.328-3.68-10.143-7.912-1.161-9.202.433-18.111.726-27.316l18.129 5.56z"
fill="#fff" fill="#fff"
/> />
<ellipse <ellipse cx="208.4" cy="286.718" rx="13.719" ry="14.86" />
cx="208.4"
cy="286.718"
rx="13.719"
ry="14.86"
/>
<ellipse <ellipse
cx="214.64" cx="214.64"
cy="290.071" cy="290.071"
@@ -95,19 +90,9 @@ const features: Array<Feature> = [
ry="3.777" ry="3.777"
fill="#fff" fill="#fff"
/> />
<ellipse <ellipse cx="323.348" cy="283.017" rx="13.491" ry="14.86" />
cx="323.348"
cy="283.017"
rx="13.491"
ry="14.86"
/>
<g fill="#fff"> <g fill="#fff">
<ellipse <ellipse cx="329.485" cy="286.371" rx="3.181" ry="3.777" />
cx="329.485"
cy="286.371"
rx="3.181"
ry="3.777"
/>
<path d="M279.137 354.685c-5.986 14.507 3.338 43.515 19.579 22.119-1.161-9.202.433-18.111.726-27.316l-20.305 5.197z" /> <path d="M279.137 354.685c-5.986 14.507 3.338 43.515 19.579 22.119-1.161-9.202.433-18.111.726-27.316l-20.305 5.197z" />
</g> </g>
<path <path
@@ -226,60 +211,60 @@ const features: Array<Feature> = [
</g> </g>
</svg> </svg>
</> </>
) );
}, },
}, },
{ {
name: 'secondaryFeatures.users', name: "secondaryFeatures.users",
summary: 'secondaryFeatures.usersSummary', summary: "secondaryFeatures.usersSummary",
description: 'secondaryFeatures.usersDes', description: "secondaryFeatures.usersDes",
image: '/secondary/users.png', image: "/secondary/users.png",
icon: function InventoryIcon() { icon: function InventoryIcon() {
return ( return (
<> <>
<Users className="size-5 text-primary" /> <Users className="size-5 text-primary" />
</> </>
) );
}, },
}, },
{ {
name: 'secondaryFeatures.terminal', name: "secondaryFeatures.terminal",
summary: 'secondaryFeatures.terminalSummary', summary: "secondaryFeatures.terminalSummary",
description: 'secondaryFeatures.terminalDes', description: "secondaryFeatures.terminalDes",
image: '/secondary/terminal.png', image: "/secondary/terminal.png",
icon: function ContactsIcon() { icon: function ContactsIcon() {
return ( return (
<> <>
<Terminal className="size-5 text-primary" /> <Terminal className="size-5 text-primary" />
</> </>
) );
}, },
}, },
] ];
function Feature({ function Feature({
feature, feature,
isActive, isActive,
className, className,
...props ...props
}: React.ComponentPropsWithoutRef<'div'> & { }: React.ComponentPropsWithoutRef<"div"> & {
feature: Feature feature: Feature;
isActive: boolean isActive: boolean;
}) { }) {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
return ( return (
<div <div
className={cn( className={cn(
className, className,
!isActive ? 'opacity-75 hover:opacity-100 ' : 'rounded-xl', !isActive ? "opacity-75 hover:opacity-100 " : "rounded-xl",
' relative p-4', " relative p-4",
)} )}
{...props} {...props}
> >
<div <div
className={cn( className={cn(
'flex size-9 items-center justify-center rounded-lg', "flex size-9 items-center justify-center rounded-lg",
isActive ? 'bg-border' : 'bg-muted', isActive ? "bg-border" : "bg-muted",
)} )}
> >
<feature.icon /> <feature.icon />
@@ -289,7 +274,7 @@ function Feature({
layoutId="bubble" layoutId="bubble"
className="absolute inset-0 z-10 rounded-xl bg-white/5 mix-blend-difference" className="absolute inset-0 z-10 rounded-xl bg-white/5 mix-blend-difference"
transition={{ transition={{
type: 'spring', type: "spring",
bounce: 0.2, bounce: 0.2,
duration: 0.6, duration: 0.6,
}} }}
@@ -297,8 +282,8 @@ function Feature({
)} )}
<h3 <h3
className={cn( className={cn(
'mt-6 text-sm font-medium', "mt-6 text-sm font-medium",
isActive ? 'text-primary' : 'text-primary/85', isActive ? "text-primary" : "text-primary/85",
)} )}
> >
{feature.name} {feature.name}
@@ -310,7 +295,7 @@ function Feature({
{t(feature.description)} {t(feature.description)}
</p> </p>
</div> </div>
) );
} }
function FeaturesMobile() { function FeaturesMobile() {
@@ -318,11 +303,7 @@ function FeaturesMobile() {
<div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden"> <div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden">
{features.map((feature) => ( {features.map((feature) => (
<div key={feature.summary}> <div key={feature.summary}>
<Feature <Feature feature={feature} className="mx-auto max-w-2xl" isActive />
feature={feature}
className="mx-auto max-w-2xl"
isActive
/>
<div className="relative mt-10 pb-10"> <div className="relative mt-10 pb-10">
<div className="absolute -inset-x-4 bottom-0 top-8 bg-muted sm:-inset-x-6" /> <div className="absolute -inset-x-4 bottom-0 top-8 bg-muted sm:-inset-x-6" />
<div className="relative mx-auto w-[52.75rem] overflow-hidden rounded-xl bg-white shadow-lg shadow-slate-900/5 ring-1 ring-slate-500/10"> <div className="relative mx-auto w-[52.75rem] overflow-hidden rounded-xl bg-white shadow-lg shadow-slate-900/5 ring-1 ring-slate-500/10">
@@ -337,11 +318,11 @@ function FeaturesMobile() {
</div> </div>
))} ))}
</div> </div>
) );
} }
function FeaturesDesktop() { function FeaturesDesktop() {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
return ( return (
<Tab.Group as="div" className="hidden lg:mt-20 lg:block"> <Tab.Group as="div" className="hidden lg:mt-20 lg:block">
{({ selectedIndex }) => ( {({ selectedIndex }) => (
@@ -371,9 +352,8 @@ function FeaturesDesktop() {
static static
key={feature.summary} key={feature.summary}
className={cn( className={cn(
'px-5 transition duration-500 ease-in-out ui-not-focus-visible:outline-none', "px-5 transition duration-500 ease-in-out ui-not-focus-visible:outline-none",
featureIndex !== selectedIndex && featureIndex !== selectedIndex && "opacity-60",
'opacity-60',
)} )}
style={{ style={{
transform: `translateX(-${selectedIndex * 100}%)`, transform: `translateX(-${selectedIndex * 100}%)`,
@@ -396,11 +376,11 @@ function FeaturesDesktop() {
</> </>
)} )}
</Tab.Group> </Tab.Group>
) );
} }
export function SecondaryFeatures() { export function SecondaryFeatures() {
const t = useTranslations('HomePage') const t = useTranslations("HomePage");
return ( return (
<section <section
id="secondary-features" id="secondary-features"
@@ -410,15 +390,15 @@ export function SecondaryFeatures() {
<Container className="max-w-[95rem]"> <Container className="max-w-[95rem]">
<div className="mx-auto max-w-2xl md:text-center"> <div className="mx-auto max-w-2xl md:text-center">
<h2 className="font-display text-3xl tracking-tight text-primary sm:text-4xl"> <h2 className="font-display text-3xl tracking-tight text-primary sm:text-4xl">
{t('secondaryFeatures.title')} {t("secondaryFeatures.title")}
</h2> </h2>
<p className="mt-4 text-lg tracking-tight text-muted-foreground"> <p className="mt-4 text-lg tracking-tight text-muted-foreground">
{t('secondaryFeatures.des')} {t("secondaryFeatures.des")}
</p> </p>
</div> </div>
<FeaturesMobile /> <FeaturesMobile />
<FeaturesDesktop /> <FeaturesDesktop />
</Container> </Container>
</section> </section>
) );
} }

View File

@@ -1,10 +1,10 @@
import { Link } from '@/i18n/routing' import { Link } from "@/i18n/routing";
import { Footer } from './Footer' import { useTranslations } from "next-intl";
import { Header } from './Header' import { Footer } from "./Footer";
import { useTranslations } from 'next-intl' import { Header } from "./Header";
export function SlimLayout() { export function SlimLayout() {
const t = useTranslations('404') const t = useTranslations("404");
return ( return (
<> <>
<div> <div>
@@ -12,16 +12,12 @@ export function SlimLayout() {
</div> </div>
<main className="flex flex-auto items-center justify-center text-center"> <main className="flex flex-auto items-center justify-center text-center">
<div> <div>
<h1 className="mb-4 text-6xl font-semibold text-primary"> <h1 className="mb-4 text-6xl font-semibold text-primary">404</h1>
404 <p className="mb-4 text-lg text-muted-foreground">{t("title")}</p>
</h1>
<p className="mb-4 text-lg text-muted-foreground">
{t('title')}
</p>
<p className="mt-4 text-muted-foreground"> <p className="mt-4 text-muted-foreground">
{t('des')}{' '} {t("des")}{" "}
<Link href="/" className="text-primary"> <Link href="/" className="text-primary">
{t('action')} {t("action")}
</Link> </Link>
</p> </p>
</div> </div>
@@ -30,5 +26,5 @@ export function SlimLayout() {
<Footer /> <Footer />
</div> </div>
</> </>
) );
} }

View File

@@ -1,16 +1,16 @@
'use client' "use client";
import * as React from 'react' import * as SelectPrimitive from "@radix-ui/react-select";
import * as SelectPrimitive from '@radix-ui/react-select' import { Check, ChevronDown, ChevronUp } from "lucide-react";
import { Check, ChevronDown, ChevronUp } from 'lucide-react' import * as React from "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< const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>, React.ElementRef<typeof SelectPrimitive.Trigger>,
@@ -19,7 +19,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger <SelectPrimitive.Trigger
ref={ref} ref={ref}
className={cn( className={cn(
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1', "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className, className,
)} )}
{...props} {...props}
@@ -29,8 +29,8 @@ const SelectTrigger = React.forwardRef<
<ChevronDown className="h-4 w-4 opacity-50" /> <ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon> </SelectPrimitive.Icon>
</SelectPrimitive.Trigger> </SelectPrimitive.Trigger>
)) ));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectScrollUpButton = React.forwardRef< const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>, React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
@@ -39,15 +39,15 @@ const SelectScrollUpButton = React.forwardRef<
<SelectPrimitive.ScrollUpButton <SelectPrimitive.ScrollUpButton
ref={ref} ref={ref}
className={cn( className={cn(
'flex cursor-default items-center justify-center py-1', "flex cursor-default items-center justify-center py-1",
className, className,
)} )}
{...props} {...props}
> >
<ChevronUp className="h-4 w-4" /> <ChevronUp className="h-4 w-4" />
</SelectPrimitive.ScrollUpButton> </SelectPrimitive.ScrollUpButton>
)) ));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
const SelectScrollDownButton = React.forwardRef< const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>, React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
@@ -56,28 +56,28 @@ const SelectScrollDownButton = React.forwardRef<
<SelectPrimitive.ScrollDownButton <SelectPrimitive.ScrollDownButton
ref={ref} ref={ref}
className={cn( className={cn(
'flex cursor-default items-center justify-center py-1', "flex cursor-default items-center justify-center py-1",
className, className,
)} )}
{...props} {...props}
> >
<ChevronDown className="h-4 w-4" /> <ChevronDown className="h-4 w-4" />
</SelectPrimitive.ScrollDownButton> </SelectPrimitive.ScrollDownButton>
)) ));
SelectScrollDownButton.displayName = SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName SelectPrimitive.ScrollDownButton.displayName;
const SelectContent = React.forwardRef< const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>, React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = 'popper', ...props }, ref) => ( >(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal> <SelectPrimitive.Portal>
<SelectPrimitive.Content <SelectPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === 'popper' && position === "popper" &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className, className,
)} )}
position={position} position={position}
@@ -86,9 +86,9 @@ const SelectContent = React.forwardRef<
<SelectScrollUpButton /> <SelectScrollUpButton />
<SelectPrimitive.Viewport <SelectPrimitive.Viewport
className={cn( className={cn(
'p-1', "p-1",
position === 'popper' && position === "popper" &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]', "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
)} )}
> >
{children} {children}
@@ -96,8 +96,8 @@ const SelectContent = React.forwardRef<
<SelectScrollDownButton /> <SelectScrollDownButton />
</SelectPrimitive.Content> </SelectPrimitive.Content>
</SelectPrimitive.Portal> </SelectPrimitive.Portal>
)) ));
SelectContent.displayName = SelectPrimitive.Content.displayName SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef< const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>, React.ElementRef<typeof SelectPrimitive.Label>,
@@ -105,11 +105,11 @@ const SelectLabel = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.Label <SelectPrimitive.Label
ref={ref} ref={ref}
className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)} className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
{...props} {...props}
/> />
)) ));
SelectLabel.displayName = SelectPrimitive.Label.displayName SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef< const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>, React.ElementRef<typeof SelectPrimitive.Item>,
@@ -118,7 +118,7 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item <SelectPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className, className,
)} )}
{...props} {...props}
@@ -131,8 +131,8 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText> <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item> </SelectPrimitive.Item>
)) ));
SelectItem.displayName = SelectPrimitive.Item.displayName SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef< const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>, React.ElementRef<typeof SelectPrimitive.Separator>,
@@ -140,11 +140,11 @@ const SelectSeparator = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.Separator <SelectPrimitive.Separator
ref={ref} ref={ref}
className={cn('-mx-1 my-1 h-px bg-muted', className)} className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props} {...props}
/> />
)) ));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
export { export {
Select, Select,
@@ -157,4 +157,4 @@ export {
SelectSeparator, SelectSeparator,
SelectScrollUpButton, SelectScrollUpButton,
SelectScrollDownButton, SelectScrollDownButton,
} };

View File

@@ -1,12 +1,12 @@
import { notFound } from 'next/navigation' import { getRequestConfig } from "next-intl/server";
import { getRequestConfig } from 'next-intl/server' import { notFound } from "next/navigation";
import { routing } from './routing' import { routing } from "./routing";
export default getRequestConfig(async ({ locale }) => { export default getRequestConfig(async ({ locale }) => {
// Validate that the incoming `locale` parameter is valid // Validate that the incoming `locale` parameter is valid
if (!routing.locales.includes(locale as any)) notFound() if (!routing.locales.includes(locale as any)) notFound();
return { return {
messages: (await import(`../locales/${locale}.json`)).default, messages: (await import(`../locales/${locale}.json`)).default,
} };
}) });

View File

@@ -1,16 +1,16 @@
import { defineRouting } from 'next-intl/routing' import { createSharedPathnamesNavigation } from "next-intl/navigation";
import { createSharedPathnamesNavigation } from 'next-intl/navigation' import { defineRouting } from "next-intl/routing";
export const routing = defineRouting({ export const routing = defineRouting({
// A list of all locales that are supported // A list of all locales that are supported
locales: ['en', 'zh-Hans'], locales: ["en", "zh-Hans"],
// Used when no locale matches // Used when no locale matches
defaultLocale: 'en', defaultLocale: "en",
localePrefix: 'as-needed', localePrefix: "as-needed",
}) });
// Lightweight wrappers around Next.js' navigation APIs // Lightweight wrappers around Next.js' navigation APIs
// that will consider the routing configuration // that will consider the routing configuration
export const { Link, redirect, usePathname, useRouter } = export const { Link, redirect, usePathname, useRouter } =
createSharedPathnamesNavigation(routing) createSharedPathnamesNavigation(routing);

View File

@@ -7,8 +7,8 @@
"support": "Support", "support": "Support",
"discord": "Discord", "discord": "Discord",
"i18nButtonPlaceholder": "Language", "i18nButtonPlaceholder": "Language",
"i18nEn":"English", "i18nEn": "English",
"i18nZh-Hans":"简体中文" "i18nZh-Hans": "简体中文"
}, },
"hero": { "hero": {
"deploy": "Deploy", "deploy": "Deploy",

View File

@@ -7,8 +7,8 @@
"support": "赞助", "support": "赞助",
"discord": "Discord", "discord": "Discord",
"i18nButtonPlaceholder": "语言", "i18nButtonPlaceholder": "语言",
"i18nEn":"English", "i18nEn": "English",
"i18nZh-Hans":"简体中文" "i18nZh-Hans": "简体中文"
}, },
"hero": { "hero": {
"deploy": "部署在", "deploy": "部署在",

View File

@@ -1,9 +1,9 @@
import createMiddleware from 'next-intl/middleware' import createMiddleware from "next-intl/middleware";
import { routing } from './i18n/routing' import { routing } from "./i18n/routing";
export default createMiddleware(routing) export default createMiddleware(routing);
export const config = { export const config = {
// Match only internationalized pathnames // Match only internationalized pathnames
matcher: ['/((?!_next|.*\\..*).*)'] matcher: ["/((?!_next|.*\\..*).*)"],
} };

View File

@@ -1,15 +1,15 @@
const createNextIntlPlugin = require('next-intl/plugin') const createNextIntlPlugin = require("next-intl/plugin");
const withNextIntl = createNextIntlPlugin() const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
eslint: { eslint: {
ignoreDuringBuilds: true, ignoreDuringBuilds: true,
}, },
typescript: { typescript: {
ignoreBuildErrors: true, ignoreBuildErrors: true,
}, },
} };
module.exports = withNextIntl(nextConfig) module.exports = withNextIntl(nextConfig);

View File

@@ -4,5 +4,5 @@ module.exports = {
semi: false, semi: false,
tabWidth: 4, tabWidth: 4,
useTabs: true, useTabs: true,
plugins: ['prettier-plugin-tailwindcss'], plugins: ["prettier-plugin-tailwindcss"],
} };