From 3e45f8b806c648fcf3faaaccd6d2100a4170b67f Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 06:00:59 -0800 Subject: [PATCH 1/7] feat(app): finalize styling --- .gitignore | 2 +- app/blog/[slug]/page.tsx | 66 +- app/blog/page.tsx | 42 +- app/case-studies/page.tsx | 10 +- app/changelog/page.tsx | 70 +- app/components/api-endpoint.tsx | 7 +- app/components/background-paths.tsx | 65 +- app/components/breadcrumb.tsx | 27 +- app/components/command-menu.tsx | 92 ++- app/components/cta-section.tsx | 22 +- app/components/docs-sidebar.tsx | 33 +- app/components/error-boundary.tsx | 30 +- app/components/feature-grid.tsx | 21 +- app/components/feature-section.tsx | 16 +- app/components/footer.tsx | 44 +- app/components/header.tsx | 123 ++-- app/components/layout-wrapper.tsx | 22 + app/components/logo.tsx | 23 +- app/components/lst-apy-graph.tsx | 35 +- app/components/lst-apy-trend-graph.tsx | 38 +- app/components/lst-comparison-table.tsx | 32 +- app/components/main-nav.tsx | 60 +- app/components/mev-protection-comparison.tsx | 171 +++++ app/components/privacy-section.tsx | 10 +- app/components/search-button.tsx | 18 +- app/components/status-indicator.tsx | 21 - .../getting-started/installation/page.tsx | 5 +- .../getting-started/introduction/page.tsx | 13 +- app/docs/layout.tsx | 11 +- app/docs/page.tsx | 35 +- app/docs/securerpc/api-reference/page.tsx | 10 +- app/fold-token/page.tsx | 58 +- app/globals.css | 1 + app/layout.tsx | 47 +- app/page.tsx | 7 +- app/products/captive-insurance/page.tsx | 31 +- app/products/fold-staking/page.tsx | 66 ++ app/products/meveth/page.tsx | 67 ++ app/products/securerpc/page.tsx | 66 ++ app/products/xga/page.tsx | 70 ++ app/solutions/auction-markets/page.tsx | 9 +- app/solutions/avs-operations/page.tsx | 9 +- app/solutions/hedging-execution/page.tsx | 22 +- app/solutions/mev-relay-protection/page.tsx | 9 +- app/solutions/mev/page.tsx | 11 +- app/solutions/page.tsx | 12 +- app/solutions/relay-protect/page.tsx | 113 +++ app/solutions/restaking/page.tsx | 11 +- app/solutions/securerpc/page.tsx | 62 -- app/solutions/staking/page.tsx | 23 +- app/technology/page.tsx | 14 +- bun.lockb | Bin components/icons.tsx | 13 +- components/theme-provider.tsx | 11 +- components/ui/accordion.tsx | 40 +- components/ui/alert-dialog.tsx | 90 ++- components/ui/alert.tsx | 54 +- components/ui/aspect-ratio.tsx | 8 +- components/ui/avatar.tsx | 29 +- components/ui/badge.tsx | 17 +- components/ui/breadcrumb.tsx | 122 ++-- components/ui/button.tsx | 25 +- components/ui/calendar.tsx | 37 +- components/ui/card.tsx | 60 +- components/ui/carousel.tsx | 396 +++++----- components/ui/chart.tsx | 284 ++++---- components/ui/checkbox.tsx | 25 +- components/ui/collapsible.tsx | 12 +- components/ui/command.tsx | 78 +- components/ui/context-menu.tsx | 106 +-- components/ui/dialog.tsx | 59 +- components/ui/drawer.tsx | 79 +- components/ui/dropdown-menu.tsx | 108 +-- components/ui/form.tsx | 126 ++-- components/ui/hover-card.tsx | 19 +- components/ui/input-otp.tsx | 41 +- components/ui/input.tsx | 37 +- components/ui/label.tsx | 29 +- components/ui/menubar.tsx | 146 ++-- components/ui/navigation-menu.tsx | 54 +- components/ui/pagination.tsx | 90 ++- components/ui/popover.tsx | 20 +- components/ui/progress.tsx | 22 +- components/ui/radio-group.tsx | 35 +- components/ui/resizable.tsx | 28 +- components/ui/scroll-area.tsx | 31 +- components/ui/select.tsx | 83 ++- components/ui/separator.tsx | 43 +- components/ui/sheet.tsx | 81 ++- components/ui/sidebar.tsx | 675 +++++++++--------- components/ui/skeleton.tsx | 16 +- components/ui/slider.tsx | 22 +- components/ui/sonner.tsx | 22 +- components/ui/switch.tsx | 21 +- components/ui/table.tsx | 112 ++- components/ui/tabs.tsx | 30 +- components/ui/textarea.tsx | 37 +- components/ui/toast.tsx | 68 +- components/ui/toaster.tsx | 16 +- components/ui/toggle-group.tsx | 44 +- components/ui/toggle.tsx | 26 +- components/ui/tooltip.tsx | 21 +- components/ui/use-mobile.tsx | 22 +- components/ui/use-toast.ts | 133 ++-- hooks/use-mobile.tsx | 22 +- hooks/use-toast.ts | 133 ++-- lib/utils.ts | 7 +- next-env.d.ts | 5 + next-sitemap.config.js | 6 + tsconfig.json | 31 +- v0-user-next.config.js | 6 - 111 files changed, 3379 insertions(+), 2516 deletions(-) create mode 100644 app/components/layout-wrapper.tsx create mode 100644 app/components/mev-protection-comparison.tsx delete mode 100644 app/components/status-indicator.tsx create mode 100644 app/products/fold-staking/page.tsx create mode 100644 app/products/meveth/page.tsx create mode 100644 app/products/securerpc/page.tsx create mode 100644 app/products/xga/page.tsx create mode 100644 app/solutions/relay-protect/page.tsx delete mode 100644 app/solutions/securerpc/page.tsx mode change 100755 => 100644 bun.lockb create mode 100644 next-env.d.ts create mode 100644 next-sitemap.config.js delete mode 100644 v0-user-next.config.js diff --git a/.gitignore b/.gitignore index 818f4b3..941fc58 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,6 @@ yarn-error.log* # typescript *.tsbuildinfo -next-env.d.ts + .DS_Store diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index 393ec41..77fd324 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -1,12 +1,43 @@ -import { notFound } from "next/navigation"; -import { Badge } from "@/components/ui/badge"; +import { notFound } from "next/navigation" +import { Badge } from "@/components/ui/badge" interface BlogPost { - slug: string; - title: string; - date: string; - content: string; - category: string; + slug: string + title: string + date: string + content: string + category: string +} + +// Simulating an API call with a timeout +async function fetchBlogPost(slug: string): Promise<BlogPost | null> { + return new Promise((resolve) => { + setTimeout(() => { + const post = blogPosts.find((post) => post.slug === slug) + resolve(post || null) + }, 100) // 100ms timeout to simulate API call + }) +} + +export async function generateStaticParams() { + // In a real application, you would fetch this data from an API or database + return blogPosts.map((post) => ({ + slug: post.slug, + })) +} + +export async function generateMetadata({ params }: { params: { slug: string } }) { + const post = await fetchBlogPost(params.slug) + + if (!post) { + return { + title: "Post Not Found", + } + } + + return { + title: post.title, + } } const blogPosts: BlogPost[] = [ @@ -118,7 +149,7 @@ const blogPosts: BlogPost[] = [ <p>As the Ethereum ecosystem evolves, Manifold Finance remains committed to providing cutting-edge solutions that leverage the latest scaling technologies.</p> `, }, -]; +] function CategoryBadge({ category }: { category: string }) { return ( @@ -130,17 +161,18 @@ function CategoryBadge({ category }: { category: string }) { : category === "Tutorial" ? "bg-green-500/10 text-green-500 hover:bg-green-500/20" : "bg-purple-500/10 text-purple-500 hover:bg-purple-500/20" - }> + } + > {category} </Badge> - ); + ) } -export default function BlogPost({ params }: { params: { slug: string } }) { - const post = blogPosts.find((post) => post.slug === params.slug); +export default async function BlogPost({ params }: { params: { slug: string } }) { + const post = await fetchBlogPost(params.slug) if (!post) { - notFound(); + notFound() } return ( @@ -154,12 +186,10 @@ export default function BlogPost({ params }: { params: { slug: string } }) { </div> <h1 className="text-4xl font-heading">{post.title}</h1> </div> - <div - className="prose dark:prose-invert max-w-none" - dangerouslySetInnerHTML={{ __html: post.content }} - /> + <div className="prose dark:prose-invert max-w-none" dangerouslySetInnerHTML={{ __html: post.content }} /> </article> </div> </div> - ); + ) } + diff --git a/app/blog/page.tsx b/app/blog/page.tsx index 2bbf2f1..4749a8c 100644 --- a/app/blog/page.tsx +++ b/app/blog/page.tsx @@ -1,12 +1,21 @@ -import Link from "next/link"; -import { Badge } from "@/components/ui/badge"; +import Link from "next/link" +import { Badge } from "@/components/ui/badge" interface BlogPost { - slug: string; - title: string; - date: string; - excerpt: string; - category: string; + slug: string + title: string + date: string + excerpt: string + category: string +} + +// Simulating an API call with a timeout +async function fetchBlogPosts(): Promise<BlogPost[]> { + return new Promise((resolve) => { + setTimeout(() => { + resolve(blogPosts) + }, 100) // 100ms timeout to simulate API call + }) } const blogPosts: BlogPost[] = [ @@ -22,8 +31,7 @@ const blogPosts: BlogPost[] = [ slug: "optimizing-defi-strategies", title: "Optimizing DeFi Strategies with Manifold Finance", date: "February 1, 2025", - excerpt: - "Discover how to leverage Manifold Finance's tools to optimize your DeFi strategies and maximize returns.", + excerpt: "Discover how to leverage Manifold Finance's tools to optimize your DeFi strategies and maximize returns.", category: "Tutorial", }, { @@ -34,7 +42,7 @@ const blogPosts: BlogPost[] = [ "We share our thoughts on the future of Ethereum scaling solutions and how Manifold Finance is positioned to support the ecosystem.", category: "Industry Insights", }, -]; +] function CategoryBadge({ category }: { category: string }) { return ( @@ -46,19 +54,22 @@ function CategoryBadge({ category }: { category: string }) { : category === "Tutorial" ? "bg-green-500/10 text-green-500 hover:bg-green-500/20" : "bg-purple-500/10 text-purple-500 hover:bg-purple-500/20" - }> + } + > {category} </Badge> - ); + ) } -export default function BlogPage() { +export default async function BlogPage() { + const posts = await fetchBlogPosts() + return ( <div className="min-h-screen bg-background"> <div className="container max-w-4xl mx-auto px-4 py-24"> <h1 className="text-4xl font-heading mb-8">Blog</h1> <div className="space-y-12"> - {blogPosts.map((post) => ( + {posts.map((post) => ( <article key={post.slug} className="space-y-4"> <div className="flex items-center gap-4"> <time className="text-sm text-muted-foreground">{post.date}</time> @@ -78,5 +89,6 @@ export default function BlogPage() { </div> </div> </div> - ); + ) } + diff --git a/app/case-studies/page.tsx b/app/case-studies/page.tsx index cd25a97..76e4e70 100644 --- a/app/case-studies/page.tsx +++ b/app/case-studies/page.tsx @@ -1,12 +1,9 @@ -import { BackgroundPaths } from "../components/background-paths"; +import { BackgroundPaths } from "../components/background-paths" export default function CaseStudiesPage() { return ( <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths - title="Case Studies|" - subtitle="See how leading projects are leveraging Manifold Finance" - /> + <BackgroundPaths title="Case Studies|" subtitle="See how leading projects are leveraging Manifold Finance" /> <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Success Stories</h2> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> @@ -26,5 +23,6 @@ export default function CaseStudiesPage() { </div> </main> </div> - ); + ) } + diff --git a/app/changelog/page.tsx b/app/changelog/page.tsx index a17d03c..d2ab3ad 100644 --- a/app/changelog/page.tsx +++ b/app/changelog/page.tsx @@ -1,26 +1,26 @@ -import { Badge } from "@/components/ui/badge"; -import { ArrowLeft, ArrowRight } from "lucide-react"; -import Link from "next/link"; +import { Badge } from "@/components/ui/badge" +import { ArrowLeft, ArrowRight } from "lucide-react" +import Link from "next/link" interface ChangelogEntry { - date: string; - version: string; - platform: string; - title: string; - type: "public" | "beta" | "alpha"; - changes: string[]; + date: string + version: string + platform: string + title: string + type: "public" | "beta" | "alpha" + changes: string[] previousRelease?: { - date: string; - version: string; - platform: string; - type: "public" | "beta" | "alpha"; - }; + date: string + version: string + platform: string + type: "public" | "beta" | "alpha" + } nextRelease?: { - date: string; - version: string; - platform: string; - type: "public" | "beta" | "alpha"; - }; + date: string + version: string + platform: string + type: "public" | "beta" | "alpha" + } } const changelog: ChangelogEntry = { @@ -46,7 +46,7 @@ const changelog: ChangelogEntry = { platform: "Mobile", type: "public", }, -}; +} function VersionBadge({ type }: { type: ChangelogEntry["type"] }) { return ( @@ -58,10 +58,11 @@ function VersionBadge({ type }: { type: ChangelogEntry["type"] }) { : type === "beta" ? "bg-yellow-500/10 text-yellow-500 hover:bg-yellow-500/20" : "bg-blue-500/10 text-blue-500 hover:bg-blue-500/20" - }> + } + > {type} </Badge> - ); + ) } function ReleaseNavigation({ @@ -71,16 +72,14 @@ function ReleaseNavigation({ version, platform, }: { - type: "previous" | "next"; - direction: "left" | "right"; - date: string; - version: string; - platform: string; + type: "previous" | "next" + direction: "left" | "right" + date: string + version: string + platform: string }) { return ( - <Link - href="#" - className="block p-6 rounded-lg border border-border bg-card hover:bg-accent transition-colors"> + <Link href="#" className="block p-6 rounded-lg border border-border bg-card hover:bg-accent transition-colors"> <div className="flex items-center gap-2 text-sm text-muted-foreground mb-4"> {direction === "left" && <ArrowLeft className="w-4 h-4" />} {type === "previous" ? "Previous" : "Next"} release @@ -93,7 +92,7 @@ function ReleaseNavigation({ </div> </div> </Link> - ); + ) } export default function ChangelogPage() { @@ -121,10 +120,8 @@ export default function ChangelogPage() { {change.includes("Enter") ? ( <> Fixed bug where pressing{" "} - <code className="px-1.5 py-0.5 rounded-md bg-muted font-mono text-sm"> - Enter - </code>{" "} - inside a blockquote would not continue the blockquote onto the next line. + <code className="px-1.5 py-0.5 rounded-md bg-muted font-mono text-sm">Enter</code> inside a + blockquote would not continue the blockquote onto the next line. </> ) : ( change @@ -157,5 +154,6 @@ export default function ChangelogPage() { </article> </div> </div> - ); + ) } + diff --git a/app/components/api-endpoint.tsx b/app/components/api-endpoint.tsx index 9ec5cd7..624100d 100644 --- a/app/components/api-endpoint.tsx +++ b/app/components/api-endpoint.tsx @@ -1,5 +1,5 @@ -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" export function APIEndpoint() { return ( @@ -20,5 +20,6 @@ export function APIEndpoint() { Get started with our SecureRPC API for reliable and secure blockchain interactions. </p> </div> - ); + ) } + diff --git a/app/components/background-paths.tsx b/app/components/background-paths.tsx index 471149b..7b865e7 100644 --- a/app/components/background-paths.tsx +++ b/app/components/background-paths.tsx @@ -1,24 +1,24 @@ -"use client"; +"use client" -import { motion } from "framer-motion"; -import { Button } from "@/components/ui/button"; -import Link from "next/link"; +import { motion } from "framer-motion" +import { Button } from "@/components/ui/button" +import Link from "next/link" interface BackgroundPathsProps { - title: string; - subtitle?: string; + title: string + subtitle?: string primaryCta?: { - href: string; - text: string; - variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"; - className?: string; - }; + href: string + text: string + variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" + className?: string + } secondaryCta?: { - href: string; - text: string; - variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"; - className?: string; - }; + href: string + text: string + variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" + className?: string + } } function FloatingPaths({ position }: { position: number }) { @@ -31,7 +31,7 @@ function FloatingPaths({ position }: { position: number }) { } ${1600 + i * 20 * position} ${1600 - i * 25} ${1600 + i * 20 * position} ${1600 - i * 25}`, color: `rgba(124,228,108,${0.02 + i * 0.015})`, width: 0.5 + i * 0.05, - })); + })) return ( <div className="absolute inset-0 pointer-events-none"> @@ -59,17 +59,12 @@ function FloatingPaths({ position }: { position: number }) { ))} </svg> </div> - ); + ) } -export function BackgroundPaths({ - title, - subtitle, - primaryCta, - secondaryCta, -}: BackgroundPathsProps) { - const [mainText, cursor] = title.split("|"); - const words = mainText.split(" "); +export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: BackgroundPathsProps) { + const [mainText, cursor] = title.split("|") + const words = mainText.split(" ") return ( <div className="relative min-h-screen w-full flex items-center justify-center overflow-hidden bg-blackA12"> @@ -85,7 +80,8 @@ export function BackgroundPaths({ initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 2 }} - className="max-w-4xl mx-auto space-y-6"> + className="max-w-4xl mx-auto space-y-6" + > <h1 className="text-3xl sm:text-5xl md:text-7xl lg:text-8xl font-bold tracking-tighter font-heading"> {words.map((word, wordIndex) => ( <span key={wordIndex} className="inline-block mr-4 last:mr-0"> @@ -100,7 +96,8 @@ export function BackgroundPaths({ stiffness: 150, damping: 25, }} - className="inline-block text-white"> + className="inline-block text-white" + > {letter} </motion.span> ))} @@ -115,7 +112,8 @@ export function BackgroundPaths({ repeat: Number.POSITIVE_INFINITY, ease: "linear", }} - className="inline-block text-green9 ml-2"> + className="inline-block text-green9 ml-2" + > | </motion.span> )} @@ -126,7 +124,8 @@ export function BackgroundPaths({ initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 1, duration: 1 }} - className="text-lg sm:text-xl md:text-2xl text-whiteA11"> + className="text-lg sm:text-xl md:text-2xl text-whiteA11" + > {subtitle} </motion.p> )} @@ -136,7 +135,8 @@ export function BackgroundPaths({ initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 1.5, duration: 1 }} - className="flex flex-wrap items-center justify-center gap-4 mt-8"> + className="flex flex-wrap items-center justify-center gap-4 mt-8" + > {primaryCta && ( <Link href={primaryCta.href}> <Button variant={primaryCta.variant} className={primaryCta.className}> @@ -156,5 +156,6 @@ export function BackgroundPaths({ </motion.div> </div> </div> - ); + ) } + diff --git a/app/components/breadcrumb.tsx b/app/components/breadcrumb.tsx index b47a17b..4d282aa 100644 --- a/app/components/breadcrumb.tsx +++ b/app/components/breadcrumb.tsx @@ -1,24 +1,22 @@ -"use client"; +"use client" -import Link from "next/link"; -import { usePathname } from "next/navigation"; -import { ChevronRight, Home } from "lucide-react"; +import Link from "next/link" +import { usePathname } from "next/navigation" +import { ChevronRight, Home } from "lucide-react" export function Breadcrumb() { - const pathname = usePathname(); - const segments = pathname.split("/").filter(Boolean); + const pathname = usePathname() + const segments = pathname.split("/").filter(Boolean) return ( - <nav - aria-label="Breadcrumb" - className="mb-6 flex items-center space-x-2 text-sm text-muted-foreground"> + <nav aria-label="Breadcrumb" className="mb-6 flex items-center space-x-2 text-sm text-muted-foreground"> <Link href="/" className="flex items-center hover:text-foreground"> <Home className="h-4 w-4" /> </Link> {segments.map((segment, index) => { - const href = `/${segments.slice(0, index + 1).join("/")}`; - const isLast = index === segments.length - 1; - const title = segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, " "); + const href = `/${segments.slice(0, index + 1).join("/")}` + const isLast = index === segments.length - 1 + const title = segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, " ") return ( <div key={href} className="flex items-center"> @@ -31,8 +29,9 @@ export function Breadcrumb() { </Link> )} </div> - ); + ) })} </nav> - ); + ) } + diff --git a/app/components/command-menu.tsx b/app/components/command-menu.tsx index 25eb4da..437f093 100644 --- a/app/components/command-menu.tsx +++ b/app/components/command-menu.tsx @@ -1,13 +1,13 @@ -"use client"; +"use client" -import * as React from "react"; -import { useRouter } from "next/navigation"; -import type { DialogProps } from "@radix-ui/react-dialog"; -import { Command as CommandPrimitive } from "cmdk"; -import { Search } from "lucide-react"; +import * as React from "react" +import { useRouter } from "next/navigation" +import type { DialogProps } from "@radix-ui/react-dialog" +import { Command as CommandPrimitive } from "cmdk" +import { Search } from "lucide-react" -import { cn } from "@/lib/utils"; -import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { cn } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" const Command = React.forwardRef< React.ElementRef<typeof CommandPrimitive>, @@ -21,8 +21,8 @@ const Command = React.forwardRef< )} {...props} /> -)); -Command.displayName = CommandPrimitive.displayName; +)) +Command.displayName = CommandPrimitive.displayName interface CommandDialogProps extends DialogProps {} @@ -35,8 +35,8 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => { </Command> </DialogContent> </Dialog> - ); -}; + ) +} const CommandInput = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Input>, @@ -53,9 +53,9 @@ const CommandInput = React.forwardRef< {...props} /> </div> -)); +)) -CommandInput.displayName = CommandPrimitive.Input.displayName; +CommandInput.displayName = CommandPrimitive.Input.displayName const CommandList = React.forwardRef< React.ElementRef<typeof CommandPrimitive.List>, @@ -66,18 +66,16 @@ const CommandList = React.forwardRef< className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} {...props} /> -)); +)) -CommandList.displayName = CommandPrimitive.List.displayName; +CommandList.displayName = CommandPrimitive.List.displayName const CommandEmpty = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Empty>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> ->((props, ref) => ( - <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} /> -)); +>((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />) -CommandEmpty.displayName = CommandPrimitive.Empty.displayName; +CommandEmpty.displayName = CommandPrimitive.Empty.displayName const CommandGroup = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Group>, @@ -91,21 +89,17 @@ const CommandGroup = React.forwardRef< )} {...props} /> -)); +)) -CommandGroup.displayName = CommandPrimitive.Group.displayName; +CommandGroup.displayName = CommandPrimitive.Group.displayName const CommandSeparator = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Separator>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator> >(({ className, ...props }, ref) => ( - <CommandPrimitive.Separator - ref={ref} - className={cn("-mx-1 h-px bg-border", className)} - {...props} - /> -)); -CommandSeparator.displayName = CommandPrimitive.Separator.displayName; + <CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} /> +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName const CommandItem = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Item>, @@ -119,40 +113,35 @@ const CommandItem = React.forwardRef< )} {...props} /> -)); +)) -CommandItem.displayName = CommandPrimitive.Item.displayName; +CommandItem.displayName = CommandPrimitive.Item.displayName const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { - return ( - <span - className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} - {...props} - /> - ); -}; -CommandShortcut.displayName = "CommandShortcut"; + return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} /> +} +CommandShortcut.displayName = "CommandShortcut" export function CommandMenu() { - const [open, setOpen] = React.useState(false); - const router = useRouter(); + const [open, setOpen] = React.useState(false) + const router = useRouter() React.useEffect(() => { const down = (e: KeyboardEvent) => { if (e.key === "k" && (e.metaKey || e.ctrlKey)) { - e.preventDefault(); - setOpen((open) => !open); + e.preventDefault() + setOpen((open) => !open) } - }; + } - document.addEventListener("keydown", down); - return () => document.removeEventListener("keydown", down); - }, []); + document.addEventListener("keydown", down) + return () => document.removeEventListener("keydown", down) + }, []) const runCommand = React.useCallback((command: () => unknown) => { - setOpen(false); - command(); - }, []); + setOpen(false) + command() + }, []) return ( <CommandDialog open={open} onOpenChange={setOpen}> @@ -178,5 +167,6 @@ export function CommandMenu() { </CommandGroup> </CommandList> </CommandDialog> - ); + ) } + diff --git a/app/components/cta-section.tsx b/app/components/cta-section.tsx index c123c30..dc417b7 100644 --- a/app/components/cta-section.tsx +++ b/app/components/cta-section.tsx @@ -1,6 +1,6 @@ -import Link from "next/link"; -import { Button } from "@/components/ui/button"; -import { ArrowRight } from "lucide-react"; +import Link from "next/link" +import { Button } from "@/components/ui/button" +import { ArrowRight } from "lucide-react" export function CTASection() { return ( @@ -8,19 +8,14 @@ export function CTASection() { <div className="container mx-auto px-6"> <div className="flex flex-col md:flex-row justify-between items-center"> <div className="mb-8 md:mb-0 md:mr-8 max-w-2xl"> - <h2 className="text-3xl font-bold mb-4 text-white"> - Ready to optimize your Ethereum infrastructure? - </h2> + <h2 className="text-3xl font-bold mb-4 text-white">Ready to optimize your Ethereum infrastructure?</h2> <p className="text-lg text-mauveA11"> - Join thousands of validators leveraging Manifold's ecosystem for high-performance - staking, MEV optimization, and secure blockchain interactions. + Join thousands of validators leveraging Manifold's ecosystem for high-performance staking, MEV + optimization, and secure blockchain interactions. </p> </div> <div className="flex flex-col sm:flex-row gap-4"> - <Button - asChild - variant="default" - className="bg-green9 hover:bg-green10 text-white rounded-full px-6 h-12"> + <Button asChild variant="default" className="bg-green9 hover:bg-green10 text-white rounded-full px-6 h-12"> <Link href="/get-started" className="flex items-center gap-2"> Get Started <ArrowRight className="w-4 h-4" /> @@ -30,5 +25,6 @@ export function CTASection() { </div> </div> </section> - ); + ) } + diff --git a/app/components/docs-sidebar.tsx b/app/components/docs-sidebar.tsx index 4ab4170..6682db7 100644 --- a/app/components/docs-sidebar.tsx +++ b/app/components/docs-sidebar.tsx @@ -1,14 +1,14 @@ -"use client"; +"use client" -import Link from "next/link"; -import { usePathname } from "next/navigation"; -import { cn } from "@/lib/utils"; -import { ScrollArea } from "@/components/ui/scroll-area"; +import Link from "next/link" +import { usePathname } from "next/navigation" +import { cn } from "@/lib/utils" +import { ScrollArea } from "@/components/ui/scroll-area" interface DocLink { - title: string; - href: string; - items?: { title: string; href: string }[]; + title: string + href: string + items?: { title: string; href: string }[] } const docs: DocLink[] = [ @@ -52,10 +52,10 @@ const docs: DocLink[] = [ title: "FAQ", href: "/docs/faq", }, -]; +] export function DocsSidebar() { - const pathname = usePathname(); + const pathname = usePathname() return ( <ScrollArea className="h-full py-6 pl-4"> @@ -72,7 +72,8 @@ export function DocsSidebar() { pathname === section.href ? "text-primary font-semibold" : "text-muted-foreground hover:text-primary", - )}> + )} + > {section.title} </Link> {section.items?.map((item) => ( @@ -81,10 +82,9 @@ export function DocsSidebar() { href={item.href} className={cn( "block py-1 text-sm ml-4", - pathname === item.href - ? "text-primary font-medium" - : "text-muted-foreground hover:text-primary", - )}> + pathname === item.href ? "text-primary font-medium" : "text-muted-foreground hover:text-primary", + )} + > {item.title} </Link> ))} @@ -94,5 +94,6 @@ export function DocsSidebar() { </div> </div> </ScrollArea> - ); + ) } + diff --git a/app/components/error-boundary.tsx b/app/components/error-boundary.tsx index 87dba68..183ec73 100644 --- a/app/components/error-boundary.tsx +++ b/app/components/error-boundary.tsx @@ -1,27 +1,27 @@ -"use client"; +"use client" -import React, { type ErrorInfo, type ReactNode } from "react"; +import React, { type ErrorInfo, type ReactNode } from "react" interface ErrorBoundaryProps { - children: ReactNode; + children: ReactNode } interface ErrorBoundaryState { - hasError: boolean; + hasError: boolean } class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> { constructor(props: ErrorBoundaryProps) { - super(props); - this.state = { hasError: false }; + super(props) + this.state = { hasError: false } } static getDerivedStateFromError(_: Error): ErrorBoundaryState { - return { hasError: true }; + return { hasError: true } } componentDidCatch(error: Error, errorInfo: ErrorInfo) { - console.error("ErrorBoundary caught an error:", error, errorInfo); + console.error("ErrorBoundary caught an error:", error, errorInfo) } render() { @@ -31,21 +31,23 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta <div className="text-center"> <h1 className="text-4xl font-bold mb-4">Oops! Something went wrong.</h1> <p className="text-xl mb-8"> - We're sorry for the inconvenience. Please try refreshing the page or contact support - if the problem persists. + We're sorry for the inconvenience. Please try refreshing the page or contact support if the problem + persists. </p> <button onClick={() => this.setState({ hasError: false })} - className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded"> + className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded" + > Try Again </button> </div> </div> - ); + ) } - return this.props.children; + return this.props.children } } -export default ErrorBoundary; +export default ErrorBoundary + diff --git a/app/components/feature-grid.tsx b/app/components/feature-grid.tsx index 68174b3..ff28cf0 100644 --- a/app/components/feature-grid.tsx +++ b/app/components/feature-grid.tsx @@ -1,5 +1,5 @@ -import type React from "react"; -import { Zap, Shield, DollarSign, Server } from "lucide-react"; +import type React from "react" +import { Zap, Shield, DollarSign } from "lucide-react" export function FeatureGrid() { return ( @@ -21,20 +21,16 @@ export function FeatureGrid() { description="Maximize MEV earnings with our advanced strategies and tools." /> <FeatureCard - icon={<Server className="w-6 h-6" />} - title="Enterprise SecureRPC" - description="Stable and reliable blockchain interactions for your applications." + icon={<Shield className="w-6 h-6" />} + title="Relay+ Protect" + description="Advanced MEV protection and transaction privacy for Ethereum." /> </div> </div> - ); + ) } -function FeatureCard({ - icon, - title, - description, -}: { icon: React.ReactNode; title: string; description: string }) { +function FeatureCard({ icon, title, description }: { icon: React.ReactNode; title: string; description: string }) { return ( <div className="p-8 rounded-lg bg-white/5 border border-white/10"> <div className="w-12 h-12 rounded-lg bg-[#31C4B9]/10 flex items-center justify-center text-[#31C4B9] mb-4"> @@ -43,5 +39,6 @@ function FeatureCard({ <h3 className="text-lg font-semibold mb-2">{title}</h3> <p className="text-gray-400 text-sm">{description}</p> </div> - ); + ) } + diff --git a/app/components/feature-section.tsx b/app/components/feature-section.tsx index 02829b5..6baa231 100644 --- a/app/components/feature-section.tsx +++ b/app/components/feature-section.tsx @@ -1,13 +1,13 @@ -import type { LucideIcon } from "lucide-react"; +import type { LucideIcon } from "lucide-react" interface Feature { - icon: LucideIcon; - title: string; - description: string; + icon: LucideIcon + title: string + description: string } interface FeatureSectionProps { - features: Feature[]; + features: Feature[] } export function FeatureSection({ features }: FeatureSectionProps) { @@ -16,7 +16,8 @@ export function FeatureSection({ features }: FeatureSectionProps) { {features.map((feature, index) => ( <div key={index} - className="relative p-6 rounded-lg border border-white/[0.08] bg-black/40 backdrop-blur-sm hover:border-white/[0.12] transition-colors"> + className="relative p-6 rounded-lg border border-white/[0.08] bg-black/40 backdrop-blur-sm hover:border-white/[0.12] transition-colors" + > <div className="w-12 h-12 rounded-lg bg-[#31C4B9]/10 flex items-center justify-center mb-4"> <feature.icon className="w-6 h-6 text-[#31C4B9]" /> </div> @@ -25,5 +26,6 @@ export function FeatureSection({ features }: FeatureSectionProps) { </div> ))} </div> - ); + ) } + diff --git a/app/components/footer.tsx b/app/components/footer.tsx index d1d01cd..f19c506 100644 --- a/app/components/footer.tsx +++ b/app/components/footer.tsx @@ -1,9 +1,10 @@ -import Link from "next/link"; -import { Twitter, Github } from "lucide-react"; -import { Badge } from "@/components/ui/badge"; +import Link from "next/link" +import { Twitter, Github } from "lucide-react" +import { Logo } from "./logo" +import { HoverCard, HoverCardTrigger, HoverCardContent } from "@/components/ui/hover-card" // This would typically come from an environment variable or build-time constant -const GIT_VERSION_HASH = "a1b2c3d"; +const GIT_VERSION_HASH = "a1b2c3d" export function Footer() { return ( @@ -12,10 +13,10 @@ export function Footer() { <div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0"> <div className="flex flex-col items-center md:items-start space-y-2"> <Link href="/" className="text-lg font-semibold text-white"> - Manifold Finance + <Logo className="h-8 w-8" /> </Link> <p className="text-sm text-gray-400 text-center md:text-left"> - © 2025 Manifold Finance. All rights reserved. + © {new Date().getFullYear()} All rights reserved. </p> </div> <div className="flex items-center space-x-4"> @@ -23,25 +24,44 @@ export function Footer() { href="https://twitter.com/manifoldfinance" target="_blank" rel="noopener noreferrer" - className="text-gray-400 hover:text-white transition-colors"> + className="text-gray-400 hover:text-white transition-colors" + > <Twitter className="w-5 h-5" /> </Link> <Link href="https://github.com/manifoldfinance" target="_blank" rel="noopener noreferrer" - className="text-gray-400 hover:text-white transition-colors"> + className="text-gray-400 hover:text-white transition-colors" + > <Github className="w-5 h-5" /> </Link> </div> </div> <div className="flex justify-between items-center mt-4 pt-4 border-t border-gray-800"> - <Badge color="jade" variant="soft" radius="full"> - Systems Nominal - </Badge> + <HoverCard> + <HoverCardTrigger asChild> + <div className="flex items-center space-x-2 cursor-pointer"> + <div className="h-2 w-2 rounded-full bg-[#b8faf6]" /> + <span className="text-sm text-muted-foreground">Operational</span> + </div> + </HoverCardTrigger> + <HoverCardContent className="w-80"> + <div className="flex justify-between space-x-4"> + <div className="space-y-1"> + <h4 className="text-sm font-semibold">System Status</h4> + <p className="text-sm">All systems are operational.</p> + <div className="flex items-center pt-2"> + <span className="text-xs text-muted-foreground">Last checked: {new Date().toLocaleString()}</span> + </div> + </div> + </div> + </HoverCardContent> + </HoverCard> <span className="text-xs text-gray-500">Version: {GIT_VERSION_HASH}</span> </div> </div> </footer> - ); + ) } + diff --git a/app/components/header.tsx b/app/components/header.tsx index 15f6686..a15f9cb 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -1,10 +1,10 @@ -"use client"; +"use client" -import * as React from "react"; -import Link from "next/link"; -import { Logo } from "@/app/components/logo"; -import { StatusIndicator } from "@/app/components/status-indicator"; -import { cn } from "@/lib/utils"; +import * as React from "react" +import Link from "next/link" +import Image from "next/image" +import { Logo } from "@/app/components/logo" +import { cn } from "@/lib/utils" import { NavigationMenu, NavigationMenuContent, @@ -13,11 +13,11 @@ import { NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, -} from "@/components/ui/navigation-menu"; -import { Button } from "@/components/ui/button"; -import { Menu } from "lucide-react"; +} from "@/components/ui/navigation-menu" +import { Button } from "@/components/ui/button" +import { Menu } from "lucide-react" -const products: { title: string; href: string; description: string }[] = [ +const solutions: { title: string; href: string; description: string }[] = [ { title: "High-Performance Staking", href: "/solutions/staking", @@ -38,7 +38,30 @@ const products: { title: string; href: string; description: string }[] = [ href: "/solutions/securerpc", description: "Stable and reliable blockchain interactions for your applications.", }, -]; +] + +const products: { title: string; href: string; description: string }[] = [ + { + title: "FOLD Staking", + href: "/products/fold-staking", + description: "Stake your FOLD tokens and earn rewards.", + }, + { + title: "SecureRPC", + href: "/products/securerpc", + description: "Enterprise-grade RPC service for secure blockchain interactions.", + }, + { + title: "XGA", + href: "/products/xga", + description: "Cross-chain Governance Aggregator for decentralized decision-making.", + }, + { + title: "mevETH", + href: "/products/meveth", + description: "Maximized MEV rewards for Ethereum staking.", + }, +] const resources: { title: string; href: string; description: string }[] = [ { @@ -61,7 +84,7 @@ const resources: { title: string; href: string; description: string }[] = [ href: "/support", description: "Get help from our team and community.", }, -]; +] const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>( ({ className, title, children, ...props }, ref) => { @@ -73,18 +96,19 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", className, )} - {...props}> + {...props} + > <div className="text-sm font-medium leading-none">{title}</div> <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> </NavigationMenuLink> </li> - ); + ) }, -); -ListItem.displayName = "ListItem"; +) +ListItem.displayName = "ListItem" function MobileMenu() { - const [isOpen, setIsOpen] = React.useState(false); + const [isOpen, setIsOpen] = React.useState(false) return ( <div className="md:hidden"> @@ -93,7 +117,6 @@ function MobileMenu() { </Button> {isOpen && ( <div className="absolute top-16 left-0 w-full bg-background border-b border-border p-4"> - {/* Add mobile menu items here */} <nav className="flex flex-col space-y-4"> <Link href="/solutions" className="text-sm font-medium"> Solutions @@ -111,7 +134,7 @@ function MobileMenu() { </div> )} </div> - ); + ) } export function Header() { @@ -121,47 +144,39 @@ export function Header() { <div className="flex items-center justify-between h-16 md:h-20"> <Link href="/" className="flex items-center"> <Logo className="h-8 w-8 md:h-10 md:w-10" /> - <span className="ml-2 text-lg font-semibold hidden sm:inline">Manifold Finance</span> </Link> <div className="flex items-center space-x-4"> <NavigationMenu className="hidden md:block"> <NavigationMenuList> <NavigationMenuItem> - <NavigationMenuTrigger className="text-foreground"> - Products - </NavigationMenuTrigger> + <NavigationMenuTrigger className="text-foreground">Solutions</NavigationMenuTrigger> <NavigationMenuContent> <div className="grid grid-cols-[1fr_2fr] w-[600px]"> <NavigationMenuLink asChild> <a className="flex flex-col justify-between h-full select-none rounded-l-md bg-gradient-to-br from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md" - href="/solutions/mev"> + href="/solutions/staking" + > <div> - <svg - aria-hidden - width="38" - height="38" - viewBox="0 0 25 25" - fill="currentColor" - className="h-6 w-6 text-primary mb-3"> - <path d="M12 25C7.58173 25 4 21.4183 4 17C4 12.5817 7.58173 9 12 9V25Z"></path> - <path d="M12 0H4V8H12V0Z"></path> - <path d="M17 8C19.2091 8 21 6.20914 21 4C21 1.79086 19.2091 0 17 0C14.7909 0 13 1.79086 13 4C13 6.20914 14.7909 8 17 8Z"></path> - </svg> - <div className="text-lg font-medium text-foreground mb-2"> - MEV Optimization - </div> + <Image + src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Ethereum2_Logo-G7XZRKQfQ3ujqhgs1ZKjTpoe3zVqab.png" + alt="Ethereum Logo" + width={38} + height={38} + className="mb-3" + /> + <div className="text-lg font-medium text-foreground mb-2">High-Performance Staking</div> <p className="text-sm text-muted-foreground"> - Maximize MEV earnings with our advanced strategies and tools. + Build and manage efficient staking solutions for maximum returns. </p> </div> <div className="text-sm font-medium text-primary mt-4">Learn more →</div> </a> </NavigationMenuLink> <ul className="grid gap-3 p-6 bg-background rounded-r-md"> - {products.map((product) => ( - <ListItem key={product.title} title={product.title} href={product.href}> - {product.description} + {solutions.map((solution) => ( + <ListItem key={solution.title} title={solution.title} href={solution.href}> + {solution.description} </ListItem> ))} </ul> @@ -169,9 +184,19 @@ export function Header() { </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> - <NavigationMenuTrigger className="text-foreground"> - Resources - </NavigationMenuTrigger> + <NavigationMenuTrigger className="text-foreground">Products</NavigationMenuTrigger> + <NavigationMenuContent> + <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> + {products.map((product) => ( + <ListItem key={product.title} title={product.title} href={product.href}> + {product.description} + </ListItem> + ))} + </ul> + </NavigationMenuContent> + </NavigationMenuItem> + <NavigationMenuItem> + <NavigationMenuTrigger className="text-foreground">Resources</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> {resources.map((resource) => ( @@ -184,18 +209,16 @@ export function Header() { </NavigationMenuItem> <NavigationMenuItem> <Link href="/docs" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}> - Documentation - </NavigationMenuLink> + <NavigationMenuLink className={navigationMenuTriggerStyle()}>Documentation</NavigationMenuLink> </Link> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> - <StatusIndicator status="operational" className="hidden sm:flex" /> <MobileMenu /> </div> </div> </div> </header> - ); + ) } + diff --git a/app/components/layout-wrapper.tsx b/app/components/layout-wrapper.tsx new file mode 100644 index 0000000..321a60e --- /dev/null +++ b/app/components/layout-wrapper.tsx @@ -0,0 +1,22 @@ +"use client" + +import { usePathname } from "next/navigation" +import { Footer } from "./footer" +import type React from "react" // Added import for React + +interface LayoutWrapperProps { + children: React.ReactNode +} + +export function LayoutWrapper({ children }: LayoutWrapperProps) { + const pathname = usePathname() + const isHomePage = pathname === "/" + + return ( + <> + {children} + {!isHomePage && <Footer />} + </> + ) +} + diff --git a/app/components/logo.tsx b/app/components/logo.tsx index 8c63b56..44c42b1 100644 --- a/app/components/logo.tsx +++ b/app/components/logo.tsx @@ -1,15 +1,12 @@ -export function Logo() { +export function Logo({ className }: { className?: string }) { return ( - <svg width="40" height="40" viewBox="0 0 40 40" fill="none" className="text-white"> - <path - d="M20 40c11.046 0 20-8.954 20-20S31.046 0 20 0 0 8.954 0 20s8.954 20 20 20z" - fill="currentColor" - fillOpacity={0.2} - /> - <path - d="M20 36c8.837 0 16-7.163 16-16S28.837 4 20 4 4 11.163 4 20s7.163 16 16 16z" - fill="currentColor" - /> - </svg> - ); + <img + src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Manifold_Finance-8kgmcbTmJJQLsmQpk6qrv8hVQys1H6.png" + alt="Manifold Finance Logo" + className={className} + width={40} + height={40} + /> + ) } + diff --git a/app/components/lst-apy-graph.tsx b/app/components/lst-apy-graph.tsx index 6e75c2f..0cd05d2 100644 --- a/app/components/lst-apy-graph.tsx +++ b/app/components/lst-apy-graph.tsx @@ -1,18 +1,10 @@ -"use client"; -import { - Line, - LineChart, - ResponsiveContainer, - XAxis, - YAxis, - Tooltip, - CartesianGrid, -} from "recharts"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +"use client" +import { Line, LineChart, ResponsiveContainer, XAxis, YAxis, Tooltip, CartesianGrid } from "recharts" +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" interface LSTData { - name: string; - apy: number; + name: string + apy: number } const lstData: LSTData[] = [ @@ -20,29 +12,21 @@ const lstData: LSTData[] = [ { name: "stETH", apy: 4.8 }, { name: "rETH", apy: 4.9 }, { name: "oETH", apy: 5.0 }, -]; +] export function LSTAPYGraph() { return ( <Card> <CardHeader> <CardTitle>LST APY Comparison</CardTitle> - <CardDescription> - Annual Percentage Yield for different Liquid Staking Tokens (Log Scale) - </CardDescription> + <CardDescription>Annual Percentage Yield for different Liquid Staking Tokens (Log Scale)</CardDescription> </CardHeader> <CardContent className="pb-4"> <div className="h-[300px]"> <ResponsiveContainer width="100%" height="100%"> <LineChart data={lstData}> <CartesianGrid strokeDasharray="3 3" /> - <XAxis - dataKey="name" - stroke="#888888" - fontSize={12} - tickLine={false} - axisLine={false} - /> + <XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} /> <YAxis stroke="#888888" fontSize={12} @@ -69,5 +53,6 @@ export function LSTAPYGraph() { </div> </CardContent> </Card> - ); + ) } + diff --git a/app/components/lst-apy-trend-graph.tsx b/app/components/lst-apy-trend-graph.tsx index 53b52b5..0f8228d 100644 --- a/app/components/lst-apy-trend-graph.tsx +++ b/app/components/lst-apy-trend-graph.tsx @@ -1,22 +1,13 @@ -"use client"; -import { - Line, - LineChart, - ResponsiveContainer, - XAxis, - YAxis, - Tooltip, - CartesianGrid, - Legend, -} from "recharts"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +"use client" +import { Line, LineChart, ResponsiveContainer, XAxis, YAxis, Tooltip, CartesianGrid, Legend } from "recharts" +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" interface LSTTrendData { - quarter: string; - mevETH: number; - stETH: number; - rETH: number; - oETH: number; + quarter: string + mevETH: number + stETH: number + rETH: number + oETH: number } const lstTrendData: LSTTrendData[] = [ @@ -24,7 +15,7 @@ const lstTrendData: LSTTrendData[] = [ { quarter: "Q2 2024", mevETH: 5.2, stETH: 4.7, rETH: 4.8, oETH: 4.9 }, { quarter: "Q3 2024", mevETH: 5.4, stETH: 4.6, rETH: 4.7, oETH: 4.8 }, { quarter: "Q4 2024", mevETH: 5.6, stETH: 4.5, rETH: 4.6, oETH: 4.7 }, -]; +] export function LSTAPYTrendGraph() { return ( @@ -38,13 +29,7 @@ export function LSTAPYTrendGraph() { <ResponsiveContainer width="100%" height="100%"> <LineChart data={lstTrendData}> <CartesianGrid strokeDasharray="3 3" /> - <XAxis - dataKey="quarter" - stroke="#888888" - fontSize={12} - tickLine={false} - axisLine={false} - /> + <XAxis dataKey="quarter" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} /> <YAxis stroke="#888888" fontSize={12} @@ -92,5 +77,6 @@ export function LSTAPYTrendGraph() { </div> </CardContent> </Card> - ); + ) } + diff --git a/app/components/lst-comparison-table.tsx b/app/components/lst-comparison-table.tsx index e0bf14a..ee8b42d 100644 --- a/app/components/lst-comparison-table.tsx +++ b/app/components/lst-comparison-table.tsx @@ -1,22 +1,15 @@ -"use client"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; -import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip"; -import { Info } from "lucide-react"; +"use client" +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" +import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip" +import { Info } from "lucide-react" interface LSTData { - name: string; - apy: number; - tvl: string; - fee: string; - decentralization: "Low" | "Medium" | "High"; - liquidityScore: number; + name: string + apy: number + tvl: string + fee: string + decentralization: "Low" | "Medium" | "High" + liquidityScore: number } const lstData: LSTData[] = [ @@ -52,7 +45,7 @@ const lstData: LSTData[] = [ decentralization: "Low", liquidityScore: 6, }, -]; +] export function LSTComparisonTable() { return ( @@ -94,5 +87,6 @@ export function LSTComparisonTable() { </Table> </div> </TooltipProvider> - ); + ) } + diff --git a/app/components/main-nav.tsx b/app/components/main-nav.tsx index fb06a6f..60c28dc 100644 --- a/app/components/main-nav.tsx +++ b/app/components/main-nav.tsx @@ -1,11 +1,11 @@ -"use client"; +"use client" -import * as React from "react"; -import Link from "next/link"; -import { Menu } from "lucide-react"; +import * as React from "react" +import Link from "next/link" +import { Menu } from "lucide-react" -import { cn } from "@/lib/utils"; -import { Icons } from "@/components/icons"; +import { cn } from "@/lib/utils" +import { Icons } from "@/components/icons" import { NavigationMenu, NavigationMenuContent, @@ -14,9 +14,9 @@ import { NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, -} from "@/components/ui/navigation-menu"; -import { Button } from "@/components/ui/button"; -import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; +} from "@/components/ui/navigation-menu" +import { Button } from "@/components/ui/button" +import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet" const solutions: { title: string; href: string; description: string }[] = [ { @@ -34,7 +34,12 @@ const solutions: { title: string; href: string; description: string }[] = [ href: "/solutions/avs-operations", description: "Streamline your Autonomous Validation System operations for enhanced efficiency.", }, -]; + { + title: "Relay+ Protect", + href: "/solutions/relay-protect", + description: "Advanced MEV protection and transaction privacy for Ethereum.", + }, +] const products: { title: string; href: string; description: string }[] = [ ...solutions, @@ -48,7 +53,7 @@ const products: { title: string; href: string; description: string }[] = [ href: "/fold-token", description: "Learn about our native ERC20 token powering the Manifold Finance ecosystem.", }, -]; +] export function MainNav() { return ( @@ -107,23 +112,19 @@ export function MainNav() { </NavigationMenuItem> <NavigationMenuItem> <Link href="/docs" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}> - Documentation - </NavigationMenuLink> + <NavigationMenuLink className={navigationMenuTriggerStyle()}>Documentation</NavigationMenuLink> </Link> </NavigationMenuItem> <NavigationMenuItem> <Link href="/blog" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}> - Blog - </NavigationMenuLink> + <NavigationMenuLink className={navigationMenuTriggerStyle()}>Blog</NavigationMenuLink> </Link> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </div> </> - ); + ) } const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>( @@ -137,27 +138,23 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", className, )} - {...props}> + {...props} + > <div className="text-sm font-medium leading-none">{title}</div> <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> </a> </NavigationMenuLink> </li> - ); + ) }, -); -ListItem.displayName = "ListItem"; +) +ListItem.displayName = "ListItem" -function MobileNavItem({ - title, - items, -}: { title: string; items: { title: string; href: string }[] }) { - const [isOpen, setIsOpen] = React.useState(false); +function MobileNavItem({ title, items }: { title: string; items: { title: string; href: string }[] }) { + const [isOpen, setIsOpen] = React.useState(false) return ( <div> - <button - onClick={() => setIsOpen(!isOpen)} - className="flex w-full items-center justify-between py-2 text-left"> + <button onClick={() => setIsOpen(!isOpen)} className="flex w-full items-center justify-between py-2 text-left"> {title} <Icons.chevronDown className={cn("h-4 w-4 transition-transform", isOpen && "rotate-180")} /> </button> @@ -171,5 +168,6 @@ function MobileNavItem({ </div> )} </div> - ); + ) } + diff --git a/app/components/mev-protection-comparison.tsx b/app/components/mev-protection-comparison.tsx new file mode 100644 index 0000000..318cfb0 --- /dev/null +++ b/app/components/mev-protection-comparison.tsx @@ -0,0 +1,171 @@ +"use client" + +import { useState } from "react" +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +import { Button } from "@/components/ui/button" +import { ChevronDown, ChevronUp } from "lucide-react" + +interface ComparisonData { + feature: string + relayProtect: string + flashbotsMevShare: string + mevBlocker: string +} + +const comparisonData: ComparisonData[] = [ + { + feature: "Architecture Foundation", + relayProtect: "Private mempool implementation with complete transaction isolation", + flashbotsMevShare: "Transparent order flow with partial information disclosure", + mevBlocker: "Hybrid approach combining privacy with controlled information flow", + }, + { + feature: "Transaction Privacy", + relayProtect: "Full privacy until validator commitment, zero information leakage during pending state", + flashbotsMevShare: "Partial privacy with strategic information hints for market efficiency", + mevBlocker: "Enhanced privacy with selective disclosure mechanisms", + }, + { + feature: "Processing Pipeline", + relayProtect: "Direct entry into encrypted transaction pool with validator-only access", + flashbotsMevShare: "Routing through trusted builder network with hint system", + mevBlocker: "Multi-stage processing with privacy-preserving intermediaries", + }, + { + feature: "Block Construction Method", + relayProtect: "Private block building with complete state knowledge", + flashbotsMevShare: "Collaborative block building with partial information sharing", + mevBlocker: "Hybrid block building with selective validator participation", + }, + { + feature: "Network Integration", + relayProtect: "Deep integration with validator networks, minimal external dependencies", + flashbotsMevShare: "Extensive integration across multiple builder networks", + mevBlocker: "Moderate integration requirements with existing infrastructure", + }, + { + feature: "Economic Model", + relayProtect: "Users retain 70-80% of MEV protection benefits, lower validator share", + flashbotsMevShare: "Equal distribution between users, builders, and validators", + mevBlocker: "Variable distribution favoring validator incentivization", + }, + { + feature: "Market Impact", + relayProtect: "Reduces overall MEV extraction by 85-95% through complete privacy", + flashbotsMevShare: "Reduces MEV extraction by 60-75% through controlled disclosure", + mevBlocker: "Reduces MEV extraction by 70-85% through hybrid approach", + }, + { + feature: "Implementation Complexity", + relayProtect: "High initial setup complexity, simpler long-term maintenance", + flashbotsMevShare: "Moderate complexity with established infrastructure", + mevBlocker: "Moderate to high complexity with ongoing maintenance needs", + }, + { + feature: "Validator Requirements", + relayProtect: "Enhanced validation capabilities with privacy preservation", + flashbotsMevShare: "Standard validation with builder network participation", + mevBlocker: "Advanced validation with privacy protocol support", + }, + { + feature: "Network Overhead", + relayProtect: "Low network overhead due to efficient encryption", + flashbotsMevShare: "Moderate overhead from hint system and builder network", + mevBlocker: "Moderate to high overhead from privacy protocols", + }, + { + feature: "Cost Structure", + relayProtect: "Lower direct costs, higher initial setup investment", + flashbotsMevShare: "Moderate costs with established fee structure", + mevBlocker: "Variable costs depending on network conditions", + }, + { + feature: "Backrunning Prevention", + relayProtect: "Near-complete prevention through full transaction privacy", + flashbotsMevShare: "Partial prevention through controlled information flow", + mevBlocker: "Enhanced prevention through hybrid privacy model", + }, + { + feature: "Scaling Capabilities", + relayProtect: "Highly scalable with minimal bottlenecks", + flashbotsMevShare: "Moderately scalable with potential builder constraints", + mevBlocker: "Scalable with some privacy-related limitations", + }, + { + feature: "Integration Flexibility", + relayProtect: "Limited flexibility due to strict privacy requirements", + flashbotsMevShare: "High flexibility with multiple integration options", + mevBlocker: "Moderate flexibility with hybrid approach", + }, + { + feature: "Upgrade Path", + relayProtect: "Clear upgrade path with backward compatibility", + flashbotsMevShare: "Complex upgrade path with multiple stakeholders", + mevBlocker: "Moderate upgrade complexity with partial compatibility", + }, +] + +export function MEVProtectionComparison() { + const [expandedRows, setExpandedRows] = useState<number[]>([]) + + const toggleRow = (index: number) => { + setExpandedRows((prev) => (prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index])) + } + + return ( + <Card> + <CardHeader> + <CardTitle>MEV Protection Comparison</CardTitle> + <CardDescription>Compare Relay+ Protect with other MEV protection solutions</CardDescription> + </CardHeader> + <CardContent> + <div className="overflow-x-auto"> + <table className="w-full border-collapse"> + <thead> + <tr className="bg-muted"> + <th className="p-2 text-left font-semibold">Feature</th> + <th className="p-2 text-left font-semibold">Relay+ Protect</th> + <th className="p-2 text-left font-semibold">Flashbots MEV-Share</th> + <th className="p-2 text-left font-semibold">MEV Blocker</th> + </tr> + </thead> + <tbody> + {comparisonData.map((row, index) => ( + <tr key={index} className="border-t border-muted"> + <td className="p-2 font-medium">{row.feature}</td> + <td className="p-2"> + <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}>{row.relayProtect}</div> + {row.relayProtect.length > 100 && ( + <Button variant="ghost" size="sm" onClick={() => toggleRow(index)} className="mt-1"> + {expandedRows.includes(index) ? ( + <> + <ChevronUp className="h-4 w-4 mr-1" /> + Show less + </> + ) : ( + <> + <ChevronDown className="h-4 w-4 mr-1" /> + Show more + </> + )} + </Button> + )} + </td> + <td className="p-2"> + <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}> + {row.flashbotsMevShare} + </div> + </td> + <td className="p-2"> + <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}>{row.mevBlocker}</div> + </td> + </tr> + ))} + </tbody> + </table> + </div> + </CardContent> + </Card> + ) +} + diff --git a/app/components/privacy-section.tsx b/app/components/privacy-section.tsx index fe6e88c..954e057 100644 --- a/app/components/privacy-section.tsx +++ b/app/components/privacy-section.tsx @@ -1,4 +1,4 @@ -import { Shield } from "lucide-react"; +import { Shield } from "lucide-react" export function PrivacySection() { return ( @@ -8,10 +8,10 @@ export function PrivacySection() { <h3 className="text-xl font-semibold">Privacy and Security</h3> </div> <p className="text-gray-400"> - At Manifold Finance, we prioritize the privacy and security of our users. Our infrastructure - is built with state-of-the-art encryption and security measures to ensure your data and - transactions remain protected. + At Manifold Finance, we prioritize the privacy and security of our users. Our infrastructure is built with + state-of-the-art encryption and security measures to ensure your data and transactions remain protected. </p> </div> - ); + ) } + diff --git a/app/components/search-button.tsx b/app/components/search-button.tsx index a4c327e..2fcf5a9 100644 --- a/app/components/search-button.tsx +++ b/app/components/search-button.tsx @@ -1,22 +1,20 @@ -"use client"; +"use client" -import { useCallback } from "react"; -import { Button } from "@/components/ui/button"; +import { useCallback } from "react" +import { Button } from "@/components/ui/button" export function SearchButton() { const handleClick = useCallback(() => { - document.dispatchEvent(new KeyboardEvent("keydown", { key: "k", metaKey: true })); - }, []); + document.dispatchEvent(new KeyboardEvent("keydown", { key: "k", metaKey: true })) + }, []) return ( - <Button - onClick={handleClick} - variant="outline" - className="bg-white/5 text-white hover:bg-white/10"> + <Button onClick={handleClick} variant="outline" className="bg-white/5 text-white hover:bg-white/10"> <span className="hidden md:inline-flex">Search...</span> <kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-white/20 bg-white/10 px-1.5 font-mono text-[10px] font-medium text-white/70 opacity-100 ml-2"> <span className="text-xs">⌘</span>K </kbd> </Button> - ); + ) } + diff --git a/app/components/status-indicator.tsx b/app/components/status-indicator.tsx deleted file mode 100644 index 8b629c6..0000000 --- a/app/components/status-indicator.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { cn } from "@/lib/utils"; - -type StatusIndicatorProps = { - status: "operational" | "degraded" | "outage"; -}; - -export function StatusIndicator({ status }: StatusIndicatorProps) { - return ( - <div className="flex items-center space-x-2"> - <div - className={cn( - "h-2 w-2 rounded-full", - status === "operational" && "bg-green-500", - status === "degraded" && "bg-yellow-500", - status === "outage" && "bg-red-500", - )} - /> - <span className="text-sm text-muted-foreground capitalize">{status}</span> - </div> - ); -} diff --git a/app/docs/getting-started/installation/page.tsx b/app/docs/getting-started/installation/page.tsx index 022ec8b..aa093f2 100644 --- a/app/docs/getting-started/installation/page.tsx +++ b/app/docs/getting-started/installation/page.tsx @@ -1,4 +1,4 @@ -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" export default function InstallationPage() { return ( @@ -44,5 +44,6 @@ export default function InstallationPage() { </pre> </div> </div> - ); + ) } + diff --git a/app/docs/getting-started/introduction/page.tsx b/app/docs/getting-started/introduction/page.tsx index 40759a3..a57591f 100644 --- a/app/docs/getting-started/introduction/page.tsx +++ b/app/docs/getting-started/introduction/page.tsx @@ -3,16 +3,16 @@ export default function IntroductionPage() { <div className="space-y-6"> <h1 className="text-3xl font-bold">Introduction</h1> <p className="text-lg text-muted-foreground"> - Manifold Finance provides optimized infrastructure for the next generation of Ethereum, - offering high-performance staking, MEV optimization, and enterprise-grade SecureRPC. + Manifold Finance provides optimized infrastructure for the next generation of Ethereum, offering + high-performance staking, MEV optimization, and enterprise-grade SecureRPC. </p> <div className="space-y-4"> <h2 className="text-2xl font-semibold">What is Manifold Finance?</h2> <p> - Manifold Finance is a comprehensive suite of tools and services designed to optimize your - Ethereum infrastructure. Our platform helps you maximize returns through efficient - staking, MEV optimization, and secure RPC endpoints. + Manifold Finance is a comprehensive suite of tools and services designed to optimize your Ethereum + infrastructure. Our platform helps you maximize returns through efficient staking, MEV optimization, and + secure RPC endpoints. </p> <h3 className="text-xl font-semibold">Key Features</h3> @@ -24,5 +24,6 @@ export default function IntroductionPage() { </ul> </div> </div> - ); + ) } + diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx index 72f081c..68276e9 100644 --- a/app/docs/layout.tsx +++ b/app/docs/layout.tsx @@ -1,7 +1,7 @@ -import { DocsSidebar } from "@/app/components/docs-sidebar"; -import { Breadcrumb } from "@/app/components/breadcrumb"; -import { ScrollArea } from "@/components/ui/scroll-area"; -import type React from "react"; // Added import for React +import { DocsSidebar } from "@/app/components/docs-sidebar" +import { Breadcrumb } from "@/app/components/breadcrumb" +import { ScrollArea } from "@/components/ui/scroll-area" +import type React from "react" // Added import for React export default function DocsLayout({ children }: { children: React.ReactNode }) { return ( @@ -21,5 +21,6 @@ export default function DocsLayout({ children }: { children: React.ReactNode }) </ScrollArea> </div> </div> - ); + ) } + diff --git a/app/docs/page.tsx b/app/docs/page.tsx index c0d916d..f6dd83a 100644 --- a/app/docs/page.tsx +++ b/app/docs/page.tsx @@ -1,28 +1,27 @@ -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import Link from "next/link"; -import { ArrowRight } from "lucide-react"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +import Link from "next/link" +import { ArrowRight } from "lucide-react" export default function DocsPage() { return ( <div className="space-y-6"> <h1 className="text-3xl font-bold">Documentation</h1> <p className="text-muted-foreground text-lg"> - Welcome to the Manifold Finance documentation. Here you'll find comprehensive guides and - documentation to help you start working with Manifold Finance as quickly as possible. + Welcome to the Manifold Finance documentation. Here you'll find comprehensive guides and documentation to help + you start working with Manifold Finance as quickly as possible. </p> <div className="grid gap-6 md:grid-cols-2"> <Card> <CardHeader> <CardTitle>Getting Started</CardTitle> - <CardDescription> - Learn the basics of Manifold Finance and get started with our platform. - </CardDescription> + <CardDescription>Learn the basics of Manifold Finance and get started with our platform.</CardDescription> </CardHeader> <CardContent> <Link href="/docs/getting-started/introduction" - className="text-primary hover:underline inline-flex items-center"> + className="text-primary hover:underline inline-flex items-center" + > Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> @@ -31,14 +30,13 @@ export default function DocsPage() { <Card> <CardHeader> <CardTitle>API Reference</CardTitle> - <CardDescription> - Detailed documentation for our SecureRPC API endpoints and features. - </CardDescription> + <CardDescription>Detailed documentation for our SecureRPC API endpoints and features.</CardDescription> </CardHeader> <CardContent> <Link href="/docs/securerpc/api-reference" - className="text-primary hover:underline inline-flex items-center"> + className="text-primary hover:underline inline-flex items-center" + > Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> @@ -52,9 +50,7 @@ export default function DocsPage() { </CardDescription> </CardHeader> <CardContent> - <Link - href="/docs/staking/overview" - className="text-primary hover:underline inline-flex items-center"> + <Link href="/docs/staking/overview" className="text-primary hover:underline inline-flex items-center"> Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> @@ -68,14 +64,13 @@ export default function DocsPage() { </CardDescription> </CardHeader> <CardContent> - <Link - href="/docs/faq" - className="text-primary hover:underline inline-flex items-center"> + <Link href="/docs/faq" className="text-primary hover:underline inline-flex items-center"> Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> </Card> </div> </div> - ); + ) } + diff --git a/app/docs/securerpc/api-reference/page.tsx b/app/docs/securerpc/api-reference/page.tsx index 9d68478..0ef647d 100644 --- a/app/docs/securerpc/api-reference/page.tsx +++ b/app/docs/securerpc/api-reference/page.tsx @@ -10,8 +10,7 @@ export default function ApiReferencePage() { <section className="space-y-4"> <h2 className="text-2xl font-semibold">Authentication</h2> <p> - All API endpoints require authentication using your API key. Include your API key in the - request headers: + All API endpoints require authentication using your API key. Include your API key in the request headers: </p> <pre className="rounded-lg bg-muted p-4"> <code>{`X-API-Key: your_api_key`}</code> @@ -31,9 +30,7 @@ export default function ApiReferencePage() { <div className="rounded-lg border p-4"> <h3 className="text-xl font-semibold">GET /status</h3> - <p className="text-muted-foreground mt-2"> - Get the current status of the SecureRPC service. - </p> + <p className="text-muted-foreground mt-2">Get the current status of the SecureRPC service.</p> <pre className="rounded-lg bg-muted p-4 mt-4"> <code>{`curl -X GET "https://api.manifoldfinance.com/v1/status" \\ -H "X-API-Key: your_api_key"`}</code> @@ -53,5 +50,6 @@ export default function ApiReferencePage() { </section> </div> </div> - ); + ) } + diff --git a/app/fold-token/page.tsx b/app/fold-token/page.tsx index ddb9e3c..27d9e57 100644 --- a/app/fold-token/page.tsx +++ b/app/fold-token/page.tsx @@ -1,24 +1,20 @@ -import { BackgroundPaths } from "../components/background-paths"; -import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import Link from "next/link"; -import { ExternalLink, FileText, ShieldCheck, Zap } from "lucide-react"; +import { BackgroundPaths } from "../components/background-paths" +import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import Link from "next/link" +import { ExternalLink, FileText, ShieldCheck, Zap } from "lucide-react" export default function FoldTokenPage() { return ( <div className="min-h-screen bg-black text-white"> - <BackgroundPaths - title="FOLD Token|" - subtitle="The ERC20 token powering Manifold Finance's ecosystem" - /> + <BackgroundPaths title="FOLD Token|" subtitle="The ERC20 token powering Manifold Finance's ecosystem" /> <main className="container mx-auto px-4 py-12"> <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">What is FOLD?</h2> <p className="text-base sm:text-lg mb-4"> - FOLD is the native ERC20 token of the Manifold Finance ecosystem. It serves multiple - purposes within our platform, including governance, staking, and accessing premium - features. + FOLD is the native ERC20 token of the Manifold Finance ecosystem. It serves multiple purposes within our + platform, including governance, staking, and accessing premium features. </p> <div className="flex flex-wrap gap-2"> <Badge variant="secondary">ERC20</Badge> @@ -79,8 +75,8 @@ export default function FoldTokenPage() { <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Token Distribution</h2> <p className="text-base sm:text-lg mb-4"> - The initial distribution of FOLD tokens is designed to ensure a fair launch and - sustainable growth of the Manifold Finance ecosystem: + The initial distribution of FOLD tokens is designed to ensure a fair launch and sustainable growth of the + Manifold Finance ecosystem: </p> <ul className="list-disc list-inside space-y-2 mb-4"> <li>40% - Community Treasury</li> @@ -90,17 +86,16 @@ export default function FoldTokenPage() { <li>5% - Ecosystem Development Fund</li> </ul> <p className="text-base sm:text-lg mb-4"> - This distribution ensures that a significant portion of tokens is allocated to the - community and ecosystem growth, while also incentivizing long-term commitment from the - team and early supporters. + This distribution ensures that a significant portion of tokens is allocated to the community and ecosystem + growth, while also incentivizing long-term commitment from the team and early supporters. </p> </section> <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Governance</h2> <p className="text-base sm:text-lg mb-4"> - FOLD token holders have the power to participate in the governance of the Manifold - Finance protocol. This includes: + FOLD token holders have the power to participate in the governance of the Manifold Finance protocol. This + includes: </p> <ul className="list-disc list-inside space-y-2 mb-4"> <li>Proposing and voting on protocol upgrades</li> @@ -109,16 +104,16 @@ export default function FoldTokenPage() { <li>Allocating resources from the Community Treasury</li> </ul> <p className="text-base sm:text-lg"> - The governance process is designed to be transparent and inclusive, ensuring that all - token holders have a voice in the future direction of Manifold Finance. + The governance process is designed to be transparent and inclusive, ensuring that all token holders have a + voice in the future direction of Manifold Finance. </p> </section> <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Staking and Rewards</h2> <p className="text-base sm:text-lg mb-4"> - FOLD token holders can stake their tokens to earn rewards and contribute to the security - of the Manifold Finance network. Staking benefits include: + FOLD token holders can stake their tokens to earn rewards and contribute to the security of the Manifold + Finance network. Staking benefits include: </p> <ul className="list-disc list-inside space-y-2 mb-4"> <li>Earning passive income through staking rewards</li> @@ -127,8 +122,7 @@ export default function FoldTokenPage() { <li>Participation in network security and validation</li> </ul> <p className="text-base sm:text-lg"> - The staking mechanism is designed to encourage long-term holding and active - participation in the ecosystem. + The staking mechanism is designed to encourage long-term holding and active participation in the ecosystem. </p> </section> @@ -139,9 +133,8 @@ export default function FoldTokenPage() { <span className="text-base sm:text-lg font-semibold">Audited and Secure</span> </div> <p className="text-base sm:text-lg mb-4"> - The FOLD token smart contract has undergone rigorous security audits by leading - blockchain security firms to ensure the safety of our users' funds and the integrity of - the Manifold Finance ecosystem. + The FOLD token smart contract has undergone rigorous security audits by leading blockchain security firms to + ensure the safety of our users' funds and the integrity of the Manifold Finance ecosystem. </p> <Button asChild variant="outline"> <Link href="/security" className="inline-flex items-center"> @@ -153,8 +146,8 @@ export default function FoldTokenPage() { <section> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Get FOLD</h2> <p className="text-base sm:text-lg mb-4"> - FOLD tokens are available on several decentralized exchanges and can be earned through - participation in Manifold Finance's services. + FOLD tokens are available on several decentralized exchanges and can be earned through participation in + Manifold Finance's services. </p> <div className="flex flex-wrap gap-4"> <Button asChild variant="default"> @@ -167,5 +160,6 @@ export default function FoldTokenPage() { </section> </main> </div> - ); + ) } + diff --git a/app/globals.css b/app/globals.css index 59e819b..da3a241 100644 --- a/app/globals.css +++ b/app/globals.css @@ -90,3 +90,4 @@ @apply font-heading; } } + diff --git a/app/layout.tsx b/app/layout.tsx index 8cdfba4..2947fd5 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,22 +1,22 @@ -import { Space_Grotesk, Noto_Sans } from "next/font/google"; -import { Footer } from "./components/footer"; -import ErrorBoundary from "./components/error-boundary"; -import "./globals.css"; -import type { Metadata } from "next"; -import { CommandMenu } from "./components/command-menu"; -import { Header } from "./components/header"; -import type React from "react"; +import { Space_Grotesk, Noto_Sans } from "next/font/google" +import ErrorBoundary from "./components/error-boundary" +import "./globals.css" +import type { Metadata } from "next" +import { CommandMenu } from "./components/command-menu" +import { Header } from "./components/header" +import type React from "react" +import { LayoutWrapper } from "./components/layout-wrapper" const spaceGrotesk = Space_Grotesk({ subsets: ["latin"], variable: "--font-space-grotesk", -}); +}) const notoSans = Noto_Sans({ subsets: ["latin"], weight: ["400", "700"], variable: "--font-noto-sans", -}); +}) export const metadata: Metadata = { metadataBase: new URL("https://manifoldfinance.com"), @@ -26,14 +26,7 @@ export const metadata: Metadata = { }, description: "Manifold Finance provides optimized infrastructure for the next generation of Ethereum, offering high-performance staking, MEV optimization, and enterprise-grade SecureRPC.", - keywords: [ - "Manifold Finance", - "Ethereum", - "Staking", - "MEV", - "SecureRPC", - "Blockchain Infrastructure", - ], + keywords: ["Manifold Finance", "Ethereum", "Staking", "MEV", "SecureRPC", "Blockchain Infrastructure"], authors: [{ name: "Manifold Finance" }], creator: "Manifold Finance", publisher: "Manifold Finance", @@ -73,24 +66,28 @@ export const metadata: Metadata = { apple: "/apple-touch-icon.png", }, manifest: "https://manifoldfinance.com/site.webmanifest", -}; +} export default function RootLayout({ children, }: { - children: React.ReactNode; + children: React.ReactNode }) { + //const pathname = usePathname() + //const isHomePage = pathname === "/" + return ( <html lang="en" className={`dark ${spaceGrotesk.variable} ${notoSans.variable}`}> - <body - className={`min-h-screen bg-background text-foreground flex flex-col ${notoSans.className}`}> + <body className={`min-h-screen bg-background text-foreground flex flex-col ${notoSans.className}`}> <ErrorBoundary> <Header /> - <main className="flex-grow pt-20">{children}</main> - <Footer /> + <LayoutWrapper> + <main className="flex-grow pt-20">{children}</main> + </LayoutWrapper> <CommandMenu /> </ErrorBoundary> </body> </html> - ); + ) } + diff --git a/app/page.tsx b/app/page.tsx index a2e2742..76af662 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,8 +1,8 @@ -import { BackgroundPaths } from "./components/background-paths"; +import { BackgroundPaths } from "./components/background-paths" export default function Page() { return ( - <div className="min-h-screen bg-[#141414] text-white flex flex-col"> + <div className="min-h-screen text-white flex flex-col"> <main className="flex-grow"> <BackgroundPaths title="Manifold Finance|" @@ -22,5 +22,6 @@ export default function Page() { /> </main> </div> - ); + ) } + diff --git a/app/products/captive-insurance/page.tsx b/app/products/captive-insurance/page.tsx index e94877c..6759786 100644 --- a/app/products/captive-insurance/page.tsx +++ b/app/products/captive-insurance/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths"; +import { BackgroundPaths } from "../../components/background-paths" export default function CaptiveInsurancePage() { return ( @@ -10,9 +10,8 @@ export default function CaptiveInsurancePage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Captive Insurance</h2> <p className="text-lg mb-6"> - Our Captive Insurance product offers tailored insurance solutions designed specifically - for blockchain and DeFi projects, providing robust protection against unique risks in the - crypto space. + Our Captive Insurance product offers tailored insurance solutions designed specifically for blockchain and + DeFi projects, providing robust protection against unique risks in the crypto space. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 mt-12"> <div className="bg-gray-800 p-6 rounded-lg"> @@ -37,30 +36,28 @@ export default function CaptiveInsurancePage() { <div className="mt-12"> <h3 className="text-2xl font-bold mb-4">How It Works</h3> <p className="text-lg mb-4"> - Our Captive Insurance solution leverages blockchain technology to provide transparent, - efficient, and automated insurance processes: + Our Captive Insurance solution leverages blockchain technology to provide transparent, efficient, and + automated insurance processes: </p> <ol className="list-decimal list-inside space-y-2 ml-4"> <li>Risk Assessment: We analyze your project's specific risks and vulnerabilities.</li> + <li>Custom Policy Creation: We design a tailored insurance policy to address your unique needs.</li> <li> - Custom Policy Creation: We design a tailored insurance policy to address your unique - needs. + Smart Contract Integration: Insurance policies are implemented as smart contracts for automated claims + processing. </li> <li> - Smart Contract Integration: Insurance policies are implemented as smart contracts for - automated claims processing. + Continuous Monitoring: Our systems continuously monitor for potential risks and automatically adjust + coverage as needed. </li> <li> - Continuous Monitoring: Our systems continuously monitor for potential risks and - automatically adjust coverage as needed. - </li> - <li> - Streamlined Claims: In the event of a covered incident, claims are processed quickly - and efficiently through our blockchain-based system. + Streamlined Claims: In the event of a covered incident, claims are processed quickly and efficiently + through our blockchain-based system. </li> </ol> </div> </main> </div> - ); + ) } + diff --git a/app/products/fold-staking/page.tsx b/app/products/fold-staking/page.tsx new file mode 100644 index 0000000..18cf3d5 --- /dev/null +++ b/app/products/fold-staking/page.tsx @@ -0,0 +1,66 @@ +import { BackgroundPaths } from "@/app/components/background-paths" +import { FeatureSection } from "@/app/components/feature-section" +import { Coins, Lock, BarChart, Zap } from "lucide-react" + +const foldStakingFeatures = [ + { + icon: Coins, + title: "Earn Rewards", + description: "Stake your FOLD tokens and earn competitive rewards.", + }, + { + icon: Lock, + title: "Secure Staking", + description: "Your staked tokens are protected by advanced security measures.", + }, + { + icon: BarChart, + title: "Performance Tracking", + description: "Monitor your staking performance with real-time analytics.", + }, + { + icon: Zap, + title: "Quick Withdrawals", + description: "Flexible withdrawal options with minimal waiting periods.", + }, +] + +export default function FoldStakingPage() { + return ( + <div className="min-h-screen bg-[#1616b4] text-white"> + <BackgroundPaths title="FOLD Staking|" subtitle="Maximize your returns by staking FOLD tokens" /> + <main className="container mx-auto px-4 py-12"> + <FeatureSection features={foldStakingFeatures} /> + + <section className="mt-16"> + <h2 className="text-3xl font-bold mb-6">Why Stake FOLD?</h2> + <p className="text-lg mb-6"> + Staking FOLD tokens allows you to earn rewards while supporting the Manifold Finance ecosystem. By + participating in FOLD staking, you contribute to the network's security and decentralization. + </p> + <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> + <div className="bg-[#c9b3f5] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Benefits</h3> + <ul className="list-disc list-inside space-y-2 text-[#b8faf6]"> + <li>Earn passive income through staking rewards</li> + <li>Participate in governance decisions</li> + <li>Contribute to network security</li> + <li>Potential for long-term token value appreciation</li> + </ul> + </div> + <div className="bg-[#c9b3f5] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">How to Start</h3> + <ol className="list-decimal list-inside space-y-2 text-[#b8faf6]"> + <li>Acquire FOLD tokens</li> + <li>Choose your preferred staking method</li> + <li>Lock your tokens in the staking contract</li> + <li>Start earning rewards</li> + </ol> + </div> + </div> + </section> + </main> + </div> + ) +} + diff --git a/app/products/meveth/page.tsx b/app/products/meveth/page.tsx new file mode 100644 index 0000000..2de57f9 --- /dev/null +++ b/app/products/meveth/page.tsx @@ -0,0 +1,67 @@ +import { BackgroundPaths } from "@/app/components/background-paths" +import { FeatureSection } from "@/app/components/feature-section" +import { Zap, TrendingUp, Shield, Coins } from "lucide-react" + +const mevETHFeatures = [ + { + icon: Zap, + title: "MEV Optimization", + description: "Maximize your staking rewards through advanced MEV strategies.", + }, + { + icon: TrendingUp, + title: "Enhanced Yields", + description: "Benefit from higher yields compared to traditional staking.", + }, + { + icon: Shield, + title: "Secure Staking", + description: "Your staked ETH is protected by robust security measures.", + }, + { + icon: Coins, + title: "Liquid Staking", + description: "Receive mevETH tokens while your ETH is staked.", + }, +] + +export default function MevETHPage() { + return ( + <div className="min-h-screen bg-[#1616b4] text-white"> + <BackgroundPaths title="mevETH|" subtitle="Maximized MEV rewards for Ethereum staking" /> + <main className="container mx-auto px-4 py-12"> + <FeatureSection features={mevETHFeatures} /> + + <section className="mt-16"> + <h2 className="text-3xl font-bold mb-6">What is mevETH?</h2> + <p className="text-lg mb-6"> + mevETH is a revolutionary staking solution that optimizes your Ethereum staking rewards by capturing Miner + Extractable Value (MEV). By staking with mevETH, you can potentially earn higher returns compared to + traditional staking methods. + </p> + <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> + <div className="bg-[#b8faf6] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Benefits of mevETH</h3> + <ul className="list-disc list-inside space-y-2 text-[#f0cdc2]"> + <li>Higher staking yields through MEV capture</li> + <li>Liquid staking tokens for improved capital efficiency</li> + <li>Participation in Ethereum network security</li> + <li>Transparent and fair reward distribution</li> + </ul> + </div> + <div className="bg-[#b8faf6] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">How to Get Started</h3> + <ol className="list-decimal list-inside space-y-2 text-[#f0cdc2]"> + <li>Connect your wallet to the mevETH platform</li> + <li>Deposit your ETH for staking</li> + <li>Receive mevETH tokens in return</li> + <li>Start earning optimized staking rewards</li> + </ol> + </div> + </div> + </section> + </main> + </div> + ) +} + diff --git a/app/products/securerpc/page.tsx b/app/products/securerpc/page.tsx new file mode 100644 index 0000000..ee4294e --- /dev/null +++ b/app/products/securerpc/page.tsx @@ -0,0 +1,66 @@ +import { BackgroundPaths } from "@/app/components/background-paths" +import { FeatureSection } from "@/app/components/feature-section" +import { Shield, Zap, Lock, Server } from "lucide-react" + +const secureRPCFeatures = [ + { + icon: Shield, + title: "Enhanced Security", + description: "Enterprise-grade security for all your RPC calls.", + }, + { + icon: Zap, + title: "High Performance", + description: "Lightning-fast response times and high throughput.", + }, + { + icon: Lock, + title: "Privacy Protection", + description: "Advanced measures to protect your transaction privacy.", + }, + { + icon: Server, + title: "Reliable Infrastructure", + description: "Robust and scalable infrastructure for 24/7 availability.", + }, +] + +export default function SecureRPCPage() { + return ( + <div className="min-h-screen bg-[#1616b4] text-white"> + <BackgroundPaths title="SecureRPC|" subtitle="Enterprise-grade RPC service for secure blockchain interactions" /> + <main className="container mx-auto px-4 py-12"> + <FeatureSection features={secureRPCFeatures} /> + + <section className="mt-16"> + <h2 className="text-3xl font-bold mb-6">Why Choose SecureRPC?</h2> + <p className="text-lg mb-6"> + SecureRPC provides a robust and secure infrastructure for all your blockchain interactions. Whether you're + building DApps or managing large-scale operations, our service ensures reliability and protection. + </p> + <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> + <div className="bg-[#88aaf1] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Key Features</h3> + <ul className="list-disc list-inside space-y-2 text-[#b8faf6]"> + <li>Multi-layer security protocols</li> + <li>Low-latency global network</li> + <li>Advanced DDoS protection</li> + <li>Customizable API endpoints</li> + </ul> + </div> + <div className="bg-[#88aaf1] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Use Cases</h3> + <ul className="list-disc list-inside space-y-2 text-[#b8faf6]"> + <li>DApp development and deployment</li> + <li>High-frequency trading operations</li> + <li>Blockchain data analytics</li> + <li>Enterprise blockchain solutions</li> + </ul> + </div> + </div> + </section> + </main> + </div> + ) +} + diff --git a/app/products/xga/page.tsx b/app/products/xga/page.tsx new file mode 100644 index 0000000..e355c60 --- /dev/null +++ b/app/products/xga/page.tsx @@ -0,0 +1,70 @@ +import { BackgroundPaths } from "@/app/components/background-paths" +import { FeatureSection } from "@/app/components/feature-section" +import { Globe, Users, Link, VoteIcon } from "lucide-react" + +const xgaFeatures = [ + { + icon: Globe, + title: "Cross-Chain Governance", + description: "Participate in governance across multiple blockchain networks.", + }, + { + icon: Users, + title: "Community-Driven", + description: "Empower your community with decentralized decision-making.", + }, + { + icon: Link, + title: "Interoperability", + description: "Seamless integration with various blockchain ecosystems.", + }, + { + icon: VoteIcon, + title: "Efficient Voting", + description: "Streamlined voting process for quick and secure decisions.", + }, +] + +export default function XGAPage() { + return ( + <div className="min-h-screen bg-[#1616b4] text-white"> + <BackgroundPaths + title="XGA: Cross-chain Governance Aggregator|" + subtitle="Empowering decentralized decision-making across blockchains" + /> + <main className="container mx-auto px-4 py-12"> + <FeatureSection features={xgaFeatures} /> + + <section className="mt-16"> + <h2 className="text-3xl font-bold mb-6">What is XGA?</h2> + <p className="text-lg mb-6"> + XGA (Cross-chain Governance Aggregator) is a revolutionary platform that enables seamless governance across + multiple blockchain networks. It provides a unified interface for participating in decentralized + decision-making processes. + </p> + <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> + <div className="bg-[#f0cdc2] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Key Benefits</h3> + <ul className="list-disc list-inside space-y-2 text-[#b8faf6]"> + <li>Unified governance across multiple chains</li> + <li>Increased community engagement</li> + <li>Enhanced transparency in decision-making</li> + <li>Reduced governance fragmentation</li> + </ul> + </div> + <div className="bg-[#f0cdc2] bg-opacity-20 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">How It Works</h3> + <ol className="list-decimal list-inside space-y-2 text-[#b8faf6]"> + <li>Connect your wallet to XGA</li> + <li>Browse active proposals across chains</li> + <li>Cast your votes securely</li> + <li>Track proposal outcomes in real-time</li> + </ol> + </div> + </div> + </section> + </main> + </div> + ) +} + diff --git a/app/solutions/auction-markets/page.tsx b/app/solutions/auction-markets/page.tsx index d97b829..9819c75 100644 --- a/app/solutions/auction-markets/page.tsx +++ b/app/solutions/auction-markets/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths"; +import { BackgroundPaths } from "../../components/background-paths" export default function AuctionMarketsPage() { return ( @@ -10,11 +10,12 @@ export default function AuctionMarketsPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Auction Markets</h2> <p className="text-lg mb-6"> - Our auction market solutions provide efficient and transparent mechanisms for - decentralized finance, optimizing value discovery and liquidity. + Our auction market solutions provide efficient and transparent mechanisms for decentralized finance, + optimizing value discovery and liquidity. </p> {/* Add more content here */} </main> </div> - ); + ) } + diff --git a/app/solutions/avs-operations/page.tsx b/app/solutions/avs-operations/page.tsx index ad30f0b..0fdea04 100644 --- a/app/solutions/avs-operations/page.tsx +++ b/app/solutions/avs-operations/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths"; +import { BackgroundPaths } from "../../components/background-paths" export default function AvsOperationsPage() { return ( @@ -10,11 +10,12 @@ export default function AvsOperationsPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">AVS Operations</h2> <p className="text-lg mb-6"> - Our AVS operations solutions help you streamline and optimize your Autonomous Validation - System for maximum efficiency and reliability. + Our AVS operations solutions help you streamline and optimize your Autonomous Validation System for maximum + efficiency and reliability. </p> {/* Add more content here */} </main> </div> - ); + ) } + diff --git a/app/solutions/hedging-execution/page.tsx b/app/solutions/hedging-execution/page.tsx index 9260b03..aceb6f5 100644 --- a/app/solutions/hedging-execution/page.tsx +++ b/app/solutions/hedging-execution/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths"; +import { BackgroundPaths } from "../../components/background-paths" export default function HedgingExecutionPage() { return ( @@ -10,8 +10,8 @@ export default function HedgingExecutionPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-8 text-center">Hedging and Execution</h2> <p className="text-base sm:text-lg mb-6 text-gray-300"> - Our advanced hedging and execution tools help you optimize your trading strategies and - manage risk effectively in the volatile crypto market. + Our advanced hedging and execution tools help you optimize your trading strategies and manage risk effectively + in the volatile crypto market. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 mt-12"> <div className="bg-gray-800 p-6 rounded-lg"> @@ -36,23 +36,19 @@ export default function HedgingExecutionPage() { <div className="mt-12"> <h3 className="text-xl sm:text-2xl font-bold mb-4">How It Works</h3> <p className="text-base sm:text-lg mb-4 text-gray-300"> - Our Hedging and Execution solution leverages advanced algorithms and real-time data to - optimize your trading strategies: + Our Hedging and Execution solution leverages advanced algorithms and real-time data to optimize your trading + strategies: </p> <ol className="list-decimal list-inside space-y-2 ml-4 text-gray-300"> <li>Market Analysis: Continuous monitoring of market conditions and trends.</li> <li>Strategy Formulation: Development of tailored hedging and execution strategies.</li> - <li> - Automated Execution: Implementation of strategies through our high-performance trading - engine. - </li> + <li>Automated Execution: Implementation of strategies through our high-performance trading engine.</li> <li>Risk Management: Real-time risk assessment and automatic adjustments.</li> - <li> - Performance Reporting: Comprehensive analytics and reporting on strategy performance. - </li> + <li>Performance Reporting: Comprehensive analytics and reporting on strategy performance.</li> </ol> </div> </main> </div> - ); + ) } + diff --git a/app/solutions/mev-relay-protection/page.tsx b/app/solutions/mev-relay-protection/page.tsx index 44c20c4..99916f9 100644 --- a/app/solutions/mev-relay-protection/page.tsx +++ b/app/solutions/mev-relay-protection/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths"; +import { BackgroundPaths } from "../../components/background-paths" export default function MevRelayProtectionPage() { return ( @@ -10,11 +10,12 @@ export default function MevRelayProtectionPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">MEV Relay and Protection</h2> <p className="text-lg mb-6"> - Our MEV relay and protection services help safeguard your transactions and maximize value - in the face of MEV extraction. + Our MEV relay and protection services help safeguard your transactions and maximize value in the face of MEV + extraction. </p> {/* Add more content here */} </main> </div> - ); + ) } + diff --git a/app/solutions/mev/page.tsx b/app/solutions/mev/page.tsx index 0ebb0c2..e6721bc 100644 --- a/app/solutions/mev/page.tsx +++ b/app/solutions/mev/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "../../components/background-paths"; -import { FeatureSection } from "../../components/feature-section"; -import { DollarSign, Zap, Shield, LineChart } from "lucide-react"; +import { BackgroundPaths } from "../../components/background-paths" +import { FeatureSection } from "../../components/feature-section" +import { DollarSign, Zap, Shield, LineChart } from "lucide-react" export default function MevPage() { const mevFeatures = [ @@ -24,7 +24,7 @@ export default function MevPage() { title: "MEV Analytics", description: "Detailed analytics and reporting of MEV activities.", }, - ]; + ] return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -37,5 +37,6 @@ export default function MevPage() { {/* Rest of the content remains the same */} </main> </div> - ); + ) } + diff --git a/app/solutions/page.tsx b/app/solutions/page.tsx index c18db46..ea0ba32 100644 --- a/app/solutions/page.tsx +++ b/app/solutions/page.tsx @@ -1,17 +1,15 @@ -import { BackgroundPaths } from "../components/background-paths"; -import { FeatureGrid } from "../components/feature-grid"; +import { BackgroundPaths } from "../components/background-paths" +import { FeatureGrid } from "../components/feature-grid" export default function SolutionsPage() { return ( <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths - title="Our Solutions|" - subtitle="Optimized infrastructure for the next generation of Ethereum" - /> + <BackgroundPaths title="Our Solutions|" subtitle="Optimized infrastructure for the next generation of Ethereum" /> <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Explore Our Solutions</h2> <FeatureGrid /> </main> </div> - ); + ) } + diff --git a/app/solutions/relay-protect/page.tsx b/app/solutions/relay-protect/page.tsx new file mode 100644 index 0000000..36230fe --- /dev/null +++ b/app/solutions/relay-protect/page.tsx @@ -0,0 +1,113 @@ +import { BackgroundPaths } from "../../components/background-paths" +import { FeatureSection } from "../../components/feature-section" +import { MEVProtectionComparison } from "../../components/mev-protection-comparison" +import { Shield, Zap, Lock, Eye } from "lucide-react" + +export default function RelayProtectPage() { + const relayProtectFeatures = [ + { + icon: Shield, + title: "MEV Protection", + description: "Safeguard your transactions against frontrunning and sandwich attacks.", + }, + { + icon: Zap, + title: "High-Performance Relay", + description: "Fast and reliable transaction relay to the Ethereum network.", + }, + { + icon: Lock, + title: "Transaction Privacy", + description: "Enhanced privacy features to protect your transaction details.", + }, + { + icon: Eye, + title: "Transparent Execution", + description: "Full visibility into transaction execution and MEV capture.", + }, + ] + + return ( + <div className="min-h-screen bg-blackA12 text-white"> + <BackgroundPaths + title="Relay+ Protect|" + subtitle="Advanced MEV protection and transaction privacy for Ethereum" + /> + <main className="container mx-auto px-4 py-12"> + <FeatureSection features={relayProtectFeatures} /> + + <section className="mt-12"> + <h2 className="text-3xl font-bold mb-6">How Relay+ Protect Works</h2> + <p className="text-lg mb-6"> + Relay+ Protect combines advanced MEV protection techniques with a high-performance relay network to ensure + your transactions are executed fairly and privately on the Ethereum network. + </p> + <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> + <div className="bg-blackA6 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Key Features</h3> + <ul className="list-disc list-inside space-y-2 text-mauveA11"> + <li>Real-time MEV detection and mitigation</li> + <li>Private mempool for sensitive transactions</li> + <li>Optimized transaction ordering</li> + <li>Transparent MEV redistribution</li> + </ul> + </div> + <div className="bg-blackA6 p-6 rounded-lg"> + <h3 className="text-xl font-semibold mb-4">Benefits</h3> + <ul className="list-disc list-inside space-y-2 text-mauveA11"> + <li>Reduced slippage on large trades</li> + <li>Enhanced transaction privacy</li> + <li>Lower risk of frontrunning</li> + <li>Improved overall trading performance</li> + </ul> + </div> + </div> + </section> + + <section className="mt-16"> + <h2 className="text-3xl font-bold mb-6">Comparing MEV Protection Solutions</h2> + <p className="text-lg mb-6"> + See how Relay+ Protect compares to other MEV protection solutions in the market. Our advanced architecture + and focus on privacy set us apart from the competition. + </p> + <MEVProtectionComparison /> + </section> + + <section className="mt-16"> + <h2 className="text-3xl font-bold mb-6">Why Choose Relay+ Protect?</h2> + <p className="text-lg mb-6"> + Relay+ Protect offers superior MEV protection through its unique architecture and focus on transaction + privacy. Here's why it stands out: + </p> + <ul className="list-disc list-inside space-y-4 text-lg text-mauveA11"> + <li> + <span className="text-white font-semibold">Complete Transaction Isolation:</span> Our private mempool + implementation ensures your transactions remain fully private until validator commitment, minimizing the + risk of frontrunning and other MEV attacks. + </li> + <li> + <span className="text-white font-semibold">Highest Market Impact:</span> Relay+ Protect reduces overall + MEV extraction by 85-95%, significantly outperforming other solutions in the market. + </li> + <li> + <span className="text-white font-semibold">User-Centric Economic Model:</span> Users retain 70-80% of MEV + protection benefits, ensuring that the value captured from MEV protection primarily benefits you, not + intermediaries. + </li> + <li> + <span className="text-white font-semibold">Scalability and Efficiency:</span> Our solution is highly + scalable with minimal bottlenecks and low network overhead, ensuring consistent performance as the network + grows. + </li> + <li> + <span className="text-white font-semibold">Future-Proof Design:</span> With a clear upgrade path and + backward compatibility, Relay+ Protect is designed to evolve with the Ethereum ecosystem while maintaining + its core benefits. + </li> + </ul> + </section> + </main> + </div> + ) +} + diff --git a/app/solutions/restaking/page.tsx b/app/solutions/restaking/page.tsx index 5623125..f82fd7d 100644 --- a/app/solutions/restaking/page.tsx +++ b/app/solutions/restaking/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "../../components/background-paths"; -import { FeatureSection } from "../../components/feature-section"; -import { Shield, Lock, Repeat, BarChart3 } from "lucide-react"; +import { BackgroundPaths } from "../../components/background-paths" +import { FeatureSection } from "../../components/feature-section" +import { Shield, Lock, Repeat, BarChart3 } from "lucide-react" export default function RestakingPage() { const restakingFeatures = [ @@ -24,7 +24,7 @@ export default function RestakingPage() { title: "Yield Optimization", description: "Maximize returns through optimized restaking strategies.", }, - ]; + ] return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -58,5 +58,6 @@ export default function RestakingPage() { </div> */} </main> </div> - ); + ) } + diff --git a/app/solutions/securerpc/page.tsx b/app/solutions/securerpc/page.tsx deleted file mode 100644 index ddde6a7..0000000 --- a/app/solutions/securerpc/page.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { BackgroundPaths } from "../../components/background-paths"; -import { FeatureSection } from "../../components/feature-section"; -import { Server, Shield, Zap, LineChart } from "lucide-react"; -import { APIEndpoint } from "../../components/api-endpoint"; - -export default function SecureRpcPage() { - const secureRpcFeatures = [ - { - icon: Server, - title: "Enterprise SecureRPC", - description: "Stable and reliable blockchain interactions for your applications.", - }, - { - icon: Shield, - title: "Enhanced Security", - description: "Advanced security measures to protect your RPC endpoints.", - }, - { - icon: Zap, - title: "High Performance", - description: "Lightning-fast response times and minimal latency.", - }, - { - icon: LineChart, - title: "Scalable Infrastructure", - description: "Enterprise-grade infrastructure that scales with your needs.", - }, - ]; - - return ( - <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths - title="Enterprise SecureRPC|" - subtitle="Stable and reliable blockchain interactions for your applications" - /> - <main className="container mx-auto px-4 py-12"> - <FeatureSection features={secureRpcFeatures} /> - <div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8"> - <div className="bg-blackA6 p-6 rounded-lg"> - <h3 className="text-xl font-semibold mb-4">Features</h3> - <ul className="list-disc list-inside text-mauveA11"> - <li>High-performance RPC endpoints</li> - <li>Advanced security measures</li> - <li>Load balancing and failover</li> - <li>Customizable rate limiting</li> - </ul> - </div> - <div className="bg-blackA6 p-6 rounded-lg"> - <h3 className="text-xl font-semibold mb-4">Benefits</h3> - <ul className="list-disc list-inside text-mauveA11"> - <li>Ensure reliable blockchain interactions</li> - <li>Protect against malicious attacks</li> - <li>Scale your dApp infrastructure effortlessly</li> - <li>Reduce operational costs and complexity</li> - </ul> - </div> - </div> - <APIEndpoint /> - </main> - </div> - ); -} diff --git a/app/solutions/staking/page.tsx b/app/solutions/staking/page.tsx index 722f31b..940ac5b 100644 --- a/app/solutions/staking/page.tsx +++ b/app/solutions/staking/page.tsx @@ -1,10 +1,10 @@ -import { BackgroundPaths } from "../../components/background-paths"; -import { FeatureSection } from "../../components/feature-section"; -import { LSTComparisonTable } from "../../components/lst-comparison-table"; -import { LSTAPYGraph } from "../../components/lst-apy-graph"; -import { LSTAPYTrendGraph } from "../../components/lst-apy-trend-graph"; -import { Zap, Shield, LineChart, Server } from "lucide-react"; -import { TooltipProvider } from "@/components/ui/tooltip"; +import { BackgroundPaths } from "../../components/background-paths" +import { FeatureSection } from "../../components/feature-section" +import { LSTComparisonTable } from "../../components/lst-comparison-table" +import { LSTAPYGraph } from "../../components/lst-apy-graph" +import { LSTAPYTrendGraph } from "../../components/lst-apy-trend-graph" +import { Zap, Shield, LineChart, Server } from "lucide-react" +import { TooltipProvider } from "@/components/ui/tooltip" export default function StakingPage() { const stakingFeatures = [ @@ -28,7 +28,7 @@ export default function StakingPage() { title: "Validator Management", description: "Streamlined validator setup and maintenance tools.", }, - ]; + ] return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -60,9 +60,7 @@ export default function StakingPage() { </section> <section className="mt-12 md:mt-16"> - <h2 className="text-2xl md:text-3xl font-bold mb-4 md:mb-8"> - Why Choose Manifold Finance for Staking? - </h2> + <h2 className="text-2xl md:text-3xl font-bold mb-4 md:mb-8">Why Choose Manifold Finance for Staking?</h2> <div className="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8"> <div className="bg-blackA6 p-4 md:p-6 rounded-lg"> <h3 className="text-xl font-semibold mb-4">Features</h3> @@ -88,5 +86,6 @@ export default function StakingPage() { </section> </main> </div> - ); + ) } + diff --git a/app/technology/page.tsx b/app/technology/page.tsx index abc80cb..8493e8b 100644 --- a/app/technology/page.tsx +++ b/app/technology/page.tsx @@ -1,20 +1,15 @@ -import { BackgroundPaths } from "../components/background-paths"; +import { BackgroundPaths } from "../components/background-paths" export default function TechnologyPage() { return ( <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths - title="Our Technology|" - subtitle="Learn about the technology powering our solutions" - /> + <BackgroundPaths title="Our Technology|" subtitle="Learn about the technology powering our solutions" /> <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Cutting-Edge Technology</h2> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-blackA6 p-6 rounded-lg"> <h3 className="text-xl font-semibold mb-4">High-Performance Staking</h3> - <p className="text-mauveA11"> - Description of the technology behind our staking solutions... - </p> + <p className="text-mauveA11">Description of the technology behind our staking solutions...</p> </div> <div className="bg-blackA6 p-6 rounded-lg"> <h3 className="text-xl font-semibold mb-4">MEV Optimization</h3> @@ -31,5 +26,6 @@ export default function TechnologyPage() { </div> </main> </div> - ); + ) } + diff --git a/bun.lockb b/bun.lockb old mode 100755 new mode 100644 diff --git a/components/icons.tsx b/components/icons.tsx index 04bc958..b4728e2 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -1,12 +1,6 @@ -import { - type LightbulbIcon as LucideProps, - Moon, - SunMedium, - Twitter, - type LucideIcon, -} from "lucide-react"; +import { type LightbulbIcon as LucideProps, Moon, SunMedium, Twitter, type LucideIcon } from "lucide-react" -export type Icon = LucideIcon; +export type Icon = LucideIcon export const Icons = { sun: SunMedium, @@ -20,4 +14,5 @@ export const Icons = { /> </svg> ), -}; +} + diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx index 3bc117a..55c2f6e 100644 --- a/components/theme-provider.tsx +++ b/components/theme-provider.tsx @@ -1,8 +1,11 @@ -"use client"; +'use client' -import * as React from "react"; -import { ThemeProvider as NextThemesProvider, type ThemeProviderProps } from "next-themes"; +import * as React from 'react' +import { + ThemeProvider as NextThemesProvider, + type ThemeProviderProps, +} from 'next-themes' export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return <NextThemesProvider {...props}>{children}</NextThemesProvider>; + return <NextThemesProvider {...props}>{children}</NextThemesProvider> } diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx index 7f5d4c8..24c788c 100644 --- a/components/ui/accordion.tsx +++ b/components/ui/accordion.tsx @@ -1,20 +1,24 @@ -"use client"; +"use client" -import * as React from "react"; -import * as AccordionPrimitive from "@radix-ui/react-accordion"; -import { ChevronDown } from "lucide-react"; +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const Accordion = AccordionPrimitive.Root; +const Accordion = AccordionPrimitive.Root const AccordionItem = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Item>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> >(({ className, ...props }, ref) => ( - <AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} /> -)); -AccordionItem.displayName = "AccordionItem"; + <AccordionPrimitive.Item + ref={ref} + className={cn("border-b", className)} + {...props} + /> +)) +AccordionItem.displayName = "AccordionItem" const AccordionTrigger = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Trigger>, @@ -25,15 +29,16 @@ const AccordionTrigger = React.forwardRef< ref={ref} className={cn( "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180", - className, + className )} - {...props}> + {...props} + > {children} <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> </AccordionPrimitive.Trigger> </AccordionPrimitive.Header> -)); -AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName const AccordionContent = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Content>, @@ -42,11 +47,12 @@ const AccordionContent = React.forwardRef< <AccordionPrimitive.Content ref={ref} className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" - {...props}> + {...props} + > <div className={cn("pb-4 pt-0", className)}>{children}</div> </AccordionPrimitive.Content> -)); +)) -AccordionContent.displayName = AccordionPrimitive.Content.displayName; +AccordionContent.displayName = AccordionPrimitive.Content.displayName -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx index a7cbc9a..25e7b47 100644 --- a/components/ui/alert-dialog.tsx +++ b/components/ui/alert-dialog.tsx @@ -1,16 +1,16 @@ -"use client"; +"use client" -import * as React from "react"; -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" -import { cn } from "@/lib/utils"; -import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" -const AlertDialog = AlertDialogPrimitive.Root; +const AlertDialog = AlertDialogPrimitive.Root -const AlertDialogTrigger = AlertDialogPrimitive.Trigger; +const AlertDialogTrigger = AlertDialogPrimitive.Trigger -const AlertDialogPortal = AlertDialogPrimitive.Portal; +const AlertDialogPortal = AlertDialogPrimitive.Portal const AlertDialogOverlay = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Overlay>, @@ -19,13 +19,13 @@ const AlertDialogOverlay = React.forwardRef< <AlertDialogPrimitive.Overlay className={cn( "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className, + className )} {...props} ref={ref} /> -)); -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName const AlertDialogContent = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Content>, @@ -37,26 +37,41 @@ const AlertDialogContent = React.forwardRef< ref={ref} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", - className, + className )} {...props} /> </AlertDialogPortal> -)); -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName -const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} /> -); -AlertDialogHeader.displayName = "AlertDialogHeader"; +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) => ( + <div + className={cn( + "flex flex-col space-y-2 text-center sm:text-left", + className + )} + {...props} + /> +) +AlertDialogHeader.displayName = "AlertDialogHeader" -const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) => ( <div - className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} + className={cn( + "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", + className + )} {...props} /> -); -AlertDialogFooter.displayName = "AlertDialogFooter"; +) +AlertDialogFooter.displayName = "AlertDialogFooter" const AlertDialogTitle = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Title>, @@ -67,8 +82,8 @@ const AlertDialogTitle = React.forwardRef< className={cn("text-lg font-semibold", className)} {...props} /> -)); -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName const AlertDialogDescription = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Description>, @@ -79,16 +94,21 @@ const AlertDialogDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)); -AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName const AlertDialogAction = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Action>, React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> >(({ className, ...props }, ref) => ( - <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} /> -)); -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; + <AlertDialogPrimitive.Action + ref={ref} + className={cn(buttonVariants(), className)} + {...props} + /> +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName const AlertDialogCancel = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Cancel>, @@ -96,11 +116,15 @@ const AlertDialogCancel = React.forwardRef< >(({ className, ...props }, ref) => ( <AlertDialogPrimitive.Cancel ref={ref} - className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)} + className={cn( + buttonVariants({ variant: "outline" }), + "mt-2 sm:mt-0", + className + )} {...props} /> -)); -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName export { AlertDialog, @@ -114,4 +138,4 @@ export { AlertDialogDescription, AlertDialogAction, AlertDialogCancel, -}; +} diff --git a/components/ui/alert.tsx b/components/ui/alert.tsx index bc1429c..41fa7e0 100644 --- a/components/ui/alert.tsx +++ b/components/ui/alert.tsx @@ -1,7 +1,7 @@ -import * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const alertVariants = cva( "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", @@ -16,34 +16,44 @@ const alertVariants = cva( defaultVariants: { variant: "default", }, - }, -); + } +) const Alert = React.forwardRef< HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants> >(({ className, variant, ...props }, ref) => ( - <div ref={ref} role="alert" className={cn(alertVariants({ variant }), className)} {...props} /> -)); -Alert.displayName = "Alert"; + <div + ref={ref} + role="alert" + className={cn(alertVariants({ variant }), className)} + {...props} + /> +)) +Alert.displayName = "Alert" -const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>( - ({ className, ...props }, ref) => ( - <h5 - ref={ref} - className={cn("mb-1 font-medium leading-none tracking-tight", className)} - {...props} - /> - ), -); -AlertTitle.displayName = "AlertTitle"; +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes<HTMLHeadingElement> +>(({ className, ...props }, ref) => ( + <h5 + ref={ref} + className={cn("mb-1 font-medium leading-none tracking-tight", className)} + {...props} + /> +)) +AlertTitle.displayName = "AlertTitle" const AlertDescription = React.forwardRef< HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement> >(({ className, ...props }, ref) => ( - <div ref={ref} className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} /> -)); -AlertDescription.displayName = "AlertDescription"; + <div + ref={ref} + className={cn("text-sm [&_p]:leading-relaxed", className)} + {...props} + /> +)) +AlertDescription.displayName = "AlertDescription" -export { Alert, AlertTitle, AlertDescription }; +export { Alert, AlertTitle, AlertDescription } diff --git a/components/ui/aspect-ratio.tsx b/components/ui/aspect-ratio.tsx index 359bc94..d6a5226 100644 --- a/components/ui/aspect-ratio.tsx +++ b/components/ui/aspect-ratio.tsx @@ -1,7 +1,7 @@ -"use client"; +"use client" -import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" -const AspectRatio = AspectRatioPrimitive.Root; +const AspectRatio = AspectRatioPrimitive.Root -export { AspectRatio }; +export { AspectRatio } diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx index 7904926..51e507b 100644 --- a/components/ui/avatar.tsx +++ b/components/ui/avatar.tsx @@ -1,9 +1,9 @@ -"use client"; +"use client" -import * as React from "react"; -import * as AvatarPrimitive from "@radix-ui/react-avatar"; +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Avatar = React.forwardRef< React.ElementRef<typeof AvatarPrimitive.Root>, @@ -11,11 +11,14 @@ const Avatar = React.forwardRef< >(({ className, ...props }, ref) => ( <AvatarPrimitive.Root ref={ref} - className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)} + className={cn( + "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", + className + )} {...props} /> -)); -Avatar.displayName = AvatarPrimitive.Root.displayName; +)) +Avatar.displayName = AvatarPrimitive.Root.displayName const AvatarImage = React.forwardRef< React.ElementRef<typeof AvatarPrimitive.Image>, @@ -26,8 +29,8 @@ const AvatarImage = React.forwardRef< className={cn("aspect-square h-full w-full", className)} {...props} /> -)); -AvatarImage.displayName = AvatarPrimitive.Image.displayName; +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName const AvatarFallback = React.forwardRef< React.ElementRef<typeof AvatarPrimitive.Fallback>, @@ -37,11 +40,11 @@ const AvatarFallback = React.forwardRef< ref={ref} className={cn( "flex h-full w-full items-center justify-center rounded-full bg-muted", - className, + className )} {...props} /> -)); -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName -export { Avatar, AvatarImage, AvatarFallback }; +export { Avatar, AvatarImage, AvatarFallback } diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx index 9ab4cc0..480a6ee 100644 --- a/components/ui/badge.tsx +++ b/components/ui/badge.tsx @@ -1,6 +1,6 @@ -import type * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils"; +import type * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "@/lib/utils" const badgeVariants = cva( "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", @@ -30,14 +30,13 @@ const badgeVariants = cva( radius: "default", }, }, -); +) -export interface BadgeProps - extends React.HTMLAttributes<HTMLDivElement>, - VariantProps<typeof badgeVariants> {} +export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {} function Badge({ className, variant, color, radius, ...props }: BadgeProps) { - return <div className={cn(badgeVariants({ variant, color, radius }), className)} {...props} />; + return <div className={cn(badgeVariants({ variant, color, radius }), className)} {...props} /> } -export { Badge, badgeVariants }; +export { Badge, badgeVariants } + diff --git a/components/ui/breadcrumb.tsx b/components/ui/breadcrumb.tsx index bcdd0a1..60e6c96 100644 --- a/components/ui/breadcrumb.tsx +++ b/components/ui/breadcrumb.tsx @@ -1,45 +1,51 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { ChevronRight, MoreHorizontal } from "lucide-react"; +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Breadcrumb = React.forwardRef< HTMLElement, React.ComponentPropsWithoutRef<"nav"> & { - separator?: React.ReactNode; + separator?: React.ReactNode } ->(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />); -Breadcrumb.displayName = "Breadcrumb"; +>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />) +Breadcrumb.displayName = "Breadcrumb" -const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<"ol">>( - ({ className, ...props }, ref) => ( - <ol - ref={ref} - className={cn( - "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", - className, - )} - {...props} - /> - ), -); -BreadcrumbList.displayName = "BreadcrumbList"; +const BreadcrumbList = React.forwardRef< + HTMLOListElement, + React.ComponentPropsWithoutRef<"ol"> +>(({ className, ...props }, ref) => ( + <ol + ref={ref} + className={cn( + "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", + className + )} + {...props} + /> +)) +BreadcrumbList.displayName = "BreadcrumbList" -const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<"li">>( - ({ className, ...props }, ref) => ( - <li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} /> - ), -); -BreadcrumbItem.displayName = "BreadcrumbItem"; +const BreadcrumbItem = React.forwardRef< + HTMLLIElement, + React.ComponentPropsWithoutRef<"li"> +>(({ className, ...props }, ref) => ( + <li + ref={ref} + className={cn("inline-flex items-center gap-1.5", className)} + {...props} + /> +)) +BreadcrumbItem.displayName = "BreadcrumbItem" const BreadcrumbLink = React.forwardRef< HTMLAnchorElement, React.ComponentPropsWithoutRef<"a"> & { - asChild?: boolean; + asChild?: boolean } >(({ asChild, className, ...props }, ref) => { - const Comp = asChild ? Slot : "a"; + const Comp = asChild ? Slot : "a" return ( <Comp @@ -47,46 +53,56 @@ const BreadcrumbLink = React.forwardRef< className={cn("transition-colors hover:text-foreground", className)} {...props} /> - ); -}); -BreadcrumbLink.displayName = "BreadcrumbLink"; + ) +}) +BreadcrumbLink.displayName = "BreadcrumbLink" -const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<"span">>( - ({ className, ...props }, ref) => ( - <span - ref={ref} - role="link" - aria-disabled="true" - aria-current="page" - className={cn("font-normal text-foreground", className)} - {...props} - /> - ), -); -BreadcrumbPage.displayName = "BreadcrumbPage"; +const BreadcrumbPage = React.forwardRef< + HTMLSpanElement, + React.ComponentPropsWithoutRef<"span"> +>(({ className, ...props }, ref) => ( + <span + ref={ref} + role="link" + aria-disabled="true" + aria-current="page" + className={cn("font-normal text-foreground", className)} + {...props} + /> +)) +BreadcrumbPage.displayName = "BreadcrumbPage" -const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => ( +const BreadcrumbSeparator = ({ + children, + className, + ...props +}: React.ComponentProps<"li">) => ( <li role="presentation" aria-hidden="true" className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)} - {...props}> + {...props} + > {children ?? <ChevronRight />} </li> -); -BreadcrumbSeparator.displayName = "BreadcrumbSeparator"; +) +BreadcrumbSeparator.displayName = "BreadcrumbSeparator" -const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => ( +const BreadcrumbEllipsis = ({ + className, + ...props +}: React.ComponentProps<"span">) => ( <span role="presentation" aria-hidden="true" className={cn("flex h-9 w-9 items-center justify-center", className)} - {...props}> + {...props} + > <MoreHorizontal className="h-4 w-4" /> <span className="sr-only">More</span> </span> -); -BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"; +) +BreadcrumbEllipsis.displayName = "BreadcrumbElipssis" export { Breadcrumb, @@ -96,4 +112,4 @@ export { BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis, -}; +} diff --git a/components/ui/button.tsx b/components/ui/button.tsx index 3176a6d..108dd01 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -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 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", @@ -28,22 +28,21 @@ const buttonVariants = cva( 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"; - return ( - <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> - ); + 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 }; diff --git a/components/ui/calendar.tsx b/components/ui/calendar.tsx index 87a22d9..61d2b45 100644 --- a/components/ui/calendar.tsx +++ b/components/ui/calendar.tsx @@ -1,15 +1,20 @@ -"use client"; +"use client" -import * as React from "react"; -import { ChevronLeft, ChevronRight } from "lucide-react"; -import { DayPicker } from "react-day-picker"; +import * as React from "react" +import { ChevronLeft, ChevronRight } from "lucide-react" +import { DayPicker } from "react-day-picker" -import { cn } from "@/lib/utils"; -import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" -export type CalendarProps = React.ComponentProps<typeof DayPicker>; +export type CalendarProps = React.ComponentProps<typeof DayPicker> -function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { return ( <DayPicker showOutsideDays={showOutsideDays} @@ -22,18 +27,19 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C nav: "space-x-1 flex items-center", nav_button: cn( buttonVariants({ variant: "outline" }), - "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100", + "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100" ), nav_button_previous: "absolute left-1", nav_button_next: "absolute right-1", table: "w-full border-collapse space-y-1", head_row: "flex", - head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", + head_cell: + "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", row: "flex w-full mt-2", cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20", day: cn( buttonVariants({ variant: "ghost" }), - "h-9 w-9 p-0 font-normal aria-selected:opacity-100", + "h-9 w-9 p-0 font-normal aria-selected:opacity-100" ), day_range_end: "day-range-end", day_selected: @@ -42,7 +48,8 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C day_outside: "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground", day_disabled: "text-muted-foreground opacity-50", - day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground", + day_range_middle: + "aria-selected:bg-accent aria-selected:text-accent-foreground", day_hidden: "invisible", ...classNames, }} @@ -52,8 +59,8 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C }} {...props} /> - ); + ) } -Calendar.displayName = "Calendar"; +Calendar.displayName = "Calendar" -export { Calendar }; +export { Calendar } diff --git a/components/ui/card.tsx b/components/ui/card.tsx index 117feb7..0906be5 100644 --- a/components/ui/card.tsx +++ b/components/ui/card.tsx @@ -1,56 +1,44 @@ -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, React.HTMLAttributes<HTMLDivElement>>( - ({ className, ...props }, ref) => ( - <div - ref={ref} - className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} - {...props} - /> - ), -); -Card.displayName = "Card"; +const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => ( + <div ref={ref} className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} {...props} /> +)) +Card.displayName = "Card" const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} /> ), -); -CardHeader.displayName = "CardHeader"; +) +CardHeader.displayName = "CardHeader" const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>( ({ className, ...props }, ref) => ( - <h3 - ref={ref} - className={cn("text-2xl font-semibold leading-none tracking-tight", className)} - {...props} - /> + <h3 ref={ref} className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} /> ), -); -CardTitle.displayName = "CardTitle"; +) +CardTitle.displayName = "CardTitle" -const CardDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes<HTMLParagraphElement> ->(({ className, ...props }, ref) => ( - <p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> -)); -CardDescription.displayName = "CardDescription"; - -const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( +const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>( ({ className, ...props }, ref) => ( - <div ref={ref} className={cn("p-6 pt-0", className)} {...props} /> + <p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> ), -); -CardContent.displayName = "CardContent"; +) +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" const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} 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 }; diff --git a/components/ui/carousel.tsx b/components/ui/carousel.tsx index 50f3511..ec505d0 100644 --- a/components/ui/carousel.tsx +++ b/components/ui/carousel.tsx @@ -1,232 +1,256 @@ -"use client"; +"use client" -import * as React from "react"; -import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react"; -import { ArrowLeft, ArrowRight } from "lucide-react"; +import * as React from "react" +import useEmblaCarousel, { + type UseEmblaCarouselType, +} from "embla-carousel-react" +import { ArrowLeft, ArrowRight } from "lucide-react" -import { cn } from "@/lib/utils"; -import { Button } from "@/components/ui/button"; +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" -type CarouselApi = UseEmblaCarouselType[1]; -type UseCarouselParameters = Parameters<typeof useEmblaCarousel>; -type CarouselOptions = UseCarouselParameters[0]; -type CarouselPlugin = UseCarouselParameters[1]; +type CarouselApi = UseEmblaCarouselType[1] +type UseCarouselParameters = Parameters<typeof useEmblaCarousel> +type CarouselOptions = UseCarouselParameters[0] +type CarouselPlugin = UseCarouselParameters[1] type CarouselProps = { - opts?: CarouselOptions; - plugins?: CarouselPlugin; - orientation?: "horizontal" | "vertical"; - setApi?: (api: CarouselApi) => void; -}; + opts?: CarouselOptions + plugins?: CarouselPlugin + orientation?: "horizontal" | "vertical" + setApi?: (api: CarouselApi) => void +} type CarouselContextProps = { - carouselRef: ReturnType<typeof useEmblaCarousel>[0]; - api: ReturnType<typeof useEmblaCarousel>[1]; - scrollPrev: () => void; - scrollNext: () => void; - canScrollPrev: boolean; - canScrollNext: boolean; -} & CarouselProps; + carouselRef: ReturnType<typeof useEmblaCarousel>[0] + api: ReturnType<typeof useEmblaCarousel>[1] + scrollPrev: () => void + scrollNext: () => void + canScrollPrev: boolean + canScrollNext: boolean +} & CarouselProps -const CarouselContext = React.createContext<CarouselContextProps | null>(null); +const CarouselContext = React.createContext<CarouselContextProps | null>(null) function useCarousel() { - const context = React.useContext(CarouselContext); + const context = React.useContext(CarouselContext) if (!context) { - throw new Error("useCarousel must be used within a <Carousel />"); + throw new Error("useCarousel must be used within a <Carousel />") } - return context; + return context } const Carousel = React.forwardRef< HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & CarouselProps ->(({ orientation = "horizontal", opts, setApi, plugins, className, children, ...props }, ref) => { - const [carouselRef, api] = useEmblaCarousel( +>( + ( { - ...opts, - axis: orientation === "horizontal" ? "x" : "y", + orientation = "horizontal", + opts, + setApi, + plugins, + className, + children, + ...props }, - plugins, - ); - const [canScrollPrev, setCanScrollPrev] = React.useState(false); - const [canScrollNext, setCanScrollNext] = React.useState(false); - - const onSelect = React.useCallback((api: CarouselApi) => { - if (!api) { - return; - } - - setCanScrollPrev(api.canScrollPrev()); - setCanScrollNext(api.canScrollNext()); - }, []); - - const scrollPrev = React.useCallback(() => { - api?.scrollPrev(); - }, [api]); - - const scrollNext = React.useCallback(() => { - api?.scrollNext(); - }, [api]); - - const handleKeyDown = React.useCallback( - (event: React.KeyboardEvent<HTMLDivElement>) => { - if (event.key === "ArrowLeft") { - event.preventDefault(); - scrollPrev(); - } else if (event.key === "ArrowRight") { - event.preventDefault(); - scrollNext(); + ref + ) => { + const [carouselRef, api] = useEmblaCarousel( + { + ...opts, + axis: orientation === "horizontal" ? "x" : "y", + }, + plugins + ) + const [canScrollPrev, setCanScrollPrev] = React.useState(false) + const [canScrollNext, setCanScrollNext] = React.useState(false) + + const onSelect = React.useCallback((api: CarouselApi) => { + if (!api) { + return } - }, - [scrollPrev, scrollNext], - ); - React.useEffect(() => { - if (!api || !setApi) { - return; - } + setCanScrollPrev(api.canScrollPrev()) + setCanScrollNext(api.canScrollNext()) + }, []) + + const scrollPrev = React.useCallback(() => { + api?.scrollPrev() + }, [api]) - setApi(api); - }, [api, setApi]); + const scrollNext = React.useCallback(() => { + api?.scrollNext() + }, [api]) - React.useEffect(() => { - if (!api) { - return; - } + const handleKeyDown = React.useCallback( + (event: React.KeyboardEvent<HTMLDivElement>) => { + if (event.key === "ArrowLeft") { + event.preventDefault() + scrollPrev() + } else if (event.key === "ArrowRight") { + event.preventDefault() + scrollNext() + } + }, + [scrollPrev, scrollNext] + ) - onSelect(api); - api.on("reInit", onSelect); - api.on("select", onSelect); + React.useEffect(() => { + if (!api || !setApi) { + return + } - return () => { - api?.off("select", onSelect); - }; - }, [api, onSelect]); + setApi(api) + }, [api, setApi]) - return ( - <CarouselContext.Provider - value={{ - carouselRef, - api: api, - opts, - orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), - scrollPrev, - scrollNext, - canScrollPrev, - canScrollNext, - }}> - <div - ref={ref} - onKeyDownCapture={handleKeyDown} - className={cn("relative", className)} - role="region" - aria-roledescription="carousel" - {...props}> - {children} - </div> - </CarouselContext.Provider> - ); -}); -Carousel.displayName = "Carousel"; - -const CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( - ({ className, ...props }, ref) => { - const { carouselRef, orientation } = useCarousel(); + React.useEffect(() => { + if (!api) { + return + } + + onSelect(api) + api.on("reInit", onSelect) + api.on("select", onSelect) + + return () => { + api?.off("select", onSelect) + } + }, [api, onSelect]) return ( - <div ref={carouselRef} className="overflow-hidden"> + <CarouselContext.Provider + value={{ + carouselRef, + api: api, + opts, + orientation: + orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), + scrollPrev, + scrollNext, + canScrollPrev, + canScrollNext, + }} + > <div ref={ref} - className={cn( - "flex", - orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", - className, - )} + onKeyDownCapture={handleKeyDown} + className={cn("relative", className)} + role="region" + aria-roledescription="carousel" {...props} - /> - </div> - ); - }, -); -CarouselContent.displayName = "CarouselContent"; + > + {children} + </div> + </CarouselContext.Provider> + ) + } +) +Carousel.displayName = "Carousel" -const CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( - ({ className, ...props }, ref) => { - const { orientation } = useCarousel(); +const CarouselContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => { + const { carouselRef, orientation } = useCarousel() - return ( + return ( + <div ref={carouselRef} className="overflow-hidden"> <div ref={ref} - role="group" - aria-roledescription="slide" className={cn( - "min-w-0 shrink-0 grow-0 basis-full", - orientation === "horizontal" ? "pl-4" : "pt-4", - className, + "flex", + orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", + className )} {...props} /> - ); - }, -); -CarouselItem.displayName = "CarouselItem"; + </div> + ) +}) +CarouselContent.displayName = "CarouselContent" -const CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>( - ({ className, variant = "outline", size = "icon", ...props }, ref) => { - const { orientation, scrollPrev, canScrollPrev } = useCarousel(); +const CarouselItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => { + const { orientation } = useCarousel() - return ( - <Button - ref={ref} - variant={variant} - size={size} - className={cn( - "absolute h-8 w-8 rounded-full", - orientation === "horizontal" - ? "-left-12 top-1/2 -translate-y-1/2" - : "-top-12 left-1/2 -translate-x-1/2 rotate-90", - className, - )} - disabled={!canScrollPrev} - onClick={scrollPrev} - {...props}> - <ArrowLeft className="h-4 w-4" /> - <span className="sr-only">Previous slide</span> - </Button> - ); - }, -); -CarouselPrevious.displayName = "CarouselPrevious"; - -const CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>( - ({ className, variant = "outline", size = "icon", ...props }, ref) => { - const { orientation, scrollNext, canScrollNext } = useCarousel(); + return ( + <div + ref={ref} + role="group" + aria-roledescription="slide" + className={cn( + "min-w-0 shrink-0 grow-0 basis-full", + orientation === "horizontal" ? "pl-4" : "pt-4", + className + )} + {...props} + /> + ) +}) +CarouselItem.displayName = "CarouselItem" - return ( - <Button - ref={ref} - variant={variant} - size={size} - className={cn( - "absolute h-8 w-8 rounded-full", - orientation === "horizontal" - ? "-right-12 top-1/2 -translate-y-1/2" - : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", - className, - )} - disabled={!canScrollNext} - onClick={scrollNext} - {...props}> - <ArrowRight className="h-4 w-4" /> - <span className="sr-only">Next slide</span> - </Button> - ); - }, -); -CarouselNext.displayName = "CarouselNext"; +const CarouselPrevious = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<typeof Button> +>(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollPrev, canScrollPrev } = useCarousel() + + return ( + <Button + ref={ref} + variant={variant} + size={size} + className={cn( + "absolute h-8 w-8 rounded-full", + orientation === "horizontal" + ? "-left-12 top-1/2 -translate-y-1/2" + : "-top-12 left-1/2 -translate-x-1/2 rotate-90", + className + )} + disabled={!canScrollPrev} + onClick={scrollPrev} + {...props} + > + <ArrowLeft className="h-4 w-4" /> + <span className="sr-only">Previous slide</span> + </Button> + ) +}) +CarouselPrevious.displayName = "CarouselPrevious" + +const CarouselNext = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<typeof Button> +>(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + <Button + ref={ref} + variant={variant} + size={size} + className={cn( + "absolute h-8 w-8 rounded-full", + orientation === "horizontal" + ? "-right-12 top-1/2 -translate-y-1/2" + : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", + className + )} + disabled={!canScrollNext} + onClick={scrollNext} + {...props} + > + <ArrowRight className="h-4 w-4" /> + <span className="sr-only">Next slide</span> + </Button> + ) +}) +CarouselNext.displayName = "CarouselNext" export { type CarouselApi, @@ -235,4 +259,4 @@ export { CarouselItem, CarouselPrevious, CarouselNext, -}; +} diff --git a/components/ui/chart.tsx b/components/ui/chart.tsx index 0cb110f..8620baa 100644 --- a/components/ui/chart.tsx +++ b/components/ui/chart.tsx @@ -1,48 +1,50 @@ -"use client"; +"use client" -import * as React from "react"; -import * as RechartsPrimitive from "recharts"; +import * as React from "react" +import * as RechartsPrimitive from "recharts" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" // Format: { THEME_NAME: CSS_SELECTOR } -const THEMES = { light: "", dark: ".dark" } as const; +const THEMES = { light: "", dark: ".dark" } as const export type ChartConfig = { [k in string]: { - label?: React.ReactNode; - icon?: React.ComponentType; + label?: React.ReactNode + icon?: React.ComponentType } & ( | { color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> } - ); -}; + ) +} type ChartContextProps = { - config: ChartConfig; -}; + config: ChartConfig +} -const ChartContext = React.createContext<ChartContextProps | null>(null); +const ChartContext = React.createContext<ChartContextProps | null>(null) function useChart() { - const context = React.useContext(ChartContext); + const context = React.useContext(ChartContext) if (!context) { - throw new Error("useChart must be used within a <ChartContainer />"); + throw new Error("useChart must be used within a <ChartContainer />") } - return context; + return context } const ChartContainer = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - config: ChartConfig; - children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"]; + config: ChartConfig + children: React.ComponentProps< + typeof RechartsPrimitive.ResponsiveContainer + >["children"] } >(({ id, className, children, config, ...props }, ref) => { - const uniqueId = React.useId(); - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`; + const uniqueId = React.useId() + const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` return ( <ChartContext.Provider value={{ config }}> @@ -51,22 +53,27 @@ const ChartContainer = React.forwardRef< ref={ref} className={cn( "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", - className, + className )} - {...props}> + {...props} + > <ChartStyle id={chartId} config={config} /> - <RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer> + <RechartsPrimitive.ResponsiveContainer> + {children} + </RechartsPrimitive.ResponsiveContainer> </div> </ChartContext.Provider> - ); -}); -ChartContainer.displayName = "Chart"; + ) +}) +ChartContainer.displayName = "Chart" const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { - const colorConfig = Object.entries(config).filter(([_, config]) => config.theme || config.color); + const colorConfig = Object.entries(config).filter( + ([_, config]) => config.theme || config.color + ) if (!colorConfig.length) { - return null; + return null } return ( @@ -78,30 +85,32 @@ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { - const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color; - return color ? ` --color-${key}: ${color};` : null; + const color = + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.color + return color ? ` --color-${key}: ${color};` : null }) .join("\n")} } -`, +` ) .join("\n"), }} /> - ); -}; + ) +} -const ChartTooltip = RechartsPrimitive.Tooltip; +const ChartTooltip = RechartsPrimitive.Tooltip const ChartTooltipContent = React.forwardRef< HTMLDivElement, React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<"div"> & { - hideLabel?: boolean; - hideIndicator?: boolean; - indicator?: "line" | "dot" | "dashed"; - nameKey?: string; - labelKey?: string; + hideLabel?: boolean + hideIndicator?: boolean + indicator?: "line" | "dot" | "dashed" + nameKey?: string + labelKey?: string } >( ( @@ -120,63 +129,75 @@ const ChartTooltipContent = React.forwardRef< nameKey, labelKey, }, - ref, + ref ) => { - const { config } = useChart(); + const { config } = useChart() const tooltipLabel = React.useMemo(() => { if (hideLabel || !payload?.length) { - return null; + return null } - const [item] = payload; - const key = `${labelKey || item.dataKey || item.name || "value"}`; - const itemConfig = getPayloadConfigFromPayload(config, item, key); + const [item] = payload + const key = `${labelKey || item.dataKey || item.name || "value"}` + const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" ? config[label as keyof typeof config]?.label || label - : itemConfig?.label; + : itemConfig?.label if (labelFormatter) { return ( - <div className={cn("font-medium", labelClassName)}>{labelFormatter(value, payload)}</div> - ); + <div className={cn("font-medium", labelClassName)}> + {labelFormatter(value, payload)} + </div> + ) } if (!value) { - return null; + return null } - return <div className={cn("font-medium", labelClassName)}>{value}</div>; - }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]); + return <div className={cn("font-medium", labelClassName)}>{value}</div> + }, [ + label, + labelFormatter, + payload, + hideLabel, + labelClassName, + config, + labelKey, + ]) if (!active || !payload?.length) { - return null; + return null } - const nestLabel = payload.length === 1 && indicator !== "dot"; + const nestLabel = payload.length === 1 && indicator !== "dot" return ( <div ref={ref} className={cn( "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl", - className, - )}> + className + )} + > {!nestLabel ? tooltipLabel : null} <div className="grid gap-1.5"> {payload.map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}`; - const itemConfig = getPayloadConfigFromPayload(config, item, key); - const indicatorColor = color || item.payload.fill || item.color; + const key = `${nameKey || item.name || item.dataKey || "value"}` + const itemConfig = getPayloadConfigFromPayload(config, item, key) + const indicatorColor = color || item.payload.fill || item.color return ( <div key={item.dataKey} className={cn( "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", - indicator === "dot" && "items-center", - )}> + indicator === "dot" && "items-center" + )} + > {formatter && item?.value !== undefined && item.name ? ( formatter(item.value, item.name, item, index, item.payload) ) : ( @@ -194,7 +215,7 @@ const ChartTooltipContent = React.forwardRef< "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed", "my-0.5": nestLabel && indicator === "dashed", - }, + } )} style={ { @@ -208,8 +229,9 @@ const ChartTooltipContent = React.forwardRef< <div className={cn( "flex flex-1 justify-between leading-none", - nestLabel ? "items-end" : "items-center", - )}> + nestLabel ? "items-end" : "items-center" + )} + > <div className="grid gap-1.5"> {nestLabel ? tooltipLabel : null} <span className="text-muted-foreground"> @@ -225,92 +247,112 @@ const ChartTooltipContent = React.forwardRef< </> )} </div> - ); + ) })} </div> </div> - ); - }, -); -ChartTooltipContent.displayName = "ChartTooltip"; + ) + } +) +ChartTooltipContent.displayName = "ChartTooltip" -const ChartLegend = RechartsPrimitive.Legend; +const ChartLegend = RechartsPrimitive.Legend const ChartLegendContent = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & { - hideIcon?: boolean; - nameKey?: string; + hideIcon?: boolean + nameKey?: string } ->(({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, ref) => { - const { config } = useChart(); - - if (!payload?.length) { - return null; - } +>( + ( + { className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, + ref + ) => { + const { config } = useChart() - return ( - <div - ref={ref} - className={cn( - "flex items-center justify-center gap-4", - verticalAlign === "top" ? "pb-3" : "pt-3", - className, - )}> - {payload.map((item) => { - const key = `${nameKey || item.dataKey || "value"}`; - const itemConfig = getPayloadConfigFromPayload(config, item, key); + if (!payload?.length) { + return null + } - return ( - <div - key={item.value} - className={cn( - "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground", - )}> - {itemConfig?.icon && !hideIcon ? ( - <itemConfig.icon /> - ) : ( - <div - className="h-2 w-2 shrink-0 rounded-[2px]" - style={{ - backgroundColor: item.color, - }} - /> - )} - {itemConfig?.label} - </div> - ); - })} - </div> - ); -}); -ChartLegendContent.displayName = "ChartLegend"; + return ( + <div + ref={ref} + className={cn( + "flex items-center justify-center gap-4", + verticalAlign === "top" ? "pb-3" : "pt-3", + className + )} + > + {payload.map((item) => { + const key = `${nameKey || item.dataKey || "value"}` + const itemConfig = getPayloadConfigFromPayload(config, item, key) + + return ( + <div + key={item.value} + className={cn( + "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" + )} + > + {itemConfig?.icon && !hideIcon ? ( + <itemConfig.icon /> + ) : ( + <div + className="h-2 w-2 shrink-0 rounded-[2px]" + style={{ + backgroundColor: item.color, + }} + /> + )} + {itemConfig?.label} + </div> + ) + })} + </div> + ) + } +) +ChartLegendContent.displayName = "ChartLegend" // Helper to extract item config from a payload. -function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) { +function getPayloadConfigFromPayload( + config: ChartConfig, + payload: unknown, + key: string +) { if (typeof payload !== "object" || payload === null) { - return undefined; + return undefined } const payloadPayload = - "payload" in payload && typeof payload.payload === "object" && payload.payload !== null + "payload" in payload && + typeof payload.payload === "object" && + payload.payload !== null ? payload.payload - : undefined; + : undefined - let configLabelKey: string = key; + let configLabelKey: string = key - if (key in payload && typeof payload[key as keyof typeof payload] === "string") { - configLabelKey = payload[key as keyof typeof payload] as string; + if ( + key in payload && + typeof payload[key as keyof typeof payload] === "string" + ) { + configLabelKey = payload[key as keyof typeof payload] as string } else if ( payloadPayload && key in payloadPayload && typeof payloadPayload[key as keyof typeof payloadPayload] === "string" ) { - configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string; + configLabelKey = payloadPayload[ + key as keyof typeof payloadPayload + ] as string } - return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]; + return configLabelKey in config + ? config[configLabelKey] + : config[key as keyof typeof config] } export { @@ -320,4 +362,4 @@ export { ChartLegend, ChartLegendContent, ChartStyle, -}; +} diff --git a/components/ui/checkbox.tsx b/components/ui/checkbox.tsx index ecb1699..df61a13 100644 --- a/components/ui/checkbox.tsx +++ b/components/ui/checkbox.tsx @@ -1,10 +1,10 @@ -"use client"; +"use client" -import * as React from "react"; -import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; -import { Check } from "lucide-react"; +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Checkbox = React.forwardRef< React.ElementRef<typeof CheckboxPrimitive.Root>, @@ -14,14 +14,17 @@ const Checkbox = React.forwardRef< ref={ref} className={cn( "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground", - className, + className )} - {...props}> - <CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}> + {...props} + > + <CheckboxPrimitive.Indicator + className={cn("flex items-center justify-center text-current")} + > <Check className="h-4 w-4" /> </CheckboxPrimitive.Indicator> </CheckboxPrimitive.Root> -)); -Checkbox.displayName = CheckboxPrimitive.Root.displayName; +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName -export { Checkbox }; +export { Checkbox } diff --git a/components/ui/collapsible.tsx b/components/ui/collapsible.tsx index cb003d1..9fa4894 100644 --- a/components/ui/collapsible.tsx +++ b/components/ui/collapsible.tsx @@ -1,11 +1,11 @@ -"use client"; +"use client" -import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" -const Collapsible = CollapsiblePrimitive.Root; +const Collapsible = CollapsiblePrimitive.Root -const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger -const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent -export { Collapsible, CollapsibleTrigger, CollapsibleContent }; +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/components/ui/command.tsx b/components/ui/command.tsx index 20cc294..59a2645 100644 --- a/components/ui/command.tsx +++ b/components/ui/command.tsx @@ -1,12 +1,12 @@ -"use client"; +"use client" -import * as React from "react"; -import { type DialogProps } from "@radix-ui/react-dialog"; -import { Command as CommandPrimitive } from "cmdk"; -import { Search } from "lucide-react"; +import * as React from "react" +import { type DialogProps } from "@radix-ui/react-dialog" +import { Command as CommandPrimitive } from "cmdk" +import { Search } from "lucide-react" -import { cn } from "@/lib/utils"; -import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { cn } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" const Command = React.forwardRef< React.ElementRef<typeof CommandPrimitive>, @@ -16,12 +16,12 @@ const Command = React.forwardRef< ref={ref} className={cn( "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", - className, + className )} {...props} /> -)); -Command.displayName = CommandPrimitive.displayName; +)) +Command.displayName = CommandPrimitive.displayName const CommandDialog = ({ children, ...props }: DialogProps) => { return ( @@ -32,8 +32,8 @@ const CommandDialog = ({ children, ...props }: DialogProps) => { </Command> </DialogContent> </Dialog> - ); -}; + ) +} const CommandInput = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Input>, @@ -45,14 +45,14 @@ const CommandInput = React.forwardRef< ref={ref} className={cn( "flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", - className, + className )} {...props} /> </div> -)); +)) -CommandInput.displayName = CommandPrimitive.Input.displayName; +CommandInput.displayName = CommandPrimitive.Input.displayName const CommandList = React.forwardRef< React.ElementRef<typeof CommandPrimitive.List>, @@ -63,18 +63,22 @@ const CommandList = React.forwardRef< className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} {...props} /> -)); +)) -CommandList.displayName = CommandPrimitive.List.displayName; +CommandList.displayName = CommandPrimitive.List.displayName const CommandEmpty = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Empty>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> >((props, ref) => ( - <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} /> -)); + <CommandPrimitive.Empty + ref={ref} + className="py-6 text-center text-sm" + {...props} + /> +)) -CommandEmpty.displayName = CommandPrimitive.Empty.displayName; +CommandEmpty.displayName = CommandPrimitive.Empty.displayName const CommandGroup = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Group>, @@ -84,13 +88,13 @@ const CommandGroup = React.forwardRef< ref={ref} className={cn( "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", - className, + className )} {...props} /> -)); +)) -CommandGroup.displayName = CommandPrimitive.Group.displayName; +CommandGroup.displayName = CommandPrimitive.Group.displayName const CommandSeparator = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Separator>, @@ -101,8 +105,8 @@ const CommandSeparator = React.forwardRef< className={cn("-mx-1 h-px bg-border", className)} {...props} /> -)); -CommandSeparator.displayName = CommandPrimitive.Separator.displayName; +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName const CommandItem = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Item>, @@ -112,23 +116,29 @@ const CommandItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", - className, + className )} {...props} /> -)); +)) -CommandItem.displayName = CommandPrimitive.Item.displayName; +CommandItem.displayName = CommandPrimitive.Item.displayName -const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes<HTMLSpanElement>) => { return ( <span - className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} + className={cn( + "ml-auto text-xs tracking-widest text-muted-foreground", + className + )} {...props} /> - ); -}; -CommandShortcut.displayName = "CommandShortcut"; + ) +} +CommandShortcut.displayName = "CommandShortcut" export { Command, @@ -140,4 +150,4 @@ export { CommandItem, CommandShortcut, CommandSeparator, -}; +} diff --git a/components/ui/context-menu.tsx b/components/ui/context-menu.tsx index 7503973..93ef37b 100644 --- a/components/ui/context-menu.tsx +++ b/components/ui/context-menu.tsx @@ -1,27 +1,27 @@ -"use client"; +"use client" -import * as React from "react"; -import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"; -import { Check, ChevronRight, Circle } from "lucide-react"; +import * as React from "react" +import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" +import { Check, ChevronRight, Circle } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const ContextMenu = ContextMenuPrimitive.Root; +const ContextMenu = ContextMenuPrimitive.Root -const ContextMenuTrigger = ContextMenuPrimitive.Trigger; +const ContextMenuTrigger = ContextMenuPrimitive.Trigger -const ContextMenuGroup = ContextMenuPrimitive.Group; +const ContextMenuGroup = ContextMenuPrimitive.Group -const ContextMenuPortal = ContextMenuPrimitive.Portal; +const ContextMenuPortal = ContextMenuPrimitive.Portal -const ContextMenuSub = ContextMenuPrimitive.Sub; +const ContextMenuSub = ContextMenuPrimitive.Sub -const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup; +const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup const ContextMenuSubTrigger = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>, React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & { - inset?: boolean; + inset?: boolean } >(({ className, inset, children, ...props }, ref) => ( <ContextMenuPrimitive.SubTrigger @@ -29,14 +29,15 @@ const ContextMenuSubTrigger = React.forwardRef< className={cn( "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", inset && "pl-8", - className, + className )} - {...props}> + {...props} + > {children} <ChevronRight className="ml-auto h-4 w-4" /> </ContextMenuPrimitive.SubTrigger> -)); -ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName; +)) +ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName const ContextMenuSubContent = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.SubContent>, @@ -46,12 +47,12 @@ const ContextMenuSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 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", - className, + className )} {...props} /> -)); -ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName; +)) +ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName const ContextMenuContent = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Content>, @@ -62,18 +63,18 @@ const ContextMenuContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 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", - className, + className )} {...props} /> </ContextMenuPrimitive.Portal> -)); -ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName; +)) +ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName const ContextMenuItem = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Item>, React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & { - inset?: boolean; + inset?: boolean } >(({ className, inset, ...props }, ref) => ( <ContextMenuPrimitive.Item @@ -81,12 +82,12 @@ const ContextMenuItem = React.forwardRef< className={cn( "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", - className, + className )} {...props} /> -)); -ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName; +)) +ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName const ContextMenuCheckboxItem = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>, @@ -96,10 +97,11 @@ const ContextMenuCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex 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 )} checked={checked} - {...props}> + {...props} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <ContextMenuPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -107,8 +109,9 @@ const ContextMenuCheckboxItem = React.forwardRef< </span> {children} </ContextMenuPrimitive.CheckboxItem> -)); -ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName; +)) +ContextMenuCheckboxItem.displayName = + ContextMenuPrimitive.CheckboxItem.displayName const ContextMenuRadioItem = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.RadioItem>, @@ -118,9 +121,10 @@ const ContextMenuRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex 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} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <ContextMenuPrimitive.ItemIndicator> <Circle className="h-2 w-2 fill-current" /> @@ -128,22 +132,26 @@ const ContextMenuRadioItem = React.forwardRef< </span> {children} </ContextMenuPrimitive.RadioItem> -)); -ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName; +)) +ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName const ContextMenuLabel = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Label>, React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & { - inset?: boolean; + inset?: boolean } >(({ className, inset, ...props }, ref) => ( <ContextMenuPrimitive.Label ref={ref} - className={cn("px-2 py-1.5 text-sm font-semibold text-foreground", inset && "pl-8", className)} + className={cn( + "px-2 py-1.5 text-sm font-semibold text-foreground", + inset && "pl-8", + className + )} {...props} /> -)); -ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName; +)) +ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName const ContextMenuSeparator = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Separator>, @@ -154,18 +162,24 @@ const ContextMenuSeparator = React.forwardRef< className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} /> -)); -ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName; +)) +ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName -const ContextMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { +const ContextMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes<HTMLSpanElement>) => { return ( <span - className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} + className={cn( + "ml-auto text-xs tracking-widest text-muted-foreground", + className + )} {...props} /> - ); -}; -ContextMenuShortcut.displayName = "ContextMenuShortcut"; + ) +} +ContextMenuShortcut.displayName = "ContextMenuShortcut" export { ContextMenu, @@ -183,4 +197,4 @@ export { ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup, -}; +} diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index 26c52e2..f17698b 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -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>, @@ -41,7 +41,8 @@ const DialogContent = React.forwardRef< "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", className, )} - {...props}> + {...props} + > {children} <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> <X className="h-4 w-4" /> @@ -49,21 +50,18 @@ const DialogContent = React.forwardRef< </DialogPrimitive.Close> </DialogPrimitive.Content> </DialogPortal> -)); -DialogContent.displayName = DialogPrimitive.Content.displayName; +)) +DialogContent.displayName = DialogPrimitive.Content.displayName const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} /> -); -DialogHeader.displayName = "DialogHeader"; +) +DialogHeader.displayName = "DialogHeader" const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} - {...props} - /> -); -DialogFooter.displayName = "DialogFooter"; + <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} /> +) +DialogFooter.displayName = "DialogFooter" const DialogTitle = React.forwardRef< React.ElementRef<typeof DialogPrimitive.Title>, @@ -74,20 +72,16 @@ const DialogTitle = React.forwardRef< className={cn("text-lg font-semibold leading-none tracking-tight", className)} {...props} /> -)); -DialogTitle.displayName = DialogPrimitive.Title.displayName; +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName const DialogDescription = React.forwardRef< React.ElementRef<typeof DialogPrimitive.Description>, React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> >(({ className, ...props }, ref) => ( - <DialogPrimitive.Description - ref={ref} - className={cn("text-sm text-muted-foreground", className)} - {...props} - /> -)); -DialogDescription.displayName = DialogPrimitive.Description.displayName; + <DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName export { Dialog, @@ -100,4 +94,5 @@ export { DialogFooter, DialogTitle, DialogDescription, -}; +} + diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx index ab26c97..6a0ef53 100644 --- a/components/ui/drawer.tsx +++ b/components/ui/drawer.tsx @@ -1,23 +1,26 @@ -"use client"; +"use client" -import * as React from "react"; -import { Drawer as DrawerPrimitive } from "vaul"; +import * as React from "react" +import { Drawer as DrawerPrimitive } from "vaul" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) => ( - <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} /> -); -Drawer.displayName = "Drawer"; + <DrawerPrimitive.Root + shouldScaleBackground={shouldScaleBackground} + {...props} + /> +) +Drawer.displayName = "Drawer" -const DrawerTrigger = DrawerPrimitive.Trigger; +const DrawerTrigger = DrawerPrimitive.Trigger -const DrawerPortal = DrawerPrimitive.Portal; +const DrawerPortal = DrawerPrimitive.Portal -const DrawerClose = DrawerPrimitive.Close; +const DrawerClose = DrawerPrimitive.Close const DrawerOverlay = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Overlay>, @@ -28,8 +31,8 @@ const DrawerOverlay = React.forwardRef< className={cn("fixed inset-0 z-50 bg-black/80", className)} {...props} /> -)); -DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName; +)) +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName const DrawerContent = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Content>, @@ -41,25 +44,38 @@ const DrawerContent = React.forwardRef< ref={ref} className={cn( "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background", - className, + className )} - {...props}> + {...props} + > <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" /> {children} </DrawerPrimitive.Content> </DrawerPortal> -)); -DrawerContent.displayName = "DrawerContent"; +)) +DrawerContent.displayName = "DrawerContent" -const DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} {...props} /> -); -DrawerHeader.displayName = "DrawerHeader"; +const DrawerHeader = ({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) => ( + <div + className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} + {...props} + /> +) +DrawerHeader.displayName = "DrawerHeader" -const DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} /> -); -DrawerFooter.displayName = "DrawerFooter"; +const DrawerFooter = ({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) => ( + <div + className={cn("mt-auto flex flex-col gap-2 p-4", className)} + {...props} + /> +) +DrawerFooter.displayName = "DrawerFooter" const DrawerTitle = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Title>, @@ -67,11 +83,14 @@ const DrawerTitle = React.forwardRef< >(({ className, ...props }, ref) => ( <DrawerPrimitive.Title ref={ref} - className={cn("text-lg font-semibold leading-none tracking-tight", className)} + className={cn( + "text-lg font-semibold leading-none tracking-tight", + className + )} {...props} /> -)); -DrawerTitle.displayName = DrawerPrimitive.Title.displayName; +)) +DrawerTitle.displayName = DrawerPrimitive.Title.displayName const DrawerDescription = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Description>, @@ -82,8 +101,8 @@ const DrawerDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)); -DrawerDescription.displayName = DrawerPrimitive.Description.displayName; +)) +DrawerDescription.displayName = DrawerPrimitive.Description.displayName export { Drawer, @@ -96,4 +115,4 @@ export { DrawerFooter, DrawerTitle, DrawerDescription, -}; +} diff --git a/components/ui/dropdown-menu.tsx b/components/ui/dropdown-menu.tsx index b8fd83b..0fc4c0e 100644 --- a/components/ui/dropdown-menu.tsx +++ b/components/ui/dropdown-menu.tsx @@ -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 @@ -29,14 +29,16 @@ const DropdownMenuSubTrigger = React.forwardRef< className={cn( "flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", - className, + className )} - {...props}> + {...props} + > {children} <ChevronRight className="ml-auto" /> </DropdownMenuPrimitive.SubTrigger> -)); -DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName const DropdownMenuSubContent = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.SubContent>, @@ -46,12 +48,13 @@ const DropdownMenuSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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", - className, + className )} {...props} /> -)); -DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName const DropdownMenuContent = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.Content>, @@ -63,18 +66,18 @@ const DropdownMenuContent = React.forwardRef< sideOffset={sideOffset} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 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", - className, + className )} {...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 @@ -82,12 +85,12 @@ const DropdownMenuItem = React.forwardRef< className={cn( "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", - className, + className )} {...props} /> -)); -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName const DropdownMenuCheckboxItem = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>, @@ -97,10 +100,11 @@ const DropdownMenuCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", - className, + className )} checked={checked} - {...props}> + {...props} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <DropdownMenuPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -108,8 +112,9 @@ const DropdownMenuCheckboxItem = React.forwardRef< </span> {children} </DropdownMenuPrimitive.CheckboxItem> -)); -DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName const DropdownMenuRadioItem = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>, @@ -119,9 +124,10 @@ const DropdownMenuRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", - className, + className )} - {...props}> + {...props} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <DropdownMenuPrimitive.ItemIndicator> <Circle className="h-2 w-2 fill-current" /> @@ -129,22 +135,26 @@ 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 ref={ref} - className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} + className={cn( + "px-2 py-1.5 text-sm font-semibold", + inset && "pl-8", + className + )} {...props} /> -)); -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName const DropdownMenuSeparator = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.Separator>, @@ -155,15 +165,21 @@ 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, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes<HTMLSpanElement>) => { return ( - <span className={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...props} /> - ); -}; -DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; + <span + className={cn("ml-auto text-xs tracking-widest opacity-60", className)} + {...props} + /> + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" export { DropdownMenu, @@ -181,4 +197,4 @@ export { DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, -}; +} diff --git a/components/ui/form.tsx b/components/ui/form.tsx index 2c322f8..ce264ae 100644 --- a/components/ui/form.tsx +++ b/components/ui/form.tsx @@ -1,8 +1,8 @@ -"use client"; +"use client" -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, @@ -10,25 +10,27 @@ import { FieldValues, FormProvider, useFormContext, -} from "react-hook-form"; +} 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>, + TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> > = { - name: TName; -}; + name: TName +} -const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue); +const FormFieldContext = React.createContext<FormFieldContextValue>( + {} as FormFieldContextValue +) const FormField = < TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, + TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> >({ ...props }: ControllerProps<TFieldValues, TName>) => { @@ -36,21 +38,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, @@ -59,33 +61,36 @@ const useFormField = () => { formDescriptionId: `${id}-form-item-description`, formMessageId: `${id}-form-item-message`, ...fieldState, - }; -}; + } +} type FormItemContextValue = { - id: string; -}; + id: string +} -const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue); +const FormItemContext = React.createContext<FormItemContextValue>( + {} as FormItemContextValue +) -const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( - ({ className, ...props }, ref) => { - const id = React.useId(); +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => { + const id = React.useId() - return ( - <FormItemContext.Provider value={{ id }}> - <div ref={ref} className={cn("space-y-2", className)} {...props} /> - </FormItemContext.Provider> - ); - }, -); -FormItem.displayName = "FormItem"; + return ( + <FormItemContext.Provider value={{ id }}> + <div ref={ref} className={cn("space-y-2", className)} {...props} /> + </FormItemContext.Provider> + ) +}) +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 @@ -94,33 +99,37 @@ 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 ref={ref} id={formItemId} - aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`} + aria-describedby={ + !error + ? `${formDescriptionId}` + : `${formDescriptionId} ${formMessageId}` + } 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 @@ -129,19 +138,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 ( @@ -149,12 +158,13 @@ const FormMessage = React.forwardRef< ref={ref} id={formMessageId} className={cn("text-sm font-medium text-destructive", className)} - {...props}> + {...props} + > {body} </p> - ); -}); -FormMessage.displayName = "FormMessage"; + ) +}) +FormMessage.displayName = "FormMessage" export { useFormField, @@ -165,4 +175,4 @@ export { FormDescription, FormMessage, FormField, -}; +} diff --git a/components/ui/hover-card.tsx b/components/ui/hover-card.tsx index 9e8c62d..158208a 100644 --- a/components/ui/hover-card.tsx +++ b/components/ui/hover-card.tsx @@ -1,13 +1,13 @@ -"use client"; +"use client" -import * as React from "react"; -import * as HoverCardPrimitive from "@radix-ui/react-hover-card"; +import * as React from "react" +import * as HoverCardPrimitive from "@radix-ui/react-hover-card" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const HoverCard = HoverCardPrimitive.Root; +const HoverCard = HoverCardPrimitive.Root -const HoverCardTrigger = HoverCardPrimitive.Trigger; +const HoverCardTrigger = HoverCardPrimitive.Trigger const HoverCardContent = React.forwardRef< React.ElementRef<typeof HoverCardPrimitive.Content>, @@ -23,7 +23,8 @@ const HoverCardContent = React.forwardRef< )} {...props} /> -)); -HoverCardContent.displayName = HoverCardPrimitive.Content.displayName; +)) +HoverCardContent.displayName = HoverCardPrimitive.Content.displayName + +export { HoverCard, HoverCardTrigger, HoverCardContent } -export { HoverCard, HoverCardTrigger, HoverCardContent }; diff --git a/components/ui/input-otp.tsx b/components/ui/input-otp.tsx index 41d2e2b..f66fcfa 100644 --- a/components/ui/input-otp.tsx +++ b/components/ui/input-otp.tsx @@ -1,10 +1,10 @@ -"use client"; +"use client" -import * as React from "react"; -import { OTPInput, OTPInputContext } from "input-otp"; -import { Dot } from "lucide-react"; +import * as React from "react" +import { OTPInput, OTPInputContext } from "input-otp" +import { Dot } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const InputOTP = React.forwardRef< React.ElementRef<typeof OTPInput>, @@ -14,28 +14,28 @@ const InputOTP = React.forwardRef< ref={ref} containerClassName={cn( "flex items-center gap-2 has-[:disabled]:opacity-50", - containerClassName, + containerClassName )} className={cn("disabled:cursor-not-allowed", className)} {...props} /> -)); -InputOTP.displayName = "InputOTP"; +)) +InputOTP.displayName = "InputOTP" const InputOTPGroup = React.forwardRef< React.ElementRef<"div">, React.ComponentPropsWithoutRef<"div"> >(({ className, ...props }, ref) => ( <div ref={ref} className={cn("flex items-center", className)} {...props} /> -)); -InputOTPGroup.displayName = "InputOTPGroup"; +)) +InputOTPGroup.displayName = "InputOTPGroup" const InputOTPSlot = React.forwardRef< React.ElementRef<"div">, React.ComponentPropsWithoutRef<"div"> & { index: number } >(({ index, className, ...props }, ref) => { - const inputOTPContext = React.useContext(OTPInputContext); - const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]; + const inputOTPContext = React.useContext(OTPInputContext) + const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index] return ( <div @@ -43,9 +43,10 @@ const InputOTPSlot = React.forwardRef< className={cn( "relative flex h-10 w-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md", isActive && "z-10 ring-2 ring-ring ring-offset-background", - className, + className )} - {...props}> + {...props} + > {char} {hasFakeCaret && ( <div className="pointer-events-none absolute inset-0 flex items-center justify-center"> @@ -53,9 +54,9 @@ const InputOTPSlot = React.forwardRef< </div> )} </div> - ); -}); -InputOTPSlot.displayName = "InputOTPSlot"; + ) +}) +InputOTPSlot.displayName = "InputOTPSlot" const InputOTPSeparator = React.forwardRef< React.ElementRef<"div">, @@ -64,7 +65,7 @@ const InputOTPSeparator = React.forwardRef< <div ref={ref} role="separator" {...props}> <Dot /> </div> -)); -InputOTPSeparator.displayName = "InputOTPSeparator"; +)) +InputOTPSeparator.displayName = "InputOTPSeparator" -export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } diff --git a/components/ui/input.tsx b/components/ui/input.tsx index 84da2c0..79a855f 100644 --- a/components/ui/input.tsx +++ b/components/ui/input.tsx @@ -1,24 +1,23 @@ -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> {} -const Input = React.forwardRef<HTMLInputElement, InputProps>( - ({ className, type, ...props }, ref) => { - return ( - <input - type={type} - className={cn( - "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", - className, - )} - ref={ref} - {...props} - /> - ); - }, -); -Input.displayName = "Input"; +const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => { + return ( + <input + type={type} + className={cn( + "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", + className, + )} + ref={ref} + {...props} + /> + ) +}) +Input.displayName = "Input" + +export { Input } -export { Input }; diff --git a/components/ui/label.tsx b/components/ui/label.tsx index 392197c..5341821 100644 --- a/components/ui/label.tsx +++ b/components/ui/label.tsx @@ -1,21 +1,26 @@ -"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", -); + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) const Label = React.forwardRef< React.ElementRef<typeof LabelPrimitive.Root>, - React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants> + React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & + VariantProps<typeof labelVariants> >(({ className, ...props }, ref) => ( - <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} /> -)); -Label.displayName = LabelPrimitive.Root.displayName; + <LabelPrimitive.Root + ref={ref} + className={cn(labelVariants(), className)} + {...props} + /> +)) +Label.displayName = LabelPrimitive.Root.displayName -export { Label }; +export { Label } diff --git a/components/ui/menubar.tsx b/components/ui/menubar.tsx index 815aeec..5586fa9 100644 --- a/components/ui/menubar.tsx +++ b/components/ui/menubar.tsx @@ -1,20 +1,20 @@ -"use client"; +"use client" -import * as React from "react"; -import * as MenubarPrimitive from "@radix-ui/react-menubar"; -import { Check, ChevronRight, Circle } from "lucide-react"; +import * as React from "react" +import * as MenubarPrimitive from "@radix-ui/react-menubar" +import { Check, ChevronRight, Circle } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const MenubarMenu = MenubarPrimitive.Menu; +const MenubarMenu = MenubarPrimitive.Menu -const MenubarGroup = MenubarPrimitive.Group; +const MenubarGroup = MenubarPrimitive.Group -const MenubarPortal = MenubarPrimitive.Portal; +const MenubarPortal = MenubarPrimitive.Portal -const MenubarSub = MenubarPrimitive.Sub; +const MenubarSub = MenubarPrimitive.Sub -const MenubarRadioGroup = MenubarPrimitive.RadioGroup; +const MenubarRadioGroup = MenubarPrimitive.RadioGroup const Menubar = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Root>, @@ -24,12 +24,12 @@ const Menubar = React.forwardRef< ref={ref} className={cn( "flex h-10 items-center space-x-1 rounded-md border bg-background p-1", - className, + className )} {...props} /> -)); -Menubar.displayName = MenubarPrimitive.Root.displayName; +)) +Menubar.displayName = MenubarPrimitive.Root.displayName const MenubarTrigger = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Trigger>, @@ -39,17 +39,17 @@ const MenubarTrigger = React.forwardRef< ref={ref} className={cn( "flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", - className, + className )} {...props} /> -)); -MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName; +)) +MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName const MenubarSubTrigger = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.SubTrigger>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & { - inset?: boolean; + inset?: boolean } >(({ className, inset, children, ...props }, ref) => ( <MenubarPrimitive.SubTrigger @@ -57,14 +57,15 @@ const MenubarSubTrigger = React.forwardRef< className={cn( "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", inset && "pl-8", - className, + className )} - {...props}> + {...props} + > {children} <ChevronRight className="ml-auto h-4 w-4" /> </MenubarPrimitive.SubTrigger> -)); -MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName; +)) +MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName const MenubarSubContent = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.SubContent>, @@ -74,37 +75,42 @@ const MenubarSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground 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", - className, + className )} {...props} /> -)); -MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName; +)) +MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName const MenubarContent = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Content>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content> ->(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => ( - <MenubarPrimitive.Portal> - <MenubarPrimitive.Content - ref={ref} - align={align} - alignOffset={alignOffset} - sideOffset={sideOffset} - className={cn( - "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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", - className, - )} - {...props} - /> - </MenubarPrimitive.Portal> -)); -MenubarContent.displayName = MenubarPrimitive.Content.displayName; +>( + ( + { className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, + ref + ) => ( + <MenubarPrimitive.Portal> + <MenubarPrimitive.Content + ref={ref} + align={align} + alignOffset={alignOffset} + sideOffset={sideOffset} + className={cn( + "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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", + className + )} + {...props} + /> + </MenubarPrimitive.Portal> + ) +) +MenubarContent.displayName = MenubarPrimitive.Content.displayName const MenubarItem = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Item>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & { - inset?: boolean; + inset?: boolean } >(({ className, inset, ...props }, ref) => ( <MenubarPrimitive.Item @@ -112,12 +118,12 @@ const MenubarItem = React.forwardRef< className={cn( "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", - className, + className )} {...props} /> -)); -MenubarItem.displayName = MenubarPrimitive.Item.displayName; +)) +MenubarItem.displayName = MenubarPrimitive.Item.displayName const MenubarCheckboxItem = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.CheckboxItem>, @@ -127,10 +133,11 @@ const MenubarCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex 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 )} checked={checked} - {...props}> + {...props} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <MenubarPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -138,8 +145,8 @@ const MenubarCheckboxItem = React.forwardRef< </span> {children} </MenubarPrimitive.CheckboxItem> -)); -MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName; +)) +MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName const MenubarRadioItem = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.RadioItem>, @@ -149,9 +156,10 @@ const MenubarRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex 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} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <MenubarPrimitive.ItemIndicator> <Circle className="h-2 w-2 fill-current" /> @@ -159,22 +167,26 @@ const MenubarRadioItem = React.forwardRef< </span> {children} </MenubarPrimitive.RadioItem> -)); -MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName; +)) +MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName const MenubarLabel = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Label>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & { - inset?: boolean; + inset?: boolean } >(({ className, inset, ...props }, ref) => ( <MenubarPrimitive.Label ref={ref} - className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} + className={cn( + "px-2 py-1.5 text-sm font-semibold", + inset && "pl-8", + className + )} {...props} /> -)); -MenubarLabel.displayName = MenubarPrimitive.Label.displayName; +)) +MenubarLabel.displayName = MenubarPrimitive.Label.displayName const MenubarSeparator = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Separator>, @@ -185,18 +197,24 @@ const MenubarSeparator = React.forwardRef< className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} /> -)); -MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName; +)) +MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName -const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { +const MenubarShortcut = ({ + className, + ...props +}: React.HTMLAttributes<HTMLSpanElement>) => { return ( <span - className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} + className={cn( + "ml-auto text-xs tracking-widest text-muted-foreground", + className + )} {...props} /> - ); -}; -MenubarShortcut.displayname = "MenubarShortcut"; + ) +} +MenubarShortcut.displayname = "MenubarShortcut" export { Menubar, @@ -215,4 +233,4 @@ export { MenubarGroup, MenubarSub, MenubarShortcut, -}; +} diff --git a/components/ui/navigation-menu.tsx b/components/ui/navigation-menu.tsx index 083eb5f..722248b 100644 --- a/components/ui/navigation-menu.tsx +++ b/components/ui/navigation-menu.tsx @@ -1,11 +1,11 @@ -"use client"; +"use client" -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>, @@ -14,12 +14,13 @@ const NavigationMenu = React.forwardRef< <NavigationMenuPrimitive.Root ref={ref} className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)} - {...props}> + {...props} + > {children} <NavigationMenuViewport /> </NavigationMenuPrimitive.Root> -)); -NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName; +)) +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName const NavigationMenuList = React.forwardRef< React.ElementRef<typeof NavigationMenuPrimitive.List>, @@ -30,14 +31,14 @@ const NavigationMenuList = React.forwardRef< className={cn("group flex flex-1 list-none items-center justify-center space-x-1", className)} {...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>, @@ -46,15 +47,16 @@ const NavigationMenuTrigger = React.forwardRef< <NavigationMenuPrimitive.Trigger ref={ref} className={cn(navigationMenuTriggerStyle(), "group", className)} - {...props}> + {...props} + > {children}{" "} <ChevronDown className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180" aria-hidden="true" /> </NavigationMenuPrimitive.Trigger> -)); -NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName; +)) +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName const NavigationMenuContent = React.forwardRef< React.ElementRef<typeof NavigationMenuPrimitive.Content>, @@ -68,10 +70,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>, @@ -87,8 +89,8 @@ const NavigationMenuViewport = React.forwardRef< {...props} /> </div> -)); -NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName; +)) +NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName const NavigationMenuIndicator = React.forwardRef< React.ElementRef<typeof NavigationMenuPrimitive.Indicator>, @@ -100,11 +102,12 @@ const NavigationMenuIndicator = React.forwardRef< "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", className, )} - {...props}> + {...props} + > <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; +)) +NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName export { navigationMenuTriggerStyle, @@ -116,4 +119,5 @@ export { NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, -}; +} + diff --git a/components/ui/pagination.tsx b/components/ui/pagination.tsx index 3786db8..ea40d19 100644 --- a/components/ui/pagination.tsx +++ b/components/ui/pagination.tsx @@ -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,27 +11,40 @@ 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, React.ComponentProps<"ul">>( - ({ className, ...props }, ref) => ( - <ul ref={ref} className={cn("flex flex-row items-center gap-1", className)} {...props} /> - ), -); -PaginationContent.displayName = "PaginationContent"; +const PaginationContent = React.forwardRef< + HTMLUListElement, + React.ComponentProps<"ul"> +>(({ className, ...props }, ref) => ( + <ul + ref={ref} + className={cn("flex flex-row items-center gap-1", className)} + {...props} + /> +)) +PaginationContent.displayName = "PaginationContent" -const PaginationItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( - ({ className, ...props }, ref) => <li ref={ref} className={cn("", className)} {...props} />, -); -PaginationItem.displayName = "PaginationItem"; +const PaginationItem = React.forwardRef< + HTMLLIElement, + React.ComponentProps<"li"> +>(({ className, ...props }, ref) => ( + <li ref={ref} className={cn("", className)} {...props} /> +)) +PaginationItem.displayName = "PaginationItem" type PaginationLinkProps = { - isActive?: boolean; + isActive?: boolean } & Pick<ButtonProps, "size"> & - React.ComponentProps<"a">; + React.ComponentProps<"a"> -const PaginationLink = ({ className, isActive, size = "icon", ...props }: PaginationLinkProps) => ( +const PaginationLink = ({ + className, + isActive, + size = "icon", + ...props +}: PaginationLinkProps) => ( <a aria-current={isActive ? "page" : undefined} className={cn( @@ -39,12 +52,12 @@ const PaginationLink = ({ className, isActive, size = "icon", ...props }: Pagina variant: isActive ? "outline" : "ghost", size, }), - className, + className )} {...props} /> -); -PaginationLink.displayName = "PaginationLink"; +) +PaginationLink.displayName = "PaginationLink" const PaginationPrevious = ({ className, @@ -54,35 +67,44 @@ const PaginationPrevious = ({ aria-label="Go to previous page" size="default" className={cn("gap-1 pl-2.5", className)} - {...props}> + {...props} + > <ChevronLeft className="h-4 w-4" /> <span>Previous</span> </PaginationLink> -); -PaginationPrevious.displayName = "PaginationPrevious"; +) +PaginationPrevious.displayName = "PaginationPrevious" -const PaginationNext = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => ( +const PaginationNext = ({ + className, + ...props +}: React.ComponentProps<typeof PaginationLink>) => ( <PaginationLink aria-label="Go to next page" size="default" className={cn("gap-1 pr-2.5", className)} - {...props}> + {...props} + > <span>Next</span> <ChevronRight className="h-4 w-4" /> </PaginationLink> -); -PaginationNext.displayName = "PaginationNext"; +) +PaginationNext.displayName = "PaginationNext" -const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => ( +const PaginationEllipsis = ({ + className, + ...props +}: React.ComponentProps<"span">) => ( <span aria-hidden className={cn("flex h-9 w-9 items-center justify-center", className)} - {...props}> + {...props} + > <MoreHorizontal className="h-4 w-4" /> <span className="sr-only">More pages</span> </span> -); -PaginationEllipsis.displayName = "PaginationEllipsis"; +) +PaginationEllipsis.displayName = "PaginationEllipsis" export { Pagination, @@ -92,4 +114,4 @@ export { PaginationLink, PaginationNext, PaginationPrevious, -}; +} diff --git a/components/ui/popover.tsx b/components/ui/popover.tsx index 73be7bb..a0ec48b 100644 --- a/components/ui/popover.tsx +++ b/components/ui/popover.tsx @@ -1,13 +1,13 @@ -"use client"; +"use client" -import * as React from "react"; -import * as PopoverPrimitive from "@radix-ui/react-popover"; +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const Popover = PopoverPrimitive.Root; +const Popover = PopoverPrimitive.Root -const PopoverTrigger = PopoverPrimitive.Trigger; +const PopoverTrigger = PopoverPrimitive.Trigger const PopoverContent = React.forwardRef< React.ElementRef<typeof PopoverPrimitive.Content>, @@ -20,12 +20,12 @@ const PopoverContent = React.forwardRef< sideOffset={sideOffset} className={cn( "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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", - className, + className )} {...props} /> </PopoverPrimitive.Portal> -)); -PopoverContent.displayName = PopoverPrimitive.Content.displayName; +)) +PopoverContent.displayName = PopoverPrimitive.Content.displayName -export { Popover, PopoverTrigger, PopoverContent }; +export { Popover, PopoverTrigger, PopoverContent } diff --git a/components/ui/progress.tsx b/components/ui/progress.tsx index 5fb27c7..5c87ea4 100644 --- a/components/ui/progress.tsx +++ b/components/ui/progress.tsx @@ -1,9 +1,9 @@ -"use client"; +"use client" -import * as React from "react"; -import * as ProgressPrimitive from "@radix-ui/react-progress"; +import * as React from "react" +import * as ProgressPrimitive from "@radix-ui/react-progress" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Progress = React.forwardRef< React.ElementRef<typeof ProgressPrimitive.Root>, @@ -11,14 +11,18 @@ const Progress = React.forwardRef< >(({ className, value, ...props }, ref) => ( <ProgressPrimitive.Root ref={ref} - className={cn("relative h-4 w-full overflow-hidden rounded-full bg-secondary", className)} - {...props}> + className={cn( + "relative h-4 w-full overflow-hidden rounded-full bg-secondary", + className + )} + {...props} + > <ProgressPrimitive.Indicator className="h-full w-full flex-1 bg-primary transition-all" style={{ transform: `translateX(-${100 - (value || 0)}%)` }} /> </ProgressPrimitive.Root> -)); -Progress.displayName = ProgressPrimitive.Root.displayName; +)) +Progress.displayName = ProgressPrimitive.Root.displayName -export { Progress }; +export { Progress } diff --git a/components/ui/radio-group.tsx b/components/ui/radio-group.tsx index 5485bed..e9bde17 100644 --- a/components/ui/radio-group.tsx +++ b/components/ui/radio-group.tsx @@ -1,18 +1,24 @@ -"use client"; +"use client" -import * as React from "react"; -import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; -import { Circle } from "lucide-react"; +import * as React from "react" +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" +import { Circle } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const RadioGroup = React.forwardRef< React.ElementRef<typeof RadioGroupPrimitive.Root>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> >(({ className, ...props }, ref) => { - return <RadioGroupPrimitive.Root className={cn("grid gap-2", className)} {...props} ref={ref} />; -}); -RadioGroup.displayName = RadioGroupPrimitive.Root.displayName; + return ( + <RadioGroupPrimitive.Root + className={cn("grid gap-2", className)} + {...props} + ref={ref} + /> + ) +}) +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName const RadioGroupItem = React.forwardRef< React.ElementRef<typeof RadioGroupPrimitive.Item>, @@ -23,15 +29,16 @@ const RadioGroupItem = React.forwardRef< ref={ref} className={cn( "aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", - className, + className )} - {...props}> + {...props} + > <RadioGroupPrimitive.Indicator className="flex items-center justify-center"> <Circle className="h-2.5 w-2.5 fill-current text-current" /> </RadioGroupPrimitive.Indicator> </RadioGroupPrimitive.Item> - ); -}); -RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; + ) +}) +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName -export { RadioGroup, RadioGroupItem }; +export { RadioGroup, RadioGroupItem } diff --git a/components/ui/resizable.tsx b/components/ui/resizable.tsx index 04dcae9..f4bc558 100644 --- a/components/ui/resizable.tsx +++ b/components/ui/resizable.tsx @@ -1,41 +1,45 @@ -"use client"; +"use client" -import { GripVertical } from "lucide-react"; -import * as ResizablePrimitive from "react-resizable-panels"; +import { GripVertical } from "lucide-react" +import * as ResizablePrimitive from "react-resizable-panels" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const ResizablePanelGroup = ({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => ( <ResizablePrimitive.PanelGroup - className={cn("flex h-full w-full data-[panel-group-direction=vertical]:flex-col", className)} + className={cn( + "flex h-full w-full data-[panel-group-direction=vertical]:flex-col", + className + )} {...props} /> -); +) -const ResizablePanel = ResizablePrimitive.Panel; +const ResizablePanel = ResizablePrimitive.Panel const ResizableHandle = ({ withHandle, className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { - withHandle?: boolean; + withHandle?: boolean }) => ( <ResizablePrimitive.PanelResizeHandle className={cn( "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90", - className, + className )} - {...props}> + {...props} + > {withHandle && ( <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border"> <GripVertical className="h-2.5 w-2.5" /> </div> )} </ResizablePrimitive.PanelResizeHandle> -); +) -export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; +export { ResizablePanelGroup, ResizablePanel, ResizableHandle } diff --git a/components/ui/scroll-area.tsx b/components/ui/scroll-area.tsx index 6d14a6f..c8164b9 100644 --- a/components/ui/scroll-area.tsx +++ b/components/ui/scroll-area.tsx @@ -1,26 +1,21 @@ -"use client"; +"use client" -import * as React from "react"; -import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const ScrollArea = React.forwardRef< React.ElementRef<typeof ScrollAreaPrimitive.Root>, React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> >(({ className, children, ...props }, ref) => ( - <ScrollAreaPrimitive.Root - ref={ref} - className={cn("relative overflow-hidden", className)} - {...props}> - <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]"> - {children} - </ScrollAreaPrimitive.Viewport> + <ScrollAreaPrimitive.Root ref={ref} className={cn("relative overflow-hidden", className)} {...props}> + <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">{children}</ScrollAreaPrimitive.Viewport> <ScrollBar /> <ScrollAreaPrimitive.Corner /> </ScrollAreaPrimitive.Root> -)); -ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName const ScrollBar = React.forwardRef< React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>, @@ -35,10 +30,12 @@ const ScrollBar = React.forwardRef< orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]", className, )} - {...props}> + {...props} + > <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" /> </ScrollAreaPrimitive.ScrollAreaScrollbar> -)); -ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } -export { ScrollArea, ScrollBar }; diff --git a/components/ui/select.tsx b/components/ui/select.tsx index 1eec896..cbe5a36 100644 --- a/components/ui/select.tsx +++ b/components/ui/select.tsx @@ -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>, @@ -20,16 +20,17 @@ const SelectTrigger = React.forwardRef< ref={ref} 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", - className, + className )} - {...props}> + {...props} + > {children} <SelectPrimitive.Icon asChild> <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>, @@ -37,12 +38,16 @@ const SelectScrollUpButton = React.forwardRef< >(({ className, ...props }, ref) => ( <SelectPrimitive.ScrollUpButton ref={ref} - className={cn("flex cursor-default items-center justify-center py-1", className)} - {...props}> + className={cn( + "flex cursor-default items-center justify-center py-1", + className + )} + {...props} + > <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>, @@ -50,12 +55,17 @@ const SelectScrollDownButton = React.forwardRef< >(({ className, ...props }, ref) => ( <SelectPrimitive.ScrollDownButton ref={ref} - className={cn("flex cursor-default items-center justify-center py-1", className)} - {...props}> + className={cn( + "flex cursor-default items-center justify-center py-1", + className + )} + {...props} + > <ChevronDown className="h-4 w-4" /> </SelectPrimitive.ScrollDownButton> -)); -SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName const SelectContent = React.forwardRef< React.ElementRef<typeof SelectPrimitive.Content>, @@ -68,24 +78,26 @@ const SelectContent = React.forwardRef< "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" && "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} - {...props}> + {...props} + > <SelectScrollUpButton /> <SelectPrimitive.Viewport className={cn( "p-1", 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} </SelectPrimitive.Viewport> <SelectScrollDownButton /> </SelectPrimitive.Content> </SelectPrimitive.Portal> -)); -SelectContent.displayName = SelectPrimitive.Content.displayName; +)) +SelectContent.displayName = SelectPrimitive.Content.displayName const SelectLabel = React.forwardRef< React.ElementRef<typeof SelectPrimitive.Label>, @@ -96,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>, @@ -107,9 +119,10 @@ const SelectItem = React.forwardRef< ref={ref} 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", - className, + className )} - {...props}> + {...props} + > <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <SelectPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -118,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>, @@ -130,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, @@ -144,4 +157,4 @@ export { SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, -}; +} diff --git a/components/ui/separator.tsx b/components/ui/separator.tsx index ee84f69..12d81c4 100644 --- a/components/ui/separator.tsx +++ b/components/ui/separator.tsx @@ -1,26 +1,31 @@ -"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>, React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> ->(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => ( - <SeparatorPrimitive.Root - ref={ref} - decorative={decorative} - orientation={orientation} - className={cn( - "shrink-0 bg-border", - orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", - className, - )} - {...props} - /> -)); -Separator.displayName = SeparatorPrimitive.Root.displayName; +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + <SeparatorPrimitive.Root + ref={ref} + decorative={decorative} + orientation={orientation} + className={cn( + "shrink-0 bg-border", + orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", + className + )} + {...props} + /> + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName -export { Separator }; +export { Separator } diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx index 2ed3e4d..a37f17b 100644 --- a/components/ui/sheet.tsx +++ b/components/ui/sheet.tsx @@ -1,19 +1,19 @@ -"use client"; +"use client" -import * as React from "react"; -import * as SheetPrimitive from "@radix-ui/react-dialog"; -import { cva, type VariantProps } from "class-variance-authority"; -import { X } from "lucide-react"; +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from "lucide-react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const Sheet = SheetPrimitive.Root; +const Sheet = SheetPrimitive.Root -const SheetTrigger = SheetPrimitive.Trigger; +const SheetTrigger = SheetPrimitive.Trigger -const SheetClose = SheetPrimitive.Close; +const SheetClose = SheetPrimitive.Close -const SheetPortal = SheetPrimitive.Portal; +const SheetPortal = SheetPrimitive.Portal const SheetOverlay = React.forwardRef< React.ElementRef<typeof SheetPrimitive.Overlay>, @@ -22,13 +22,13 @@ const SheetOverlay = React.forwardRef< <SheetPrimitive.Overlay className={cn( "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className, + className )} {...props} ref={ref} /> -)); -SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName const sheetVariants = cva( "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", @@ -46,8 +46,8 @@ const sheetVariants = cva( defaultVariants: { side: "right", }, - }, -); + } +) interface SheetContentProps extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, @@ -59,7 +59,11 @@ const SheetContent = React.forwardRef< >(({ side = "right", className, children, ...props }, ref) => ( <SheetPortal> <SheetOverlay /> - <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}> + <SheetPrimitive.Content + ref={ref} + className={cn(sheetVariants({ side }), className)} + {...props} + > {children} <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"> <X className="h-4 w-4" /> @@ -67,21 +71,36 @@ const SheetContent = React.forwardRef< </SheetPrimitive.Close> </SheetPrimitive.Content> </SheetPortal> -)); -SheetContent.displayName = SheetPrimitive.Content.displayName; +)) +SheetContent.displayName = SheetPrimitive.Content.displayName -const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} /> -); -SheetHeader.displayName = "SheetHeader"; +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) => ( + <div + className={cn( + "flex flex-col space-y-2 text-center sm:text-left", + className + )} + {...props} + /> +) +SheetHeader.displayName = "SheetHeader" -const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) => ( <div - className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} + className={cn( + "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", + className + )} {...props} /> -); -SheetFooter.displayName = "SheetFooter"; +) +SheetFooter.displayName = "SheetFooter" const SheetTitle = React.forwardRef< React.ElementRef<typeof SheetPrimitive.Title>, @@ -92,8 +111,8 @@ const SheetTitle = React.forwardRef< className={cn("text-lg font-semibold text-foreground", className)} {...props} /> -)); -SheetTitle.displayName = SheetPrimitive.Title.displayName; +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName const SheetDescription = React.forwardRef< React.ElementRef<typeof SheetPrimitive.Description>, @@ -104,8 +123,8 @@ const SheetDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)); -SheetDescription.displayName = SheetPrimitive.Description.displayName; +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName export { Sheet, @@ -118,4 +137,4 @@ export { SheetFooter, SheetTitle, SheetDescription, -}; +} diff --git a/components/ui/sidebar.tsx b/components/ui/sidebar.tsx index 4f4e430..eeb2d7a 100644 --- a/components/ui/sidebar.tsx +++ b/components/ui/sidebar.tsx @@ -1,53 +1,58 @@ -"use client"; - -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { VariantProps, cva } from "class-variance-authority"; -import { PanelLeft } from "lucide-react"; - -import { useIsMobile } from "@/hooks/use-mobile"; -import { cn } from "@/lib/utils"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Separator } from "@/components/ui/separator"; -import { Sheet, SheetContent } from "@/components/ui/sheet"; -import { Skeleton } from "@/components/ui/skeleton"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; - -const SIDEBAR_COOKIE_NAME = "sidebar:state"; -const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; -const SIDEBAR_WIDTH = "16rem"; -const SIDEBAR_WIDTH_MOBILE = "18rem"; -const SIDEBAR_WIDTH_ICON = "3rem"; -const SIDEBAR_KEYBOARD_SHORTCUT = "b"; +"use client" + +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { VariantProps, cva } from "class-variance-authority" +import { PanelLeft } from "lucide-react" + +import { useIsMobile } from "@/hooks/use-mobile" +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Separator } from "@/components/ui/separator" +import { Sheet, SheetContent } from "@/components/ui/sheet" +import { Skeleton } from "@/components/ui/skeleton" +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" + +const SIDEBAR_COOKIE_NAME = "sidebar:state" +const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 +const SIDEBAR_WIDTH = "16rem" +const SIDEBAR_WIDTH_MOBILE = "18rem" +const SIDEBAR_WIDTH_ICON = "3rem" +const SIDEBAR_KEYBOARD_SHORTCUT = "b" type SidebarContext = { - state: "expanded" | "collapsed"; - open: boolean; - setOpen: (open: boolean) => void; - openMobile: boolean; - setOpenMobile: (open: boolean) => void; - isMobile: boolean; - toggleSidebar: () => void; -}; + state: "expanded" | "collapsed" + open: boolean + setOpen: (open: boolean) => void + openMobile: boolean + setOpenMobile: (open: boolean) => void + isMobile: boolean + toggleSidebar: () => void +} -const SidebarContext = React.createContext<SidebarContext | null>(null); +const SidebarContext = React.createContext<SidebarContext | null>(null) function useSidebar() { - const context = React.useContext(SidebarContext); + const context = React.useContext(SidebarContext) if (!context) { - throw new Error("useSidebar must be used within a SidebarProvider."); + throw new Error("useSidebar must be used within a SidebarProvider.") } - return context; + return context } const SidebarProvider = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - defaultOpen?: boolean; - open?: boolean; - onOpenChange?: (open: boolean) => void; + defaultOpen?: boolean + open?: boolean + onOpenChange?: (open: boolean) => void } >( ( @@ -60,51 +65,56 @@ const SidebarProvider = React.forwardRef< children, ...props }, - ref, + ref ) => { - const isMobile = useIsMobile(); - const [openMobile, setOpenMobile] = React.useState(false); + const isMobile = useIsMobile() + const [openMobile, setOpenMobile] = React.useState(false) // This is the internal state of the sidebar. // We use openProp and setOpenProp for control from outside the component. - const [_open, _setOpen] = React.useState(defaultOpen); - const open = openProp ?? _open; + const [_open, _setOpen] = React.useState(defaultOpen) + const open = openProp ?? _open const setOpen = React.useCallback( (value: boolean | ((value: boolean) => boolean)) => { - const openState = typeof value === "function" ? value(open) : value; + const openState = typeof value === "function" ? value(open) : value if (setOpenProp) { - setOpenProp(openState); + setOpenProp(openState) } else { - _setOpen(openState); + _setOpen(openState) } // This sets the cookie to keep the sidebar state. - document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`; + document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` }, - [setOpenProp, open], - ); + [setOpenProp, open] + ) // Helper to toggle the sidebar. const toggleSidebar = React.useCallback(() => { - return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open); - }, [isMobile, setOpen, setOpenMobile]); + return isMobile + ? setOpenMobile((open) => !open) + : setOpen((open) => !open) + }, [isMobile, setOpen, setOpenMobile]) // Adds a keyboard shortcut to toggle the sidebar. React.useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) { - event.preventDefault(); - toggleSidebar(); + if ( + event.key === SIDEBAR_KEYBOARD_SHORTCUT && + (event.metaKey || event.ctrlKey) + ) { + event.preventDefault() + toggleSidebar() } - }; + } - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); - }, [toggleSidebar]); + window.addEventListener("keydown", handleKeyDown) + return () => window.removeEventListener("keydown", handleKeyDown) + }, [toggleSidebar]) // We add a state so that we can do data-state="expanded" or "collapsed". // This makes it easier to style the sidebar with Tailwind classes. - const state = open ? "expanded" : "collapsed"; + const state = open ? "expanded" : "collapsed" const contextValue = React.useMemo<SidebarContext>( () => ({ @@ -116,8 +126,8 @@ const SidebarProvider = React.forwardRef< setOpenMobile, toggleSidebar, }), - [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar], - ); + [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] + ) return ( <SidebarContext.Provider value={contextValue}> @@ -132,25 +142,26 @@ const SidebarProvider = React.forwardRef< } className={cn( "group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar", - className, + className )} ref={ref} - {...props}> + {...props} + > {children} </div> </TooltipProvider> </SidebarContext.Provider> - ); - }, -); -SidebarProvider.displayName = "SidebarProvider"; + ) + } +) +SidebarProvider.displayName = "SidebarProvider" const Sidebar = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - side?: "left" | "right"; - variant?: "sidebar" | "floating" | "inset"; - collapsible?: "offcanvas" | "icon" | "none"; + side?: "left" | "right" + variant?: "sidebar" | "floating" | "inset" + collapsible?: "offcanvas" | "icon" | "none" } >( ( @@ -162,22 +173,23 @@ const Sidebar = React.forwardRef< children, ...props }, - ref, + ref ) => { - const { isMobile, state, openMobile, setOpenMobile } = useSidebar(); + const { isMobile, state, openMobile, setOpenMobile } = useSidebar() if (collapsible === "none") { return ( <div className={cn( "flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground", - className, + className )} ref={ref} - {...props}> + {...props} + > {children} </div> - ); + ) } if (isMobile) { @@ -192,11 +204,12 @@ const Sidebar = React.forwardRef< "--sidebar-width": SIDEBAR_WIDTH_MOBILE, } as React.CSSProperties } - side={side}> + side={side} + > <div className="flex h-full w-full flex-col">{children}</div> </SheetContent> </Sheet> - ); + ) } return ( @@ -206,7 +219,8 @@ const Sidebar = React.forwardRef< data-state={state} data-collapsible={state === "collapsed" ? collapsible : ""} data-variant={variant} - data-side={side}> + data-side={side} + > {/* This is what handles the sidebar gap on desktop */} <div className={cn( @@ -215,7 +229,7 @@ const Sidebar = React.forwardRef< "group-data-[side=right]:rotate-180", variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]" - : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]", + : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]" )} /> <div @@ -228,26 +242,28 @@ const Sidebar = React.forwardRef< variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]" : "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l", - className, + className )} - {...props}> + {...props} + > <div data-sidebar="sidebar" - className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"> + className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow" + > {children} </div> </div> </div> - ); - }, -); -Sidebar.displayName = "Sidebar"; + ) + } +) +Sidebar.displayName = "Sidebar" const SidebarTrigger = React.forwardRef< React.ElementRef<typeof Button>, React.ComponentProps<typeof Button> >(({ className, onClick, ...props }, ref) => { - const { toggleSidebar } = useSidebar(); + const { toggleSidebar } = useSidebar() return ( <Button @@ -257,61 +273,64 @@ const SidebarTrigger = React.forwardRef< size="icon" className={cn("h-7 w-7", className)} onClick={(event) => { - onClick?.(event); - toggleSidebar(); + onClick?.(event) + toggleSidebar() }} - {...props}> + {...props} + > <PanelLeft /> <span className="sr-only">Toggle Sidebar</span> </Button> - ); -}); -SidebarTrigger.displayName = "SidebarTrigger"; + ) +}) +SidebarTrigger.displayName = "SidebarTrigger" -const SidebarRail = React.forwardRef<HTMLButtonElement, React.ComponentProps<"button">>( - ({ className, ...props }, ref) => { - const { toggleSidebar } = useSidebar(); +const SidebarRail = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<"button"> +>(({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar() - return ( - <button - ref={ref} - data-sidebar="rail" - aria-label="Toggle Sidebar" - tabIndex={-1} - onClick={toggleSidebar} - title="Toggle Sidebar" - className={cn( - "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", - "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", - "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", - "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", - "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", - "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", - className, - )} - {...props} - /> - ); - }, -); -SidebarRail.displayName = "SidebarRail"; + return ( + <button + ref={ref} + data-sidebar="rail" + aria-label="Toggle Sidebar" + tabIndex={-1} + onClick={toggleSidebar} + title="Toggle Sidebar" + className={cn( + "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", + "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", + "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", + "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", + "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", + "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", + className + )} + {...props} + /> + ) +}) +SidebarRail.displayName = "SidebarRail" -const SidebarInset = React.forwardRef<HTMLDivElement, React.ComponentProps<"main">>( - ({ className, ...props }, ref) => { - return ( - <main - ref={ref} - className={cn( - "relative flex min-h-svh flex-1 flex-col bg-background", - "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow", - className, - )} - {...props} - /> - ); - }, -); -SidebarInset.displayName = "SidebarInset"; +const SidebarInset = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"main"> +>(({ className, ...props }, ref) => { + return ( + <main + ref={ref} + className={cn( + "relative flex min-h-svh flex-1 flex-col bg-background", + "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow", + className + )} + {...props} + /> + ) +}) +SidebarInset.displayName = "SidebarInset" const SidebarInput = React.forwardRef< React.ElementRef<typeof Input>, @@ -323,41 +342,43 @@ const SidebarInput = React.forwardRef< data-sidebar="input" className={cn( "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring", - className, + className )} {...props} /> - ); -}); -SidebarInput.displayName = "SidebarInput"; + ) +}) +SidebarInput.displayName = "SidebarInput" -const SidebarHeader = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( - ({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="header" - className={cn("flex flex-col gap-2 p-2", className)} - {...props} - /> - ); - }, -); -SidebarHeader.displayName = "SidebarHeader"; +const SidebarHeader = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> +>(({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="header" + className={cn("flex flex-col gap-2 p-2", className)} + {...props} + /> + ) +}) +SidebarHeader.displayName = "SidebarHeader" -const SidebarFooter = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( - ({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="footer" - className={cn("flex flex-col gap-2 p-2", className)} - {...props} - /> - ); - }, -); -SidebarFooter.displayName = "SidebarFooter"; +const SidebarFooter = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> +>(({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="footer" + className={cn("flex flex-col gap-2 p-2", className)} + {...props} + /> + ) +}) +SidebarFooter.displayName = "SidebarFooter" const SidebarSeparator = React.forwardRef< React.ElementRef<typeof Separator>, @@ -370,46 +391,48 @@ const SidebarSeparator = React.forwardRef< className={cn("mx-2 w-auto bg-sidebar-border", className)} {...props} /> - ); -}); -SidebarSeparator.displayName = "SidebarSeparator"; + ) +}) +SidebarSeparator.displayName = "SidebarSeparator" -const SidebarContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( - ({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="content" - className={cn( - "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", - className, - )} - {...props} - /> - ); - }, -); -SidebarContent.displayName = "SidebarContent"; +const SidebarContent = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> +>(({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="content" + className={cn( + "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", + className + )} + {...props} + /> + ) +}) +SidebarContent.displayName = "SidebarContent" -const SidebarGroup = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( - ({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="group" - className={cn("relative flex w-full min-w-0 flex-col p-2", className)} - {...props} - /> - ); - }, -); -SidebarGroup.displayName = "SidebarGroup"; +const SidebarGroup = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> +>(({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="group" + className={cn("relative flex w-full min-w-0 flex-col p-2", className)} + {...props} + /> + ) +}) +SidebarGroup.displayName = "SidebarGroup" const SidebarGroupLabel = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { asChild?: boolean } >(({ className, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "div"; + const Comp = asChild ? Slot : "div" return ( <Comp @@ -418,19 +441,19 @@ const SidebarGroupLabel = React.forwardRef< className={cn( "duration-200 flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", - className, + className )} {...props} /> - ); -}); -SidebarGroupLabel.displayName = "SidebarGroupLabel"; + ) +}) +SidebarGroupLabel.displayName = "SidebarGroupLabel" const SidebarGroupAction = React.forwardRef< HTMLButtonElement, React.ComponentProps<"button"> & { asChild?: boolean } >(({ className, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; + const Comp = asChild ? Slot : "button" return ( <Comp @@ -441,49 +464,52 @@ const SidebarGroupAction = React.forwardRef< // Increases the hit area of the button on mobile. "after:absolute after:-inset-2 after:md:hidden", "group-data-[collapsible=icon]:hidden", - className, + className )} {...props} /> - ); -}); -SidebarGroupAction.displayName = "SidebarGroupAction"; - -const SidebarGroupContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( - ({ className, ...props }, ref) => ( - <div - ref={ref} - data-sidebar="group-content" - className={cn("w-full text-sm", className)} - {...props} - /> - ), -); -SidebarGroupContent.displayName = "SidebarGroupContent"; - -const SidebarMenu = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>( - ({ className, ...props }, ref) => ( - <ul - ref={ref} - data-sidebar="menu" - className={cn("flex w-full min-w-0 flex-col gap-1", className)} - {...props} - /> - ), -); -SidebarMenu.displayName = "SidebarMenu"; + ) +}) +SidebarGroupAction.displayName = "SidebarGroupAction" -const SidebarMenuItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( - ({ className, ...props }, ref) => ( - <li - ref={ref} - data-sidebar="menu-item" - className={cn("group/menu-item relative", className)} - {...props} - /> - ), -); -SidebarMenuItem.displayName = "SidebarMenuItem"; +const SidebarGroupContent = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> +>(({ className, ...props }, ref) => ( + <div + ref={ref} + data-sidebar="group-content" + className={cn("w-full text-sm", className)} + {...props} + /> +)) +SidebarGroupContent.displayName = "SidebarGroupContent" + +const SidebarMenu = React.forwardRef< + HTMLUListElement, + React.ComponentProps<"ul"> +>(({ className, ...props }, ref) => ( + <ul + ref={ref} + data-sidebar="menu" + className={cn("flex w-full min-w-0 flex-col gap-1", className)} + {...props} + /> +)) +SidebarMenu.displayName = "SidebarMenu" + +const SidebarMenuItem = React.forwardRef< + HTMLLIElement, + React.ComponentProps<"li"> +>(({ className, ...props }, ref) => ( + <li + ref={ref} + data-sidebar="menu-item" + className={cn("group/menu-item relative", className)} + {...props} + /> +)) +SidebarMenuItem.displayName = "SidebarMenuItem" const sidebarMenuButtonVariants = cva( "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", @@ -504,15 +530,15 @@ const sidebarMenuButtonVariants = cva( variant: "default", size: "default", }, - }, -); + } +) const SidebarMenuButton = React.forwardRef< HTMLButtonElement, React.ComponentProps<"button"> & { - asChild?: boolean; - isActive?: boolean; - tooltip?: string | React.ComponentProps<typeof TooltipContent>; + asChild?: boolean + isActive?: boolean + tooltip?: string | React.ComponentProps<typeof TooltipContent> } & VariantProps<typeof sidebarMenuButtonVariants> >( ( @@ -525,10 +551,10 @@ const SidebarMenuButton = React.forwardRef< className, ...props }, - ref, + ref ) => { - const Comp = asChild ? Slot : "button"; - const { isMobile, state } = useSidebar(); + const Comp = asChild ? Slot : "button" + const { isMobile, state } = useSidebar() const button = ( <Comp @@ -539,16 +565,16 @@ const SidebarMenuButton = React.forwardRef< className={cn(sidebarMenuButtonVariants({ variant, size }), className)} {...props} /> - ); + ) if (!tooltip) { - return button; + return button } if (typeof tooltip === "string") { tooltip = { children: tooltip, - }; + } } return ( @@ -561,19 +587,19 @@ const SidebarMenuButton = React.forwardRef< {...tooltip} /> </Tooltip> - ); - }, -); -SidebarMenuButton.displayName = "SidebarMenuButton"; + ) + } +) +SidebarMenuButton.displayName = "SidebarMenuButton" const SidebarMenuAction = React.forwardRef< HTMLButtonElement, React.ComponentProps<"button"> & { - asChild?: boolean; - showOnHover?: boolean; + asChild?: boolean + showOnHover?: boolean } >(({ className, asChild = false, showOnHover = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; + const Comp = asChild ? Slot : "button" return ( <Comp @@ -589,52 +615,59 @@ const SidebarMenuAction = React.forwardRef< "group-data-[collapsible=icon]:hidden", showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0", - className, + className )} {...props} /> - ); -}); -SidebarMenuAction.displayName = "SidebarMenuAction"; + ) +}) +SidebarMenuAction.displayName = "SidebarMenuAction" -const SidebarMenuBadge = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( - ({ className, ...props }, ref) => ( - <div - ref={ref} - data-sidebar="menu-badge" - className={cn( - "absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground select-none pointer-events-none", - "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", - "peer-data-[size=sm]/menu-button:top-1", - "peer-data-[size=default]/menu-button:top-1.5", - "peer-data-[size=lg]/menu-button:top-2.5", - "group-data-[collapsible=icon]:hidden", - className, - )} - {...props} - /> - ), -); -SidebarMenuBadge.displayName = "SidebarMenuBadge"; +const SidebarMenuBadge = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> +>(({ className, ...props }, ref) => ( + <div + ref={ref} + data-sidebar="menu-badge" + className={cn( + "absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground select-none pointer-events-none", + "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", + "peer-data-[size=sm]/menu-button:top-1", + "peer-data-[size=default]/menu-button:top-1.5", + "peer-data-[size=lg]/menu-button:top-2.5", + "group-data-[collapsible=icon]:hidden", + className + )} + {...props} + /> +)) +SidebarMenuBadge.displayName = "SidebarMenuBadge" const SidebarMenuSkeleton = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - showIcon?: boolean; + showIcon?: boolean } >(({ className, showIcon = false, ...props }, ref) => { // Random width between 50 to 90%. const width = React.useMemo(() => { - return `${Math.floor(Math.random() * 40) + 50}%`; - }, []); + return `${Math.floor(Math.random() * 40) + 50}%` + }, []) return ( <div ref={ref} data-sidebar="menu-skeleton" className={cn("rounded-md h-8 flex gap-2 px-2 items-center", className)} - {...props}> - {showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />} + {...props} + > + {showIcon && ( + <Skeleton + className="size-4 rounded-md" + data-sidebar="menu-skeleton-icon" + /> + )} <Skeleton className="h-4 flex-1 max-w-[--skeleton-width]" data-sidebar="menu-skeleton-text" @@ -645,40 +678,42 @@ const SidebarMenuSkeleton = React.forwardRef< } /> </div> - ); -}); -SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton"; - -const SidebarMenuSub = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>( - ({ className, ...props }, ref) => ( - <ul - ref={ref} - data-sidebar="menu-sub" - className={cn( - "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", - "group-data-[collapsible=icon]:hidden", - className, - )} - {...props} - /> - ), -); -SidebarMenuSub.displayName = "SidebarMenuSub"; - -const SidebarMenuSubItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( - ({ ...props }, ref) => <li ref={ref} {...props} />, -); -SidebarMenuSubItem.displayName = "SidebarMenuSubItem"; + ) +}) +SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton" + +const SidebarMenuSub = React.forwardRef< + HTMLUListElement, + React.ComponentProps<"ul"> +>(({ className, ...props }, ref) => ( + <ul + ref={ref} + data-sidebar="menu-sub" + className={cn( + "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", + "group-data-[collapsible=icon]:hidden", + className + )} + {...props} + /> +)) +SidebarMenuSub.displayName = "SidebarMenuSub" + +const SidebarMenuSubItem = React.forwardRef< + HTMLLIElement, + React.ComponentProps<"li"> +>(({ ...props }, ref) => <li ref={ref} {...props} />) +SidebarMenuSubItem.displayName = "SidebarMenuSubItem" const SidebarMenuSubButton = React.forwardRef< HTMLAnchorElement, React.ComponentProps<"a"> & { - asChild?: boolean; - size?: "sm" | "md"; - isActive?: boolean; + asChild?: boolean + size?: "sm" | "md" + isActive?: boolean } >(({ asChild = false, size = "md", isActive, className, ...props }, ref) => { - const Comp = asChild ? Slot : "a"; + const Comp = asChild ? Slot : "a" return ( <Comp @@ -692,13 +727,13 @@ const SidebarMenuSubButton = React.forwardRef< size === "sm" && "text-xs", size === "md" && "text-sm", "group-data-[collapsible=icon]:hidden", - className, + className )} {...props} /> - ); -}); -SidebarMenuSubButton.displayName = "SidebarMenuSubButton"; + ) +}) +SidebarMenuSubButton.displayName = "SidebarMenuSubButton" export { Sidebar, @@ -725,4 +760,4 @@ export { SidebarSeparator, SidebarTrigger, useSidebar, -}; +} diff --git a/components/ui/skeleton.tsx b/components/ui/skeleton.tsx index 6690a13..01b8b6d 100644 --- a/components/ui/skeleton.tsx +++ b/components/ui/skeleton.tsx @@ -1,7 +1,15 @@ -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) { - return <div className={cn("animate-pulse rounded-md bg-muted", className)} {...props} />; +function Skeleton({ + className, + ...props +}: React.HTMLAttributes<HTMLDivElement>) { + return ( + <div + className={cn("animate-pulse rounded-md bg-muted", className)} + {...props} + /> + ) } -export { Skeleton }; +export { Skeleton } diff --git a/components/ui/slider.tsx b/components/ui/slider.tsx index d4d1df7..c31c2b3 100644 --- a/components/ui/slider.tsx +++ b/components/ui/slider.tsx @@ -1,9 +1,9 @@ -"use client"; +"use client" -import * as React from "react"; -import * as SliderPrimitive from "@radix-ui/react-slider"; +import * as React from "react" +import * as SliderPrimitive from "@radix-ui/react-slider" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Slider = React.forwardRef< React.ElementRef<typeof SliderPrimitive.Root>, @@ -11,14 +11,18 @@ const Slider = React.forwardRef< >(({ className, ...props }, ref) => ( <SliderPrimitive.Root ref={ref} - className={cn("relative flex w-full touch-none select-none items-center", className)} - {...props}> + className={cn( + "relative flex w-full touch-none select-none items-center", + className + )} + {...props} + > <SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> <SliderPrimitive.Range className="absolute h-full bg-primary" /> </SliderPrimitive.Track> <SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background 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" /> </SliderPrimitive.Root> -)); -Slider.displayName = SliderPrimitive.Root.displayName; +)) +Slider.displayName = SliderPrimitive.Root.displayName -export { Slider }; +export { Slider } diff --git a/components/ui/sonner.tsx b/components/ui/sonner.tsx index 8d084f8..452f4d9 100644 --- a/components/ui/sonner.tsx +++ b/components/ui/sonner.tsx @@ -1,12 +1,12 @@ -"use client"; +"use client" -import { useTheme } from "next-themes"; -import { Toaster as Sonner } from "sonner"; +import { useTheme } from "next-themes" +import { Toaster as Sonner } from "sonner" -type ToasterProps = React.ComponentProps<typeof Sonner>; +type ToasterProps = React.ComponentProps<typeof Sonner> const Toaster = ({ ...props }: ToasterProps) => { - const { theme = "system" } = useTheme(); + const { theme = "system" } = useTheme() return ( <Sonner @@ -17,13 +17,15 @@ const Toaster = ({ ...props }: ToasterProps) => { toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg", description: "group-[.toast]:text-muted-foreground", - actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", - cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", + actionButton: + "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", + cancelButton: + "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", }, }} {...props} /> - ); -}; + ) +} -export { Toaster }; +export { Toaster } diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx index 728ed7f..bc69cf2 100644 --- a/components/ui/switch.tsx +++ b/components/ui/switch.tsx @@ -1,9 +1,9 @@ -"use client"; +"use client" -import * as React from "react"; -import * as SwitchPrimitives from "@radix-ui/react-switch"; +import * as React from "react" +import * as SwitchPrimitives from "@radix-ui/react-switch" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const Switch = React.forwardRef< React.ElementRef<typeof SwitchPrimitives.Root>, @@ -12,17 +12,18 @@ const Switch = React.forwardRef< <SwitchPrimitives.Root className={cn( "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", - className, + className )} {...props} - ref={ref}> + ref={ref} + > <SwitchPrimitives.Thumb className={cn( - "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0", + "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0" )} /> </SwitchPrimitives.Root> -)); -Switch.displayName = SwitchPrimitives.Root.displayName; +)) +Switch.displayName = SwitchPrimitives.Root.displayName -export { Switch }; +export { Switch } diff --git a/components/ui/table.tsx b/components/ui/table.tsx index 07184f5..32355b3 100644 --- a/components/ui/table.tsx +++ b/components/ui/table.tsx @@ -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, React.HTMLAttributes<HTMLTableElement>>( ({ className, ...props }, ref) => ( @@ -8,84 +8,66 @@ const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableE <table ref={ref} className={cn("w-full caption-bottom text-sm", className)} {...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"; +const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>( + ({ className, ...props }, ref) => <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />, +) +TableHeader.displayName = "TableHeader" -const TableBody = React.forwardRef< - HTMLTableSectionElement, - React.HTMLAttributes<HTMLTableSectionElement> ->(({ className, ...props }, ref) => ( - <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} /> -)); -TableBody.displayName = "TableBody"; +const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>( + ({ className, ...props }, ref) => ( + <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} /> + ), +) +TableBody.displayName = "TableBody" -const TableFooter = React.forwardRef< - HTMLTableSectionElement, - React.HTMLAttributes<HTMLTableSectionElement> ->(({ className, ...props }, ref) => ( - <tfoot - ref={ref} - className={cn("bg-primary font-medium text-primary-foreground", className)} - {...props} - /> -)); -TableFooter.displayName = "TableFooter"; +const TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>( + ({ className, ...props }, ref) => ( + <tfoot ref={ref} className={cn("bg-primary font-medium text-primary-foreground", className)} {...props} /> + ), +) +TableFooter.displayName = "TableFooter" const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>( ({ className, ...props }, ref) => ( <tr + ref={ref} + className={cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className)} + {...props} + /> + ), +) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>( + ({ className, ...props }, ref) => ( + <th ref={ref} className={cn( - "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", + "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", className, )} {...props} /> ), -); -TableRow.displayName = "TableRow"; +) +TableHead.displayName = "TableHead" -const TableHead = React.forwardRef< - HTMLTableCellElement, - React.ThHTMLAttributes<HTMLTableCellElement> ->(({ className, ...props }, ref) => ( - <th - ref={ref} - className={cn( - "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", - className, - )} - {...props} - /> -)); -TableHead.displayName = "TableHead"; +const TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>( + ({ className, ...props }, ref) => ( + <td ref={ref} className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)} {...props} /> + ), +) +TableCell.displayName = "TableCell" -const TableCell = React.forwardRef< - HTMLTableCellElement, - React.TdHTMLAttributes<HTMLTableCellElement> ->(({ className, ...props }, ref) => ( - <td - ref={ref} - className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)} - {...props} - /> -)); -TableCell.displayName = "TableCell"; +const TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>( + ({ className, ...props }, ref) => ( + <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} /> + ), +) +TableCaption.displayName = "TableCaption" -const TableCaption = React.forwardRef< - HTMLTableCaptionElement, - React.HTMLAttributes<HTMLTableCaptionElement> ->(({ className, ...props }, ref) => ( - <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} /> -)); -TableCaption.displayName = "TableCaption"; +export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } -export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }; diff --git a/components/ui/tabs.tsx b/components/ui/tabs.tsx index ca123a0..26eb109 100644 --- a/components/ui/tabs.tsx +++ b/components/ui/tabs.tsx @@ -1,11 +1,11 @@ -"use client"; +"use client" -import * as React from "react"; -import * as TabsPrimitive from "@radix-ui/react-tabs"; +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const Tabs = TabsPrimitive.Root; +const Tabs = TabsPrimitive.Root const TabsList = React.forwardRef< React.ElementRef<typeof TabsPrimitive.List>, @@ -15,12 +15,12 @@ const TabsList = React.forwardRef< ref={ref} className={cn( "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", - className, + className )} {...props} /> -)); -TabsList.displayName = TabsPrimitive.List.displayName; +)) +TabsList.displayName = TabsPrimitive.List.displayName const TabsTrigger = React.forwardRef< React.ElementRef<typeof TabsPrimitive.Trigger>, @@ -30,12 +30,12 @@ const TabsTrigger = React.forwardRef< ref={ref} className={cn( "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm", - className, + className )} {...props} /> -)); -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName const TabsContent = React.forwardRef< React.ElementRef<typeof TabsPrimitive.Content>, @@ -45,11 +45,11 @@ const TabsContent = React.forwardRef< ref={ref} className={cn( "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", - className, + className )} {...props} /> -)); -TabsContent.displayName = TabsPrimitive.Content.displayName; +)) +TabsContent.displayName = TabsPrimitive.Content.displayName -export { Tabs, TabsList, TabsTrigger, TabsContent }; +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx index 69391b2..4d858bb 100644 --- a/components/ui/textarea.tsx +++ b/components/ui/textarea.tsx @@ -1,21 +1,22 @@ -import * as React from "react"; +import * as React from "react" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<"textarea">>( - ({ className, ...props }, ref) => { - return ( - <textarea - className={cn( - "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", - className, - )} - ref={ref} - {...props} - /> - ); - }, -); -Textarea.displayName = "Textarea"; +const Textarea = React.forwardRef< + HTMLTextAreaElement, + React.ComponentProps<"textarea"> +>(({ className, ...props }, ref) => { + return ( + <textarea + className={cn( + "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", + className + )} + ref={ref} + {...props} + /> + ) +}) +Textarea.displayName = "Textarea" -export { Textarea }; +export { Textarea } diff --git a/components/ui/toast.tsx b/components/ui/toast.tsx index cc51d5f..521b94b 100644 --- a/components/ui/toast.tsx +++ b/components/ui/toast.tsx @@ -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>, @@ -17,12 +17,12 @@ const ToastViewport = React.forwardRef< ref={ref} className={cn( "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]", - className, + className )} {...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", @@ -37,12 +37,13 @@ const toastVariants = cva( defaultVariants: { variant: "default", }, - }, -); + } +) const Toast = React.forwardRef< React.ElementRef<typeof ToastPrimitives.Root>, - React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants> + React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & + VariantProps<typeof toastVariants> >(({ className, variant, ...props }, ref) => { return ( <ToastPrimitives.Root @@ -50,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>, @@ -62,12 +63,12 @@ const ToastAction = React.forwardRef< ref={ref} className={cn( "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive", - className, + className )} {...props} /> -)); -ToastAction.displayName = ToastPrimitives.Action.displayName; +)) +ToastAction.displayName = ToastPrimitives.Action.displayName const ToastClose = React.forwardRef< React.ElementRef<typeof ToastPrimitives.Close>, @@ -77,22 +78,27 @@ const ToastClose = React.forwardRef< ref={ref} className={cn( "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600", - className, + className )} toast-close="" - {...props}> + {...props} + > <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>, React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title> >(({ className, ...props }, ref) => ( - <ToastPrimitives.Title ref={ref} className={cn("text-sm font-semibold", className)} {...props} /> -)); -ToastTitle.displayName = ToastPrimitives.Title.displayName; + <ToastPrimitives.Title + ref={ref} + className={cn("text-sm font-semibold", className)} + {...props} + /> +)) +ToastTitle.displayName = ToastPrimitives.Title.displayName const ToastDescription = React.forwardRef< React.ElementRef<typeof ToastPrimitives.Description>, @@ -103,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, @@ -120,4 +126,4 @@ export { ToastDescription, ToastClose, ToastAction, -}; +} diff --git a/components/ui/toaster.tsx b/components/ui/toaster.tsx index bdda26e..171beb4 100644 --- a/components/ui/toaster.tsx +++ b/components/ui/toaster.tsx @@ -1,6 +1,6 @@ -"use client"; +"use client" -import { useToast } from "@/hooks/use-toast"; +import { useToast } from "@/hooks/use-toast" import { Toast, ToastClose, @@ -8,10 +8,10 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@/components/ui/toast"; +} from "@/components/ui/toast" export function Toaster() { - const { toasts } = useToast(); + const { toasts } = useToast() return ( <ToastProvider> @@ -20,14 +20,16 @@ export function Toaster() { <Toast key={id} {...props}> <div className="grid gap-1"> {title && <ToastTitle>{title}</ToastTitle>} - {description && <ToastDescription>{description}</ToastDescription>} + {description && ( + <ToastDescription>{description}</ToastDescription> + )} </div> {action} <ToastClose /> </Toast> - ); + ) })} <ToastViewport /> </ToastProvider> - ); + ) } diff --git a/components/ui/toggle-group.tsx b/components/ui/toggle-group.tsx index ff17f9b..1c876bb 100644 --- a/components/ui/toggle-group.tsx +++ b/components/ui/toggle-group.tsx @@ -1,16 +1,18 @@ -"use client"; +"use client" -import * as React from "react"; -import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"; -import { type VariantProps } from "class-variance-authority"; +import * as React from "react" +import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" +import { type VariantProps } from "class-variance-authority" -import { cn } from "@/lib/utils"; -import { toggleVariants } from "@/components/ui/toggle"; +import { cn } from "@/lib/utils" +import { toggleVariants } from "@/components/ui/toggle" -const ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants>>({ +const ToggleGroupContext = React.createContext< + VariantProps<typeof toggleVariants> +>({ size: "default", variant: "default", -}); +}) const ToggleGroup = React.forwardRef< React.ElementRef<typeof ToggleGroupPrimitive.Root>, @@ -20,19 +22,22 @@ const ToggleGroup = React.forwardRef< <ToggleGroupPrimitive.Root ref={ref} className={cn("flex items-center justify-center gap-1", className)} - {...props}> - <ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider> + {...props} + > + <ToggleGroupContext.Provider value={{ variant, size }}> + {children} + </ToggleGroupContext.Provider> </ToggleGroupPrimitive.Root> -)); +)) -ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName; +ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName const ToggleGroupItem = React.forwardRef< React.ElementRef<typeof ToggleGroupPrimitive.Item>, React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants> >(({ className, children, variant, size, ...props }, ref) => { - const context = React.useContext(ToggleGroupContext); + const context = React.useContext(ToggleGroupContext) return ( <ToggleGroupPrimitive.Item @@ -42,14 +47,15 @@ const ToggleGroupItem = React.forwardRef< variant: context.variant || variant, size: context.size || size, }), - className, + className )} - {...props}> + {...props} + > {children} </ToggleGroupPrimitive.Item> - ); -}); + ) +}) -ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName; +ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName -export { ToggleGroup, ToggleGroupItem }; +export { ToggleGroup, ToggleGroupItem } diff --git a/components/ui/toggle.tsx b/components/ui/toggle.tsx index fa4a988..c19bea3 100644 --- a/components/ui/toggle.tsx +++ b/components/ui/toggle.tsx @@ -1,10 +1,10 @@ -"use client"; +"use client" -import * as React from "react"; -import * as TogglePrimitive from "@radix-ui/react-toggle"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react" +import * as TogglePrimitive from "@radix-ui/react-toggle" +import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const toggleVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2", @@ -12,7 +12,8 @@ const toggleVariants = cva( variants: { variant: { default: "bg-transparent", - outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", }, size: { default: "h-10 px-3 min-w-10", @@ -24,20 +25,21 @@ const toggleVariants = cva( variant: "default", size: "default", }, - }, -); + } +) const Toggle = React.forwardRef< React.ElementRef<typeof TogglePrimitive.Root>, - React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants> + React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & + VariantProps<typeof toggleVariants> >(({ className, variant, size, ...props }, ref) => ( <TogglePrimitive.Root ref={ref} className={cn(toggleVariants({ variant, size, className }))} {...props} /> -)); +)) -Toggle.displayName = TogglePrimitive.Root.displayName; +Toggle.displayName = TogglePrimitive.Root.displayName -export { Toggle, toggleVariants }; +export { Toggle, toggleVariants } diff --git a/components/ui/tooltip.tsx b/components/ui/tooltip.tsx index 2c42a2c..9006050 100644 --- a/components/ui/tooltip.tsx +++ b/components/ui/tooltip.tsx @@ -1,15 +1,15 @@ -"use client"; +"use client" -import * as React from "react"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import * as React from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const TooltipProvider = TooltipPrimitive.Provider; +const TooltipProvider = TooltipPrimitive.Provider -const Tooltip = TooltipPrimitive.Root; +const Tooltip = TooltipPrimitive.Root -const TooltipTrigger = TooltipPrimitive.Trigger; +const TooltipTrigger = TooltipPrimitive.Trigger const TooltipContent = React.forwardRef< React.ElementRef<typeof TooltipPrimitive.Content>, @@ -24,7 +24,8 @@ const TooltipContent = React.forwardRef< )} {...props} /> -)); -TooltipContent.displayName = TooltipPrimitive.Content.displayName; +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/components/ui/use-mobile.tsx b/components/ui/use-mobile.tsx index 502fd32..2b0fe1d 100644 --- a/components/ui/use-mobile.tsx +++ b/components/ui/use-mobile.tsx @@ -1,19 +1,19 @@ -import * as React from "react"; +import * as React from "react" -const MOBILE_BREAKPOINT = 768; +const MOBILE_BREAKPOINT = 768 export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined); + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - }; - mql.addEventListener("change", onChange); - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - return () => mql.removeEventListener("change", onChange); - }, []); + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + } + mql.addEventListener("change", onChange) + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + return () => mql.removeEventListener("change", onChange) + }, []) - return !!isMobile; + return !!isMobile } diff --git a/components/ui/use-toast.ts b/components/ui/use-toast.ts index 74b72e2..02e111d 100644 --- a/components/ui/use-toast.ts +++ b/components/ui/use-toast.ts @@ -1,75 +1,78 @@ -"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; +} 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); + }) + }, TOAST_REMOVE_DELAY) - toastTimeouts.set(toastId, timeout); -}; + toastTimeouts.set(toastId, timeout) +} export const reducer = (state: State, action: Action): State => { switch (action.type) { @@ -77,25 +80,27 @@ export const reducer = (state: State, action: Action): State => { return { ...state, 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)), - }; + 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 { @@ -106,46 +111,46 @@ export const reducer = (state: State, action: Action): State => { ...t, open: false, } - : t, + : t ), - }; + } } case "REMOVE_TOAST": if (action.toastId === undefined) { return { ...state, toasts: [], - }; + } } return { ...state, 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 }); + }) + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) dispatch({ type: "ADD_TOAST", @@ -154,36 +159,36 @@ function toast({ ...props }: Toast) { id, open: true, onOpenChange: (open) => { - if (!open) dismiss(); + if (!open) dismiss() }, }, - }); + }) return { id: id, dismiss, 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 }), - }; + } } -export { useToast, toast }; +export { useToast, toast } diff --git a/hooks/use-mobile.tsx b/hooks/use-mobile.tsx index 502fd32..2b0fe1d 100644 --- a/hooks/use-mobile.tsx +++ b/hooks/use-mobile.tsx @@ -1,19 +1,19 @@ -import * as React from "react"; +import * as React from "react" -const MOBILE_BREAKPOINT = 768; +const MOBILE_BREAKPOINT = 768 export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined); + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - }; - mql.addEventListener("change", onChange); - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - return () => mql.removeEventListener("change", onChange); - }, []); + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + } + mql.addEventListener("change", onChange) + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + return () => mql.removeEventListener("change", onChange) + }, []) - return !!isMobile; + return !!isMobile } diff --git a/hooks/use-toast.ts b/hooks/use-toast.ts index 74b72e2..02e111d 100644 --- a/hooks/use-toast.ts +++ b/hooks/use-toast.ts @@ -1,75 +1,78 @@ -"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; +} 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); + }) + }, TOAST_REMOVE_DELAY) - toastTimeouts.set(toastId, timeout); -}; + toastTimeouts.set(toastId, timeout) +} export const reducer = (state: State, action: Action): State => { switch (action.type) { @@ -77,25 +80,27 @@ export const reducer = (state: State, action: Action): State => { return { ...state, 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)), - }; + 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 { @@ -106,46 +111,46 @@ export const reducer = (state: State, action: Action): State => { ...t, open: false, } - : t, + : t ), - }; + } } case "REMOVE_TOAST": if (action.toastId === undefined) { return { ...state, toasts: [], - }; + } } return { ...state, 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 }); + }) + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) dispatch({ type: "ADD_TOAST", @@ -154,36 +159,36 @@ function toast({ ...props }: Toast) { id, open: true, onOpenChange: (open) => { - if (!open) dismiss(); + if (!open) dismiss() }, }, - }); + }) return { id: id, dismiss, 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 }), - }; + } } -export { useToast, toast }; +export { useToast, toast } diff --git a/lib/utils.ts b/lib/utils.ts index 365058c..bd0b3ae 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,6 +1,7 @@ -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)) } + diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..40c3d68 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,5 @@ +/// <reference types="next" /> +/// <reference types="next/image-types/global" /> + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/next-sitemap.config.js b/next-sitemap.config.js new file mode 100644 index 0000000..94b8b39 --- /dev/null +++ b/next-sitemap.config.js @@ -0,0 +1,6 @@ +/** @type {import('next-sitemap').IConfig} */ +module.exports = { + siteUrl: process.env.SITE_URL || "https://securerpc.com", + generateRobotsTxt: true, // (optional) + // ...other options +} diff --git a/tsconfig.json b/tsconfig.json index 364f802..baae42c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,20 @@ { "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "target": "ES2020", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, + "noImplicitAny": false, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", + "module": "ES2020", + "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", @@ -20,10 +25,20 @@ } ], "paths": { - "@/*": ["./*"] + "@/*": [ + "./*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules", + "_config", + "public" + ] } - diff --git a/v0-user-next.config.js b/v0-user-next.config.js deleted file mode 100644 index 91ef62f..0000000 --- a/v0-user-next.config.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, -}; - -module.exports = nextConfig; From f03367fabd916be518925a309f788baea51aca04 Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 06:01:36 -0800 Subject: [PATCH 2/7] fix(biome): fmt --- app/blog/[slug]/page.tsx | 49 +- app/blog/page.tsx | 35 +- app/case-studies/page.tsx | 10 +- app/changelog/page.tsx | 70 +- app/components/api-endpoint.tsx | 7 +- app/components/background-paths.tsx | 65 +- app/components/breadcrumb.tsx | 27 +- app/components/command-menu.tsx | 92 +-- app/components/cta-section.tsx | 22 +- app/components/docs-sidebar.tsx | 33 +- app/components/error-boundary.tsx | 30 +- app/components/feature-grid.tsx | 15 +- app/components/feature-section.tsx | 16 +- app/components/footer.tsx | 23 +- app/components/header.tsx | 68 +- app/components/layout-wrapper.tsx | 17 +- app/components/logo.tsx | 3 +- app/components/lst-apy-graph.tsx | 35 +- app/components/lst-apy-trend-graph.tsx | 38 +- app/components/lst-comparison-table.tsx | 32 +- app/components/main-nav.tsx | 55 +- app/components/mev-protection-comparison.tsx | 52 +- app/components/privacy-section.tsx | 10 +- app/components/search-button.tsx | 18 +- .../getting-started/installation/page.tsx | 5 +- .../getting-started/introduction/page.tsx | 13 +- app/docs/layout.tsx | 11 +- app/docs/page.tsx | 35 +- app/docs/securerpc/api-reference/page.tsx | 10 +- app/fold-token/page.tsx | 58 +- app/globals.css | 1 - app/layout.tsx | 39 +- app/page.tsx | 5 +- app/products/captive-insurance/page.tsx | 31 +- app/products/fold-staking/page.tsx | 21 +- app/products/meveth/page.tsx | 17 +- app/products/securerpc/page.tsx | 21 +- app/products/xga/page.tsx | 17 +- app/solutions/auction-markets/page.tsx | 9 +- app/solutions/avs-operations/page.tsx | 9 +- app/solutions/hedging-execution/page.tsx | 22 +- app/solutions/mev-relay-protection/page.tsx | 9 +- app/solutions/mev/page.tsx | 11 +- app/solutions/page.tsx | 12 +- app/solutions/relay-protect/page.tsx | 55 +- app/solutions/restaking/page.tsx | 11 +- app/solutions/staking/page.tsx | 23 +- app/technology/page.tsx | 14 +- components/icons.tsx | 13 +- components/theme-provider.tsx | 11 +- components/ui/accordion.tsx | 40 +- components/ui/alert-dialog.tsx | 90 +-- components/ui/alert.tsx | 54 +- components/ui/aspect-ratio.tsx | 8 +- components/ui/avatar.tsx | 29 +- components/ui/badge.tsx | 17 +- components/ui/breadcrumb.tsx | 122 ++-- components/ui/button.tsx | 25 +- components/ui/calendar.tsx | 37 +- components/ui/card.tsx | 60 +- components/ui/carousel.tsx | 396 +++++----- components/ui/chart.tsx | 284 ++++---- components/ui/checkbox.tsx | 25 +- components/ui/collapsible.tsx | 12 +- components/ui/command.tsx | 78 +- components/ui/context-menu.tsx | 106 ++- components/ui/dialog.tsx | 59 +- components/ui/drawer.tsx | 79 +- components/ui/dropdown-menu.tsx | 108 ++- components/ui/form.tsx | 126 ++-- components/ui/hover-card.tsx | 19 +- components/ui/input-otp.tsx | 41 +- components/ui/input.tsx | 37 +- components/ui/label.tsx | 29 +- components/ui/menubar.tsx | 146 ++-- components/ui/navigation-menu.tsx | 54 +- components/ui/pagination.tsx | 90 +-- components/ui/popover.tsx | 20 +- components/ui/progress.tsx | 22 +- components/ui/radio-group.tsx | 35 +- components/ui/resizable.tsx | 28 +- components/ui/scroll-area.tsx | 31 +- components/ui/select.tsx | 83 +-- components/ui/separator.tsx | 43 +- components/ui/sheet.tsx | 81 +-- components/ui/sidebar.tsx | 675 +++++++++--------- components/ui/skeleton.tsx | 16 +- components/ui/slider.tsx | 22 +- components/ui/sonner.tsx | 22 +- components/ui/switch.tsx | 21 +- components/ui/table.tsx | 112 +-- components/ui/tabs.tsx | 30 +- components/ui/textarea.tsx | 37 +- components/ui/toast.tsx | 68 +- components/ui/toaster.tsx | 16 +- components/ui/toggle-group.tsx | 44 +- components/ui/toggle.tsx | 26 +- components/ui/tooltip.tsx | 21 +- components/ui/use-mobile.tsx | 22 +- components/ui/use-toast.ts | 133 ++-- hooks/use-mobile.tsx | 22 +- hooks/use-toast.ts | 133 ++-- lib/utils.ts | 7 +- next-sitemap.config.js | 2 +- 104 files changed, 2506 insertions(+), 2742 deletions(-) diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index 77fd324..5b89b18 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -1,43 +1,43 @@ -import { notFound } from "next/navigation" -import { Badge } from "@/components/ui/badge" +import { notFound } from "next/navigation"; +import { Badge } from "@/components/ui/badge"; interface BlogPost { - slug: string - title: string - date: string - content: string - category: string + slug: string; + title: string; + date: string; + content: string; + category: string; } // Simulating an API call with a timeout async function fetchBlogPost(slug: string): Promise<BlogPost | null> { return new Promise((resolve) => { setTimeout(() => { - const post = blogPosts.find((post) => post.slug === slug) - resolve(post || null) - }, 100) // 100ms timeout to simulate API call - }) + const post = blogPosts.find((post) => post.slug === slug); + resolve(post || null); + }, 100); // 100ms timeout to simulate API call + }); } export async function generateStaticParams() { // In a real application, you would fetch this data from an API or database return blogPosts.map((post) => ({ slug: post.slug, - })) + })); } export async function generateMetadata({ params }: { params: { slug: string } }) { - const post = await fetchBlogPost(params.slug) + const post = await fetchBlogPost(params.slug); if (!post) { return { title: "Post Not Found", - } + }; } return { title: post.title, - } + }; } const blogPosts: BlogPost[] = [ @@ -149,7 +149,7 @@ const blogPosts: BlogPost[] = [ <p>As the Ethereum ecosystem evolves, Manifold Finance remains committed to providing cutting-edge solutions that leverage the latest scaling technologies.</p> `, }, -] +]; function CategoryBadge({ category }: { category: string }) { return ( @@ -161,18 +161,17 @@ function CategoryBadge({ category }: { category: string }) { : category === "Tutorial" ? "bg-green-500/10 text-green-500 hover:bg-green-500/20" : "bg-purple-500/10 text-purple-500 hover:bg-purple-500/20" - } - > + }> {category} </Badge> - ) + ); } export default async function BlogPost({ params }: { params: { slug: string } }) { - const post = await fetchBlogPost(params.slug) + const post = await fetchBlogPost(params.slug); if (!post) { - notFound() + notFound(); } return ( @@ -186,10 +185,12 @@ export default async function BlogPost({ params }: { params: { slug: string } }) </div> <h1 className="text-4xl font-heading">{post.title}</h1> </div> - <div className="prose dark:prose-invert max-w-none" dangerouslySetInnerHTML={{ __html: post.content }} /> + <div + className="prose dark:prose-invert max-w-none" + dangerouslySetInnerHTML={{ __html: post.content }} + /> </article> </div> </div> - ) + ); } - diff --git a/app/blog/page.tsx b/app/blog/page.tsx index 4749a8c..b7cd28a 100644 --- a/app/blog/page.tsx +++ b/app/blog/page.tsx @@ -1,21 +1,21 @@ -import Link from "next/link" -import { Badge } from "@/components/ui/badge" +import Link from "next/link"; +import { Badge } from "@/components/ui/badge"; interface BlogPost { - slug: string - title: string - date: string - excerpt: string - category: string + slug: string; + title: string; + date: string; + excerpt: string; + category: string; } // Simulating an API call with a timeout async function fetchBlogPosts(): Promise<BlogPost[]> { return new Promise((resolve) => { setTimeout(() => { - resolve(blogPosts) - }, 100) // 100ms timeout to simulate API call - }) + resolve(blogPosts); + }, 100); // 100ms timeout to simulate API call + }); } const blogPosts: BlogPost[] = [ @@ -31,7 +31,8 @@ const blogPosts: BlogPost[] = [ slug: "optimizing-defi-strategies", title: "Optimizing DeFi Strategies with Manifold Finance", date: "February 1, 2025", - excerpt: "Discover how to leverage Manifold Finance's tools to optimize your DeFi strategies and maximize returns.", + excerpt: + "Discover how to leverage Manifold Finance's tools to optimize your DeFi strategies and maximize returns.", category: "Tutorial", }, { @@ -42,7 +43,7 @@ const blogPosts: BlogPost[] = [ "We share our thoughts on the future of Ethereum scaling solutions and how Manifold Finance is positioned to support the ecosystem.", category: "Industry Insights", }, -] +]; function CategoryBadge({ category }: { category: string }) { return ( @@ -54,15 +55,14 @@ function CategoryBadge({ category }: { category: string }) { : category === "Tutorial" ? "bg-green-500/10 text-green-500 hover:bg-green-500/20" : "bg-purple-500/10 text-purple-500 hover:bg-purple-500/20" - } - > + }> {category} </Badge> - ) + ); } export default async function BlogPage() { - const posts = await fetchBlogPosts() + const posts = await fetchBlogPosts(); return ( <div className="min-h-screen bg-background"> @@ -89,6 +89,5 @@ export default async function BlogPage() { </div> </div> </div> - ) + ); } - diff --git a/app/case-studies/page.tsx b/app/case-studies/page.tsx index 76e4e70..cd25a97 100644 --- a/app/case-studies/page.tsx +++ b/app/case-studies/page.tsx @@ -1,9 +1,12 @@ -import { BackgroundPaths } from "../components/background-paths" +import { BackgroundPaths } from "../components/background-paths"; export default function CaseStudiesPage() { return ( <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths title="Case Studies|" subtitle="See how leading projects are leveraging Manifold Finance" /> + <BackgroundPaths + title="Case Studies|" + subtitle="See how leading projects are leveraging Manifold Finance" + /> <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Success Stories</h2> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> @@ -23,6 +26,5 @@ export default function CaseStudiesPage() { </div> </main> </div> - ) + ); } - diff --git a/app/changelog/page.tsx b/app/changelog/page.tsx index d2ab3ad..a17d03c 100644 --- a/app/changelog/page.tsx +++ b/app/changelog/page.tsx @@ -1,26 +1,26 @@ -import { Badge } from "@/components/ui/badge" -import { ArrowLeft, ArrowRight } from "lucide-react" -import Link from "next/link" +import { Badge } from "@/components/ui/badge"; +import { ArrowLeft, ArrowRight } from "lucide-react"; +import Link from "next/link"; interface ChangelogEntry { - date: string - version: string - platform: string - title: string - type: "public" | "beta" | "alpha" - changes: string[] + date: string; + version: string; + platform: string; + title: string; + type: "public" | "beta" | "alpha"; + changes: string[]; previousRelease?: { - date: string - version: string - platform: string - type: "public" | "beta" | "alpha" - } + date: string; + version: string; + platform: string; + type: "public" | "beta" | "alpha"; + }; nextRelease?: { - date: string - version: string - platform: string - type: "public" | "beta" | "alpha" - } + date: string; + version: string; + platform: string; + type: "public" | "beta" | "alpha"; + }; } const changelog: ChangelogEntry = { @@ -46,7 +46,7 @@ const changelog: ChangelogEntry = { platform: "Mobile", type: "public", }, -} +}; function VersionBadge({ type }: { type: ChangelogEntry["type"] }) { return ( @@ -58,11 +58,10 @@ function VersionBadge({ type }: { type: ChangelogEntry["type"] }) { : type === "beta" ? "bg-yellow-500/10 text-yellow-500 hover:bg-yellow-500/20" : "bg-blue-500/10 text-blue-500 hover:bg-blue-500/20" - } - > + }> {type} </Badge> - ) + ); } function ReleaseNavigation({ @@ -72,14 +71,16 @@ function ReleaseNavigation({ version, platform, }: { - type: "previous" | "next" - direction: "left" | "right" - date: string - version: string - platform: string + type: "previous" | "next"; + direction: "left" | "right"; + date: string; + version: string; + platform: string; }) { return ( - <Link href="#" className="block p-6 rounded-lg border border-border bg-card hover:bg-accent transition-colors"> + <Link + href="#" + className="block p-6 rounded-lg border border-border bg-card hover:bg-accent transition-colors"> <div className="flex items-center gap-2 text-sm text-muted-foreground mb-4"> {direction === "left" && <ArrowLeft className="w-4 h-4" />} {type === "previous" ? "Previous" : "Next"} release @@ -92,7 +93,7 @@ function ReleaseNavigation({ </div> </div> </Link> - ) + ); } export default function ChangelogPage() { @@ -120,8 +121,10 @@ export default function ChangelogPage() { {change.includes("Enter") ? ( <> Fixed bug where pressing{" "} - <code className="px-1.5 py-0.5 rounded-md bg-muted font-mono text-sm">Enter</code> inside a - blockquote would not continue the blockquote onto the next line. + <code className="px-1.5 py-0.5 rounded-md bg-muted font-mono text-sm"> + Enter + </code>{" "} + inside a blockquote would not continue the blockquote onto the next line. </> ) : ( change @@ -154,6 +157,5 @@ export default function ChangelogPage() { </article> </div> </div> - ) + ); } - diff --git a/app/components/api-endpoint.tsx b/app/components/api-endpoint.tsx index 624100d..9ec5cd7 100644 --- a/app/components/api-endpoint.tsx +++ b/app/components/api-endpoint.tsx @@ -1,5 +1,5 @@ -import { Button } from "@/components/ui/button" -import { Input } from "@/components/ui/input" +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; export function APIEndpoint() { return ( @@ -20,6 +20,5 @@ export function APIEndpoint() { Get started with our SecureRPC API for reliable and secure blockchain interactions. </p> </div> - ) + ); } - diff --git a/app/components/background-paths.tsx b/app/components/background-paths.tsx index 7b865e7..471149b 100644 --- a/app/components/background-paths.tsx +++ b/app/components/background-paths.tsx @@ -1,24 +1,24 @@ -"use client" +"use client"; -import { motion } from "framer-motion" -import { Button } from "@/components/ui/button" -import Link from "next/link" +import { motion } from "framer-motion"; +import { Button } from "@/components/ui/button"; +import Link from "next/link"; interface BackgroundPathsProps { - title: string - subtitle?: string + title: string; + subtitle?: string; primaryCta?: { - href: string - text: string - variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" - className?: string - } + href: string; + text: string; + variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"; + className?: string; + }; secondaryCta?: { - href: string - text: string - variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" - className?: string - } + href: string; + text: string; + variant: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"; + className?: string; + }; } function FloatingPaths({ position }: { position: number }) { @@ -31,7 +31,7 @@ function FloatingPaths({ position }: { position: number }) { } ${1600 + i * 20 * position} ${1600 - i * 25} ${1600 + i * 20 * position} ${1600 - i * 25}`, color: `rgba(124,228,108,${0.02 + i * 0.015})`, width: 0.5 + i * 0.05, - })) + })); return ( <div className="absolute inset-0 pointer-events-none"> @@ -59,12 +59,17 @@ function FloatingPaths({ position }: { position: number }) { ))} </svg> </div> - ) + ); } -export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: BackgroundPathsProps) { - const [mainText, cursor] = title.split("|") - const words = mainText.split(" ") +export function BackgroundPaths({ + title, + subtitle, + primaryCta, + secondaryCta, +}: BackgroundPathsProps) { + const [mainText, cursor] = title.split("|"); + const words = mainText.split(" "); return ( <div className="relative min-h-screen w-full flex items-center justify-center overflow-hidden bg-blackA12"> @@ -80,8 +85,7 @@ export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: B initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 2 }} - className="max-w-4xl mx-auto space-y-6" - > + className="max-w-4xl mx-auto space-y-6"> <h1 className="text-3xl sm:text-5xl md:text-7xl lg:text-8xl font-bold tracking-tighter font-heading"> {words.map((word, wordIndex) => ( <span key={wordIndex} className="inline-block mr-4 last:mr-0"> @@ -96,8 +100,7 @@ export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: B stiffness: 150, damping: 25, }} - className="inline-block text-white" - > + className="inline-block text-white"> {letter} </motion.span> ))} @@ -112,8 +115,7 @@ export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: B repeat: Number.POSITIVE_INFINITY, ease: "linear", }} - className="inline-block text-green9 ml-2" - > + className="inline-block text-green9 ml-2"> | </motion.span> )} @@ -124,8 +126,7 @@ export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: B initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 1, duration: 1 }} - className="text-lg sm:text-xl md:text-2xl text-whiteA11" - > + className="text-lg sm:text-xl md:text-2xl text-whiteA11"> {subtitle} </motion.p> )} @@ -135,8 +136,7 @@ export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: B initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 1.5, duration: 1 }} - className="flex flex-wrap items-center justify-center gap-4 mt-8" - > + className="flex flex-wrap items-center justify-center gap-4 mt-8"> {primaryCta && ( <Link href={primaryCta.href}> <Button variant={primaryCta.variant} className={primaryCta.className}> @@ -156,6 +156,5 @@ export function BackgroundPaths({ title, subtitle, primaryCta, secondaryCta }: B </motion.div> </div> </div> - ) + ); } - diff --git a/app/components/breadcrumb.tsx b/app/components/breadcrumb.tsx index 4d282aa..b47a17b 100644 --- a/app/components/breadcrumb.tsx +++ b/app/components/breadcrumb.tsx @@ -1,22 +1,24 @@ -"use client" +"use client"; -import Link from "next/link" -import { usePathname } from "next/navigation" -import { ChevronRight, Home } from "lucide-react" +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { ChevronRight, Home } from "lucide-react"; export function Breadcrumb() { - const pathname = usePathname() - const segments = pathname.split("/").filter(Boolean) + const pathname = usePathname(); + const segments = pathname.split("/").filter(Boolean); return ( - <nav aria-label="Breadcrumb" className="mb-6 flex items-center space-x-2 text-sm text-muted-foreground"> + <nav + aria-label="Breadcrumb" + className="mb-6 flex items-center space-x-2 text-sm text-muted-foreground"> <Link href="/" className="flex items-center hover:text-foreground"> <Home className="h-4 w-4" /> </Link> {segments.map((segment, index) => { - const href = `/${segments.slice(0, index + 1).join("/")}` - const isLast = index === segments.length - 1 - const title = segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, " ") + const href = `/${segments.slice(0, index + 1).join("/")}`; + const isLast = index === segments.length - 1; + const title = segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, " "); return ( <div key={href} className="flex items-center"> @@ -29,9 +31,8 @@ export function Breadcrumb() { </Link> )} </div> - ) + ); })} </nav> - ) + ); } - diff --git a/app/components/command-menu.tsx b/app/components/command-menu.tsx index 437f093..25eb4da 100644 --- a/app/components/command-menu.tsx +++ b/app/components/command-menu.tsx @@ -1,13 +1,13 @@ -"use client" +"use client"; -import * as React from "react" -import { useRouter } from "next/navigation" -import type { DialogProps } from "@radix-ui/react-dialog" -import { Command as CommandPrimitive } from "cmdk" -import { Search } from "lucide-react" +import * as React from "react"; +import { useRouter } from "next/navigation"; +import type { DialogProps } from "@radix-ui/react-dialog"; +import { Command as CommandPrimitive } from "cmdk"; +import { Search } from "lucide-react"; -import { cn } from "@/lib/utils" -import { Dialog, DialogContent } from "@/components/ui/dialog" +import { cn } from "@/lib/utils"; +import { Dialog, DialogContent } from "@/components/ui/dialog"; const Command = React.forwardRef< React.ElementRef<typeof CommandPrimitive>, @@ -21,8 +21,8 @@ const Command = React.forwardRef< )} {...props} /> -)) -Command.displayName = CommandPrimitive.displayName +)); +Command.displayName = CommandPrimitive.displayName; interface CommandDialogProps extends DialogProps {} @@ -35,8 +35,8 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => { </Command> </DialogContent> </Dialog> - ) -} + ); +}; const CommandInput = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Input>, @@ -53,9 +53,9 @@ const CommandInput = React.forwardRef< {...props} /> </div> -)) +)); -CommandInput.displayName = CommandPrimitive.Input.displayName +CommandInput.displayName = CommandPrimitive.Input.displayName; const CommandList = React.forwardRef< React.ElementRef<typeof CommandPrimitive.List>, @@ -66,16 +66,18 @@ const CommandList = React.forwardRef< className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} {...props} /> -)) +)); -CommandList.displayName = CommandPrimitive.List.displayName +CommandList.displayName = CommandPrimitive.List.displayName; const CommandEmpty = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Empty>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> ->((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />) +>((props, ref) => ( + <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} /> +)); -CommandEmpty.displayName = CommandPrimitive.Empty.displayName +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; const CommandGroup = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Group>, @@ -89,17 +91,21 @@ const CommandGroup = React.forwardRef< )} {...props} /> -)) +)); -CommandGroup.displayName = CommandPrimitive.Group.displayName +CommandGroup.displayName = CommandPrimitive.Group.displayName; const CommandSeparator = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Separator>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator> >(({ className, ...props }, ref) => ( - <CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} /> -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName + <CommandPrimitive.Separator + ref={ref} + className={cn("-mx-1 h-px bg-border", className)} + {...props} + /> +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; const CommandItem = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Item>, @@ -113,35 +119,40 @@ const CommandItem = React.forwardRef< )} {...props} /> -)) +)); -CommandItem.displayName = CommandPrimitive.Item.displayName +CommandItem.displayName = CommandPrimitive.Item.displayName; const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { - return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} /> -} -CommandShortcut.displayName = "CommandShortcut" + return ( + <span + className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} + {...props} + /> + ); +}; +CommandShortcut.displayName = "CommandShortcut"; export function CommandMenu() { - const [open, setOpen] = React.useState(false) - const router = useRouter() + const [open, setOpen] = React.useState(false); + const router = useRouter(); React.useEffect(() => { const down = (e: KeyboardEvent) => { if (e.key === "k" && (e.metaKey || e.ctrlKey)) { - e.preventDefault() - setOpen((open) => !open) + e.preventDefault(); + setOpen((open) => !open); } - } + }; - document.addEventListener("keydown", down) - return () => document.removeEventListener("keydown", down) - }, []) + document.addEventListener("keydown", down); + return () => document.removeEventListener("keydown", down); + }, []); const runCommand = React.useCallback((command: () => unknown) => { - setOpen(false) - command() - }, []) + setOpen(false); + command(); + }, []); return ( <CommandDialog open={open} onOpenChange={setOpen}> @@ -167,6 +178,5 @@ export function CommandMenu() { </CommandGroup> </CommandList> </CommandDialog> - ) + ); } - diff --git a/app/components/cta-section.tsx b/app/components/cta-section.tsx index dc417b7..c123c30 100644 --- a/app/components/cta-section.tsx +++ b/app/components/cta-section.tsx @@ -1,6 +1,6 @@ -import Link from "next/link" -import { Button } from "@/components/ui/button" -import { ArrowRight } from "lucide-react" +import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import { ArrowRight } from "lucide-react"; export function CTASection() { return ( @@ -8,14 +8,19 @@ export function CTASection() { <div className="container mx-auto px-6"> <div className="flex flex-col md:flex-row justify-between items-center"> <div className="mb-8 md:mb-0 md:mr-8 max-w-2xl"> - <h2 className="text-3xl font-bold mb-4 text-white">Ready to optimize your Ethereum infrastructure?</h2> + <h2 className="text-3xl font-bold mb-4 text-white"> + Ready to optimize your Ethereum infrastructure? + </h2> <p className="text-lg text-mauveA11"> - Join thousands of validators leveraging Manifold's ecosystem for high-performance staking, MEV - optimization, and secure blockchain interactions. + Join thousands of validators leveraging Manifold's ecosystem for high-performance + staking, MEV optimization, and secure blockchain interactions. </p> </div> <div className="flex flex-col sm:flex-row gap-4"> - <Button asChild variant="default" className="bg-green9 hover:bg-green10 text-white rounded-full px-6 h-12"> + <Button + asChild + variant="default" + className="bg-green9 hover:bg-green10 text-white rounded-full px-6 h-12"> <Link href="/get-started" className="flex items-center gap-2"> Get Started <ArrowRight className="w-4 h-4" /> @@ -25,6 +30,5 @@ export function CTASection() { </div> </div> </section> - ) + ); } - diff --git a/app/components/docs-sidebar.tsx b/app/components/docs-sidebar.tsx index 6682db7..4ab4170 100644 --- a/app/components/docs-sidebar.tsx +++ b/app/components/docs-sidebar.tsx @@ -1,14 +1,14 @@ -"use client" +"use client"; -import Link from "next/link" -import { usePathname } from "next/navigation" -import { cn } from "@/lib/utils" -import { ScrollArea } from "@/components/ui/scroll-area" +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { cn } from "@/lib/utils"; +import { ScrollArea } from "@/components/ui/scroll-area"; interface DocLink { - title: string - href: string - items?: { title: string; href: string }[] + title: string; + href: string; + items?: { title: string; href: string }[]; } const docs: DocLink[] = [ @@ -52,10 +52,10 @@ const docs: DocLink[] = [ title: "FAQ", href: "/docs/faq", }, -] +]; export function DocsSidebar() { - const pathname = usePathname() + const pathname = usePathname(); return ( <ScrollArea className="h-full py-6 pl-4"> @@ -72,8 +72,7 @@ export function DocsSidebar() { pathname === section.href ? "text-primary font-semibold" : "text-muted-foreground hover:text-primary", - )} - > + )}> {section.title} </Link> {section.items?.map((item) => ( @@ -82,9 +81,10 @@ export function DocsSidebar() { href={item.href} className={cn( "block py-1 text-sm ml-4", - pathname === item.href ? "text-primary font-medium" : "text-muted-foreground hover:text-primary", - )} - > + pathname === item.href + ? "text-primary font-medium" + : "text-muted-foreground hover:text-primary", + )}> {item.title} </Link> ))} @@ -94,6 +94,5 @@ export function DocsSidebar() { </div> </div> </ScrollArea> - ) + ); } - diff --git a/app/components/error-boundary.tsx b/app/components/error-boundary.tsx index 183ec73..87dba68 100644 --- a/app/components/error-boundary.tsx +++ b/app/components/error-boundary.tsx @@ -1,27 +1,27 @@ -"use client" +"use client"; -import React, { type ErrorInfo, type ReactNode } from "react" +import React, { type ErrorInfo, type ReactNode } from "react"; interface ErrorBoundaryProps { - children: ReactNode + children: ReactNode; } interface ErrorBoundaryState { - hasError: boolean + hasError: boolean; } class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> { constructor(props: ErrorBoundaryProps) { - super(props) - this.state = { hasError: false } + super(props); + this.state = { hasError: false }; } static getDerivedStateFromError(_: Error): ErrorBoundaryState { - return { hasError: true } + return { hasError: true }; } componentDidCatch(error: Error, errorInfo: ErrorInfo) { - console.error("ErrorBoundary caught an error:", error, errorInfo) + console.error("ErrorBoundary caught an error:", error, errorInfo); } render() { @@ -31,23 +31,21 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta <div className="text-center"> <h1 className="text-4xl font-bold mb-4">Oops! Something went wrong.</h1> <p className="text-xl mb-8"> - We're sorry for the inconvenience. Please try refreshing the page or contact support if the problem - persists. + We're sorry for the inconvenience. Please try refreshing the page or contact support + if the problem persists. </p> <button onClick={() => this.setState({ hasError: false })} - className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded" - > + className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded"> Try Again </button> </div> </div> - ) + ); } - return this.props.children + return this.props.children; } } -export default ErrorBoundary - +export default ErrorBoundary; diff --git a/app/components/feature-grid.tsx b/app/components/feature-grid.tsx index ff28cf0..bcfd087 100644 --- a/app/components/feature-grid.tsx +++ b/app/components/feature-grid.tsx @@ -1,5 +1,5 @@ -import type React from "react" -import { Zap, Shield, DollarSign } from "lucide-react" +import type React from "react"; +import { Zap, Shield, DollarSign } from "lucide-react"; export function FeatureGrid() { return ( @@ -27,10 +27,14 @@ export function FeatureGrid() { /> </div> </div> - ) + ); } -function FeatureCard({ icon, title, description }: { icon: React.ReactNode; title: string; description: string }) { +function FeatureCard({ + icon, + title, + description, +}: { icon: React.ReactNode; title: string; description: string }) { return ( <div className="p-8 rounded-lg bg-white/5 border border-white/10"> <div className="w-12 h-12 rounded-lg bg-[#31C4B9]/10 flex items-center justify-center text-[#31C4B9] mb-4"> @@ -39,6 +43,5 @@ function FeatureCard({ icon, title, description }: { icon: React.ReactNode; titl <h3 className="text-lg font-semibold mb-2">{title}</h3> <p className="text-gray-400 text-sm">{description}</p> </div> - ) + ); } - diff --git a/app/components/feature-section.tsx b/app/components/feature-section.tsx index 6baa231..02829b5 100644 --- a/app/components/feature-section.tsx +++ b/app/components/feature-section.tsx @@ -1,13 +1,13 @@ -import type { LucideIcon } from "lucide-react" +import type { LucideIcon } from "lucide-react"; interface Feature { - icon: LucideIcon - title: string - description: string + icon: LucideIcon; + title: string; + description: string; } interface FeatureSectionProps { - features: Feature[] + features: Feature[]; } export function FeatureSection({ features }: FeatureSectionProps) { @@ -16,8 +16,7 @@ export function FeatureSection({ features }: FeatureSectionProps) { {features.map((feature, index) => ( <div key={index} - className="relative p-6 rounded-lg border border-white/[0.08] bg-black/40 backdrop-blur-sm hover:border-white/[0.12] transition-colors" - > + className="relative p-6 rounded-lg border border-white/[0.08] bg-black/40 backdrop-blur-sm hover:border-white/[0.12] transition-colors"> <div className="w-12 h-12 rounded-lg bg-[#31C4B9]/10 flex items-center justify-center mb-4"> <feature.icon className="w-6 h-6 text-[#31C4B9]" /> </div> @@ -26,6 +25,5 @@ export function FeatureSection({ features }: FeatureSectionProps) { </div> ))} </div> - ) + ); } - diff --git a/app/components/footer.tsx b/app/components/footer.tsx index f19c506..7dbc4d2 100644 --- a/app/components/footer.tsx +++ b/app/components/footer.tsx @@ -1,10 +1,10 @@ -import Link from "next/link" -import { Twitter, Github } from "lucide-react" -import { Logo } from "./logo" -import { HoverCard, HoverCardTrigger, HoverCardContent } from "@/components/ui/hover-card" +import Link from "next/link"; +import { Twitter, Github } from "lucide-react"; +import { Logo } from "./logo"; +import { HoverCard, HoverCardTrigger, HoverCardContent } from "@/components/ui/hover-card"; // This would typically come from an environment variable or build-time constant -const GIT_VERSION_HASH = "a1b2c3d" +const GIT_VERSION_HASH = "a1b2c3d"; export function Footer() { return ( @@ -24,16 +24,14 @@ export function Footer() { href="https://twitter.com/manifoldfinance" target="_blank" rel="noopener noreferrer" - className="text-gray-400 hover:text-white transition-colors" - > + className="text-gray-400 hover:text-white transition-colors"> <Twitter className="w-5 h-5" /> </Link> <Link href="https://github.com/manifoldfinance" target="_blank" rel="noopener noreferrer" - className="text-gray-400 hover:text-white transition-colors" - > + className="text-gray-400 hover:text-white transition-colors"> <Github className="w-5 h-5" /> </Link> </div> @@ -52,7 +50,9 @@ export function Footer() { <h4 className="text-sm font-semibold">System Status</h4> <p className="text-sm">All systems are operational.</p> <div className="flex items-center pt-2"> - <span className="text-xs text-muted-foreground">Last checked: {new Date().toLocaleString()}</span> + <span className="text-xs text-muted-foreground"> + Last checked: {new Date().toLocaleString()} + </span> </div> </div> </div> @@ -62,6 +62,5 @@ export function Footer() { </div> </div> </footer> - ) + ); } - diff --git a/app/components/header.tsx b/app/components/header.tsx index a15f9cb..b521ca2 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import Link from "next/link" -import Image from "next/image" -import { Logo } from "@/app/components/logo" -import { cn } from "@/lib/utils" +import * as React from "react"; +import Link from "next/link"; +import Image from "next/image"; +import { Logo } from "@/app/components/logo"; +import { cn } from "@/lib/utils"; import { NavigationMenu, NavigationMenuContent, @@ -13,9 +13,9 @@ import { NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, -} from "@/components/ui/navigation-menu" -import { Button } from "@/components/ui/button" -import { Menu } from "lucide-react" +} from "@/components/ui/navigation-menu"; +import { Button } from "@/components/ui/button"; +import { Menu } from "lucide-react"; const solutions: { title: string; href: string; description: string }[] = [ { @@ -38,7 +38,7 @@ const solutions: { title: string; href: string; description: string }[] = [ href: "/solutions/securerpc", description: "Stable and reliable blockchain interactions for your applications.", }, -] +]; const products: { title: string; href: string; description: string }[] = [ { @@ -61,7 +61,7 @@ const products: { title: string; href: string; description: string }[] = [ href: "/products/meveth", description: "Maximized MEV rewards for Ethereum staking.", }, -] +]; const resources: { title: string; href: string; description: string }[] = [ { @@ -84,7 +84,7 @@ const resources: { title: string; href: string; description: string }[] = [ href: "/support", description: "Get help from our team and community.", }, -] +]; const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>( ({ className, title, children, ...props }, ref) => { @@ -96,19 +96,18 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", className, )} - {...props} - > + {...props}> <div className="text-sm font-medium leading-none">{title}</div> <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> </NavigationMenuLink> </li> - ) + ); }, -) -ListItem.displayName = "ListItem" +); +ListItem.displayName = "ListItem"; function MobileMenu() { - const [isOpen, setIsOpen] = React.useState(false) + const [isOpen, setIsOpen] = React.useState(false); return ( <div className="md:hidden"> @@ -134,7 +133,7 @@ function MobileMenu() { </div> )} </div> - ) + ); } export function Header() { @@ -149,14 +148,15 @@ export function Header() { <NavigationMenu className="hidden md:block"> <NavigationMenuList> <NavigationMenuItem> - <NavigationMenuTrigger className="text-foreground">Solutions</NavigationMenuTrigger> + <NavigationMenuTrigger className="text-foreground"> + Solutions + </NavigationMenuTrigger> <NavigationMenuContent> <div className="grid grid-cols-[1fr_2fr] w-[600px]"> <NavigationMenuLink asChild> <a className="flex flex-col justify-between h-full select-none rounded-l-md bg-gradient-to-br from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md" - href="/solutions/staking" - > + href="/solutions/staking"> <div> <Image src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Ethereum2_Logo-G7XZRKQfQ3ujqhgs1ZKjTpoe3zVqab.png" @@ -165,7 +165,9 @@ export function Header() { height={38} className="mb-3" /> - <div className="text-lg font-medium text-foreground mb-2">High-Performance Staking</div> + <div className="text-lg font-medium text-foreground mb-2"> + High-Performance Staking + </div> <p className="text-sm text-muted-foreground"> Build and manage efficient staking solutions for maximum returns. </p> @@ -175,7 +177,10 @@ export function Header() { </NavigationMenuLink> <ul className="grid gap-3 p-6 bg-background rounded-r-md"> {solutions.map((solution) => ( - <ListItem key={solution.title} title={solution.title} href={solution.href}> + <ListItem + key={solution.title} + title={solution.title} + href={solution.href}> {solution.description} </ListItem> ))} @@ -184,7 +189,9 @@ export function Header() { </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> - <NavigationMenuTrigger className="text-foreground">Products</NavigationMenuTrigger> + <NavigationMenuTrigger className="text-foreground"> + Products + </NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> {products.map((product) => ( @@ -196,7 +203,9 @@ export function Header() { </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> - <NavigationMenuTrigger className="text-foreground">Resources</NavigationMenuTrigger> + <NavigationMenuTrigger className="text-foreground"> + Resources + </NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> {resources.map((resource) => ( @@ -209,7 +218,9 @@ export function Header() { </NavigationMenuItem> <NavigationMenuItem> <Link href="/docs" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}>Documentation</NavigationMenuLink> + <NavigationMenuLink className={navigationMenuTriggerStyle()}> + Documentation + </NavigationMenuLink> </Link> </NavigationMenuItem> </NavigationMenuList> @@ -219,6 +230,5 @@ export function Header() { </div> </div> </header> - ) + ); } - diff --git a/app/components/layout-wrapper.tsx b/app/components/layout-wrapper.tsx index 321a60e..22eec08 100644 --- a/app/components/layout-wrapper.tsx +++ b/app/components/layout-wrapper.tsx @@ -1,22 +1,21 @@ -"use client" +"use client"; -import { usePathname } from "next/navigation" -import { Footer } from "./footer" -import type React from "react" // Added import for React +import { usePathname } from "next/navigation"; +import { Footer } from "./footer"; +import type React from "react"; // Added import for React interface LayoutWrapperProps { - children: React.ReactNode + children: React.ReactNode; } export function LayoutWrapper({ children }: LayoutWrapperProps) { - const pathname = usePathname() - const isHomePage = pathname === "/" + const pathname = usePathname(); + const isHomePage = pathname === "/"; return ( <> {children} {!isHomePage && <Footer />} </> - ) + ); } - diff --git a/app/components/logo.tsx b/app/components/logo.tsx index 44c42b1..2420f70 100644 --- a/app/components/logo.tsx +++ b/app/components/logo.tsx @@ -7,6 +7,5 @@ export function Logo({ className }: { className?: string }) { width={40} height={40} /> - ) + ); } - diff --git a/app/components/lst-apy-graph.tsx b/app/components/lst-apy-graph.tsx index 0cd05d2..6e75c2f 100644 --- a/app/components/lst-apy-graph.tsx +++ b/app/components/lst-apy-graph.tsx @@ -1,10 +1,18 @@ -"use client" -import { Line, LineChart, ResponsiveContainer, XAxis, YAxis, Tooltip, CartesianGrid } from "recharts" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +"use client"; +import { + Line, + LineChart, + ResponsiveContainer, + XAxis, + YAxis, + Tooltip, + CartesianGrid, +} from "recharts"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; interface LSTData { - name: string - apy: number + name: string; + apy: number; } const lstData: LSTData[] = [ @@ -12,21 +20,29 @@ const lstData: LSTData[] = [ { name: "stETH", apy: 4.8 }, { name: "rETH", apy: 4.9 }, { name: "oETH", apy: 5.0 }, -] +]; export function LSTAPYGraph() { return ( <Card> <CardHeader> <CardTitle>LST APY Comparison</CardTitle> - <CardDescription>Annual Percentage Yield for different Liquid Staking Tokens (Log Scale)</CardDescription> + <CardDescription> + Annual Percentage Yield for different Liquid Staking Tokens (Log Scale) + </CardDescription> </CardHeader> <CardContent className="pb-4"> <div className="h-[300px]"> <ResponsiveContainer width="100%" height="100%"> <LineChart data={lstData}> <CartesianGrid strokeDasharray="3 3" /> - <XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} /> + <XAxis + dataKey="name" + stroke="#888888" + fontSize={12} + tickLine={false} + axisLine={false} + /> <YAxis stroke="#888888" fontSize={12} @@ -53,6 +69,5 @@ export function LSTAPYGraph() { </div> </CardContent> </Card> - ) + ); } - diff --git a/app/components/lst-apy-trend-graph.tsx b/app/components/lst-apy-trend-graph.tsx index 0f8228d..53b52b5 100644 --- a/app/components/lst-apy-trend-graph.tsx +++ b/app/components/lst-apy-trend-graph.tsx @@ -1,13 +1,22 @@ -"use client" -import { Line, LineChart, ResponsiveContainer, XAxis, YAxis, Tooltip, CartesianGrid, Legend } from "recharts" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +"use client"; +import { + Line, + LineChart, + ResponsiveContainer, + XAxis, + YAxis, + Tooltip, + CartesianGrid, + Legend, +} from "recharts"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; interface LSTTrendData { - quarter: string - mevETH: number - stETH: number - rETH: number - oETH: number + quarter: string; + mevETH: number; + stETH: number; + rETH: number; + oETH: number; } const lstTrendData: LSTTrendData[] = [ @@ -15,7 +24,7 @@ const lstTrendData: LSTTrendData[] = [ { quarter: "Q2 2024", mevETH: 5.2, stETH: 4.7, rETH: 4.8, oETH: 4.9 }, { quarter: "Q3 2024", mevETH: 5.4, stETH: 4.6, rETH: 4.7, oETH: 4.8 }, { quarter: "Q4 2024", mevETH: 5.6, stETH: 4.5, rETH: 4.6, oETH: 4.7 }, -] +]; export function LSTAPYTrendGraph() { return ( @@ -29,7 +38,13 @@ export function LSTAPYTrendGraph() { <ResponsiveContainer width="100%" height="100%"> <LineChart data={lstTrendData}> <CartesianGrid strokeDasharray="3 3" /> - <XAxis dataKey="quarter" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} /> + <XAxis + dataKey="quarter" + stroke="#888888" + fontSize={12} + tickLine={false} + axisLine={false} + /> <YAxis stroke="#888888" fontSize={12} @@ -77,6 +92,5 @@ export function LSTAPYTrendGraph() { </div> </CardContent> </Card> - ) + ); } - diff --git a/app/components/lst-comparison-table.tsx b/app/components/lst-comparison-table.tsx index ee8b42d..e0bf14a 100644 --- a/app/components/lst-comparison-table.tsx +++ b/app/components/lst-comparison-table.tsx @@ -1,15 +1,22 @@ -"use client" -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" -import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip" -import { Info } from "lucide-react" +"use client"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip"; +import { Info } from "lucide-react"; interface LSTData { - name: string - apy: number - tvl: string - fee: string - decentralization: "Low" | "Medium" | "High" - liquidityScore: number + name: string; + apy: number; + tvl: string; + fee: string; + decentralization: "Low" | "Medium" | "High"; + liquidityScore: number; } const lstData: LSTData[] = [ @@ -45,7 +52,7 @@ const lstData: LSTData[] = [ decentralization: "Low", liquidityScore: 6, }, -] +]; export function LSTComparisonTable() { return ( @@ -87,6 +94,5 @@ export function LSTComparisonTable() { </Table> </div> </TooltipProvider> - ) + ); } - diff --git a/app/components/main-nav.tsx b/app/components/main-nav.tsx index 60c28dc..a8d02d0 100644 --- a/app/components/main-nav.tsx +++ b/app/components/main-nav.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as React from "react" -import Link from "next/link" -import { Menu } from "lucide-react" +import * as React from "react"; +import Link from "next/link"; +import { Menu } from "lucide-react"; -import { cn } from "@/lib/utils" -import { Icons } from "@/components/icons" +import { cn } from "@/lib/utils"; +import { Icons } from "@/components/icons"; import { NavigationMenu, NavigationMenuContent, @@ -14,9 +14,9 @@ import { NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, -} from "@/components/ui/navigation-menu" -import { Button } from "@/components/ui/button" -import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet" +} from "@/components/ui/navigation-menu"; +import { Button } from "@/components/ui/button"; +import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; const solutions: { title: string; href: string; description: string }[] = [ { @@ -39,7 +39,7 @@ const solutions: { title: string; href: string; description: string }[] = [ href: "/solutions/relay-protect", description: "Advanced MEV protection and transaction privacy for Ethereum.", }, -] +]; const products: { title: string; href: string; description: string }[] = [ ...solutions, @@ -53,7 +53,7 @@ const products: { title: string; href: string; description: string }[] = [ href: "/fold-token", description: "Learn about our native ERC20 token powering the Manifold Finance ecosystem.", }, -] +]; export function MainNav() { return ( @@ -112,19 +112,23 @@ export function MainNav() { </NavigationMenuItem> <NavigationMenuItem> <Link href="/docs" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}>Documentation</NavigationMenuLink> + <NavigationMenuLink className={navigationMenuTriggerStyle()}> + Documentation + </NavigationMenuLink> </Link> </NavigationMenuItem> <NavigationMenuItem> <Link href="/blog" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}>Blog</NavigationMenuLink> + <NavigationMenuLink className={navigationMenuTriggerStyle()}> + Blog + </NavigationMenuLink> </Link> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </div> </> - ) + ); } const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>( @@ -138,23 +142,27 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", className, )} - {...props} - > + {...props}> <div className="text-sm font-medium leading-none">{title}</div> <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> </a> </NavigationMenuLink> </li> - ) + ); }, -) -ListItem.displayName = "ListItem" +); +ListItem.displayName = "ListItem"; -function MobileNavItem({ title, items }: { title: string; items: { title: string; href: string }[] }) { - const [isOpen, setIsOpen] = React.useState(false) +function MobileNavItem({ + title, + items, +}: { title: string; items: { title: string; href: string }[] }) { + const [isOpen, setIsOpen] = React.useState(false); return ( <div> - <button onClick={() => setIsOpen(!isOpen)} className="flex w-full items-center justify-between py-2 text-left"> + <button + onClick={() => setIsOpen(!isOpen)} + className="flex w-full items-center justify-between py-2 text-left"> {title} <Icons.chevronDown className={cn("h-4 w-4 transition-transform", isOpen && "rotate-180")} /> </button> @@ -168,6 +176,5 @@ function MobileNavItem({ title, items }: { title: string; items: { title: string </div> )} </div> - ) + ); } - diff --git a/app/components/mev-protection-comparison.tsx b/app/components/mev-protection-comparison.tsx index 318cfb0..4d302f0 100644 --- a/app/components/mev-protection-comparison.tsx +++ b/app/components/mev-protection-comparison.tsx @@ -1,15 +1,15 @@ -"use client" +"use client"; -import { useState } from "react" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Button } from "@/components/ui/button" -import { ChevronDown, ChevronUp } from "lucide-react" +import { useState } from "react"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { ChevronDown, ChevronUp } from "lucide-react"; interface ComparisonData { - feature: string - relayProtect: string - flashbotsMevShare: string - mevBlocker: string + feature: string; + relayProtect: string; + flashbotsMevShare: string; + mevBlocker: string; } const comparisonData: ComparisonData[] = [ @@ -21,7 +21,8 @@ const comparisonData: ComparisonData[] = [ }, { feature: "Transaction Privacy", - relayProtect: "Full privacy until validator commitment, zero information leakage during pending state", + relayProtect: + "Full privacy until validator commitment, zero information leakage during pending state", flashbotsMevShare: "Partial privacy with strategic information hints for market efficiency", mevBlocker: "Enhanced privacy with selective disclosure mechanisms", }, @@ -103,20 +104,24 @@ const comparisonData: ComparisonData[] = [ flashbotsMevShare: "Complex upgrade path with multiple stakeholders", mevBlocker: "Moderate upgrade complexity with partial compatibility", }, -] +]; export function MEVProtectionComparison() { - const [expandedRows, setExpandedRows] = useState<number[]>([]) + const [expandedRows, setExpandedRows] = useState<number[]>([]); const toggleRow = (index: number) => { - setExpandedRows((prev) => (prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index])) - } + setExpandedRows((prev) => + prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index], + ); + }; return ( <Card> <CardHeader> <CardTitle>MEV Protection Comparison</CardTitle> - <CardDescription>Compare Relay+ Protect with other MEV protection solutions</CardDescription> + <CardDescription> + Compare Relay+ Protect with other MEV protection solutions + </CardDescription> </CardHeader> <CardContent> <div className="overflow-x-auto"> @@ -134,9 +139,15 @@ export function MEVProtectionComparison() { <tr key={index} className="border-t border-muted"> <td className="p-2 font-medium">{row.feature}</td> <td className="p-2"> - <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}>{row.relayProtect}</div> + <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}> + {row.relayProtect} + </div> {row.relayProtect.length > 100 && ( - <Button variant="ghost" size="sm" onClick={() => toggleRow(index)} className="mt-1"> + <Button + variant="ghost" + size="sm" + onClick={() => toggleRow(index)} + className="mt-1"> {expandedRows.includes(index) ? ( <> <ChevronUp className="h-4 w-4 mr-1" /> @@ -157,7 +168,9 @@ export function MEVProtectionComparison() { </div> </td> <td className="p-2"> - <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}>{row.mevBlocker}</div> + <div className={`${expandedRows.includes(index) ? "" : "line-clamp-2"}`}> + {row.mevBlocker} + </div> </td> </tr> ))} @@ -166,6 +179,5 @@ export function MEVProtectionComparison() { </div> </CardContent> </Card> - ) + ); } - diff --git a/app/components/privacy-section.tsx b/app/components/privacy-section.tsx index 954e057..fe6e88c 100644 --- a/app/components/privacy-section.tsx +++ b/app/components/privacy-section.tsx @@ -1,4 +1,4 @@ -import { Shield } from "lucide-react" +import { Shield } from "lucide-react"; export function PrivacySection() { return ( @@ -8,10 +8,10 @@ export function PrivacySection() { <h3 className="text-xl font-semibold">Privacy and Security</h3> </div> <p className="text-gray-400"> - At Manifold Finance, we prioritize the privacy and security of our users. Our infrastructure is built with - state-of-the-art encryption and security measures to ensure your data and transactions remain protected. + At Manifold Finance, we prioritize the privacy and security of our users. Our infrastructure + is built with state-of-the-art encryption and security measures to ensure your data and + transactions remain protected. </p> </div> - ) + ); } - diff --git a/app/components/search-button.tsx b/app/components/search-button.tsx index 2fcf5a9..a4c327e 100644 --- a/app/components/search-button.tsx +++ b/app/components/search-button.tsx @@ -1,20 +1,22 @@ -"use client" +"use client"; -import { useCallback } from "react" -import { Button } from "@/components/ui/button" +import { useCallback } from "react"; +import { Button } from "@/components/ui/button"; export function SearchButton() { const handleClick = useCallback(() => { - document.dispatchEvent(new KeyboardEvent("keydown", { key: "k", metaKey: true })) - }, []) + document.dispatchEvent(new KeyboardEvent("keydown", { key: "k", metaKey: true })); + }, []); return ( - <Button onClick={handleClick} variant="outline" className="bg-white/5 text-white hover:bg-white/10"> + <Button + onClick={handleClick} + variant="outline" + className="bg-white/5 text-white hover:bg-white/10"> <span className="hidden md:inline-flex">Search...</span> <kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-white/20 bg-white/10 px-1.5 font-mono text-[10px] font-medium text-white/70 opacity-100 ml-2"> <span className="text-xs">⌘</span>K </kbd> </Button> - ) + ); } - diff --git a/app/docs/getting-started/installation/page.tsx b/app/docs/getting-started/installation/page.tsx index aa093f2..022ec8b 100644 --- a/app/docs/getting-started/installation/page.tsx +++ b/app/docs/getting-started/installation/page.tsx @@ -1,4 +1,4 @@ -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; export default function InstallationPage() { return ( @@ -44,6 +44,5 @@ export default function InstallationPage() { </pre> </div> </div> - ) + ); } - diff --git a/app/docs/getting-started/introduction/page.tsx b/app/docs/getting-started/introduction/page.tsx index a57591f..40759a3 100644 --- a/app/docs/getting-started/introduction/page.tsx +++ b/app/docs/getting-started/introduction/page.tsx @@ -3,16 +3,16 @@ export default function IntroductionPage() { <div className="space-y-6"> <h1 className="text-3xl font-bold">Introduction</h1> <p className="text-lg text-muted-foreground"> - Manifold Finance provides optimized infrastructure for the next generation of Ethereum, offering - high-performance staking, MEV optimization, and enterprise-grade SecureRPC. + Manifold Finance provides optimized infrastructure for the next generation of Ethereum, + offering high-performance staking, MEV optimization, and enterprise-grade SecureRPC. </p> <div className="space-y-4"> <h2 className="text-2xl font-semibold">What is Manifold Finance?</h2> <p> - Manifold Finance is a comprehensive suite of tools and services designed to optimize your Ethereum - infrastructure. Our platform helps you maximize returns through efficient staking, MEV optimization, and - secure RPC endpoints. + Manifold Finance is a comprehensive suite of tools and services designed to optimize your + Ethereum infrastructure. Our platform helps you maximize returns through efficient + staking, MEV optimization, and secure RPC endpoints. </p> <h3 className="text-xl font-semibold">Key Features</h3> @@ -24,6 +24,5 @@ export default function IntroductionPage() { </ul> </div> </div> - ) + ); } - diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx index 68276e9..72f081c 100644 --- a/app/docs/layout.tsx +++ b/app/docs/layout.tsx @@ -1,7 +1,7 @@ -import { DocsSidebar } from "@/app/components/docs-sidebar" -import { Breadcrumb } from "@/app/components/breadcrumb" -import { ScrollArea } from "@/components/ui/scroll-area" -import type React from "react" // Added import for React +import { DocsSidebar } from "@/app/components/docs-sidebar"; +import { Breadcrumb } from "@/app/components/breadcrumb"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import type React from "react"; // Added import for React export default function DocsLayout({ children }: { children: React.ReactNode }) { return ( @@ -21,6 +21,5 @@ export default function DocsLayout({ children }: { children: React.ReactNode }) </ScrollArea> </div> </div> - ) + ); } - diff --git a/app/docs/page.tsx b/app/docs/page.tsx index f6dd83a..c0d916d 100644 --- a/app/docs/page.tsx +++ b/app/docs/page.tsx @@ -1,27 +1,28 @@ -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import Link from "next/link" -import { ArrowRight } from "lucide-react" +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import Link from "next/link"; +import { ArrowRight } from "lucide-react"; export default function DocsPage() { return ( <div className="space-y-6"> <h1 className="text-3xl font-bold">Documentation</h1> <p className="text-muted-foreground text-lg"> - Welcome to the Manifold Finance documentation. Here you'll find comprehensive guides and documentation to help - you start working with Manifold Finance as quickly as possible. + Welcome to the Manifold Finance documentation. Here you'll find comprehensive guides and + documentation to help you start working with Manifold Finance as quickly as possible. </p> <div className="grid gap-6 md:grid-cols-2"> <Card> <CardHeader> <CardTitle>Getting Started</CardTitle> - <CardDescription>Learn the basics of Manifold Finance and get started with our platform.</CardDescription> + <CardDescription> + Learn the basics of Manifold Finance and get started with our platform. + </CardDescription> </CardHeader> <CardContent> <Link href="/docs/getting-started/introduction" - className="text-primary hover:underline inline-flex items-center" - > + className="text-primary hover:underline inline-flex items-center"> Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> @@ -30,13 +31,14 @@ export default function DocsPage() { <Card> <CardHeader> <CardTitle>API Reference</CardTitle> - <CardDescription>Detailed documentation for our SecureRPC API endpoints and features.</CardDescription> + <CardDescription> + Detailed documentation for our SecureRPC API endpoints and features. + </CardDescription> </CardHeader> <CardContent> <Link href="/docs/securerpc/api-reference" - className="text-primary hover:underline inline-flex items-center" - > + className="text-primary hover:underline inline-flex items-center"> Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> @@ -50,7 +52,9 @@ export default function DocsPage() { </CardDescription> </CardHeader> <CardContent> - <Link href="/docs/staking/overview" className="text-primary hover:underline inline-flex items-center"> + <Link + href="/docs/staking/overview" + className="text-primary hover:underline inline-flex items-center"> Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> @@ -64,13 +68,14 @@ export default function DocsPage() { </CardDescription> </CardHeader> <CardContent> - <Link href="/docs/faq" className="text-primary hover:underline inline-flex items-center"> + <Link + href="/docs/faq" + className="text-primary hover:underline inline-flex items-center"> Read more <ArrowRight className="ml-1 h-4 w-4" /> </Link> </CardContent> </Card> </div> </div> - ) + ); } - diff --git a/app/docs/securerpc/api-reference/page.tsx b/app/docs/securerpc/api-reference/page.tsx index 0ef647d..9d68478 100644 --- a/app/docs/securerpc/api-reference/page.tsx +++ b/app/docs/securerpc/api-reference/page.tsx @@ -10,7 +10,8 @@ export default function ApiReferencePage() { <section className="space-y-4"> <h2 className="text-2xl font-semibold">Authentication</h2> <p> - All API endpoints require authentication using your API key. Include your API key in the request headers: + All API endpoints require authentication using your API key. Include your API key in the + request headers: </p> <pre className="rounded-lg bg-muted p-4"> <code>{`X-API-Key: your_api_key`}</code> @@ -30,7 +31,9 @@ export default function ApiReferencePage() { <div className="rounded-lg border p-4"> <h3 className="text-xl font-semibold">GET /status</h3> - <p className="text-muted-foreground mt-2">Get the current status of the SecureRPC service.</p> + <p className="text-muted-foreground mt-2"> + Get the current status of the SecureRPC service. + </p> <pre className="rounded-lg bg-muted p-4 mt-4"> <code>{`curl -X GET "https://api.manifoldfinance.com/v1/status" \\ -H "X-API-Key: your_api_key"`}</code> @@ -50,6 +53,5 @@ export default function ApiReferencePage() { </section> </div> </div> - ) + ); } - diff --git a/app/fold-token/page.tsx b/app/fold-token/page.tsx index 27d9e57..ddb9e3c 100644 --- a/app/fold-token/page.tsx +++ b/app/fold-token/page.tsx @@ -1,20 +1,24 @@ -import { BackgroundPaths } from "../components/background-paths" -import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card" -import { Badge } from "@/components/ui/badge" -import { Button } from "@/components/ui/button" -import Link from "next/link" -import { ExternalLink, FileText, ShieldCheck, Zap } from "lucide-react" +import { BackgroundPaths } from "../components/background-paths"; +import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import Link from "next/link"; +import { ExternalLink, FileText, ShieldCheck, Zap } from "lucide-react"; export default function FoldTokenPage() { return ( <div className="min-h-screen bg-black text-white"> - <BackgroundPaths title="FOLD Token|" subtitle="The ERC20 token powering Manifold Finance's ecosystem" /> + <BackgroundPaths + title="FOLD Token|" + subtitle="The ERC20 token powering Manifold Finance's ecosystem" + /> <main className="container mx-auto px-4 py-12"> <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">What is FOLD?</h2> <p className="text-base sm:text-lg mb-4"> - FOLD is the native ERC20 token of the Manifold Finance ecosystem. It serves multiple purposes within our - platform, including governance, staking, and accessing premium features. + FOLD is the native ERC20 token of the Manifold Finance ecosystem. It serves multiple + purposes within our platform, including governance, staking, and accessing premium + features. </p> <div className="flex flex-wrap gap-2"> <Badge variant="secondary">ERC20</Badge> @@ -75,8 +79,8 @@ export default function FoldTokenPage() { <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Token Distribution</h2> <p className="text-base sm:text-lg mb-4"> - The initial distribution of FOLD tokens is designed to ensure a fair launch and sustainable growth of the - Manifold Finance ecosystem: + The initial distribution of FOLD tokens is designed to ensure a fair launch and + sustainable growth of the Manifold Finance ecosystem: </p> <ul className="list-disc list-inside space-y-2 mb-4"> <li>40% - Community Treasury</li> @@ -86,16 +90,17 @@ export default function FoldTokenPage() { <li>5% - Ecosystem Development Fund</li> </ul> <p className="text-base sm:text-lg mb-4"> - This distribution ensures that a significant portion of tokens is allocated to the community and ecosystem - growth, while also incentivizing long-term commitment from the team and early supporters. + This distribution ensures that a significant portion of tokens is allocated to the + community and ecosystem growth, while also incentivizing long-term commitment from the + team and early supporters. </p> </section> <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Governance</h2> <p className="text-base sm:text-lg mb-4"> - FOLD token holders have the power to participate in the governance of the Manifold Finance protocol. This - includes: + FOLD token holders have the power to participate in the governance of the Manifold + Finance protocol. This includes: </p> <ul className="list-disc list-inside space-y-2 mb-4"> <li>Proposing and voting on protocol upgrades</li> @@ -104,16 +109,16 @@ export default function FoldTokenPage() { <li>Allocating resources from the Community Treasury</li> </ul> <p className="text-base sm:text-lg"> - The governance process is designed to be transparent and inclusive, ensuring that all token holders have a - voice in the future direction of Manifold Finance. + The governance process is designed to be transparent and inclusive, ensuring that all + token holders have a voice in the future direction of Manifold Finance. </p> </section> <section className="mb-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Staking and Rewards</h2> <p className="text-base sm:text-lg mb-4"> - FOLD token holders can stake their tokens to earn rewards and contribute to the security of the Manifold - Finance network. Staking benefits include: + FOLD token holders can stake their tokens to earn rewards and contribute to the security + of the Manifold Finance network. Staking benefits include: </p> <ul className="list-disc list-inside space-y-2 mb-4"> <li>Earning passive income through staking rewards</li> @@ -122,7 +127,8 @@ export default function FoldTokenPage() { <li>Participation in network security and validation</li> </ul> <p className="text-base sm:text-lg"> - The staking mechanism is designed to encourage long-term holding and active participation in the ecosystem. + The staking mechanism is designed to encourage long-term holding and active + participation in the ecosystem. </p> </section> @@ -133,8 +139,9 @@ export default function FoldTokenPage() { <span className="text-base sm:text-lg font-semibold">Audited and Secure</span> </div> <p className="text-base sm:text-lg mb-4"> - The FOLD token smart contract has undergone rigorous security audits by leading blockchain security firms to - ensure the safety of our users' funds and the integrity of the Manifold Finance ecosystem. + The FOLD token smart contract has undergone rigorous security audits by leading + blockchain security firms to ensure the safety of our users' funds and the integrity of + the Manifold Finance ecosystem. </p> <Button asChild variant="outline"> <Link href="/security" className="inline-flex items-center"> @@ -146,8 +153,8 @@ export default function FoldTokenPage() { <section> <h2 className="text-2xl sm:text-3xl font-bold mb-4">Get FOLD</h2> <p className="text-base sm:text-lg mb-4"> - FOLD tokens are available on several decentralized exchanges and can be earned through participation in - Manifold Finance's services. + FOLD tokens are available on several decentralized exchanges and can be earned through + participation in Manifold Finance's services. </p> <div className="flex flex-wrap gap-4"> <Button asChild variant="default"> @@ -160,6 +167,5 @@ export default function FoldTokenPage() { </section> </main> </div> - ) + ); } - diff --git a/app/globals.css b/app/globals.css index da3a241..59e819b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -90,4 +90,3 @@ @apply font-heading; } } - diff --git a/app/layout.tsx b/app/layout.tsx index 2947fd5..f03af9d 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,22 +1,22 @@ -import { Space_Grotesk, Noto_Sans } from "next/font/google" -import ErrorBoundary from "./components/error-boundary" -import "./globals.css" -import type { Metadata } from "next" -import { CommandMenu } from "./components/command-menu" -import { Header } from "./components/header" -import type React from "react" -import { LayoutWrapper } from "./components/layout-wrapper" +import { Space_Grotesk, Noto_Sans } from "next/font/google"; +import ErrorBoundary from "./components/error-boundary"; +import "./globals.css"; +import type { Metadata } from "next"; +import { CommandMenu } from "./components/command-menu"; +import { Header } from "./components/header"; +import type React from "react"; +import { LayoutWrapper } from "./components/layout-wrapper"; const spaceGrotesk = Space_Grotesk({ subsets: ["latin"], variable: "--font-space-grotesk", -}) +}); const notoSans = Noto_Sans({ subsets: ["latin"], weight: ["400", "700"], variable: "--font-noto-sans", -}) +}); export const metadata: Metadata = { metadataBase: new URL("https://manifoldfinance.com"), @@ -26,7 +26,14 @@ export const metadata: Metadata = { }, description: "Manifold Finance provides optimized infrastructure for the next generation of Ethereum, offering high-performance staking, MEV optimization, and enterprise-grade SecureRPC.", - keywords: ["Manifold Finance", "Ethereum", "Staking", "MEV", "SecureRPC", "Blockchain Infrastructure"], + keywords: [ + "Manifold Finance", + "Ethereum", + "Staking", + "MEV", + "SecureRPC", + "Blockchain Infrastructure", + ], authors: [{ name: "Manifold Finance" }], creator: "Manifold Finance", publisher: "Manifold Finance", @@ -66,19 +73,20 @@ export const metadata: Metadata = { apple: "/apple-touch-icon.png", }, manifest: "https://manifoldfinance.com/site.webmanifest", -} +}; export default function RootLayout({ children, }: { - children: React.ReactNode + children: React.ReactNode; }) { //const pathname = usePathname() //const isHomePage = pathname === "/" return ( <html lang="en" className={`dark ${spaceGrotesk.variable} ${notoSans.variable}`}> - <body className={`min-h-screen bg-background text-foreground flex flex-col ${notoSans.className}`}> + <body + className={`min-h-screen bg-background text-foreground flex flex-col ${notoSans.className}`}> <ErrorBoundary> <Header /> <LayoutWrapper> @@ -88,6 +96,5 @@ export default function RootLayout({ </ErrorBoundary> </body> </html> - ) + ); } - diff --git a/app/page.tsx b/app/page.tsx index 76af662..67d9f96 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "./components/background-paths" +import { BackgroundPaths } from "./components/background-paths"; export default function Page() { return ( @@ -22,6 +22,5 @@ export default function Page() { /> </main> </div> - ) + ); } - diff --git a/app/products/captive-insurance/page.tsx b/app/products/captive-insurance/page.tsx index 6759786..e94877c 100644 --- a/app/products/captive-insurance/page.tsx +++ b/app/products/captive-insurance/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths" +import { BackgroundPaths } from "../../components/background-paths"; export default function CaptiveInsurancePage() { return ( @@ -10,8 +10,9 @@ export default function CaptiveInsurancePage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Captive Insurance</h2> <p className="text-lg mb-6"> - Our Captive Insurance product offers tailored insurance solutions designed specifically for blockchain and - DeFi projects, providing robust protection against unique risks in the crypto space. + Our Captive Insurance product offers tailored insurance solutions designed specifically + for blockchain and DeFi projects, providing robust protection against unique risks in the + crypto space. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 mt-12"> <div className="bg-gray-800 p-6 rounded-lg"> @@ -36,28 +37,30 @@ export default function CaptiveInsurancePage() { <div className="mt-12"> <h3 className="text-2xl font-bold mb-4">How It Works</h3> <p className="text-lg mb-4"> - Our Captive Insurance solution leverages blockchain technology to provide transparent, efficient, and - automated insurance processes: + Our Captive Insurance solution leverages blockchain technology to provide transparent, + efficient, and automated insurance processes: </p> <ol className="list-decimal list-inside space-y-2 ml-4"> <li>Risk Assessment: We analyze your project's specific risks and vulnerabilities.</li> - <li>Custom Policy Creation: We design a tailored insurance policy to address your unique needs.</li> <li> - Smart Contract Integration: Insurance policies are implemented as smart contracts for automated claims - processing. + Custom Policy Creation: We design a tailored insurance policy to address your unique + needs. </li> <li> - Continuous Monitoring: Our systems continuously monitor for potential risks and automatically adjust - coverage as needed. + Smart Contract Integration: Insurance policies are implemented as smart contracts for + automated claims processing. </li> <li> - Streamlined Claims: In the event of a covered incident, claims are processed quickly and efficiently - through our blockchain-based system. + Continuous Monitoring: Our systems continuously monitor for potential risks and + automatically adjust coverage as needed. + </li> + <li> + Streamlined Claims: In the event of a covered incident, claims are processed quickly + and efficiently through our blockchain-based system. </li> </ol> </div> </main> </div> - ) + ); } - diff --git a/app/products/fold-staking/page.tsx b/app/products/fold-staking/page.tsx index 18cf3d5..e489c8e 100644 --- a/app/products/fold-staking/page.tsx +++ b/app/products/fold-staking/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "@/app/components/background-paths" -import { FeatureSection } from "@/app/components/feature-section" -import { Coins, Lock, BarChart, Zap } from "lucide-react" +import { BackgroundPaths } from "@/app/components/background-paths"; +import { FeatureSection } from "@/app/components/feature-section"; +import { Coins, Lock, BarChart, Zap } from "lucide-react"; const foldStakingFeatures = [ { @@ -23,20 +23,24 @@ const foldStakingFeatures = [ title: "Quick Withdrawals", description: "Flexible withdrawal options with minimal waiting periods.", }, -] +]; export default function FoldStakingPage() { return ( <div className="min-h-screen bg-[#1616b4] text-white"> - <BackgroundPaths title="FOLD Staking|" subtitle="Maximize your returns by staking FOLD tokens" /> + <BackgroundPaths + title="FOLD Staking|" + subtitle="Maximize your returns by staking FOLD tokens" + /> <main className="container mx-auto px-4 py-12"> <FeatureSection features={foldStakingFeatures} /> <section className="mt-16"> <h2 className="text-3xl font-bold mb-6">Why Stake FOLD?</h2> <p className="text-lg mb-6"> - Staking FOLD tokens allows you to earn rewards while supporting the Manifold Finance ecosystem. By - participating in FOLD staking, you contribute to the network's security and decentralization. + Staking FOLD tokens allows you to earn rewards while supporting the Manifold Finance + ecosystem. By participating in FOLD staking, you contribute to the network's security + and decentralization. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-[#c9b3f5] bg-opacity-20 p-6 rounded-lg"> @@ -61,6 +65,5 @@ export default function FoldStakingPage() { </section> </main> </div> - ) + ); } - diff --git a/app/products/meveth/page.tsx b/app/products/meveth/page.tsx index 2de57f9..cb6b119 100644 --- a/app/products/meveth/page.tsx +++ b/app/products/meveth/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "@/app/components/background-paths" -import { FeatureSection } from "@/app/components/feature-section" -import { Zap, TrendingUp, Shield, Coins } from "lucide-react" +import { BackgroundPaths } from "@/app/components/background-paths"; +import { FeatureSection } from "@/app/components/feature-section"; +import { Zap, TrendingUp, Shield, Coins } from "lucide-react"; const mevETHFeatures = [ { @@ -23,7 +23,7 @@ const mevETHFeatures = [ title: "Liquid Staking", description: "Receive mevETH tokens while your ETH is staked.", }, -] +]; export default function MevETHPage() { return ( @@ -35,9 +35,9 @@ export default function MevETHPage() { <section className="mt-16"> <h2 className="text-3xl font-bold mb-6">What is mevETH?</h2> <p className="text-lg mb-6"> - mevETH is a revolutionary staking solution that optimizes your Ethereum staking rewards by capturing Miner - Extractable Value (MEV). By staking with mevETH, you can potentially earn higher returns compared to - traditional staking methods. + mevETH is a revolutionary staking solution that optimizes your Ethereum staking rewards + by capturing Miner Extractable Value (MEV). By staking with mevETH, you can potentially + earn higher returns compared to traditional staking methods. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-[#b8faf6] bg-opacity-20 p-6 rounded-lg"> @@ -62,6 +62,5 @@ export default function MevETHPage() { </section> </main> </div> - ) + ); } - diff --git a/app/products/securerpc/page.tsx b/app/products/securerpc/page.tsx index ee4294e..a47e077 100644 --- a/app/products/securerpc/page.tsx +++ b/app/products/securerpc/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "@/app/components/background-paths" -import { FeatureSection } from "@/app/components/feature-section" -import { Shield, Zap, Lock, Server } from "lucide-react" +import { BackgroundPaths } from "@/app/components/background-paths"; +import { FeatureSection } from "@/app/components/feature-section"; +import { Shield, Zap, Lock, Server } from "lucide-react"; const secureRPCFeatures = [ { @@ -23,20 +23,24 @@ const secureRPCFeatures = [ title: "Reliable Infrastructure", description: "Robust and scalable infrastructure for 24/7 availability.", }, -] +]; export default function SecureRPCPage() { return ( <div className="min-h-screen bg-[#1616b4] text-white"> - <BackgroundPaths title="SecureRPC|" subtitle="Enterprise-grade RPC service for secure blockchain interactions" /> + <BackgroundPaths + title="SecureRPC|" + subtitle="Enterprise-grade RPC service for secure blockchain interactions" + /> <main className="container mx-auto px-4 py-12"> <FeatureSection features={secureRPCFeatures} /> <section className="mt-16"> <h2 className="text-3xl font-bold mb-6">Why Choose SecureRPC?</h2> <p className="text-lg mb-6"> - SecureRPC provides a robust and secure infrastructure for all your blockchain interactions. Whether you're - building DApps or managing large-scale operations, our service ensures reliability and protection. + SecureRPC provides a robust and secure infrastructure for all your blockchain + interactions. Whether you're building DApps or managing large-scale operations, our + service ensures reliability and protection. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-[#88aaf1] bg-opacity-20 p-6 rounded-lg"> @@ -61,6 +65,5 @@ export default function SecureRPCPage() { </section> </main> </div> - ) + ); } - diff --git a/app/products/xga/page.tsx b/app/products/xga/page.tsx index e355c60..d428f14 100644 --- a/app/products/xga/page.tsx +++ b/app/products/xga/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "@/app/components/background-paths" -import { FeatureSection } from "@/app/components/feature-section" -import { Globe, Users, Link, VoteIcon } from "lucide-react" +import { BackgroundPaths } from "@/app/components/background-paths"; +import { FeatureSection } from "@/app/components/feature-section"; +import { Globe, Users, Link, VoteIcon } from "lucide-react"; const xgaFeatures = [ { @@ -23,7 +23,7 @@ const xgaFeatures = [ title: "Efficient Voting", description: "Streamlined voting process for quick and secure decisions.", }, -] +]; export default function XGAPage() { return ( @@ -38,9 +38,9 @@ export default function XGAPage() { <section className="mt-16"> <h2 className="text-3xl font-bold mb-6">What is XGA?</h2> <p className="text-lg mb-6"> - XGA (Cross-chain Governance Aggregator) is a revolutionary platform that enables seamless governance across - multiple blockchain networks. It provides a unified interface for participating in decentralized - decision-making processes. + XGA (Cross-chain Governance Aggregator) is a revolutionary platform that enables + seamless governance across multiple blockchain networks. It provides a unified interface + for participating in decentralized decision-making processes. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-[#f0cdc2] bg-opacity-20 p-6 rounded-lg"> @@ -65,6 +65,5 @@ export default function XGAPage() { </section> </main> </div> - ) + ); } - diff --git a/app/solutions/auction-markets/page.tsx b/app/solutions/auction-markets/page.tsx index 9819c75..d97b829 100644 --- a/app/solutions/auction-markets/page.tsx +++ b/app/solutions/auction-markets/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths" +import { BackgroundPaths } from "../../components/background-paths"; export default function AuctionMarketsPage() { return ( @@ -10,12 +10,11 @@ export default function AuctionMarketsPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Auction Markets</h2> <p className="text-lg mb-6"> - Our auction market solutions provide efficient and transparent mechanisms for decentralized finance, - optimizing value discovery and liquidity. + Our auction market solutions provide efficient and transparent mechanisms for + decentralized finance, optimizing value discovery and liquidity. </p> {/* Add more content here */} </main> </div> - ) + ); } - diff --git a/app/solutions/avs-operations/page.tsx b/app/solutions/avs-operations/page.tsx index 0fdea04..ad30f0b 100644 --- a/app/solutions/avs-operations/page.tsx +++ b/app/solutions/avs-operations/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths" +import { BackgroundPaths } from "../../components/background-paths"; export default function AvsOperationsPage() { return ( @@ -10,12 +10,11 @@ export default function AvsOperationsPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">AVS Operations</h2> <p className="text-lg mb-6"> - Our AVS operations solutions help you streamline and optimize your Autonomous Validation System for maximum - efficiency and reliability. + Our AVS operations solutions help you streamline and optimize your Autonomous Validation + System for maximum efficiency and reliability. </p> {/* Add more content here */} </main> </div> - ) + ); } - diff --git a/app/solutions/hedging-execution/page.tsx b/app/solutions/hedging-execution/page.tsx index aceb6f5..9260b03 100644 --- a/app/solutions/hedging-execution/page.tsx +++ b/app/solutions/hedging-execution/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths" +import { BackgroundPaths } from "../../components/background-paths"; export default function HedgingExecutionPage() { return ( @@ -10,8 +10,8 @@ export default function HedgingExecutionPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-2xl sm:text-3xl font-bold mb-8 text-center">Hedging and Execution</h2> <p className="text-base sm:text-lg mb-6 text-gray-300"> - Our advanced hedging and execution tools help you optimize your trading strategies and manage risk effectively - in the volatile crypto market. + Our advanced hedging and execution tools help you optimize your trading strategies and + manage risk effectively in the volatile crypto market. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 mt-12"> <div className="bg-gray-800 p-6 rounded-lg"> @@ -36,19 +36,23 @@ export default function HedgingExecutionPage() { <div className="mt-12"> <h3 className="text-xl sm:text-2xl font-bold mb-4">How It Works</h3> <p className="text-base sm:text-lg mb-4 text-gray-300"> - Our Hedging and Execution solution leverages advanced algorithms and real-time data to optimize your trading - strategies: + Our Hedging and Execution solution leverages advanced algorithms and real-time data to + optimize your trading strategies: </p> <ol className="list-decimal list-inside space-y-2 ml-4 text-gray-300"> <li>Market Analysis: Continuous monitoring of market conditions and trends.</li> <li>Strategy Formulation: Development of tailored hedging and execution strategies.</li> - <li>Automated Execution: Implementation of strategies through our high-performance trading engine.</li> + <li> + Automated Execution: Implementation of strategies through our high-performance trading + engine. + </li> <li>Risk Management: Real-time risk assessment and automatic adjustments.</li> - <li>Performance Reporting: Comprehensive analytics and reporting on strategy performance.</li> + <li> + Performance Reporting: Comprehensive analytics and reporting on strategy performance. + </li> </ol> </div> </main> </div> - ) + ); } - diff --git a/app/solutions/mev-relay-protection/page.tsx b/app/solutions/mev-relay-protection/page.tsx index 99916f9..44c20c4 100644 --- a/app/solutions/mev-relay-protection/page.tsx +++ b/app/solutions/mev-relay-protection/page.tsx @@ -1,4 +1,4 @@ -import { BackgroundPaths } from "../../components/background-paths" +import { BackgroundPaths } from "../../components/background-paths"; export default function MevRelayProtectionPage() { return ( @@ -10,12 +10,11 @@ export default function MevRelayProtectionPage() { <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">MEV Relay and Protection</h2> <p className="text-lg mb-6"> - Our MEV relay and protection services help safeguard your transactions and maximize value in the face of MEV - extraction. + Our MEV relay and protection services help safeguard your transactions and maximize value + in the face of MEV extraction. </p> {/* Add more content here */} </main> </div> - ) + ); } - diff --git a/app/solutions/mev/page.tsx b/app/solutions/mev/page.tsx index e6721bc..0ebb0c2 100644 --- a/app/solutions/mev/page.tsx +++ b/app/solutions/mev/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "../../components/background-paths" -import { FeatureSection } from "../../components/feature-section" -import { DollarSign, Zap, Shield, LineChart } from "lucide-react" +import { BackgroundPaths } from "../../components/background-paths"; +import { FeatureSection } from "../../components/feature-section"; +import { DollarSign, Zap, Shield, LineChart } from "lucide-react"; export default function MevPage() { const mevFeatures = [ @@ -24,7 +24,7 @@ export default function MevPage() { title: "MEV Analytics", description: "Detailed analytics and reporting of MEV activities.", }, - ] + ]; return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -37,6 +37,5 @@ export default function MevPage() { {/* Rest of the content remains the same */} </main> </div> - ) + ); } - diff --git a/app/solutions/page.tsx b/app/solutions/page.tsx index ea0ba32..c18db46 100644 --- a/app/solutions/page.tsx +++ b/app/solutions/page.tsx @@ -1,15 +1,17 @@ -import { BackgroundPaths } from "../components/background-paths" -import { FeatureGrid } from "../components/feature-grid" +import { BackgroundPaths } from "../components/background-paths"; +import { FeatureGrid } from "../components/feature-grid"; export default function SolutionsPage() { return ( <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths title="Our Solutions|" subtitle="Optimized infrastructure for the next generation of Ethereum" /> + <BackgroundPaths + title="Our Solutions|" + subtitle="Optimized infrastructure for the next generation of Ethereum" + /> <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Explore Our Solutions</h2> <FeatureGrid /> </main> </div> - ) + ); } - diff --git a/app/solutions/relay-protect/page.tsx b/app/solutions/relay-protect/page.tsx index 36230fe..3c9e6cb 100644 --- a/app/solutions/relay-protect/page.tsx +++ b/app/solutions/relay-protect/page.tsx @@ -1,7 +1,7 @@ -import { BackgroundPaths } from "../../components/background-paths" -import { FeatureSection } from "../../components/feature-section" -import { MEVProtectionComparison } from "../../components/mev-protection-comparison" -import { Shield, Zap, Lock, Eye } from "lucide-react" +import { BackgroundPaths } from "../../components/background-paths"; +import { FeatureSection } from "../../components/feature-section"; +import { MEVProtectionComparison } from "../../components/mev-protection-comparison"; +import { Shield, Zap, Lock, Eye } from "lucide-react"; export default function RelayProtectPage() { const relayProtectFeatures = [ @@ -25,7 +25,7 @@ export default function RelayProtectPage() { title: "Transparent Execution", description: "Full visibility into transaction execution and MEV capture.", }, - ] + ]; return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -39,8 +39,9 @@ export default function RelayProtectPage() { <section className="mt-12"> <h2 className="text-3xl font-bold mb-6">How Relay+ Protect Works</h2> <p className="text-lg mb-6"> - Relay+ Protect combines advanced MEV protection techniques with a high-performance relay network to ensure - your transactions are executed fairly and privately on the Ethereum network. + Relay+ Protect combines advanced MEV protection techniques with a high-performance relay + network to ensure your transactions are executed fairly and privately on the Ethereum + network. </p> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-blackA6 p-6 rounded-lg"> @@ -67,8 +68,8 @@ export default function RelayProtectPage() { <section className="mt-16"> <h2 className="text-3xl font-bold mb-6">Comparing MEV Protection Solutions</h2> <p className="text-lg mb-6"> - See how Relay+ Protect compares to other MEV protection solutions in the market. Our advanced architecture - and focus on privacy set us apart from the competition. + See how Relay+ Protect compares to other MEV protection solutions in the market. Our + advanced architecture and focus on privacy set us apart from the competition. </p> <MEVProtectionComparison /> </section> @@ -76,38 +77,38 @@ export default function RelayProtectPage() { <section className="mt-16"> <h2 className="text-3xl font-bold mb-6">Why Choose Relay+ Protect?</h2> <p className="text-lg mb-6"> - Relay+ Protect offers superior MEV protection through its unique architecture and focus on transaction - privacy. Here's why it stands out: + Relay+ Protect offers superior MEV protection through its unique architecture and focus + on transaction privacy. Here's why it stands out: </p> <ul className="list-disc list-inside space-y-4 text-lg text-mauveA11"> <li> - <span className="text-white font-semibold">Complete Transaction Isolation:</span> Our private mempool - implementation ensures your transactions remain fully private until validator commitment, minimizing the - risk of frontrunning and other MEV attacks. + <span className="text-white font-semibold">Complete Transaction Isolation:</span> Our + private mempool implementation ensures your transactions remain fully private until + validator commitment, minimizing the risk of frontrunning and other MEV attacks. </li> <li> - <span className="text-white font-semibold">Highest Market Impact:</span> Relay+ Protect reduces overall - MEV extraction by 85-95%, significantly outperforming other solutions in the market. + <span className="text-white font-semibold">Highest Market Impact:</span> Relay+ + Protect reduces overall MEV extraction by 85-95%, significantly outperforming other + solutions in the market. </li> <li> - <span className="text-white font-semibold">User-Centric Economic Model:</span> Users retain 70-80% of MEV - protection benefits, ensuring that the value captured from MEV protection primarily benefits you, not - intermediaries. + <span className="text-white font-semibold">User-Centric Economic Model:</span> Users + retain 70-80% of MEV protection benefits, ensuring that the value captured from MEV + protection primarily benefits you, not intermediaries. </li> <li> - <span className="text-white font-semibold">Scalability and Efficiency:</span> Our solution is highly - scalable with minimal bottlenecks and low network overhead, ensuring consistent performance as the network - grows. + <span className="text-white font-semibold">Scalability and Efficiency:</span> Our + solution is highly scalable with minimal bottlenecks and low network overhead, + ensuring consistent performance as the network grows. </li> <li> - <span className="text-white font-semibold">Future-Proof Design:</span> With a clear upgrade path and - backward compatibility, Relay+ Protect is designed to evolve with the Ethereum ecosystem while maintaining - its core benefits. + <span className="text-white font-semibold">Future-Proof Design:</span> With a clear + upgrade path and backward compatibility, Relay+ Protect is designed to evolve with the + Ethereum ecosystem while maintaining its core benefits. </li> </ul> </section> </main> </div> - ) + ); } - diff --git a/app/solutions/restaking/page.tsx b/app/solutions/restaking/page.tsx index f82fd7d..5623125 100644 --- a/app/solutions/restaking/page.tsx +++ b/app/solutions/restaking/page.tsx @@ -1,6 +1,6 @@ -import { BackgroundPaths } from "../../components/background-paths" -import { FeatureSection } from "../../components/feature-section" -import { Shield, Lock, Repeat, BarChart3 } from "lucide-react" +import { BackgroundPaths } from "../../components/background-paths"; +import { FeatureSection } from "../../components/feature-section"; +import { Shield, Lock, Repeat, BarChart3 } from "lucide-react"; export default function RestakingPage() { const restakingFeatures = [ @@ -24,7 +24,7 @@ export default function RestakingPage() { title: "Yield Optimization", description: "Maximize returns through optimized restaking strategies.", }, - ] + ]; return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -58,6 +58,5 @@ export default function RestakingPage() { </div> */} </main> </div> - ) + ); } - diff --git a/app/solutions/staking/page.tsx b/app/solutions/staking/page.tsx index 940ac5b..722f31b 100644 --- a/app/solutions/staking/page.tsx +++ b/app/solutions/staking/page.tsx @@ -1,10 +1,10 @@ -import { BackgroundPaths } from "../../components/background-paths" -import { FeatureSection } from "../../components/feature-section" -import { LSTComparisonTable } from "../../components/lst-comparison-table" -import { LSTAPYGraph } from "../../components/lst-apy-graph" -import { LSTAPYTrendGraph } from "../../components/lst-apy-trend-graph" -import { Zap, Shield, LineChart, Server } from "lucide-react" -import { TooltipProvider } from "@/components/ui/tooltip" +import { BackgroundPaths } from "../../components/background-paths"; +import { FeatureSection } from "../../components/feature-section"; +import { LSTComparisonTable } from "../../components/lst-comparison-table"; +import { LSTAPYGraph } from "../../components/lst-apy-graph"; +import { LSTAPYTrendGraph } from "../../components/lst-apy-trend-graph"; +import { Zap, Shield, LineChart, Server } from "lucide-react"; +import { TooltipProvider } from "@/components/ui/tooltip"; export default function StakingPage() { const stakingFeatures = [ @@ -28,7 +28,7 @@ export default function StakingPage() { title: "Validator Management", description: "Streamlined validator setup and maintenance tools.", }, - ] + ]; return ( <div className="min-h-screen bg-blackA12 text-white"> @@ -60,7 +60,9 @@ export default function StakingPage() { </section> <section className="mt-12 md:mt-16"> - <h2 className="text-2xl md:text-3xl font-bold mb-4 md:mb-8">Why Choose Manifold Finance for Staking?</h2> + <h2 className="text-2xl md:text-3xl font-bold mb-4 md:mb-8"> + Why Choose Manifold Finance for Staking? + </h2> <div className="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8"> <div className="bg-blackA6 p-4 md:p-6 rounded-lg"> <h3 className="text-xl font-semibold mb-4">Features</h3> @@ -86,6 +88,5 @@ export default function StakingPage() { </section> </main> </div> - ) + ); } - diff --git a/app/technology/page.tsx b/app/technology/page.tsx index 8493e8b..abc80cb 100644 --- a/app/technology/page.tsx +++ b/app/technology/page.tsx @@ -1,15 +1,20 @@ -import { BackgroundPaths } from "../components/background-paths" +import { BackgroundPaths } from "../components/background-paths"; export default function TechnologyPage() { return ( <div className="min-h-screen bg-blackA12 text-white"> - <BackgroundPaths title="Our Technology|" subtitle="Learn about the technology powering our solutions" /> + <BackgroundPaths + title="Our Technology|" + subtitle="Learn about the technology powering our solutions" + /> <main className="container mx-auto px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Cutting-Edge Technology</h2> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="bg-blackA6 p-6 rounded-lg"> <h3 className="text-xl font-semibold mb-4">High-Performance Staking</h3> - <p className="text-mauveA11">Description of the technology behind our staking solutions...</p> + <p className="text-mauveA11"> + Description of the technology behind our staking solutions... + </p> </div> <div className="bg-blackA6 p-6 rounded-lg"> <h3 className="text-xl font-semibold mb-4">MEV Optimization</h3> @@ -26,6 +31,5 @@ export default function TechnologyPage() { </div> </main> </div> - ) + ); } - diff --git a/components/icons.tsx b/components/icons.tsx index b4728e2..04bc958 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -1,6 +1,12 @@ -import { type LightbulbIcon as LucideProps, Moon, SunMedium, Twitter, type LucideIcon } from "lucide-react" +import { + type LightbulbIcon as LucideProps, + Moon, + SunMedium, + Twitter, + type LucideIcon, +} from "lucide-react"; -export type Icon = LucideIcon +export type Icon = LucideIcon; export const Icons = { sun: SunMedium, @@ -14,5 +20,4 @@ export const Icons = { /> </svg> ), -} - +}; diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx index 55c2f6e..3bc117a 100644 --- a/components/theme-provider.tsx +++ b/components/theme-provider.tsx @@ -1,11 +1,8 @@ -'use client' +"use client"; -import * as React from 'react' -import { - ThemeProvider as NextThemesProvider, - type ThemeProviderProps, -} from 'next-themes' +import * as React from "react"; +import { ThemeProvider as NextThemesProvider, type ThemeProviderProps } from "next-themes"; export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return <NextThemesProvider {...props}>{children}</NextThemesProvider> + return <NextThemesProvider {...props}>{children}</NextThemesProvider>; } diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx index 24c788c..7f5d4c8 100644 --- a/components/ui/accordion.tsx +++ b/components/ui/accordion.tsx @@ -1,24 +1,20 @@ -"use client" +"use client"; -import * as React from "react" -import * as AccordionPrimitive from "@radix-ui/react-accordion" -import { ChevronDown } from "lucide-react" +import * as React from "react"; +import * as AccordionPrimitive from "@radix-ui/react-accordion"; +import { ChevronDown } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Accordion = AccordionPrimitive.Root +const Accordion = AccordionPrimitive.Root; const AccordionItem = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Item>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> >(({ className, ...props }, ref) => ( - <AccordionPrimitive.Item - ref={ref} - className={cn("border-b", className)} - {...props} - /> -)) -AccordionItem.displayName = "AccordionItem" + <AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} /> +)); +AccordionItem.displayName = "AccordionItem"; const AccordionTrigger = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Trigger>, @@ -29,16 +25,15 @@ const AccordionTrigger = React.forwardRef< ref={ref} className={cn( "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180", - className + className, )} - {...props} - > + {...props}> {children} <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> </AccordionPrimitive.Trigger> </AccordionPrimitive.Header> -)) -AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName +)); +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; const AccordionContent = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Content>, @@ -47,12 +42,11 @@ const AccordionContent = React.forwardRef< <AccordionPrimitive.Content ref={ref} className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" - {...props} - > + {...props}> <div className={cn("pb-4 pt-0", className)}>{children}</div> </AccordionPrimitive.Content> -)) +)); -AccordionContent.displayName = AccordionPrimitive.Content.displayName +AccordionContent.displayName = AccordionPrimitive.Content.displayName; -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx index 25e7b47..a7cbc9a 100644 --- a/components/ui/alert-dialog.tsx +++ b/components/ui/alert-dialog.tsx @@ -1,16 +1,16 @@ -"use client" +"use client"; -import * as React from "react" -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" +import * as React from "react"; +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; -import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" +import { cn } from "@/lib/utils"; +import { buttonVariants } from "@/components/ui/button"; -const AlertDialog = AlertDialogPrimitive.Root +const AlertDialog = AlertDialogPrimitive.Root; -const AlertDialogTrigger = AlertDialogPrimitive.Trigger +const AlertDialogTrigger = AlertDialogPrimitive.Trigger; -const AlertDialogPortal = AlertDialogPrimitive.Portal +const AlertDialogPortal = AlertDialogPrimitive.Portal; const AlertDialogOverlay = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Overlay>, @@ -19,13 +19,13 @@ const AlertDialogOverlay = React.forwardRef< <AlertDialogPrimitive.Overlay className={cn( "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className + className, )} {...props} ref={ref} /> -)) -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName +)); +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; const AlertDialogContent = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Content>, @@ -37,41 +37,26 @@ const AlertDialogContent = React.forwardRef< ref={ref} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", - className + className, )} {...props} /> </AlertDialogPortal> -)) -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName +)); +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; -const AlertDialogHeader = ({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn( - "flex flex-col space-y-2 text-center sm:text-left", - className - )} - {...props} - /> -) -AlertDialogHeader.displayName = "AlertDialogHeader" +const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( + <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} /> +); +AlertDialogHeader.displayName = "AlertDialogHeader"; -const AlertDialogFooter = ({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) => ( +const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( <div - className={cn( - "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", - className - )} + className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} /> -) -AlertDialogFooter.displayName = "AlertDialogFooter" +); +AlertDialogFooter.displayName = "AlertDialogFooter"; const AlertDialogTitle = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Title>, @@ -82,8 +67,8 @@ const AlertDialogTitle = React.forwardRef< className={cn("text-lg font-semibold", className)} {...props} /> -)) -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName +)); +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; const AlertDialogDescription = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Description>, @@ -94,21 +79,16 @@ const AlertDialogDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -AlertDialogDescription.displayName = - AlertDialogPrimitive.Description.displayName +)); +AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; const AlertDialogAction = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Action>, React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> >(({ className, ...props }, ref) => ( - <AlertDialogPrimitive.Action - ref={ref} - className={cn(buttonVariants(), className)} - {...props} - /> -)) -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} /> +)); +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; const AlertDialogCancel = React.forwardRef< React.ElementRef<typeof AlertDialogPrimitive.Cancel>, @@ -116,15 +96,11 @@ const AlertDialogCancel = React.forwardRef< >(({ className, ...props }, ref) => ( <AlertDialogPrimitive.Cancel ref={ref} - className={cn( - buttonVariants({ variant: "outline" }), - "mt-2 sm:mt-0", - className - )} + className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)} {...props} /> -)) -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName +)); +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; export { AlertDialog, @@ -138,4 +114,4 @@ export { AlertDialogDescription, AlertDialogAction, AlertDialogCancel, -} +}; diff --git a/components/ui/alert.tsx b/components/ui/alert.tsx index 41fa7e0..bc1429c 100644 --- a/components/ui/alert.tsx +++ b/components/ui/alert.tsx @@ -1,7 +1,7 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const alertVariants = cva( "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", @@ -16,44 +16,34 @@ const alertVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); const Alert = React.forwardRef< HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants> >(({ className, variant, ...props }, ref) => ( - <div - ref={ref} - role="alert" - className={cn(alertVariants({ variant }), className)} - {...props} - /> -)) -Alert.displayName = "Alert" + <div ref={ref} role="alert" className={cn(alertVariants({ variant }), className)} {...props} /> +)); +Alert.displayName = "Alert"; -const AlertTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes<HTMLHeadingElement> ->(({ className, ...props }, ref) => ( - <h5 - ref={ref} - className={cn("mb-1 font-medium leading-none tracking-tight", className)} - {...props} - /> -)) -AlertTitle.displayName = "AlertTitle" +const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>( + ({ className, ...props }, ref) => ( + <h5 + ref={ref} + className={cn("mb-1 font-medium leading-none tracking-tight", className)} + {...props} + /> + ), +); +AlertTitle.displayName = "AlertTitle"; const AlertDescription = React.forwardRef< HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement> >(({ className, ...props }, ref) => ( - <div - ref={ref} - className={cn("text-sm [&_p]:leading-relaxed", className)} - {...props} - /> -)) -AlertDescription.displayName = "AlertDescription" + <div ref={ref} className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} /> +)); +AlertDescription.displayName = "AlertDescription"; -export { Alert, AlertTitle, AlertDescription } +export { Alert, AlertTitle, AlertDescription }; diff --git a/components/ui/aspect-ratio.tsx b/components/ui/aspect-ratio.tsx index d6a5226..359bc94 100644 --- a/components/ui/aspect-ratio.tsx +++ b/components/ui/aspect-ratio.tsx @@ -1,7 +1,7 @@ -"use client" +"use client"; -import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; -const AspectRatio = AspectRatioPrimitive.Root +const AspectRatio = AspectRatioPrimitive.Root; -export { AspectRatio } +export { AspectRatio }; diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx index 51e507b..7904926 100644 --- a/components/ui/avatar.tsx +++ b/components/ui/avatar.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" +import * as React from "react"; +import * as AvatarPrimitive from "@radix-ui/react-avatar"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Avatar = React.forwardRef< React.ElementRef<typeof AvatarPrimitive.Root>, @@ -11,14 +11,11 @@ const Avatar = React.forwardRef< >(({ className, ...props }, ref) => ( <AvatarPrimitive.Root ref={ref} - className={cn( - "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", - className - )} + className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)} {...props} /> -)) -Avatar.displayName = AvatarPrimitive.Root.displayName +)); +Avatar.displayName = AvatarPrimitive.Root.displayName; const AvatarImage = React.forwardRef< React.ElementRef<typeof AvatarPrimitive.Image>, @@ -29,8 +26,8 @@ const AvatarImage = React.forwardRef< className={cn("aspect-square h-full w-full", className)} {...props} /> -)) -AvatarImage.displayName = AvatarPrimitive.Image.displayName +)); +AvatarImage.displayName = AvatarPrimitive.Image.displayName; const AvatarFallback = React.forwardRef< React.ElementRef<typeof AvatarPrimitive.Fallback>, @@ -40,11 +37,11 @@ const AvatarFallback = React.forwardRef< ref={ref} className={cn( "flex h-full w-full items-center justify-center rounded-full bg-muted", - className + className, )} {...props} /> -)) -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName +)); +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; -export { Avatar, AvatarImage, AvatarFallback } +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx index 480a6ee..9ab4cc0 100644 --- a/components/ui/badge.tsx +++ b/components/ui/badge.tsx @@ -1,6 +1,6 @@ -import type * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@/lib/utils" +import type * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; +import { cn } from "@/lib/utils"; const badgeVariants = cva( "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", @@ -30,13 +30,14 @@ const badgeVariants = cva( radius: "default", }, }, -) +); -export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {} +export interface BadgeProps + extends React.HTMLAttributes<HTMLDivElement>, + VariantProps<typeof badgeVariants> {} function Badge({ className, variant, color, radius, ...props }: BadgeProps) { - return <div className={cn(badgeVariants({ variant, color, radius }), className)} {...props} /> + return <div className={cn(badgeVariants({ variant, color, radius }), className)} {...props} />; } -export { Badge, badgeVariants } - +export { Badge, badgeVariants }; diff --git a/components/ui/breadcrumb.tsx b/components/ui/breadcrumb.tsx index 60e6c96..bcdd0a1 100644 --- a/components/ui/breadcrumb.tsx +++ b/components/ui/breadcrumb.tsx @@ -1,51 +1,45 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { ChevronRight, MoreHorizontal } from "lucide-react" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { ChevronRight, MoreHorizontal } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Breadcrumb = React.forwardRef< HTMLElement, React.ComponentPropsWithoutRef<"nav"> & { - separator?: React.ReactNode + separator?: React.ReactNode; } ->(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />) -Breadcrumb.displayName = "Breadcrumb" +>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />); +Breadcrumb.displayName = "Breadcrumb"; -const BreadcrumbList = React.forwardRef< - HTMLOListElement, - React.ComponentPropsWithoutRef<"ol"> ->(({ className, ...props }, ref) => ( - <ol - ref={ref} - className={cn( - "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", - className - )} - {...props} - /> -)) -BreadcrumbList.displayName = "BreadcrumbList" +const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<"ol">>( + ({ className, ...props }, ref) => ( + <ol + ref={ref} + className={cn( + "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", + className, + )} + {...props} + /> + ), +); +BreadcrumbList.displayName = "BreadcrumbList"; -const BreadcrumbItem = React.forwardRef< - HTMLLIElement, - React.ComponentPropsWithoutRef<"li"> ->(({ className, ...props }, ref) => ( - <li - ref={ref} - className={cn("inline-flex items-center gap-1.5", className)} - {...props} - /> -)) -BreadcrumbItem.displayName = "BreadcrumbItem" +const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<"li">>( + ({ className, ...props }, ref) => ( + <li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} /> + ), +); +BreadcrumbItem.displayName = "BreadcrumbItem"; const BreadcrumbLink = React.forwardRef< HTMLAnchorElement, React.ComponentPropsWithoutRef<"a"> & { - asChild?: boolean + asChild?: boolean; } >(({ asChild, className, ...props }, ref) => { - const Comp = asChild ? Slot : "a" + const Comp = asChild ? Slot : "a"; return ( <Comp @@ -53,56 +47,46 @@ const BreadcrumbLink = React.forwardRef< className={cn("transition-colors hover:text-foreground", className)} {...props} /> - ) -}) -BreadcrumbLink.displayName = "BreadcrumbLink" + ); +}); +BreadcrumbLink.displayName = "BreadcrumbLink"; -const BreadcrumbPage = React.forwardRef< - HTMLSpanElement, - React.ComponentPropsWithoutRef<"span"> ->(({ className, ...props }, ref) => ( - <span - ref={ref} - role="link" - aria-disabled="true" - aria-current="page" - className={cn("font-normal text-foreground", className)} - {...props} - /> -)) -BreadcrumbPage.displayName = "BreadcrumbPage" +const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<"span">>( + ({ className, ...props }, ref) => ( + <span + ref={ref} + role="link" + aria-disabled="true" + aria-current="page" + className={cn("font-normal text-foreground", className)} + {...props} + /> + ), +); +BreadcrumbPage.displayName = "BreadcrumbPage"; -const BreadcrumbSeparator = ({ - children, - className, - ...props -}: React.ComponentProps<"li">) => ( +const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => ( <li role="presentation" aria-hidden="true" className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)} - {...props} - > + {...props}> {children ?? <ChevronRight />} </li> -) -BreadcrumbSeparator.displayName = "BreadcrumbSeparator" +); +BreadcrumbSeparator.displayName = "BreadcrumbSeparator"; -const BreadcrumbEllipsis = ({ - className, - ...props -}: React.ComponentProps<"span">) => ( +const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => ( <span role="presentation" aria-hidden="true" className={cn("flex h-9 w-9 items-center justify-center", className)} - {...props} - > + {...props}> <MoreHorizontal className="h-4 w-4" /> <span className="sr-only">More</span> </span> -) -BreadcrumbEllipsis.displayName = "BreadcrumbElipssis" +); +BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"; export { Breadcrumb, @@ -112,4 +96,4 @@ export { BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis, -} +}; diff --git a/components/ui/button.tsx b/components/ui/button.tsx index 108dd01..3176a6d 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -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 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", @@ -28,21 +28,22 @@ const buttonVariants = cva( 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" - return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> + const Comp = asChild ? Slot : "button"; + return ( + <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> + ); }, -) -Button.displayName = "Button" - -export { Button, buttonVariants } +); +Button.displayName = "Button"; +export { Button, buttonVariants }; diff --git a/components/ui/calendar.tsx b/components/ui/calendar.tsx index 61d2b45..87a22d9 100644 --- a/components/ui/calendar.tsx +++ b/components/ui/calendar.tsx @@ -1,20 +1,15 @@ -"use client" +"use client"; -import * as React from "react" -import { ChevronLeft, ChevronRight } from "lucide-react" -import { DayPicker } from "react-day-picker" +import * as React from "react"; +import { ChevronLeft, ChevronRight } from "lucide-react"; +import { DayPicker } from "react-day-picker"; -import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" +import { cn } from "@/lib/utils"; +import { buttonVariants } from "@/components/ui/button"; -export type CalendarProps = React.ComponentProps<typeof DayPicker> +export type CalendarProps = React.ComponentProps<typeof DayPicker>; -function Calendar({ - className, - classNames, - showOutsideDays = true, - ...props -}: CalendarProps) { +function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { return ( <DayPicker showOutsideDays={showOutsideDays} @@ -27,19 +22,18 @@ function Calendar({ nav: "space-x-1 flex items-center", nav_button: cn( buttonVariants({ variant: "outline" }), - "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100" + "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100", ), nav_button_previous: "absolute left-1", nav_button_next: "absolute right-1", table: "w-full border-collapse space-y-1", head_row: "flex", - head_cell: - "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", + head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", row: "flex w-full mt-2", cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20", day: cn( buttonVariants({ variant: "ghost" }), - "h-9 w-9 p-0 font-normal aria-selected:opacity-100" + "h-9 w-9 p-0 font-normal aria-selected:opacity-100", ), day_range_end: "day-range-end", day_selected: @@ -48,8 +42,7 @@ function Calendar({ day_outside: "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground", day_disabled: "text-muted-foreground opacity-50", - day_range_middle: - "aria-selected:bg-accent aria-selected:text-accent-foreground", + day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground", day_hidden: "invisible", ...classNames, }} @@ -59,8 +52,8 @@ function Calendar({ }} {...props} /> - ) + ); } -Calendar.displayName = "Calendar" +Calendar.displayName = "Calendar"; -export { Calendar } +export { Calendar }; diff --git a/components/ui/card.tsx b/components/ui/card.tsx index 0906be5..117feb7 100644 --- a/components/ui/card.tsx +++ b/components/ui/card.tsx @@ -1,44 +1,56 @@ -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, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => ( - <div ref={ref} className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} {...props} /> -)) -Card.displayName = "Card" +const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( + ({ className, ...props }, ref) => ( + <div + ref={ref} + className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} + {...props} + /> + ), +); +Card.displayName = "Card"; const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} /> ), -) -CardHeader.displayName = "CardHeader" +); +CardHeader.displayName = "CardHeader"; const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>( ({ className, ...props }, ref) => ( - <h3 ref={ref} className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} /> + <h3 + ref={ref} + className={cn("text-2xl font-semibold leading-none tracking-tight", className)} + {...props} + /> ), -) -CardTitle.displayName = "CardTitle" +); +CardTitle.displayName = "CardTitle"; -const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>( - ({ className, ...props }, ref) => ( - <p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> - ), -) -CardDescription.displayName = "CardDescription" +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes<HTMLParagraphElement> +>(({ className, ...props }, ref) => ( + <p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> +)); +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" + ({ className, ...props }, ref) => ( + <div ref={ref} className={cn("p-6 pt-0", className)} {...props} /> + ), +); +CardContent.displayName = "CardContent"; const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} /> ), -) -CardFooter.displayName = "CardFooter" - -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } +); +CardFooter.displayName = "CardFooter"; +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/components/ui/carousel.tsx b/components/ui/carousel.tsx index ec505d0..50f3511 100644 --- a/components/ui/carousel.tsx +++ b/components/ui/carousel.tsx @@ -1,256 +1,232 @@ -"use client" +"use client"; -import * as React from "react" -import useEmblaCarousel, { - type UseEmblaCarouselType, -} from "embla-carousel-react" -import { ArrowLeft, ArrowRight } from "lucide-react" +import * as React from "react"; +import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react"; +import { ArrowLeft, ArrowRight } from "lucide-react"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; -type CarouselApi = UseEmblaCarouselType[1] -type UseCarouselParameters = Parameters<typeof useEmblaCarousel> -type CarouselOptions = UseCarouselParameters[0] -type CarouselPlugin = UseCarouselParameters[1] +type CarouselApi = UseEmblaCarouselType[1]; +type UseCarouselParameters = Parameters<typeof useEmblaCarousel>; +type CarouselOptions = UseCarouselParameters[0]; +type CarouselPlugin = UseCarouselParameters[1]; type CarouselProps = { - opts?: CarouselOptions - plugins?: CarouselPlugin - orientation?: "horizontal" | "vertical" - setApi?: (api: CarouselApi) => void -} + opts?: CarouselOptions; + plugins?: CarouselPlugin; + orientation?: "horizontal" | "vertical"; + setApi?: (api: CarouselApi) => void; +}; type CarouselContextProps = { - carouselRef: ReturnType<typeof useEmblaCarousel>[0] - api: ReturnType<typeof useEmblaCarousel>[1] - scrollPrev: () => void - scrollNext: () => void - canScrollPrev: boolean - canScrollNext: boolean -} & CarouselProps + carouselRef: ReturnType<typeof useEmblaCarousel>[0]; + api: ReturnType<typeof useEmblaCarousel>[1]; + scrollPrev: () => void; + scrollNext: () => void; + canScrollPrev: boolean; + canScrollNext: boolean; +} & CarouselProps; -const CarouselContext = React.createContext<CarouselContextProps | null>(null) +const CarouselContext = React.createContext<CarouselContextProps | null>(null); function useCarousel() { - const context = React.useContext(CarouselContext) + const context = React.useContext(CarouselContext); if (!context) { - throw new Error("useCarousel must be used within a <Carousel />") + throw new Error("useCarousel must be used within a <Carousel />"); } - return context + return context; } const Carousel = React.forwardRef< HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & CarouselProps ->( - ( +>(({ orientation = "horizontal", opts, setApi, plugins, className, children, ...props }, ref) => { + const [carouselRef, api] = useEmblaCarousel( { - orientation = "horizontal", - opts, - setApi, - plugins, - className, - children, - ...props + ...opts, + axis: orientation === "horizontal" ? "x" : "y", }, - ref - ) => { - const [carouselRef, api] = useEmblaCarousel( - { - ...opts, - axis: orientation === "horizontal" ? "x" : "y", - }, - plugins - ) - const [canScrollPrev, setCanScrollPrev] = React.useState(false) - const [canScrollNext, setCanScrollNext] = React.useState(false) - - const onSelect = React.useCallback((api: CarouselApi) => { - if (!api) { - return + plugins, + ); + const [canScrollPrev, setCanScrollPrev] = React.useState(false); + const [canScrollNext, setCanScrollNext] = React.useState(false); + + const onSelect = React.useCallback((api: CarouselApi) => { + if (!api) { + return; + } + + setCanScrollPrev(api.canScrollPrev()); + setCanScrollNext(api.canScrollNext()); + }, []); + + const scrollPrev = React.useCallback(() => { + api?.scrollPrev(); + }, [api]); + + const scrollNext = React.useCallback(() => { + api?.scrollNext(); + }, [api]); + + const handleKeyDown = React.useCallback( + (event: React.KeyboardEvent<HTMLDivElement>) => { + if (event.key === "ArrowLeft") { + event.preventDefault(); + scrollPrev(); + } else if (event.key === "ArrowRight") { + event.preventDefault(); + scrollNext(); } + }, + [scrollPrev, scrollNext], + ); - setCanScrollPrev(api.canScrollPrev()) - setCanScrollNext(api.canScrollNext()) - }, []) - - const scrollPrev = React.useCallback(() => { - api?.scrollPrev() - }, [api]) - - const scrollNext = React.useCallback(() => { - api?.scrollNext() - }, [api]) - - const handleKeyDown = React.useCallback( - (event: React.KeyboardEvent<HTMLDivElement>) => { - if (event.key === "ArrowLeft") { - event.preventDefault() - scrollPrev() - } else if (event.key === "ArrowRight") { - event.preventDefault() - scrollNext() - } - }, - [scrollPrev, scrollNext] - ) + React.useEffect(() => { + if (!api || !setApi) { + return; + } - React.useEffect(() => { - if (!api || !setApi) { - return - } + setApi(api); + }, [api, setApi]); - setApi(api) - }, [api, setApi]) + React.useEffect(() => { + if (!api) { + return; + } - React.useEffect(() => { - if (!api) { - return - } + onSelect(api); + api.on("reInit", onSelect); + api.on("select", onSelect); - onSelect(api) - api.on("reInit", onSelect) - api.on("select", onSelect) + return () => { + api?.off("select", onSelect); + }; + }, [api, onSelect]); - return () => { - api?.off("select", onSelect) - } - }, [api, onSelect]) + return ( + <CarouselContext.Provider + value={{ + carouselRef, + api: api, + opts, + orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), + scrollPrev, + scrollNext, + canScrollPrev, + canScrollNext, + }}> + <div + ref={ref} + onKeyDownCapture={handleKeyDown} + className={cn("relative", className)} + role="region" + aria-roledescription="carousel" + {...props}> + {children} + </div> + </CarouselContext.Provider> + ); +}); +Carousel.displayName = "Carousel"; + +const CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( + ({ className, ...props }, ref) => { + const { carouselRef, orientation } = useCarousel(); return ( - <CarouselContext.Provider - value={{ - carouselRef, - api: api, - opts, - orientation: - orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), - scrollPrev, - scrollNext, - canScrollPrev, - canScrollNext, - }} - > + <div ref={carouselRef} className="overflow-hidden"> <div ref={ref} - onKeyDownCapture={handleKeyDown} - className={cn("relative", className)} - role="region" - aria-roledescription="carousel" + className={cn( + "flex", + orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", + className, + )} {...props} - > - {children} - </div> - </CarouselContext.Provider> - ) - } -) -Carousel.displayName = "Carousel" + /> + </div> + ); + }, +); +CarouselContent.displayName = "CarouselContent"; -const CarouselContent = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes<HTMLDivElement> ->(({ className, ...props }, ref) => { - const { carouselRef, orientation } = useCarousel() +const CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( + ({ className, ...props }, ref) => { + const { orientation } = useCarousel(); - return ( - <div ref={carouselRef} className="overflow-hidden"> + return ( <div ref={ref} + role="group" + aria-roledescription="slide" className={cn( - "flex", - orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", - className + "min-w-0 shrink-0 grow-0 basis-full", + orientation === "horizontal" ? "pl-4" : "pt-4", + className, )} {...props} /> - </div> - ) -}) -CarouselContent.displayName = "CarouselContent" + ); + }, +); +CarouselItem.displayName = "CarouselItem"; -const CarouselItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes<HTMLDivElement> ->(({ className, ...props }, ref) => { - const { orientation } = useCarousel() - - return ( - <div - ref={ref} - role="group" - aria-roledescription="slide" - className={cn( - "min-w-0 shrink-0 grow-0 basis-full", - orientation === "horizontal" ? "pl-4" : "pt-4", - className - )} - {...props} - /> - ) -}) -CarouselItem.displayName = "CarouselItem" - -const CarouselPrevious = React.forwardRef< - HTMLButtonElement, - React.ComponentProps<typeof Button> ->(({ className, variant = "outline", size = "icon", ...props }, ref) => { - const { orientation, scrollPrev, canScrollPrev } = useCarousel() +const CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>( + ({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollPrev, canScrollPrev } = useCarousel(); - return ( - <Button - ref={ref} - variant={variant} - size={size} - className={cn( - "absolute h-8 w-8 rounded-full", - orientation === "horizontal" - ? "-left-12 top-1/2 -translate-y-1/2" - : "-top-12 left-1/2 -translate-x-1/2 rotate-90", - className - )} - disabled={!canScrollPrev} - onClick={scrollPrev} - {...props} - > - <ArrowLeft className="h-4 w-4" /> - <span className="sr-only">Previous slide</span> - </Button> - ) -}) -CarouselPrevious.displayName = "CarouselPrevious" - -const CarouselNext = React.forwardRef< - HTMLButtonElement, - React.ComponentProps<typeof Button> ->(({ className, variant = "outline", size = "icon", ...props }, ref) => { - const { orientation, scrollNext, canScrollNext } = useCarousel() + return ( + <Button + ref={ref} + variant={variant} + size={size} + className={cn( + "absolute h-8 w-8 rounded-full", + orientation === "horizontal" + ? "-left-12 top-1/2 -translate-y-1/2" + : "-top-12 left-1/2 -translate-x-1/2 rotate-90", + className, + )} + disabled={!canScrollPrev} + onClick={scrollPrev} + {...props}> + <ArrowLeft className="h-4 w-4" /> + <span className="sr-only">Previous slide</span> + </Button> + ); + }, +); +CarouselPrevious.displayName = "CarouselPrevious"; + +const CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>( + ({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollNext, canScrollNext } = useCarousel(); - return ( - <Button - ref={ref} - variant={variant} - size={size} - className={cn( - "absolute h-8 w-8 rounded-full", - orientation === "horizontal" - ? "-right-12 top-1/2 -translate-y-1/2" - : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", - className - )} - disabled={!canScrollNext} - onClick={scrollNext} - {...props} - > - <ArrowRight className="h-4 w-4" /> - <span className="sr-only">Next slide</span> - </Button> - ) -}) -CarouselNext.displayName = "CarouselNext" + return ( + <Button + ref={ref} + variant={variant} + size={size} + className={cn( + "absolute h-8 w-8 rounded-full", + orientation === "horizontal" + ? "-right-12 top-1/2 -translate-y-1/2" + : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", + className, + )} + disabled={!canScrollNext} + onClick={scrollNext} + {...props}> + <ArrowRight className="h-4 w-4" /> + <span className="sr-only">Next slide</span> + </Button> + ); + }, +); +CarouselNext.displayName = "CarouselNext"; export { type CarouselApi, @@ -259,4 +235,4 @@ export { CarouselItem, CarouselPrevious, CarouselNext, -} +}; diff --git a/components/ui/chart.tsx b/components/ui/chart.tsx index 8620baa..0cb110f 100644 --- a/components/ui/chart.tsx +++ b/components/ui/chart.tsx @@ -1,50 +1,48 @@ -"use client" +"use client"; -import * as React from "react" -import * as RechartsPrimitive from "recharts" +import * as React from "react"; +import * as RechartsPrimitive from "recharts"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; // Format: { THEME_NAME: CSS_SELECTOR } -const THEMES = { light: "", dark: ".dark" } as const +const THEMES = { light: "", dark: ".dark" } as const; export type ChartConfig = { [k in string]: { - label?: React.ReactNode - icon?: React.ComponentType + label?: React.ReactNode; + icon?: React.ComponentType; } & ( | { color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> } - ) -} + ); +}; type ChartContextProps = { - config: ChartConfig -} + config: ChartConfig; +}; -const ChartContext = React.createContext<ChartContextProps | null>(null) +const ChartContext = React.createContext<ChartContextProps | null>(null); function useChart() { - const context = React.useContext(ChartContext) + const context = React.useContext(ChartContext); if (!context) { - throw new Error("useChart must be used within a <ChartContainer />") + throw new Error("useChart must be used within a <ChartContainer />"); } - return context + return context; } const ChartContainer = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - config: ChartConfig - children: React.ComponentProps< - typeof RechartsPrimitive.ResponsiveContainer - >["children"] + config: ChartConfig; + children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"]; } >(({ id, className, children, config, ...props }, ref) => { - const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const uniqueId = React.useId(); + const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`; return ( <ChartContext.Provider value={{ config }}> @@ -53,27 +51,22 @@ const ChartContainer = React.forwardRef< ref={ref} className={cn( "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", - className + className, )} - {...props} - > + {...props}> <ChartStyle id={chartId} config={config} /> - <RechartsPrimitive.ResponsiveContainer> - {children} - </RechartsPrimitive.ResponsiveContainer> + <RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer> </div> </ChartContext.Provider> - ) -}) -ChartContainer.displayName = "Chart" + ); +}); +ChartContainer.displayName = "Chart"; const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { - const colorConfig = Object.entries(config).filter( - ([_, config]) => config.theme || config.color - ) + const colorConfig = Object.entries(config).filter(([_, config]) => config.theme || config.color); if (!colorConfig.length) { - return null + return null; } return ( @@ -85,32 +78,30 @@ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { - const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || - itemConfig.color - return color ? ` --color-${key}: ${color};` : null + const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color; + return color ? ` --color-${key}: ${color};` : null; }) .join("\n")} } -` +`, ) .join("\n"), }} /> - ) -} + ); +}; -const ChartTooltip = RechartsPrimitive.Tooltip +const ChartTooltip = RechartsPrimitive.Tooltip; const ChartTooltipContent = React.forwardRef< HTMLDivElement, React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<"div"> & { - hideLabel?: boolean - hideIndicator?: boolean - indicator?: "line" | "dot" | "dashed" - nameKey?: string - labelKey?: string + hideLabel?: boolean; + hideIndicator?: boolean; + indicator?: "line" | "dot" | "dashed"; + nameKey?: string; + labelKey?: string; } >( ( @@ -129,75 +120,63 @@ const ChartTooltipContent = React.forwardRef< nameKey, labelKey, }, - ref + ref, ) => { - const { config } = useChart() + const { config } = useChart(); const tooltipLabel = React.useMemo(() => { if (hideLabel || !payload?.length) { - return null + return null; } - const [item] = payload - const key = `${labelKey || item.dataKey || item.name || "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) + const [item] = payload; + const key = `${labelKey || item.dataKey || item.name || "value"}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); const value = !labelKey && typeof label === "string" ? config[label as keyof typeof config]?.label || label - : itemConfig?.label + : itemConfig?.label; if (labelFormatter) { return ( - <div className={cn("font-medium", labelClassName)}> - {labelFormatter(value, payload)} - </div> - ) + <div className={cn("font-medium", labelClassName)}>{labelFormatter(value, payload)}</div> + ); } if (!value) { - return null + return null; } - return <div className={cn("font-medium", labelClassName)}>{value}</div> - }, [ - label, - labelFormatter, - payload, - hideLabel, - labelClassName, - config, - labelKey, - ]) + return <div className={cn("font-medium", labelClassName)}>{value}</div>; + }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]); if (!active || !payload?.length) { - return null + return null; } - const nestLabel = payload.length === 1 && indicator !== "dot" + const nestLabel = payload.length === 1 && indicator !== "dot"; return ( <div ref={ref} className={cn( "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl", - className - )} - > + className, + )}> {!nestLabel ? tooltipLabel : null} <div className="grid gap-1.5"> {payload.map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const key = `${nameKey || item.name || item.dataKey || "value"}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); + const indicatorColor = color || item.payload.fill || item.color; return ( <div key={item.dataKey} className={cn( "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", - indicator === "dot" && "items-center" - )} - > + indicator === "dot" && "items-center", + )}> {formatter && item?.value !== undefined && item.name ? ( formatter(item.value, item.name, item, index, item.payload) ) : ( @@ -215,7 +194,7 @@ const ChartTooltipContent = React.forwardRef< "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed", "my-0.5": nestLabel && indicator === "dashed", - } + }, )} style={ { @@ -229,9 +208,8 @@ const ChartTooltipContent = React.forwardRef< <div className={cn( "flex flex-1 justify-between leading-none", - nestLabel ? "items-end" : "items-center" - )} - > + nestLabel ? "items-end" : "items-center", + )}> <div className="grid gap-1.5"> {nestLabel ? tooltipLabel : null} <span className="text-muted-foreground"> @@ -247,112 +225,92 @@ const ChartTooltipContent = React.forwardRef< </> )} </div> - ) + ); })} </div> </div> - ) - } -) -ChartTooltipContent.displayName = "ChartTooltip" + ); + }, +); +ChartTooltipContent.displayName = "ChartTooltip"; -const ChartLegend = RechartsPrimitive.Legend +const ChartLegend = RechartsPrimitive.Legend; const ChartLegendContent = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & { - hideIcon?: boolean - nameKey?: string + hideIcon?: boolean; + nameKey?: string; } ->( - ( - { className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, - ref - ) => { - const { config } = useChart() +>(({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, ref) => { + const { config } = useChart(); - if (!payload?.length) { - return null - } - - return ( - <div - ref={ref} - className={cn( - "flex items-center justify-center gap-4", - verticalAlign === "top" ? "pb-3" : "pt-3", - className - )} - > - {payload.map((item) => { - const key = `${nameKey || item.dataKey || "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) - - return ( - <div - key={item.value} - className={cn( - "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" - )} - > - {itemConfig?.icon && !hideIcon ? ( - <itemConfig.icon /> - ) : ( - <div - className="h-2 w-2 shrink-0 rounded-[2px]" - style={{ - backgroundColor: item.color, - }} - /> - )} - {itemConfig?.label} - </div> - ) - })} - </div> - ) + if (!payload?.length) { + return null; } -) -ChartLegendContent.displayName = "ChartLegend" + + return ( + <div + ref={ref} + className={cn( + "flex items-center justify-center gap-4", + verticalAlign === "top" ? "pb-3" : "pt-3", + className, + )}> + {payload.map((item) => { + const key = `${nameKey || item.dataKey || "value"}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); + + return ( + <div + key={item.value} + className={cn( + "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground", + )}> + {itemConfig?.icon && !hideIcon ? ( + <itemConfig.icon /> + ) : ( + <div + className="h-2 w-2 shrink-0 rounded-[2px]" + style={{ + backgroundColor: item.color, + }} + /> + )} + {itemConfig?.label} + </div> + ); + })} + </div> + ); +}); +ChartLegendContent.displayName = "ChartLegend"; // Helper to extract item config from a payload. -function getPayloadConfigFromPayload( - config: ChartConfig, - payload: unknown, - key: string -) { +function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) { if (typeof payload !== "object" || payload === null) { - return undefined + return undefined; } const payloadPayload = - "payload" in payload && - typeof payload.payload === "object" && - payload.payload !== null + "payload" in payload && typeof payload.payload === "object" && payload.payload !== null ? payload.payload - : undefined + : undefined; - let configLabelKey: string = key + let configLabelKey: string = key; - if ( - key in payload && - typeof payload[key as keyof typeof payload] === "string" - ) { - configLabelKey = payload[key as keyof typeof payload] as string + if (key in payload && typeof payload[key as keyof typeof payload] === "string") { + configLabelKey = payload[key as keyof typeof payload] as string; } else if ( payloadPayload && key in payloadPayload && typeof payloadPayload[key as keyof typeof payloadPayload] === "string" ) { - configLabelKey = payloadPayload[ - key as keyof typeof payloadPayload - ] as string + configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string; } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]; } export { @@ -362,4 +320,4 @@ export { ChartLegend, ChartLegendContent, ChartStyle, -} +}; diff --git a/components/ui/checkbox.tsx b/components/ui/checkbox.tsx index df61a13..ecb1699 100644 --- a/components/ui/checkbox.tsx +++ b/components/ui/checkbox.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import * as CheckboxPrimitive from "@radix-ui/react-checkbox" -import { Check } from "lucide-react" +import * as React from "react"; +import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; +import { Check } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Checkbox = React.forwardRef< React.ElementRef<typeof CheckboxPrimitive.Root>, @@ -14,17 +14,14 @@ const Checkbox = React.forwardRef< ref={ref} className={cn( "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground", - className + className, )} - {...props} - > - <CheckboxPrimitive.Indicator - className={cn("flex items-center justify-center text-current")} - > + {...props}> + <CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}> <Check className="h-4 w-4" /> </CheckboxPrimitive.Indicator> </CheckboxPrimitive.Root> -)) -Checkbox.displayName = CheckboxPrimitive.Root.displayName +)); +Checkbox.displayName = CheckboxPrimitive.Root.displayName; -export { Checkbox } +export { Checkbox }; diff --git a/components/ui/collapsible.tsx b/components/ui/collapsible.tsx index 9fa4894..cb003d1 100644 --- a/components/ui/collapsible.tsx +++ b/components/ui/collapsible.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; -const Collapsible = CollapsiblePrimitive.Root +const Collapsible = CollapsiblePrimitive.Root; -const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; -const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; -export { Collapsible, CollapsibleTrigger, CollapsibleContent } +export { Collapsible, CollapsibleTrigger, CollapsibleContent }; diff --git a/components/ui/command.tsx b/components/ui/command.tsx index 59a2645..20cc294 100644 --- a/components/ui/command.tsx +++ b/components/ui/command.tsx @@ -1,12 +1,12 @@ -"use client" +"use client"; -import * as React from "react" -import { type DialogProps } from "@radix-ui/react-dialog" -import { Command as CommandPrimitive } from "cmdk" -import { Search } from "lucide-react" +import * as React from "react"; +import { type DialogProps } from "@radix-ui/react-dialog"; +import { Command as CommandPrimitive } from "cmdk"; +import { Search } from "lucide-react"; -import { cn } from "@/lib/utils" -import { Dialog, DialogContent } from "@/components/ui/dialog" +import { cn } from "@/lib/utils"; +import { Dialog, DialogContent } from "@/components/ui/dialog"; const Command = React.forwardRef< React.ElementRef<typeof CommandPrimitive>, @@ -16,12 +16,12 @@ const Command = React.forwardRef< ref={ref} className={cn( "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", - className + className, )} {...props} /> -)) -Command.displayName = CommandPrimitive.displayName +)); +Command.displayName = CommandPrimitive.displayName; const CommandDialog = ({ children, ...props }: DialogProps) => { return ( @@ -32,8 +32,8 @@ const CommandDialog = ({ children, ...props }: DialogProps) => { </Command> </DialogContent> </Dialog> - ) -} + ); +}; const CommandInput = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Input>, @@ -45,14 +45,14 @@ const CommandInput = React.forwardRef< ref={ref} className={cn( "flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", - className + className, )} {...props} /> </div> -)) +)); -CommandInput.displayName = CommandPrimitive.Input.displayName +CommandInput.displayName = CommandPrimitive.Input.displayName; const CommandList = React.forwardRef< React.ElementRef<typeof CommandPrimitive.List>, @@ -63,22 +63,18 @@ const CommandList = React.forwardRef< className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} {...props} /> -)) +)); -CommandList.displayName = CommandPrimitive.List.displayName +CommandList.displayName = CommandPrimitive.List.displayName; const CommandEmpty = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Empty>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> >((props, ref) => ( - <CommandPrimitive.Empty - ref={ref} - className="py-6 text-center text-sm" - {...props} - /> -)) + <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} /> +)); -CommandEmpty.displayName = CommandPrimitive.Empty.displayName +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; const CommandGroup = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Group>, @@ -88,13 +84,13 @@ const CommandGroup = React.forwardRef< ref={ref} className={cn( "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", - className + className, )} {...props} /> -)) +)); -CommandGroup.displayName = CommandPrimitive.Group.displayName +CommandGroup.displayName = CommandPrimitive.Group.displayName; const CommandSeparator = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Separator>, @@ -105,8 +101,8 @@ const CommandSeparator = React.forwardRef< className={cn("-mx-1 h-px bg-border", className)} {...props} /> -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; const CommandItem = React.forwardRef< React.ElementRef<typeof CommandPrimitive.Item>, @@ -116,29 +112,23 @@ const CommandItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", - className + className, )} {...props} /> -)) +)); -CommandItem.displayName = CommandPrimitive.Item.displayName +CommandItem.displayName = CommandPrimitive.Item.displayName; -const CommandShortcut = ({ - className, - ...props -}: React.HTMLAttributes<HTMLSpanElement>) => { +const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { return ( <span - className={cn( - "ml-auto text-xs tracking-widest text-muted-foreground", - className - )} + className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} /> - ) -} -CommandShortcut.displayName = "CommandShortcut" + ); +}; +CommandShortcut.displayName = "CommandShortcut"; export { Command, @@ -150,4 +140,4 @@ export { CommandItem, CommandShortcut, CommandSeparator, -} +}; diff --git a/components/ui/context-menu.tsx b/components/ui/context-menu.tsx index 93ef37b..7503973 100644 --- a/components/ui/context-menu.tsx +++ b/components/ui/context-menu.tsx @@ -1,27 +1,27 @@ -"use client" +"use client"; -import * as React from "react" -import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" -import { Check, ChevronRight, Circle } from "lucide-react" +import * as React from "react"; +import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"; +import { Check, ChevronRight, Circle } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const ContextMenu = ContextMenuPrimitive.Root +const ContextMenu = ContextMenuPrimitive.Root; -const ContextMenuTrigger = ContextMenuPrimitive.Trigger +const ContextMenuTrigger = ContextMenuPrimitive.Trigger; -const ContextMenuGroup = ContextMenuPrimitive.Group +const ContextMenuGroup = ContextMenuPrimitive.Group; -const ContextMenuPortal = ContextMenuPrimitive.Portal +const ContextMenuPortal = ContextMenuPrimitive.Portal; -const ContextMenuSub = ContextMenuPrimitive.Sub +const ContextMenuSub = ContextMenuPrimitive.Sub; -const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup +const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup; const ContextMenuSubTrigger = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>, React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & { - inset?: boolean + inset?: boolean; } >(({ className, inset, children, ...props }, ref) => ( <ContextMenuPrimitive.SubTrigger @@ -29,15 +29,14 @@ const ContextMenuSubTrigger = React.forwardRef< className={cn( "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", inset && "pl-8", - className + className, )} - {...props} - > + {...props}> {children} <ChevronRight className="ml-auto h-4 w-4" /> </ContextMenuPrimitive.SubTrigger> -)) -ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName +)); +ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName; const ContextMenuSubContent = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.SubContent>, @@ -47,12 +46,12 @@ const ContextMenuSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 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", - className + className, )} {...props} /> -)) -ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName +)); +ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName; const ContextMenuContent = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Content>, @@ -63,18 +62,18 @@ const ContextMenuContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 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", - className + className, )} {...props} /> </ContextMenuPrimitive.Portal> -)) -ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName +)); +ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName; const ContextMenuItem = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Item>, React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & { - inset?: boolean + inset?: boolean; } >(({ className, inset, ...props }, ref) => ( <ContextMenuPrimitive.Item @@ -82,12 +81,12 @@ const ContextMenuItem = React.forwardRef< className={cn( "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", - className + className, )} {...props} /> -)) -ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName +)); +ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName; const ContextMenuCheckboxItem = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>, @@ -97,11 +96,10 @@ const ContextMenuCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex 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, )} checked={checked} - {...props} - > + {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <ContextMenuPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -109,9 +107,8 @@ const ContextMenuCheckboxItem = React.forwardRef< </span> {children} </ContextMenuPrimitive.CheckboxItem> -)) -ContextMenuCheckboxItem.displayName = - ContextMenuPrimitive.CheckboxItem.displayName +)); +ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName; const ContextMenuRadioItem = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.RadioItem>, @@ -121,10 +118,9 @@ const ContextMenuRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex 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}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <ContextMenuPrimitive.ItemIndicator> <Circle className="h-2 w-2 fill-current" /> @@ -132,26 +128,22 @@ const ContextMenuRadioItem = React.forwardRef< </span> {children} </ContextMenuPrimitive.RadioItem> -)) -ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName +)); +ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName; const ContextMenuLabel = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Label>, React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & { - inset?: boolean + inset?: boolean; } >(({ className, inset, ...props }, ref) => ( <ContextMenuPrimitive.Label ref={ref} - className={cn( - "px-2 py-1.5 text-sm font-semibold text-foreground", - inset && "pl-8", - className - )} + className={cn("px-2 py-1.5 text-sm font-semibold text-foreground", inset && "pl-8", className)} {...props} /> -)) -ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName +)); +ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName; const ContextMenuSeparator = React.forwardRef< React.ElementRef<typeof ContextMenuPrimitive.Separator>, @@ -162,24 +154,18 @@ const ContextMenuSeparator = React.forwardRef< className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} /> -)) -ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName +)); +ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName; -const ContextMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes<HTMLSpanElement>) => { +const ContextMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { return ( <span - className={cn( - "ml-auto text-xs tracking-widest text-muted-foreground", - className - )} + className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} /> - ) -} -ContextMenuShortcut.displayName = "ContextMenuShortcut" + ); +}; +ContextMenuShortcut.displayName = "ContextMenuShortcut"; export { ContextMenu, @@ -197,4 +183,4 @@ export { ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup, -} +}; diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index f17698b..26c52e2 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -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>, @@ -41,8 +41,7 @@ const DialogContent = React.forwardRef< "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", className, )} - {...props} - > + {...props}> {children} <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> <X className="h-4 w-4" /> @@ -50,18 +49,21 @@ const DialogContent = React.forwardRef< </DialogPrimitive.Close> </DialogPrimitive.Content> </DialogPortal> -)) -DialogContent.displayName = DialogPrimitive.Content.displayName +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} /> -) -DialogHeader.displayName = "DialogHeader" +); +DialogHeader.displayName = "DialogHeader"; const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} /> -) -DialogFooter.displayName = "DialogFooter" + <div + className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} + {...props} + /> +); +DialogFooter.displayName = "DialogFooter"; const DialogTitle = React.forwardRef< React.ElementRef<typeof DialogPrimitive.Title>, @@ -72,16 +74,20 @@ const DialogTitle = React.forwardRef< className={cn("text-lg font-semibold leading-none tracking-tight", className)} {...props} /> -)) -DialogTitle.displayName = DialogPrimitive.Title.displayName +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; const DialogDescription = React.forwardRef< React.ElementRef<typeof DialogPrimitive.Description>, React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> >(({ className, ...props }, ref) => ( - <DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -DialogDescription.displayName = DialogPrimitive.Description.displayName + <DialogPrimitive.Description + ref={ref} + className={cn("text-sm text-muted-foreground", className)} + {...props} + /> +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; export { Dialog, @@ -94,5 +100,4 @@ export { DialogFooter, DialogTitle, DialogDescription, -} - +}; diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx index 6a0ef53..ab26c97 100644 --- a/components/ui/drawer.tsx +++ b/components/ui/drawer.tsx @@ -1,26 +1,23 @@ -"use client" +"use client"; -import * as React from "react" -import { Drawer as DrawerPrimitive } from "vaul" +import * as React from "react"; +import { Drawer as DrawerPrimitive } from "vaul"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) => ( - <DrawerPrimitive.Root - shouldScaleBackground={shouldScaleBackground} - {...props} - /> -) -Drawer.displayName = "Drawer" + <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} /> +); +Drawer.displayName = "Drawer"; -const DrawerTrigger = DrawerPrimitive.Trigger +const DrawerTrigger = DrawerPrimitive.Trigger; -const DrawerPortal = DrawerPrimitive.Portal +const DrawerPortal = DrawerPrimitive.Portal; -const DrawerClose = DrawerPrimitive.Close +const DrawerClose = DrawerPrimitive.Close; const DrawerOverlay = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Overlay>, @@ -31,8 +28,8 @@ const DrawerOverlay = React.forwardRef< className={cn("fixed inset-0 z-50 bg-black/80", className)} {...props} /> -)) -DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName +)); +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName; const DrawerContent = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Content>, @@ -44,38 +41,25 @@ const DrawerContent = React.forwardRef< ref={ref} className={cn( "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background", - className + className, )} - {...props} - > + {...props}> <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" /> {children} </DrawerPrimitive.Content> </DrawerPortal> -)) -DrawerContent.displayName = "DrawerContent" +)); +DrawerContent.displayName = "DrawerContent"; -const DrawerHeader = ({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} - {...props} - /> -) -DrawerHeader.displayName = "DrawerHeader" +const DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( + <div className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} {...props} /> +); +DrawerHeader.displayName = "DrawerHeader"; -const DrawerFooter = ({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn("mt-auto flex flex-col gap-2 p-4", className)} - {...props} - /> -) -DrawerFooter.displayName = "DrawerFooter" +const DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( + <div className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} /> +); +DrawerFooter.displayName = "DrawerFooter"; const DrawerTitle = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Title>, @@ -83,14 +67,11 @@ const DrawerTitle = React.forwardRef< >(({ className, ...props }, ref) => ( <DrawerPrimitive.Title ref={ref} - className={cn( - "text-lg font-semibold leading-none tracking-tight", - className - )} + className={cn("text-lg font-semibold leading-none tracking-tight", className)} {...props} /> -)) -DrawerTitle.displayName = DrawerPrimitive.Title.displayName +)); +DrawerTitle.displayName = DrawerPrimitive.Title.displayName; const DrawerDescription = React.forwardRef< React.ElementRef<typeof DrawerPrimitive.Description>, @@ -101,8 +82,8 @@ const DrawerDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -DrawerDescription.displayName = DrawerPrimitive.Description.displayName +)); +DrawerDescription.displayName = DrawerPrimitive.Description.displayName; export { Drawer, @@ -115,4 +96,4 @@ export { DrawerFooter, DrawerTitle, DrawerDescription, -} +}; diff --git a/components/ui/dropdown-menu.tsx b/components/ui/dropdown-menu.tsx index 0fc4c0e..b8fd83b 100644 --- a/components/ui/dropdown-menu.tsx +++ b/components/ui/dropdown-menu.tsx @@ -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 @@ -29,16 +29,14 @@ const DropdownMenuSubTrigger = React.forwardRef< className={cn( "flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", - className + className, )} - {...props} - > + {...props}> {children} <ChevronRight className="ml-auto" /> </DropdownMenuPrimitive.SubTrigger> -)) -DropdownMenuSubTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName +)); +DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; const DropdownMenuSubContent = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.SubContent>, @@ -48,13 +46,12 @@ const DropdownMenuSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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", - className + className, )} {...props} /> -)) -DropdownMenuSubContent.displayName = - DropdownMenuPrimitive.SubContent.displayName +)); +DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; const DropdownMenuContent = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.Content>, @@ -66,18 +63,18 @@ const DropdownMenuContent = React.forwardRef< sideOffset={sideOffset} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 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", - className + className, )} {...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 @@ -85,12 +82,12 @@ const DropdownMenuItem = React.forwardRef< className={cn( "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", - className + className, )} {...props} /> -)) -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; const DropdownMenuCheckboxItem = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>, @@ -100,11 +97,10 @@ const DropdownMenuCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", - className + className, )} checked={checked} - {...props} - > + {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <DropdownMenuPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -112,9 +108,8 @@ const DropdownMenuCheckboxItem = React.forwardRef< </span> {children} </DropdownMenuPrimitive.CheckboxItem> -)) -DropdownMenuCheckboxItem.displayName = - DropdownMenuPrimitive.CheckboxItem.displayName +)); +DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; const DropdownMenuRadioItem = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>, @@ -124,10 +119,9 @@ const DropdownMenuRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", - className + className, )} - {...props} - > + {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <DropdownMenuPrimitive.ItemIndicator> <Circle className="h-2 w-2 fill-current" /> @@ -135,26 +129,22 @@ 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 ref={ref} - className={cn( - "px-2 py-1.5 text-sm font-semibold", - inset && "pl-8", - className - )} + className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} {...props} /> -)) -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; const DropdownMenuSeparator = React.forwardRef< React.ElementRef<typeof DropdownMenuPrimitive.Separator>, @@ -165,21 +155,15 @@ 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, - ...props -}: React.HTMLAttributes<HTMLSpanElement>) => { +const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { return ( - <span - className={cn("ml-auto text-xs tracking-widest opacity-60", className)} - {...props} - /> - ) -} -DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + <span className={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...props} /> + ); +}; +DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; export { DropdownMenu, @@ -197,4 +181,4 @@ export { DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, -} +}; diff --git a/components/ui/form.tsx b/components/ui/form.tsx index ce264ae..2c322f8 100644 --- a/components/ui/form.tsx +++ b/components/ui/form.tsx @@ -1,8 +1,8 @@ -"use client" +"use client"; -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, @@ -10,27 +10,25 @@ import { FieldValues, FormProvider, useFormContext, -} from "react-hook-form" +} 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> + TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, > = { - name: TName -} + name: TName; +}; -const FormFieldContext = React.createContext<FormFieldContextValue>( - {} as FormFieldContextValue -) +const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue); const FormField = < TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> + TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, >({ ...props }: ControllerProps<TFieldValues, TName>) => { @@ -38,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, @@ -61,36 +59,33 @@ const useFormField = () => { formDescriptionId: `${id}-form-item-description`, formMessageId: `${id}-form-item-message`, ...fieldState, - } -} + }; +}; type FormItemContextValue = { - id: string -} + id: string; +}; -const FormItemContext = React.createContext<FormItemContextValue>( - {} as FormItemContextValue -) +const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue); -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes<HTMLDivElement> ->(({ className, ...props }, ref) => { - const id = React.useId() +const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( + ({ className, ...props }, ref) => { + const id = React.useId(); - return ( - <FormItemContext.Provider value={{ id }}> - <div ref={ref} className={cn("space-y-2", className)} {...props} /> - </FormItemContext.Provider> - ) -}) -FormItem.displayName = "FormItem" + return ( + <FormItemContext.Provider value={{ id }}> + <div ref={ref} className={cn("space-y-2", className)} {...props} /> + </FormItemContext.Provider> + ); + }, +); +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 @@ -99,37 +94,33 @@ 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 ref={ref} id={formItemId} - aria-describedby={ - !error - ? `${formDescriptionId}` - : `${formDescriptionId} ${formMessageId}` - } + aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`} 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 @@ -138,19 +129,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 ( @@ -158,13 +149,12 @@ const FormMessage = React.forwardRef< ref={ref} id={formMessageId} className={cn("text-sm font-medium text-destructive", className)} - {...props} - > + {...props}> {body} </p> - ) -}) -FormMessage.displayName = "FormMessage" + ); +}); +FormMessage.displayName = "FormMessage"; export { useFormField, @@ -175,4 +165,4 @@ export { FormDescription, FormMessage, FormField, -} +}; diff --git a/components/ui/hover-card.tsx b/components/ui/hover-card.tsx index 158208a..9e8c62d 100644 --- a/components/ui/hover-card.tsx +++ b/components/ui/hover-card.tsx @@ -1,13 +1,13 @@ -"use client" +"use client"; -import * as React from "react" -import * as HoverCardPrimitive from "@radix-ui/react-hover-card" +import * as React from "react"; +import * as HoverCardPrimitive from "@radix-ui/react-hover-card"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const HoverCard = HoverCardPrimitive.Root +const HoverCard = HoverCardPrimitive.Root; -const HoverCardTrigger = HoverCardPrimitive.Trigger +const HoverCardTrigger = HoverCardPrimitive.Trigger; const HoverCardContent = React.forwardRef< React.ElementRef<typeof HoverCardPrimitive.Content>, @@ -23,8 +23,7 @@ const HoverCardContent = React.forwardRef< )} {...props} /> -)) -HoverCardContent.displayName = HoverCardPrimitive.Content.displayName - -export { HoverCard, HoverCardTrigger, HoverCardContent } +)); +HoverCardContent.displayName = HoverCardPrimitive.Content.displayName; +export { HoverCard, HoverCardTrigger, HoverCardContent }; diff --git a/components/ui/input-otp.tsx b/components/ui/input-otp.tsx index f66fcfa..41d2e2b 100644 --- a/components/ui/input-otp.tsx +++ b/components/ui/input-otp.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import { OTPInput, OTPInputContext } from "input-otp" -import { Dot } from "lucide-react" +import * as React from "react"; +import { OTPInput, OTPInputContext } from "input-otp"; +import { Dot } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const InputOTP = React.forwardRef< React.ElementRef<typeof OTPInput>, @@ -14,28 +14,28 @@ const InputOTP = React.forwardRef< ref={ref} containerClassName={cn( "flex items-center gap-2 has-[:disabled]:opacity-50", - containerClassName + containerClassName, )} className={cn("disabled:cursor-not-allowed", className)} {...props} /> -)) -InputOTP.displayName = "InputOTP" +)); +InputOTP.displayName = "InputOTP"; const InputOTPGroup = React.forwardRef< React.ElementRef<"div">, React.ComponentPropsWithoutRef<"div"> >(({ className, ...props }, ref) => ( <div ref={ref} className={cn("flex items-center", className)} {...props} /> -)) -InputOTPGroup.displayName = "InputOTPGroup" +)); +InputOTPGroup.displayName = "InputOTPGroup"; const InputOTPSlot = React.forwardRef< React.ElementRef<"div">, React.ComponentPropsWithoutRef<"div"> & { index: number } >(({ index, className, ...props }, ref) => { - const inputOTPContext = React.useContext(OTPInputContext) - const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index] + const inputOTPContext = React.useContext(OTPInputContext); + const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]; return ( <div @@ -43,10 +43,9 @@ const InputOTPSlot = React.forwardRef< className={cn( "relative flex h-10 w-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md", isActive && "z-10 ring-2 ring-ring ring-offset-background", - className + className, )} - {...props} - > + {...props}> {char} {hasFakeCaret && ( <div className="pointer-events-none absolute inset-0 flex items-center justify-center"> @@ -54,9 +53,9 @@ const InputOTPSlot = React.forwardRef< </div> )} </div> - ) -}) -InputOTPSlot.displayName = "InputOTPSlot" + ); +}); +InputOTPSlot.displayName = "InputOTPSlot"; const InputOTPSeparator = React.forwardRef< React.ElementRef<"div">, @@ -65,7 +64,7 @@ const InputOTPSeparator = React.forwardRef< <div ref={ref} role="separator" {...props}> <Dot /> </div> -)) -InputOTPSeparator.displayName = "InputOTPSeparator" +)); +InputOTPSeparator.displayName = "InputOTPSeparator"; -export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; diff --git a/components/ui/input.tsx b/components/ui/input.tsx index 79a855f..84da2c0 100644 --- a/components/ui/input.tsx +++ b/components/ui/input.tsx @@ -1,23 +1,24 @@ -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> {} -const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => { - return ( - <input - type={type} - className={cn( - "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", - className, - )} - ref={ref} - {...props} - /> - ) -}) -Input.displayName = "Input" - -export { Input } +const Input = React.forwardRef<HTMLInputElement, InputProps>( + ({ className, type, ...props }, ref) => { + return ( + <input + type={type} + className={cn( + "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", + className, + )} + ref={ref} + {...props} + /> + ); + }, +); +Input.displayName = "Input"; +export { Input }; diff --git a/components/ui/label.tsx b/components/ui/label.tsx index 5341821..392197c 100644 --- a/components/ui/label.tsx +++ b/components/ui/label.tsx @@ -1,26 +1,21 @@ -"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" -) + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +); const Label = React.forwardRef< React.ElementRef<typeof LabelPrimitive.Root>, - React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & - VariantProps<typeof labelVariants> + React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants> >(({ className, ...props }, ref) => ( - <LabelPrimitive.Root - ref={ref} - className={cn(labelVariants(), className)} - {...props} - /> -)) -Label.displayName = LabelPrimitive.Root.displayName + <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} /> +)); +Label.displayName = LabelPrimitive.Root.displayName; -export { Label } +export { Label }; diff --git a/components/ui/menubar.tsx b/components/ui/menubar.tsx index 5586fa9..815aeec 100644 --- a/components/ui/menubar.tsx +++ b/components/ui/menubar.tsx @@ -1,20 +1,20 @@ -"use client" +"use client"; -import * as React from "react" -import * as MenubarPrimitive from "@radix-ui/react-menubar" -import { Check, ChevronRight, Circle } from "lucide-react" +import * as React from "react"; +import * as MenubarPrimitive from "@radix-ui/react-menubar"; +import { Check, ChevronRight, Circle } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const MenubarMenu = MenubarPrimitive.Menu +const MenubarMenu = MenubarPrimitive.Menu; -const MenubarGroup = MenubarPrimitive.Group +const MenubarGroup = MenubarPrimitive.Group; -const MenubarPortal = MenubarPrimitive.Portal +const MenubarPortal = MenubarPrimitive.Portal; -const MenubarSub = MenubarPrimitive.Sub +const MenubarSub = MenubarPrimitive.Sub; -const MenubarRadioGroup = MenubarPrimitive.RadioGroup +const MenubarRadioGroup = MenubarPrimitive.RadioGroup; const Menubar = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Root>, @@ -24,12 +24,12 @@ const Menubar = React.forwardRef< ref={ref} className={cn( "flex h-10 items-center space-x-1 rounded-md border bg-background p-1", - className + className, )} {...props} /> -)) -Menubar.displayName = MenubarPrimitive.Root.displayName +)); +Menubar.displayName = MenubarPrimitive.Root.displayName; const MenubarTrigger = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Trigger>, @@ -39,17 +39,17 @@ const MenubarTrigger = React.forwardRef< ref={ref} className={cn( "flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", - className + className, )} {...props} /> -)) -MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName +)); +MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName; const MenubarSubTrigger = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.SubTrigger>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & { - inset?: boolean + inset?: boolean; } >(({ className, inset, children, ...props }, ref) => ( <MenubarPrimitive.SubTrigger @@ -57,15 +57,14 @@ const MenubarSubTrigger = React.forwardRef< className={cn( "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", inset && "pl-8", - className + className, )} - {...props} - > + {...props}> {children} <ChevronRight className="ml-auto h-4 w-4" /> </MenubarPrimitive.SubTrigger> -)) -MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName +)); +MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName; const MenubarSubContent = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.SubContent>, @@ -75,42 +74,37 @@ const MenubarSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground 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", - className + className, )} {...props} /> -)) -MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName +)); +MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName; const MenubarContent = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Content>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content> ->( - ( - { className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, - ref - ) => ( - <MenubarPrimitive.Portal> - <MenubarPrimitive.Content - ref={ref} - align={align} - alignOffset={alignOffset} - sideOffset={sideOffset} - className={cn( - "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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", - className - )} - {...props} - /> - </MenubarPrimitive.Portal> - ) -) -MenubarContent.displayName = MenubarPrimitive.Content.displayName +>(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => ( + <MenubarPrimitive.Portal> + <MenubarPrimitive.Content + ref={ref} + align={align} + alignOffset={alignOffset} + sideOffset={sideOffset} + className={cn( + "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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", + className, + )} + {...props} + /> + </MenubarPrimitive.Portal> +)); +MenubarContent.displayName = MenubarPrimitive.Content.displayName; const MenubarItem = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Item>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & { - inset?: boolean + inset?: boolean; } >(({ className, inset, ...props }, ref) => ( <MenubarPrimitive.Item @@ -118,12 +112,12 @@ const MenubarItem = React.forwardRef< className={cn( "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", - className + className, )} {...props} /> -)) -MenubarItem.displayName = MenubarPrimitive.Item.displayName +)); +MenubarItem.displayName = MenubarPrimitive.Item.displayName; const MenubarCheckboxItem = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.CheckboxItem>, @@ -133,11 +127,10 @@ const MenubarCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex 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, )} checked={checked} - {...props} - > + {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <MenubarPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -145,8 +138,8 @@ const MenubarCheckboxItem = React.forwardRef< </span> {children} </MenubarPrimitive.CheckboxItem> -)) -MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName +)); +MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName; const MenubarRadioItem = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.RadioItem>, @@ -156,10 +149,9 @@ const MenubarRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex 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}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <MenubarPrimitive.ItemIndicator> <Circle className="h-2 w-2 fill-current" /> @@ -167,26 +159,22 @@ const MenubarRadioItem = React.forwardRef< </span> {children} </MenubarPrimitive.RadioItem> -)) -MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName +)); +MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName; const MenubarLabel = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Label>, React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & { - inset?: boolean + inset?: boolean; } >(({ className, inset, ...props }, ref) => ( <MenubarPrimitive.Label ref={ref} - className={cn( - "px-2 py-1.5 text-sm font-semibold", - inset && "pl-8", - className - )} + className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} {...props} /> -)) -MenubarLabel.displayName = MenubarPrimitive.Label.displayName +)); +MenubarLabel.displayName = MenubarPrimitive.Label.displayName; const MenubarSeparator = React.forwardRef< React.ElementRef<typeof MenubarPrimitive.Separator>, @@ -197,24 +185,18 @@ const MenubarSeparator = React.forwardRef< className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} /> -)) -MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName +)); +MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName; -const MenubarShortcut = ({ - className, - ...props -}: React.HTMLAttributes<HTMLSpanElement>) => { +const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => { return ( <span - className={cn( - "ml-auto text-xs tracking-widest text-muted-foreground", - className - )} + className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} /> - ) -} -MenubarShortcut.displayname = "MenubarShortcut" + ); +}; +MenubarShortcut.displayname = "MenubarShortcut"; export { Menubar, @@ -233,4 +215,4 @@ export { MenubarGroup, MenubarSub, MenubarShortcut, -} +}; diff --git a/components/ui/navigation-menu.tsx b/components/ui/navigation-menu.tsx index 722248b..083eb5f 100644 --- a/components/ui/navigation-menu.tsx +++ b/components/ui/navigation-menu.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -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>, @@ -14,13 +14,12 @@ const NavigationMenu = React.forwardRef< <NavigationMenuPrimitive.Root ref={ref} className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)} - {...props} - > + {...props}> {children} <NavigationMenuViewport /> </NavigationMenuPrimitive.Root> -)) -NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName +)); +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName; const NavigationMenuList = React.forwardRef< React.ElementRef<typeof NavigationMenuPrimitive.List>, @@ -31,14 +30,14 @@ const NavigationMenuList = React.forwardRef< className={cn("group flex flex-1 list-none items-center justify-center space-x-1", className)} {...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>, @@ -47,16 +46,15 @@ const NavigationMenuTrigger = React.forwardRef< <NavigationMenuPrimitive.Trigger ref={ref} className={cn(navigationMenuTriggerStyle(), "group", className)} - {...props} - > + {...props}> {children}{" "} <ChevronDown className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180" aria-hidden="true" /> </NavigationMenuPrimitive.Trigger> -)) -NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName +)); +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName; const NavigationMenuContent = React.forwardRef< React.ElementRef<typeof NavigationMenuPrimitive.Content>, @@ -70,10 +68,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>, @@ -89,8 +87,8 @@ const NavigationMenuViewport = React.forwardRef< {...props} /> </div> -)) -NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName +)); +NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName; const NavigationMenuIndicator = React.forwardRef< React.ElementRef<typeof NavigationMenuPrimitive.Indicator>, @@ -102,12 +100,11 @@ const NavigationMenuIndicator = React.forwardRef< "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", className, )} - {...props} - > + {...props}> <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 +)); +NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName; export { navigationMenuTriggerStyle, @@ -119,5 +116,4 @@ export { NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, -} - +}; diff --git a/components/ui/pagination.tsx b/components/ui/pagination.tsx index ea40d19..3786db8 100644 --- a/components/ui/pagination.tsx +++ b/components/ui/pagination.tsx @@ -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,40 +11,27 @@ 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, - React.ComponentProps<"ul"> ->(({ className, ...props }, ref) => ( - <ul - ref={ref} - className={cn("flex flex-row items-center gap-1", className)} - {...props} - /> -)) -PaginationContent.displayName = "PaginationContent" +const PaginationContent = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>( + ({ className, ...props }, ref) => ( + <ul ref={ref} className={cn("flex flex-row items-center gap-1", className)} {...props} /> + ), +); +PaginationContent.displayName = "PaginationContent"; -const PaginationItem = React.forwardRef< - HTMLLIElement, - React.ComponentProps<"li"> ->(({ className, ...props }, ref) => ( - <li ref={ref} className={cn("", className)} {...props} /> -)) -PaginationItem.displayName = "PaginationItem" +const PaginationItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( + ({ className, ...props }, ref) => <li ref={ref} className={cn("", className)} {...props} />, +); +PaginationItem.displayName = "PaginationItem"; type PaginationLinkProps = { - isActive?: boolean + isActive?: boolean; } & Pick<ButtonProps, "size"> & - React.ComponentProps<"a"> + React.ComponentProps<"a">; -const PaginationLink = ({ - className, - isActive, - size = "icon", - ...props -}: PaginationLinkProps) => ( +const PaginationLink = ({ className, isActive, size = "icon", ...props }: PaginationLinkProps) => ( <a aria-current={isActive ? "page" : undefined} className={cn( @@ -52,12 +39,12 @@ const PaginationLink = ({ variant: isActive ? "outline" : "ghost", size, }), - className + className, )} {...props} /> -) -PaginationLink.displayName = "PaginationLink" +); +PaginationLink.displayName = "PaginationLink"; const PaginationPrevious = ({ className, @@ -67,44 +54,35 @@ const PaginationPrevious = ({ aria-label="Go to previous page" size="default" className={cn("gap-1 pl-2.5", className)} - {...props} - > + {...props}> <ChevronLeft className="h-4 w-4" /> <span>Previous</span> </PaginationLink> -) -PaginationPrevious.displayName = "PaginationPrevious" +); +PaginationPrevious.displayName = "PaginationPrevious"; -const PaginationNext = ({ - className, - ...props -}: React.ComponentProps<typeof PaginationLink>) => ( +const PaginationNext = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => ( <PaginationLink aria-label="Go to next page" size="default" className={cn("gap-1 pr-2.5", className)} - {...props} - > + {...props}> <span>Next</span> <ChevronRight className="h-4 w-4" /> </PaginationLink> -) -PaginationNext.displayName = "PaginationNext" +); +PaginationNext.displayName = "PaginationNext"; -const PaginationEllipsis = ({ - className, - ...props -}: React.ComponentProps<"span">) => ( +const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => ( <span aria-hidden className={cn("flex h-9 w-9 items-center justify-center", className)} - {...props} - > + {...props}> <MoreHorizontal className="h-4 w-4" /> <span className="sr-only">More pages</span> </span> -) -PaginationEllipsis.displayName = "PaginationEllipsis" +); +PaginationEllipsis.displayName = "PaginationEllipsis"; export { Pagination, @@ -114,4 +92,4 @@ export { PaginationLink, PaginationNext, PaginationPrevious, -} +}; diff --git a/components/ui/popover.tsx b/components/ui/popover.tsx index a0ec48b..73be7bb 100644 --- a/components/ui/popover.tsx +++ b/components/ui/popover.tsx @@ -1,13 +1,13 @@ -"use client" +"use client"; -import * as React from "react" -import * as PopoverPrimitive from "@radix-ui/react-popover" +import * as React from "react"; +import * as PopoverPrimitive from "@radix-ui/react-popover"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Popover = PopoverPrimitive.Root +const Popover = PopoverPrimitive.Root; -const PopoverTrigger = PopoverPrimitive.Trigger +const PopoverTrigger = PopoverPrimitive.Trigger; const PopoverContent = React.forwardRef< React.ElementRef<typeof PopoverPrimitive.Content>, @@ -20,12 +20,12 @@ const PopoverContent = React.forwardRef< sideOffset={sideOffset} className={cn( "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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", - className + className, )} {...props} /> </PopoverPrimitive.Portal> -)) -PopoverContent.displayName = PopoverPrimitive.Content.displayName +)); +PopoverContent.displayName = PopoverPrimitive.Content.displayName; -export { Popover, PopoverTrigger, PopoverContent } +export { Popover, PopoverTrigger, PopoverContent }; diff --git a/components/ui/progress.tsx b/components/ui/progress.tsx index 5c87ea4..5fb27c7 100644 --- a/components/ui/progress.tsx +++ b/components/ui/progress.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as ProgressPrimitive from "@radix-ui/react-progress" +import * as React from "react"; +import * as ProgressPrimitive from "@radix-ui/react-progress"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Progress = React.forwardRef< React.ElementRef<typeof ProgressPrimitive.Root>, @@ -11,18 +11,14 @@ const Progress = React.forwardRef< >(({ className, value, ...props }, ref) => ( <ProgressPrimitive.Root ref={ref} - className={cn( - "relative h-4 w-full overflow-hidden rounded-full bg-secondary", - className - )} - {...props} - > + className={cn("relative h-4 w-full overflow-hidden rounded-full bg-secondary", className)} + {...props}> <ProgressPrimitive.Indicator className="h-full w-full flex-1 bg-primary transition-all" style={{ transform: `translateX(-${100 - (value || 0)}%)` }} /> </ProgressPrimitive.Root> -)) -Progress.displayName = ProgressPrimitive.Root.displayName +)); +Progress.displayName = ProgressPrimitive.Root.displayName; -export { Progress } +export { Progress }; diff --git a/components/ui/radio-group.tsx b/components/ui/radio-group.tsx index e9bde17..5485bed 100644 --- a/components/ui/radio-group.tsx +++ b/components/ui/radio-group.tsx @@ -1,24 +1,18 @@ -"use client" +"use client"; -import * as React from "react" -import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" -import { Circle } from "lucide-react" +import * as React from "react"; +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; +import { Circle } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const RadioGroup = React.forwardRef< React.ElementRef<typeof RadioGroupPrimitive.Root>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> >(({ className, ...props }, ref) => { - return ( - <RadioGroupPrimitive.Root - className={cn("grid gap-2", className)} - {...props} - ref={ref} - /> - ) -}) -RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + return <RadioGroupPrimitive.Root className={cn("grid gap-2", className)} {...props} ref={ref} />; +}); +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName; const RadioGroupItem = React.forwardRef< React.ElementRef<typeof RadioGroupPrimitive.Item>, @@ -29,16 +23,15 @@ const RadioGroupItem = React.forwardRef< ref={ref} className={cn( "aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", - className + className, )} - {...props} - > + {...props}> <RadioGroupPrimitive.Indicator className="flex items-center justify-center"> <Circle className="h-2.5 w-2.5 fill-current text-current" /> </RadioGroupPrimitive.Indicator> </RadioGroupPrimitive.Item> - ) -}) -RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + ); +}); +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; -export { RadioGroup, RadioGroupItem } +export { RadioGroup, RadioGroupItem }; diff --git a/components/ui/resizable.tsx b/components/ui/resizable.tsx index f4bc558..04dcae9 100644 --- a/components/ui/resizable.tsx +++ b/components/ui/resizable.tsx @@ -1,45 +1,41 @@ -"use client" +"use client"; -import { GripVertical } from "lucide-react" -import * as ResizablePrimitive from "react-resizable-panels" +import { GripVertical } from "lucide-react"; +import * as ResizablePrimitive from "react-resizable-panels"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const ResizablePanelGroup = ({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => ( <ResizablePrimitive.PanelGroup - className={cn( - "flex h-full w-full data-[panel-group-direction=vertical]:flex-col", - className - )} + className={cn("flex h-full w-full data-[panel-group-direction=vertical]:flex-col", className)} {...props} /> -) +); -const ResizablePanel = ResizablePrimitive.Panel +const ResizablePanel = ResizablePrimitive.Panel; const ResizableHandle = ({ withHandle, className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { - withHandle?: boolean + withHandle?: boolean; }) => ( <ResizablePrimitive.PanelResizeHandle className={cn( "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90", - className + className, )} - {...props} - > + {...props}> {withHandle && ( <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border"> <GripVertical className="h-2.5 w-2.5" /> </div> )} </ResizablePrimitive.PanelResizeHandle> -) +); -export { ResizablePanelGroup, ResizablePanel, ResizableHandle } +export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; diff --git a/components/ui/scroll-area.tsx b/components/ui/scroll-area.tsx index c8164b9..6d14a6f 100644 --- a/components/ui/scroll-area.tsx +++ b/components/ui/scroll-area.tsx @@ -1,21 +1,26 @@ -"use client" +"use client"; -import * as React from "react" -import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" +import * as React from "react"; +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const ScrollArea = React.forwardRef< React.ElementRef<typeof ScrollAreaPrimitive.Root>, React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> >(({ className, children, ...props }, ref) => ( - <ScrollAreaPrimitive.Root ref={ref} className={cn("relative overflow-hidden", className)} {...props}> - <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">{children}</ScrollAreaPrimitive.Viewport> + <ScrollAreaPrimitive.Root + ref={ref} + className={cn("relative overflow-hidden", className)} + {...props}> + <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]"> + {children} + </ScrollAreaPrimitive.Viewport> <ScrollBar /> <ScrollAreaPrimitive.Corner /> </ScrollAreaPrimitive.Root> -)) -ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName +)); +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; const ScrollBar = React.forwardRef< React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>, @@ -30,12 +35,10 @@ const ScrollBar = React.forwardRef< orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]", className, )} - {...props} - > + {...props}> <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" /> </ScrollAreaPrimitive.ScrollAreaScrollbar> -)) -ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName - -export { ScrollArea, ScrollBar } +)); +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; +export { ScrollArea, ScrollBar }; diff --git a/components/ui/select.tsx b/components/ui/select.tsx index cbe5a36..1eec896 100644 --- a/components/ui/select.tsx +++ b/components/ui/select.tsx @@ -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>, @@ -20,17 +20,16 @@ const SelectTrigger = React.forwardRef< ref={ref} 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", - className + className, )} - {...props} - > + {...props}> {children} <SelectPrimitive.Icon asChild> <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>, @@ -38,16 +37,12 @@ const SelectScrollUpButton = React.forwardRef< >(({ className, ...props }, ref) => ( <SelectPrimitive.ScrollUpButton ref={ref} - className={cn( - "flex cursor-default items-center justify-center py-1", - className - )} - {...props} - > + className={cn("flex cursor-default items-center justify-center py-1", className)} + {...props}> <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>, @@ -55,17 +50,12 @@ const SelectScrollDownButton = React.forwardRef< >(({ className, ...props }, ref) => ( <SelectPrimitive.ScrollDownButton ref={ref} - className={cn( - "flex cursor-default items-center justify-center py-1", - className - )} - {...props} - > + className={cn("flex cursor-default items-center justify-center py-1", className)} + {...props}> <ChevronDown className="h-4 w-4" /> </SelectPrimitive.ScrollDownButton> -)) -SelectScrollDownButton.displayName = - SelectPrimitive.ScrollDownButton.displayName +)); +SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; const SelectContent = React.forwardRef< React.ElementRef<typeof SelectPrimitive.Content>, @@ -78,26 +68,24 @@ const SelectContent = React.forwardRef< "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" && "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} - {...props} - > + {...props}> <SelectScrollUpButton /> <SelectPrimitive.Viewport className={cn( "p-1", 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} </SelectPrimitive.Viewport> <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 +96,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>, @@ -119,10 +107,9 @@ const SelectItem = React.forwardRef< ref={ref} 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", - className + className, )} - {...props} - > + {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <SelectPrimitive.ItemIndicator> <Check className="h-4 w-4" /> @@ -131,8 +118,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 +130,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, @@ -157,4 +144,4 @@ export { SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, -} +}; diff --git a/components/ui/separator.tsx b/components/ui/separator.tsx index 12d81c4..ee84f69 100644 --- a/components/ui/separator.tsx +++ b/components/ui/separator.tsx @@ -1,31 +1,26 @@ -"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>, React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> ->( - ( - { className, orientation = "horizontal", decorative = true, ...props }, - ref - ) => ( - <SeparatorPrimitive.Root - ref={ref} - decorative={decorative} - orientation={orientation} - className={cn( - "shrink-0 bg-border", - orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", - className - )} - {...props} - /> - ) -) -Separator.displayName = SeparatorPrimitive.Root.displayName +>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => ( + <SeparatorPrimitive.Root + ref={ref} + decorative={decorative} + orientation={orientation} + className={cn( + "shrink-0 bg-border", + orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", + className, + )} + {...props} + /> +)); +Separator.displayName = SeparatorPrimitive.Root.displayName; -export { Separator } +export { Separator }; diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx index a37f17b..2ed3e4d 100644 --- a/components/ui/sheet.tsx +++ b/components/ui/sheet.tsx @@ -1,19 +1,19 @@ -"use client" +"use client"; -import * as React from "react" -import * as SheetPrimitive from "@radix-ui/react-dialog" -import { cva, type VariantProps } from "class-variance-authority" -import { X } from "lucide-react" +import * as React from "react"; +import * as SheetPrimitive from "@radix-ui/react-dialog"; +import { cva, type VariantProps } from "class-variance-authority"; +import { X } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Sheet = SheetPrimitive.Root +const Sheet = SheetPrimitive.Root; -const SheetTrigger = SheetPrimitive.Trigger +const SheetTrigger = SheetPrimitive.Trigger; -const SheetClose = SheetPrimitive.Close +const SheetClose = SheetPrimitive.Close; -const SheetPortal = SheetPrimitive.Portal +const SheetPortal = SheetPrimitive.Portal; const SheetOverlay = React.forwardRef< React.ElementRef<typeof SheetPrimitive.Overlay>, @@ -22,13 +22,13 @@ const SheetOverlay = React.forwardRef< <SheetPrimitive.Overlay className={cn( "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className + className, )} {...props} ref={ref} /> -)) -SheetOverlay.displayName = SheetPrimitive.Overlay.displayName +)); +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; const sheetVariants = cva( "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", @@ -46,8 +46,8 @@ const sheetVariants = cva( defaultVariants: { side: "right", }, - } -) + }, +); interface SheetContentProps extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, @@ -59,11 +59,7 @@ const SheetContent = React.forwardRef< >(({ side = "right", className, children, ...props }, ref) => ( <SheetPortal> <SheetOverlay /> - <SheetPrimitive.Content - ref={ref} - className={cn(sheetVariants({ side }), className)} - {...props} - > + <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}> {children} <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"> <X className="h-4 w-4" /> @@ -71,36 +67,21 @@ const SheetContent = React.forwardRef< </SheetPrimitive.Close> </SheetPrimitive.Content> </SheetPortal> -)) -SheetContent.displayName = SheetPrimitive.Content.displayName +)); +SheetContent.displayName = SheetPrimitive.Content.displayName; -const SheetHeader = ({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn( - "flex flex-col space-y-2 text-center sm:text-left", - className - )} - {...props} - /> -) -SheetHeader.displayName = "SheetHeader" +const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( + <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} /> +); +SheetHeader.displayName = "SheetHeader"; -const SheetFooter = ({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) => ( +const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( <div - className={cn( - "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", - className - )} + className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} /> -) -SheetFooter.displayName = "SheetFooter" +); +SheetFooter.displayName = "SheetFooter"; const SheetTitle = React.forwardRef< React.ElementRef<typeof SheetPrimitive.Title>, @@ -111,8 +92,8 @@ const SheetTitle = React.forwardRef< className={cn("text-lg font-semibold text-foreground", className)} {...props} /> -)) -SheetTitle.displayName = SheetPrimitive.Title.displayName +)); +SheetTitle.displayName = SheetPrimitive.Title.displayName; const SheetDescription = React.forwardRef< React.ElementRef<typeof SheetPrimitive.Description>, @@ -123,8 +104,8 @@ const SheetDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -SheetDescription.displayName = SheetPrimitive.Description.displayName +)); +SheetDescription.displayName = SheetPrimitive.Description.displayName; export { Sheet, @@ -137,4 +118,4 @@ export { SheetFooter, SheetTitle, SheetDescription, -} +}; diff --git a/components/ui/sidebar.tsx b/components/ui/sidebar.tsx index eeb2d7a..4f4e430 100644 --- a/components/ui/sidebar.tsx +++ b/components/ui/sidebar.tsx @@ -1,58 +1,53 @@ -"use client" - -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { VariantProps, cva } from "class-variance-authority" -import { PanelLeft } from "lucide-react" - -import { useIsMobile } from "@/hooks/use-mobile" -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" -import { Input } from "@/components/ui/input" -import { Separator } from "@/components/ui/separator" -import { Sheet, SheetContent } from "@/components/ui/sheet" -import { Skeleton } from "@/components/ui/skeleton" -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip" - -const SIDEBAR_COOKIE_NAME = "sidebar:state" -const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 -const SIDEBAR_WIDTH = "16rem" -const SIDEBAR_WIDTH_MOBILE = "18rem" -const SIDEBAR_WIDTH_ICON = "3rem" -const SIDEBAR_KEYBOARD_SHORTCUT = "b" +"use client"; + +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { VariantProps, cva } from "class-variance-authority"; +import { PanelLeft } from "lucide-react"; + +import { useIsMobile } from "@/hooks/use-mobile"; +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Separator } from "@/components/ui/separator"; +import { Sheet, SheetContent } from "@/components/ui/sheet"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; + +const SIDEBAR_COOKIE_NAME = "sidebar:state"; +const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; +const SIDEBAR_WIDTH = "16rem"; +const SIDEBAR_WIDTH_MOBILE = "18rem"; +const SIDEBAR_WIDTH_ICON = "3rem"; +const SIDEBAR_KEYBOARD_SHORTCUT = "b"; type SidebarContext = { - state: "expanded" | "collapsed" - open: boolean - setOpen: (open: boolean) => void - openMobile: boolean - setOpenMobile: (open: boolean) => void - isMobile: boolean - toggleSidebar: () => void -} + state: "expanded" | "collapsed"; + open: boolean; + setOpen: (open: boolean) => void; + openMobile: boolean; + setOpenMobile: (open: boolean) => void; + isMobile: boolean; + toggleSidebar: () => void; +}; -const SidebarContext = React.createContext<SidebarContext | null>(null) +const SidebarContext = React.createContext<SidebarContext | null>(null); function useSidebar() { - const context = React.useContext(SidebarContext) + const context = React.useContext(SidebarContext); if (!context) { - throw new Error("useSidebar must be used within a SidebarProvider.") + throw new Error("useSidebar must be used within a SidebarProvider."); } - return context + return context; } const SidebarProvider = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - defaultOpen?: boolean - open?: boolean - onOpenChange?: (open: boolean) => void + defaultOpen?: boolean; + open?: boolean; + onOpenChange?: (open: boolean) => void; } >( ( @@ -65,56 +60,51 @@ const SidebarProvider = React.forwardRef< children, ...props }, - ref + ref, ) => { - const isMobile = useIsMobile() - const [openMobile, setOpenMobile] = React.useState(false) + const isMobile = useIsMobile(); + const [openMobile, setOpenMobile] = React.useState(false); // This is the internal state of the sidebar. // We use openProp and setOpenProp for control from outside the component. - const [_open, _setOpen] = React.useState(defaultOpen) - const open = openProp ?? _open + const [_open, _setOpen] = React.useState(defaultOpen); + const open = openProp ?? _open; const setOpen = React.useCallback( (value: boolean | ((value: boolean) => boolean)) => { - const openState = typeof value === "function" ? value(open) : value + const openState = typeof value === "function" ? value(open) : value; if (setOpenProp) { - setOpenProp(openState) + setOpenProp(openState); } else { - _setOpen(openState) + _setOpen(openState); } // This sets the cookie to keep the sidebar state. - document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` + document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`; }, - [setOpenProp, open] - ) + [setOpenProp, open], + ); // Helper to toggle the sidebar. const toggleSidebar = React.useCallback(() => { - return isMobile - ? setOpenMobile((open) => !open) - : setOpen((open) => !open) - }, [isMobile, setOpen, setOpenMobile]) + return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open); + }, [isMobile, setOpen, setOpenMobile]); // Adds a keyboard shortcut to toggle the sidebar. React.useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { - if ( - event.key === SIDEBAR_KEYBOARD_SHORTCUT && - (event.metaKey || event.ctrlKey) - ) { - event.preventDefault() - toggleSidebar() + if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) { + event.preventDefault(); + toggleSidebar(); } - } + }; - window.addEventListener("keydown", handleKeyDown) - return () => window.removeEventListener("keydown", handleKeyDown) - }, [toggleSidebar]) + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [toggleSidebar]); // We add a state so that we can do data-state="expanded" or "collapsed". // This makes it easier to style the sidebar with Tailwind classes. - const state = open ? "expanded" : "collapsed" + const state = open ? "expanded" : "collapsed"; const contextValue = React.useMemo<SidebarContext>( () => ({ @@ -126,8 +116,8 @@ const SidebarProvider = React.forwardRef< setOpenMobile, toggleSidebar, }), - [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] - ) + [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar], + ); return ( <SidebarContext.Provider value={contextValue}> @@ -142,26 +132,25 @@ const SidebarProvider = React.forwardRef< } className={cn( "group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar", - className + className, )} ref={ref} - {...props} - > + {...props}> {children} </div> </TooltipProvider> </SidebarContext.Provider> - ) - } -) -SidebarProvider.displayName = "SidebarProvider" + ); + }, +); +SidebarProvider.displayName = "SidebarProvider"; const Sidebar = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - side?: "left" | "right" - variant?: "sidebar" | "floating" | "inset" - collapsible?: "offcanvas" | "icon" | "none" + side?: "left" | "right"; + variant?: "sidebar" | "floating" | "inset"; + collapsible?: "offcanvas" | "icon" | "none"; } >( ( @@ -173,23 +162,22 @@ const Sidebar = React.forwardRef< children, ...props }, - ref + ref, ) => { - const { isMobile, state, openMobile, setOpenMobile } = useSidebar() + const { isMobile, state, openMobile, setOpenMobile } = useSidebar(); if (collapsible === "none") { return ( <div className={cn( "flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground", - className + className, )} ref={ref} - {...props} - > + {...props}> {children} </div> - ) + ); } if (isMobile) { @@ -204,12 +192,11 @@ const Sidebar = React.forwardRef< "--sidebar-width": SIDEBAR_WIDTH_MOBILE, } as React.CSSProperties } - side={side} - > + side={side}> <div className="flex h-full w-full flex-col">{children}</div> </SheetContent> </Sheet> - ) + ); } return ( @@ -219,8 +206,7 @@ const Sidebar = React.forwardRef< data-state={state} data-collapsible={state === "collapsed" ? collapsible : ""} data-variant={variant} - data-side={side} - > + data-side={side}> {/* This is what handles the sidebar gap on desktop */} <div className={cn( @@ -229,7 +215,7 @@ const Sidebar = React.forwardRef< "group-data-[side=right]:rotate-180", variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]" - : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]" + : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]", )} /> <div @@ -242,28 +228,26 @@ const Sidebar = React.forwardRef< variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]" : "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l", - className + className, )} - {...props} - > + {...props}> <div data-sidebar="sidebar" - className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow" - > + className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"> {children} </div> </div> </div> - ) - } -) -Sidebar.displayName = "Sidebar" + ); + }, +); +Sidebar.displayName = "Sidebar"; const SidebarTrigger = React.forwardRef< React.ElementRef<typeof Button>, React.ComponentProps<typeof Button> >(({ className, onClick, ...props }, ref) => { - const { toggleSidebar } = useSidebar() + const { toggleSidebar } = useSidebar(); return ( <Button @@ -273,64 +257,61 @@ const SidebarTrigger = React.forwardRef< size="icon" className={cn("h-7 w-7", className)} onClick={(event) => { - onClick?.(event) - toggleSidebar() + onClick?.(event); + toggleSidebar(); }} - {...props} - > + {...props}> <PanelLeft /> <span className="sr-only">Toggle Sidebar</span> </Button> - ) -}) -SidebarTrigger.displayName = "SidebarTrigger" + ); +}); +SidebarTrigger.displayName = "SidebarTrigger"; -const SidebarRail = React.forwardRef< - HTMLButtonElement, - React.ComponentProps<"button"> ->(({ className, ...props }, ref) => { - const { toggleSidebar } = useSidebar() +const SidebarRail = React.forwardRef<HTMLButtonElement, React.ComponentProps<"button">>( + ({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar(); - return ( - <button - ref={ref} - data-sidebar="rail" - aria-label="Toggle Sidebar" - tabIndex={-1} - onClick={toggleSidebar} - title="Toggle Sidebar" - className={cn( - "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", - "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", - "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", - "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", - "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", - "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", - className - )} - {...props} - /> - ) -}) -SidebarRail.displayName = "SidebarRail" + return ( + <button + ref={ref} + data-sidebar="rail" + aria-label="Toggle Sidebar" + tabIndex={-1} + onClick={toggleSidebar} + title="Toggle Sidebar" + className={cn( + "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", + "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", + "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", + "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", + "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", + "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", + className, + )} + {...props} + /> + ); + }, +); +SidebarRail.displayName = "SidebarRail"; -const SidebarInset = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"main"> ->(({ className, ...props }, ref) => { - return ( - <main - ref={ref} - className={cn( - "relative flex min-h-svh flex-1 flex-col bg-background", - "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow", - className - )} - {...props} - /> - ) -}) -SidebarInset.displayName = "SidebarInset" +const SidebarInset = React.forwardRef<HTMLDivElement, React.ComponentProps<"main">>( + ({ className, ...props }, ref) => { + return ( + <main + ref={ref} + className={cn( + "relative flex min-h-svh flex-1 flex-col bg-background", + "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow", + className, + )} + {...props} + /> + ); + }, +); +SidebarInset.displayName = "SidebarInset"; const SidebarInput = React.forwardRef< React.ElementRef<typeof Input>, @@ -342,43 +323,41 @@ const SidebarInput = React.forwardRef< data-sidebar="input" className={cn( "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring", - className + className, )} {...props} /> - ) -}) -SidebarInput.displayName = "SidebarInput" + ); +}); +SidebarInput.displayName = "SidebarInput"; -const SidebarHeader = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> ->(({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="header" - className={cn("flex flex-col gap-2 p-2", className)} - {...props} - /> - ) -}) -SidebarHeader.displayName = "SidebarHeader" +const SidebarHeader = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( + ({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="header" + className={cn("flex flex-col gap-2 p-2", className)} + {...props} + /> + ); + }, +); +SidebarHeader.displayName = "SidebarHeader"; -const SidebarFooter = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> ->(({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="footer" - className={cn("flex flex-col gap-2 p-2", className)} - {...props} - /> - ) -}) -SidebarFooter.displayName = "SidebarFooter" +const SidebarFooter = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( + ({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="footer" + className={cn("flex flex-col gap-2 p-2", className)} + {...props} + /> + ); + }, +); +SidebarFooter.displayName = "SidebarFooter"; const SidebarSeparator = React.forwardRef< React.ElementRef<typeof Separator>, @@ -391,48 +370,46 @@ const SidebarSeparator = React.forwardRef< className={cn("mx-2 w-auto bg-sidebar-border", className)} {...props} /> - ) -}) -SidebarSeparator.displayName = "SidebarSeparator" + ); +}); +SidebarSeparator.displayName = "SidebarSeparator"; -const SidebarContent = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> ->(({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="content" - className={cn( - "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", - className - )} - {...props} - /> - ) -}) -SidebarContent.displayName = "SidebarContent" +const SidebarContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( + ({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="content" + className={cn( + "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", + className, + )} + {...props} + /> + ); + }, +); +SidebarContent.displayName = "SidebarContent"; -const SidebarGroup = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> ->(({ className, ...props }, ref) => { - return ( - <div - ref={ref} - data-sidebar="group" - className={cn("relative flex w-full min-w-0 flex-col p-2", className)} - {...props} - /> - ) -}) -SidebarGroup.displayName = "SidebarGroup" +const SidebarGroup = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( + ({ className, ...props }, ref) => { + return ( + <div + ref={ref} + data-sidebar="group" + className={cn("relative flex w-full min-w-0 flex-col p-2", className)} + {...props} + /> + ); + }, +); +SidebarGroup.displayName = "SidebarGroup"; const SidebarGroupLabel = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { asChild?: boolean } >(({ className, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "div" + const Comp = asChild ? Slot : "div"; return ( <Comp @@ -441,19 +418,19 @@ const SidebarGroupLabel = React.forwardRef< className={cn( "duration-200 flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", - className + className, )} {...props} /> - ) -}) -SidebarGroupLabel.displayName = "SidebarGroupLabel" + ); +}); +SidebarGroupLabel.displayName = "SidebarGroupLabel"; const SidebarGroupAction = React.forwardRef< HTMLButtonElement, React.ComponentProps<"button"> & { asChild?: boolean } >(({ className, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" + const Comp = asChild ? Slot : "button"; return ( <Comp @@ -464,52 +441,49 @@ const SidebarGroupAction = React.forwardRef< // Increases the hit area of the button on mobile. "after:absolute after:-inset-2 after:md:hidden", "group-data-[collapsible=icon]:hidden", - className + className, )} {...props} /> - ) -}) -SidebarGroupAction.displayName = "SidebarGroupAction" + ); +}); +SidebarGroupAction.displayName = "SidebarGroupAction"; -const SidebarGroupContent = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> ->(({ className, ...props }, ref) => ( - <div - ref={ref} - data-sidebar="group-content" - className={cn("w-full text-sm", className)} - {...props} - /> -)) -SidebarGroupContent.displayName = "SidebarGroupContent" - -const SidebarMenu = React.forwardRef< - HTMLUListElement, - React.ComponentProps<"ul"> ->(({ className, ...props }, ref) => ( - <ul - ref={ref} - data-sidebar="menu" - className={cn("flex w-full min-w-0 flex-col gap-1", className)} - {...props} - /> -)) -SidebarMenu.displayName = "SidebarMenu" - -const SidebarMenuItem = React.forwardRef< - HTMLLIElement, - React.ComponentProps<"li"> ->(({ className, ...props }, ref) => ( - <li - ref={ref} - data-sidebar="menu-item" - className={cn("group/menu-item relative", className)} - {...props} - /> -)) -SidebarMenuItem.displayName = "SidebarMenuItem" +const SidebarGroupContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( + ({ className, ...props }, ref) => ( + <div + ref={ref} + data-sidebar="group-content" + className={cn("w-full text-sm", className)} + {...props} + /> + ), +); +SidebarGroupContent.displayName = "SidebarGroupContent"; + +const SidebarMenu = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>( + ({ className, ...props }, ref) => ( + <ul + ref={ref} + data-sidebar="menu" + className={cn("flex w-full min-w-0 flex-col gap-1", className)} + {...props} + /> + ), +); +SidebarMenu.displayName = "SidebarMenu"; + +const SidebarMenuItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( + ({ className, ...props }, ref) => ( + <li + ref={ref} + data-sidebar="menu-item" + className={cn("group/menu-item relative", className)} + {...props} + /> + ), +); +SidebarMenuItem.displayName = "SidebarMenuItem"; const sidebarMenuButtonVariants = cva( "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", @@ -530,15 +504,15 @@ const sidebarMenuButtonVariants = cva( variant: "default", size: "default", }, - } -) + }, +); const SidebarMenuButton = React.forwardRef< HTMLButtonElement, React.ComponentProps<"button"> & { - asChild?: boolean - isActive?: boolean - tooltip?: string | React.ComponentProps<typeof TooltipContent> + asChild?: boolean; + isActive?: boolean; + tooltip?: string | React.ComponentProps<typeof TooltipContent>; } & VariantProps<typeof sidebarMenuButtonVariants> >( ( @@ -551,10 +525,10 @@ const SidebarMenuButton = React.forwardRef< className, ...props }, - ref + ref, ) => { - const Comp = asChild ? Slot : "button" - const { isMobile, state } = useSidebar() + const Comp = asChild ? Slot : "button"; + const { isMobile, state } = useSidebar(); const button = ( <Comp @@ -565,16 +539,16 @@ const SidebarMenuButton = React.forwardRef< className={cn(sidebarMenuButtonVariants({ variant, size }), className)} {...props} /> - ) + ); if (!tooltip) { - return button + return button; } if (typeof tooltip === "string") { tooltip = { children: tooltip, - } + }; } return ( @@ -587,19 +561,19 @@ const SidebarMenuButton = React.forwardRef< {...tooltip} /> </Tooltip> - ) - } -) -SidebarMenuButton.displayName = "SidebarMenuButton" + ); + }, +); +SidebarMenuButton.displayName = "SidebarMenuButton"; const SidebarMenuAction = React.forwardRef< HTMLButtonElement, React.ComponentProps<"button"> & { - asChild?: boolean - showOnHover?: boolean + asChild?: boolean; + showOnHover?: boolean; } >(({ className, asChild = false, showOnHover = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" + const Comp = asChild ? Slot : "button"; return ( <Comp @@ -615,59 +589,52 @@ const SidebarMenuAction = React.forwardRef< "group-data-[collapsible=icon]:hidden", showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0", - className + className, )} {...props} /> - ) -}) -SidebarMenuAction.displayName = "SidebarMenuAction" + ); +}); +SidebarMenuAction.displayName = "SidebarMenuAction"; -const SidebarMenuBadge = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> ->(({ className, ...props }, ref) => ( - <div - ref={ref} - data-sidebar="menu-badge" - className={cn( - "absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground select-none pointer-events-none", - "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", - "peer-data-[size=sm]/menu-button:top-1", - "peer-data-[size=default]/menu-button:top-1.5", - "peer-data-[size=lg]/menu-button:top-2.5", - "group-data-[collapsible=icon]:hidden", - className - )} - {...props} - /> -)) -SidebarMenuBadge.displayName = "SidebarMenuBadge" +const SidebarMenuBadge = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>( + ({ className, ...props }, ref) => ( + <div + ref={ref} + data-sidebar="menu-badge" + className={cn( + "absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground select-none pointer-events-none", + "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", + "peer-data-[size=sm]/menu-button:top-1", + "peer-data-[size=default]/menu-button:top-1.5", + "peer-data-[size=lg]/menu-button:top-2.5", + "group-data-[collapsible=icon]:hidden", + className, + )} + {...props} + /> + ), +); +SidebarMenuBadge.displayName = "SidebarMenuBadge"; const SidebarMenuSkeleton = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & { - showIcon?: boolean + showIcon?: boolean; } >(({ className, showIcon = false, ...props }, ref) => { // Random width between 50 to 90%. const width = React.useMemo(() => { - return `${Math.floor(Math.random() * 40) + 50}%` - }, []) + return `${Math.floor(Math.random() * 40) + 50}%`; + }, []); return ( <div ref={ref} data-sidebar="menu-skeleton" className={cn("rounded-md h-8 flex gap-2 px-2 items-center", className)} - {...props} - > - {showIcon && ( - <Skeleton - className="size-4 rounded-md" - data-sidebar="menu-skeleton-icon" - /> - )} + {...props}> + {showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />} <Skeleton className="h-4 flex-1 max-w-[--skeleton-width]" data-sidebar="menu-skeleton-text" @@ -678,42 +645,40 @@ const SidebarMenuSkeleton = React.forwardRef< } /> </div> - ) -}) -SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton" - -const SidebarMenuSub = React.forwardRef< - HTMLUListElement, - React.ComponentProps<"ul"> ->(({ className, ...props }, ref) => ( - <ul - ref={ref} - data-sidebar="menu-sub" - className={cn( - "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", - "group-data-[collapsible=icon]:hidden", - className - )} - {...props} - /> -)) -SidebarMenuSub.displayName = "SidebarMenuSub" - -const SidebarMenuSubItem = React.forwardRef< - HTMLLIElement, - React.ComponentProps<"li"> ->(({ ...props }, ref) => <li ref={ref} {...props} />) -SidebarMenuSubItem.displayName = "SidebarMenuSubItem" + ); +}); +SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton"; + +const SidebarMenuSub = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>( + ({ className, ...props }, ref) => ( + <ul + ref={ref} + data-sidebar="menu-sub" + className={cn( + "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", + "group-data-[collapsible=icon]:hidden", + className, + )} + {...props} + /> + ), +); +SidebarMenuSub.displayName = "SidebarMenuSub"; + +const SidebarMenuSubItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( + ({ ...props }, ref) => <li ref={ref} {...props} />, +); +SidebarMenuSubItem.displayName = "SidebarMenuSubItem"; const SidebarMenuSubButton = React.forwardRef< HTMLAnchorElement, React.ComponentProps<"a"> & { - asChild?: boolean - size?: "sm" | "md" - isActive?: boolean + asChild?: boolean; + size?: "sm" | "md"; + isActive?: boolean; } >(({ asChild = false, size = "md", isActive, className, ...props }, ref) => { - const Comp = asChild ? Slot : "a" + const Comp = asChild ? Slot : "a"; return ( <Comp @@ -727,13 +692,13 @@ const SidebarMenuSubButton = React.forwardRef< size === "sm" && "text-xs", size === "md" && "text-sm", "group-data-[collapsible=icon]:hidden", - className + className, )} {...props} /> - ) -}) -SidebarMenuSubButton.displayName = "SidebarMenuSubButton" + ); +}); +SidebarMenuSubButton.displayName = "SidebarMenuSubButton"; export { Sidebar, @@ -760,4 +725,4 @@ export { SidebarSeparator, SidebarTrigger, useSidebar, -} +}; diff --git a/components/ui/skeleton.tsx b/components/ui/skeleton.tsx index 01b8b6d..6690a13 100644 --- a/components/ui/skeleton.tsx +++ b/components/ui/skeleton.tsx @@ -1,15 +1,7 @@ -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -function Skeleton({ - className, - ...props -}: React.HTMLAttributes<HTMLDivElement>) { - return ( - <div - className={cn("animate-pulse rounded-md bg-muted", className)} - {...props} - /> - ) +function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) { + return <div className={cn("animate-pulse rounded-md bg-muted", className)} {...props} />; } -export { Skeleton } +export { Skeleton }; diff --git a/components/ui/slider.tsx b/components/ui/slider.tsx index c31c2b3..d4d1df7 100644 --- a/components/ui/slider.tsx +++ b/components/ui/slider.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as SliderPrimitive from "@radix-ui/react-slider" +import * as React from "react"; +import * as SliderPrimitive from "@radix-ui/react-slider"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Slider = React.forwardRef< React.ElementRef<typeof SliderPrimitive.Root>, @@ -11,18 +11,14 @@ const Slider = React.forwardRef< >(({ className, ...props }, ref) => ( <SliderPrimitive.Root ref={ref} - className={cn( - "relative flex w-full touch-none select-none items-center", - className - )} - {...props} - > + className={cn("relative flex w-full touch-none select-none items-center", className)} + {...props}> <SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> <SliderPrimitive.Range className="absolute h-full bg-primary" /> </SliderPrimitive.Track> <SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background 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" /> </SliderPrimitive.Root> -)) -Slider.displayName = SliderPrimitive.Root.displayName +)); +Slider.displayName = SliderPrimitive.Root.displayName; -export { Slider } +export { Slider }; diff --git a/components/ui/sonner.tsx b/components/ui/sonner.tsx index 452f4d9..8d084f8 100644 --- a/components/ui/sonner.tsx +++ b/components/ui/sonner.tsx @@ -1,12 +1,12 @@ -"use client" +"use client"; -import { useTheme } from "next-themes" -import { Toaster as Sonner } from "sonner" +import { useTheme } from "next-themes"; +import { Toaster as Sonner } from "sonner"; -type ToasterProps = React.ComponentProps<typeof Sonner> +type ToasterProps = React.ComponentProps<typeof Sonner>; const Toaster = ({ ...props }: ToasterProps) => { - const { theme = "system" } = useTheme() + const { theme = "system" } = useTheme(); return ( <Sonner @@ -17,15 +17,13 @@ const Toaster = ({ ...props }: ToasterProps) => { toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg", description: "group-[.toast]:text-muted-foreground", - actionButton: - "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", - cancelButton: - "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", + actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", + cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", }, }} {...props} /> - ) -} + ); +}; -export { Toaster } +export { Toaster }; diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx index bc69cf2..728ed7f 100644 --- a/components/ui/switch.tsx +++ b/components/ui/switch.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as SwitchPrimitives from "@radix-ui/react-switch" +import * as React from "react"; +import * as SwitchPrimitives from "@radix-ui/react-switch"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Switch = React.forwardRef< React.ElementRef<typeof SwitchPrimitives.Root>, @@ -12,18 +12,17 @@ const Switch = React.forwardRef< <SwitchPrimitives.Root className={cn( "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", - className + className, )} {...props} - ref={ref} - > + ref={ref}> <SwitchPrimitives.Thumb className={cn( - "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0" + "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0", )} /> </SwitchPrimitives.Root> -)) -Switch.displayName = SwitchPrimitives.Root.displayName +)); +Switch.displayName = SwitchPrimitives.Root.displayName; -export { Switch } +export { Switch }; diff --git a/components/ui/table.tsx b/components/ui/table.tsx index 32355b3..07184f5 100644 --- a/components/ui/table.tsx +++ b/components/ui/table.tsx @@ -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, React.HTMLAttributes<HTMLTableElement>>( ({ className, ...props }, ref) => ( @@ -8,66 +8,84 @@ const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableE <table ref={ref} className={cn("w-full caption-bottom text-sm", className)} {...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" +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes<HTMLTableSectionElement> +>(({ className, ...props }, ref) => ( + <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} /> +)); +TableHeader.displayName = "TableHeader"; -const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>( - ({ className, ...props }, ref) => ( - <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} /> - ), -) -TableBody.displayName = "TableBody" +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes<HTMLTableSectionElement> +>(({ className, ...props }, ref) => ( + <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} /> +)); +TableBody.displayName = "TableBody"; -const TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>( - ({ className, ...props }, ref) => ( - <tfoot ref={ref} className={cn("bg-primary font-medium text-primary-foreground", className)} {...props} /> - ), -) -TableFooter.displayName = "TableFooter" +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes<HTMLTableSectionElement> +>(({ className, ...props }, ref) => ( + <tfoot + ref={ref} + className={cn("bg-primary font-medium text-primary-foreground", className)} + {...props} + /> +)); +TableFooter.displayName = "TableFooter"; const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>( ({ className, ...props }, ref) => ( <tr - ref={ref} - className={cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className)} - {...props} - /> - ), -) -TableRow.displayName = "TableRow" - -const TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>( - ({ className, ...props }, ref) => ( - <th ref={ref} className={cn( - "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", + "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className, )} {...props} /> ), -) -TableHead.displayName = "TableHead" +); +TableRow.displayName = "TableRow"; -const TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>( - ({ className, ...props }, ref) => ( - <td ref={ref} className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)} {...props} /> - ), -) -TableCell.displayName = "TableCell" +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes<HTMLTableCellElement> +>(({ className, ...props }, ref) => ( + <th + ref={ref} + className={cn( + "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", + className, + )} + {...props} + /> +)); +TableHead.displayName = "TableHead"; -const TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>( - ({ className, ...props }, ref) => ( - <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} /> - ), -) -TableCaption.displayName = "TableCaption" +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes<HTMLTableCellElement> +>(({ className, ...props }, ref) => ( + <td + ref={ref} + className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)} + {...props} + /> +)); +TableCell.displayName = "TableCell"; -export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes<HTMLTableCaptionElement> +>(({ className, ...props }, ref) => ( + <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} /> +)); +TableCaption.displayName = "TableCaption"; +export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }; diff --git a/components/ui/tabs.tsx b/components/ui/tabs.tsx index 26eb109..ca123a0 100644 --- a/components/ui/tabs.tsx +++ b/components/ui/tabs.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as React from "react" -import * as TabsPrimitive from "@radix-ui/react-tabs" +import * as React from "react"; +import * as TabsPrimitive from "@radix-ui/react-tabs"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Tabs = TabsPrimitive.Root +const Tabs = TabsPrimitive.Root; const TabsList = React.forwardRef< React.ElementRef<typeof TabsPrimitive.List>, @@ -15,12 +15,12 @@ const TabsList = React.forwardRef< ref={ref} className={cn( "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", - className + className, )} {...props} /> -)) -TabsList.displayName = TabsPrimitive.List.displayName +)); +TabsList.displayName = TabsPrimitive.List.displayName; const TabsTrigger = React.forwardRef< React.ElementRef<typeof TabsPrimitive.Trigger>, @@ -30,12 +30,12 @@ const TabsTrigger = React.forwardRef< ref={ref} className={cn( "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm", - className + className, )} {...props} /> -)) -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; const TabsContent = React.forwardRef< React.ElementRef<typeof TabsPrimitive.Content>, @@ -45,11 +45,11 @@ const TabsContent = React.forwardRef< ref={ref} className={cn( "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", - className + className, )} {...props} /> -)) -TabsContent.displayName = TabsPrimitive.Content.displayName +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; -export { Tabs, TabsList, TabsTrigger, TabsContent } +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx index 4d858bb..69391b2 100644 --- a/components/ui/textarea.tsx +++ b/components/ui/textarea.tsx @@ -1,22 +1,21 @@ -import * as React from "react" +import * as React from "react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Textarea = React.forwardRef< - HTMLTextAreaElement, - React.ComponentProps<"textarea"> ->(({ className, ...props }, ref) => { - return ( - <textarea - className={cn( - "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", - className - )} - ref={ref} - {...props} - /> - ) -}) -Textarea.displayName = "Textarea" +const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<"textarea">>( + ({ className, ...props }, ref) => { + return ( + <textarea + className={cn( + "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", + className, + )} + ref={ref} + {...props} + /> + ); + }, +); +Textarea.displayName = "Textarea"; -export { Textarea } +export { Textarea }; diff --git a/components/ui/toast.tsx b/components/ui/toast.tsx index 521b94b..cc51d5f 100644 --- a/components/ui/toast.tsx +++ b/components/ui/toast.tsx @@ -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>, @@ -17,12 +17,12 @@ const ToastViewport = React.forwardRef< ref={ref} className={cn( "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]", - className + className, )} {...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", @@ -37,13 +37,12 @@ const toastVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); const Toast = React.forwardRef< React.ElementRef<typeof ToastPrimitives.Root>, - React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & - VariantProps<typeof toastVariants> + React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants> >(({ className, variant, ...props }, ref) => { return ( <ToastPrimitives.Root @@ -51,9 +50,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>, @@ -63,12 +62,12 @@ const ToastAction = React.forwardRef< ref={ref} className={cn( "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive", - className + className, )} {...props} /> -)) -ToastAction.displayName = ToastPrimitives.Action.displayName +)); +ToastAction.displayName = ToastPrimitives.Action.displayName; const ToastClose = React.forwardRef< React.ElementRef<typeof ToastPrimitives.Close>, @@ -78,27 +77,22 @@ const ToastClose = React.forwardRef< ref={ref} className={cn( "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600", - className + className, )} toast-close="" - {...props} - > + {...props}> <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>, React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title> >(({ className, ...props }, ref) => ( - <ToastPrimitives.Title - ref={ref} - className={cn("text-sm font-semibold", className)} - {...props} - /> -)) -ToastTitle.displayName = ToastPrimitives.Title.displayName + <ToastPrimitives.Title ref={ref} className={cn("text-sm font-semibold", className)} {...props} /> +)); +ToastTitle.displayName = ToastPrimitives.Title.displayName; const ToastDescription = React.forwardRef< React.ElementRef<typeof ToastPrimitives.Description>, @@ -109,12 +103,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, @@ -126,4 +120,4 @@ export { ToastDescription, ToastClose, ToastAction, -} +}; diff --git a/components/ui/toaster.tsx b/components/ui/toaster.tsx index 171beb4..bdda26e 100644 --- a/components/ui/toaster.tsx +++ b/components/ui/toaster.tsx @@ -1,6 +1,6 @@ -"use client" +"use client"; -import { useToast } from "@/hooks/use-toast" +import { useToast } from "@/hooks/use-toast"; import { Toast, ToastClose, @@ -8,10 +8,10 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@/components/ui/toast" +} from "@/components/ui/toast"; export function Toaster() { - const { toasts } = useToast() + const { toasts } = useToast(); return ( <ToastProvider> @@ -20,16 +20,14 @@ export function Toaster() { <Toast key={id} {...props}> <div className="grid gap-1"> {title && <ToastTitle>{title}</ToastTitle>} - {description && ( - <ToastDescription>{description}</ToastDescription> - )} + {description && <ToastDescription>{description}</ToastDescription>} </div> {action} <ToastClose /> </Toast> - ) + ); })} <ToastViewport /> </ToastProvider> - ) + ); } diff --git a/components/ui/toggle-group.tsx b/components/ui/toggle-group.tsx index 1c876bb..ff17f9b 100644 --- a/components/ui/toggle-group.tsx +++ b/components/ui/toggle-group.tsx @@ -1,18 +1,16 @@ -"use client" +"use client"; -import * as React from "react" -import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" -import { type VariantProps } from "class-variance-authority" +import * as React from "react"; +import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"; +import { type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" -import { toggleVariants } from "@/components/ui/toggle" +import { cn } from "@/lib/utils"; +import { toggleVariants } from "@/components/ui/toggle"; -const ToggleGroupContext = React.createContext< - VariantProps<typeof toggleVariants> ->({ +const ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants>>({ size: "default", variant: "default", -}) +}); const ToggleGroup = React.forwardRef< React.ElementRef<typeof ToggleGroupPrimitive.Root>, @@ -22,22 +20,19 @@ const ToggleGroup = React.forwardRef< <ToggleGroupPrimitive.Root ref={ref} className={cn("flex items-center justify-center gap-1", className)} - {...props} - > - <ToggleGroupContext.Provider value={{ variant, size }}> - {children} - </ToggleGroupContext.Provider> + {...props}> + <ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider> </ToggleGroupPrimitive.Root> -)) +)); -ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName +ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName; const ToggleGroupItem = React.forwardRef< React.ElementRef<typeof ToggleGroupPrimitive.Item>, React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants> >(({ className, children, variant, size, ...props }, ref) => { - const context = React.useContext(ToggleGroupContext) + const context = React.useContext(ToggleGroupContext); return ( <ToggleGroupPrimitive.Item @@ -47,15 +42,14 @@ const ToggleGroupItem = React.forwardRef< variant: context.variant || variant, size: context.size || size, }), - className + className, )} - {...props} - > + {...props}> {children} </ToggleGroupPrimitive.Item> - ) -}) + ); +}); -ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName +ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName; -export { ToggleGroup, ToggleGroupItem } +export { ToggleGroup, ToggleGroupItem }; diff --git a/components/ui/toggle.tsx b/components/ui/toggle.tsx index c19bea3..fa4a988 100644 --- a/components/ui/toggle.tsx +++ b/components/ui/toggle.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import * as TogglePrimitive from "@radix-ui/react-toggle" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import * as TogglePrimitive from "@radix-ui/react-toggle"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const toggleVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2", @@ -12,8 +12,7 @@ const toggleVariants = cva( variants: { variant: { default: "bg-transparent", - outline: - "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", }, size: { default: "h-10 px-3 min-w-10", @@ -25,21 +24,20 @@ const toggleVariants = cva( variant: "default", size: "default", }, - } -) + }, +); const Toggle = React.forwardRef< React.ElementRef<typeof TogglePrimitive.Root>, - React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & - VariantProps<typeof toggleVariants> + React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants> >(({ className, variant, size, ...props }, ref) => ( <TogglePrimitive.Root ref={ref} className={cn(toggleVariants({ variant, size, className }))} {...props} /> -)) +)); -Toggle.displayName = TogglePrimitive.Root.displayName +Toggle.displayName = TogglePrimitive.Root.displayName; -export { Toggle, toggleVariants } +export { Toggle, toggleVariants }; diff --git a/components/ui/tooltip.tsx b/components/ui/tooltip.tsx index 9006050..2c42a2c 100644 --- a/components/ui/tooltip.tsx +++ b/components/ui/tooltip.tsx @@ -1,15 +1,15 @@ -"use client" +"use client"; -import * as React from "react" -import * as TooltipPrimitive from "@radix-ui/react-tooltip" +import * as React from "react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const TooltipProvider = TooltipPrimitive.Provider +const TooltipProvider = TooltipPrimitive.Provider; -const Tooltip = TooltipPrimitive.Root +const Tooltip = TooltipPrimitive.Root; -const TooltipTrigger = TooltipPrimitive.Trigger +const TooltipTrigger = TooltipPrimitive.Trigger; const TooltipContent = React.forwardRef< React.ElementRef<typeof TooltipPrimitive.Content>, @@ -24,8 +24,7 @@ const TooltipContent = React.forwardRef< )} {...props} /> -)) -TooltipContent.displayName = TooltipPrimitive.Content.displayName - -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/components/ui/use-mobile.tsx b/components/ui/use-mobile.tsx index 2b0fe1d..502fd32 100644 --- a/components/ui/use-mobile.tsx +++ b/components/ui/use-mobile.tsx @@ -1,19 +1,19 @@ -import * as React from "react" +import * as React from "react"; -const MOBILE_BREAKPOINT = 768 +const MOBILE_BREAKPOINT = 768; export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined); React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - } - mql.addEventListener("change", onChange) - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - return () => mql.removeEventListener("change", onChange) - }, []) + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + }; + mql.addEventListener("change", onChange); + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + return () => mql.removeEventListener("change", onChange); + }, []); - return !!isMobile + return !!isMobile; } diff --git a/components/ui/use-toast.ts b/components/ui/use-toast.ts index 02e111d..74b72e2 100644 --- a/components/ui/use-toast.ts +++ b/components/ui/use-toast.ts @@ -1,78 +1,75 @@ -"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 +} 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) + }); + }, TOAST_REMOVE_DELAY); - toastTimeouts.set(toastId, timeout) -} + toastTimeouts.set(toastId, timeout); +}; export const reducer = (state: State, action: Action): State => { switch (action.type) { @@ -80,27 +77,25 @@ export const reducer = (state: State, action: Action): State => { return { ...state, 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 - ), - } + 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 { @@ -111,46 +106,46 @@ export const reducer = (state: State, action: Action): State => { ...t, open: false, } - : t + : t, ), - } + }; } case "REMOVE_TOAST": if (action.toastId === undefined) { return { ...state, toasts: [], - } + }; } return { ...state, 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 }) + }); + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); dispatch({ type: "ADD_TOAST", @@ -159,36 +154,36 @@ function toast({ ...props }: Toast) { id, open: true, onOpenChange: (open) => { - if (!open) dismiss() + if (!open) dismiss(); }, }, - }) + }); return { id: id, dismiss, 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 }), - } + }; } -export { useToast, toast } +export { useToast, toast }; diff --git a/hooks/use-mobile.tsx b/hooks/use-mobile.tsx index 2b0fe1d..502fd32 100644 --- a/hooks/use-mobile.tsx +++ b/hooks/use-mobile.tsx @@ -1,19 +1,19 @@ -import * as React from "react" +import * as React from "react"; -const MOBILE_BREAKPOINT = 768 +const MOBILE_BREAKPOINT = 768; export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined); React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - } - mql.addEventListener("change", onChange) - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - return () => mql.removeEventListener("change", onChange) - }, []) + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + }; + mql.addEventListener("change", onChange); + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + return () => mql.removeEventListener("change", onChange); + }, []); - return !!isMobile + return !!isMobile; } diff --git a/hooks/use-toast.ts b/hooks/use-toast.ts index 02e111d..74b72e2 100644 --- a/hooks/use-toast.ts +++ b/hooks/use-toast.ts @@ -1,78 +1,75 @@ -"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 +} 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) + }); + }, TOAST_REMOVE_DELAY); - toastTimeouts.set(toastId, timeout) -} + toastTimeouts.set(toastId, timeout); +}; export const reducer = (state: State, action: Action): State => { switch (action.type) { @@ -80,27 +77,25 @@ export const reducer = (state: State, action: Action): State => { return { ...state, 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 - ), - } + 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 { @@ -111,46 +106,46 @@ export const reducer = (state: State, action: Action): State => { ...t, open: false, } - : t + : t, ), - } + }; } case "REMOVE_TOAST": if (action.toastId === undefined) { return { ...state, toasts: [], - } + }; } return { ...state, 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 }) + }); + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); dispatch({ type: "ADD_TOAST", @@ -159,36 +154,36 @@ function toast({ ...props }: Toast) { id, open: true, onOpenChange: (open) => { - if (!open) dismiss() + if (!open) dismiss(); }, }, - }) + }); return { id: id, dismiss, 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 }), - } + }; } -export { useToast, toast } +export { useToast, toast }; diff --git a/lib/utils.ts b/lib/utils.ts index bd0b3ae..365058c 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,7 +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)); } - diff --git a/next-sitemap.config.js b/next-sitemap.config.js index 94b8b39..1c4cb18 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -3,4 +3,4 @@ module.exports = { siteUrl: process.env.SITE_URL || "https://securerpc.com", generateRobotsTxt: true, // (optional) // ...other options -} +}; From cfc76266ec9fc2ca03bab003a899bbd5a886d657 Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 07:09:11 -0800 Subject: [PATCH 3/7] refactor(nav): use radix --- .browserslistrc | 23 ++++ app/components/api-endpoint.tsx | 6 +- app/components/header.tsx | 20 ++-- app/components/main-nav.tsx | 177 +++++++++++++--------------- bun.lockb | Bin 126437 -> 127730 bytes components/ui/accordion.tsx | 12 +- components/ui/menubar.tsx | 8 +- components/ui/navigation-menu.tsx | 4 +- next-sitemap.config.js | 2 +- package.json | 34 +++--- public/android-chrome-192x192.png | Bin 0 -> 8642 bytes public/android-chrome-512x512.png | Bin 0 -> 28815 bytes public/apple-touch-icon-180x180.png | Bin 0 -> 7752 bytes public/apple-touch-icon-192x192.png | Bin 0 -> 8642 bytes public/favicon.ico | Bin 0 -> 1369 bytes public/og-image.jpg | Bin 0 -> 49109 bytes public/site.webmanifest | 21 ++++ 17 files changed, 169 insertions(+), 138 deletions(-) create mode 100644 .browserslistrc mode change 100644 => 100755 app/components/main-nav.tsx mode change 100644 => 100755 bun.lockb mode change 100644 => 100755 components/ui/accordion.tsx mode change 100644 => 100755 components/ui/navigation-menu.tsx create mode 100755 public/android-chrome-192x192.png create mode 100755 public/android-chrome-512x512.png create mode 100755 public/apple-touch-icon-180x180.png create mode 100755 public/apple-touch-icon-192x192.png create mode 100755 public/favicon.ico create mode 100644 public/og-image.jpg create mode 100755 public/site.webmanifest diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..4259c53 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,23 @@ +and_chr 132 +and_ff 132 +and_uc 15.5 +chrome 131 +chrome 130 +chrome 127 +chrome 126 +chrome 125 +chrome 109 +edge 131 +firefox 133 +ios_saf 18.2 +ios_saf 18.1 +ios_saf 18.0 +ios_saf 17.6-17.7 +ios_saf 17.5 +ios_saf 16.6-16.7 +ios_saf 15.6-15.8 +op_mob 80 +opera 114 +safari 18.1 +safari 17.6 +samsung 27 diff --git a/app/components/api-endpoint.tsx b/app/components/api-endpoint.tsx index 9ec5cd7..2f401de 100644 --- a/app/components/api-endpoint.tsx +++ b/app/components/api-endpoint.tsx @@ -4,11 +4,11 @@ import { Input } from "@/components/ui/input"; export function APIEndpoint() { return ( <div className="bg-blackA3 rounded-lg p-6"> - <h3 className="text-xl font-semibold mb-4 text-white">Try Our SecureRPC API</h3> + <h3 className="text-xl font-semibold mb-4 text-white">Public API Endpoint</h3> <div className="flex items-center space-x-2"> <Input type="text" - placeholder="https://api.manifoldfinance.com/v1/endpoint" + placeholder="https://api.securerpc.com/v1" className="flex-grow bg-blackA5 text-white" readOnly /> @@ -17,7 +17,7 @@ export function APIEndpoint() { </Button> </div> <p className="mt-4 text-sm text-mauveA11"> - Get started with our SecureRPC API for reliable and secure blockchain interactions. + Get started with our SecureRPC API for MEV Protection, and low latency network access. </p> </div> ); diff --git a/app/components/header.tsx b/app/components/header.tsx index b521ca2..7095728 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -90,15 +90,17 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit ({ className, title, children, ...props }, ref) => { return ( <li> - <NavigationMenuLink - ref={ref} - className={cn( - "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", - className, - )} - {...props}> - <div className="text-sm font-medium leading-none">{title}</div> - <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> + <NavigationMenuLink asChild> + <a + ref={ref} + className={cn( + "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", + className, + )} + {...props}> + <div className="text-sm font-medium leading-none">{title}</div> + <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> + </a> </NavigationMenuLink> </li> ); diff --git a/app/components/main-nav.tsx b/app/components/main-nav.tsx old mode 100644 new mode 100755 index a8d02d0..2e7ff79 --- a/app/components/main-nav.tsx +++ b/app/components/main-nav.tsx @@ -3,20 +3,19 @@ import * as React from "react"; import Link from "next/link"; import { Menu } from "lucide-react"; +import { CaretDownIcon } from "@radix-ui/react-icons"; import { cn } from "@/lib/utils"; -import { Icons } from "@/components/icons"; -import { - NavigationMenu, - NavigationMenuContent, - NavigationMenuItem, - NavigationMenuLink, - NavigationMenuList, - NavigationMenuTrigger, - navigationMenuTriggerStyle, -} from "@/components/ui/navigation-menu"; +import { Logo } from "@/app/components/logo"; import { Button } from "@/components/ui/button"; import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; +import { + Menubar, + MenubarContent, + MenubarItem, + MenubarMenu, + MenubarTrigger, +} from "@/components/ui/menubar"; const solutions: { title: string; href: string; description: string }[] = [ { @@ -57,102 +56,86 @@ const products: { title: string; href: string; description: string }[] = [ export function MainNav() { return ( - <> - <div className="md:hidden"> - <Sheet> - <SheetTrigger asChild> - <Button variant="ghost" size="icon" className="text-white"> - <Menu className="h-6 w-6" /> - <span className="sr-only">Open menu</span> - </Button> - </SheetTrigger> - <SheetContent side="left" className="w-[300px] bg-black text-white"> - <nav className="flex flex-col space-y-4"> - <Link href="/" className="text-lg font-semibold"> - Manifold Finance - </Link> - <MobileNavItem title="Solutions" items={solutions} /> - <MobileNavItem title="Products" items={products} /> - <Link href="/docs" className="py-2"> - Documentation - </Link> - <Link href="/blog" className="py-2"> - Blog - </Link> - </nav> - </SheetContent> - </Sheet> - </div> - <div className="hidden md:block"> - <NavigationMenu> - <NavigationMenuList> - <NavigationMenuItem> - <NavigationMenuTrigger>Solutions</NavigationMenuTrigger> - <NavigationMenuContent> - <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> + <header className="sticky top-0 z-50 w-full border-b bg-[#1616b4] text-white"> + <div className="container flex h-16 items-center"> + <Link href="/" className="mr-6 flex items-center space-x-2"> + <Logo className="h-6 w-6" /> + <span className="hidden font-bold sm:inline-block">Manifold Finance</span> + </Link> + <div className="flex flex-1 items-center justify-between space-x-2 md:justify-end"> + <nav className="flex items-center space-x-6 text-sm font-medium"> + <Menubar className="bg-transparent border-none"> + <MenubarMenu> + <MenubarTrigger className="text-white hover:bg-[#c9b3f5] hover:bg-opacity-20"> + Solutions + </MenubarTrigger> + <MenubarContent className="bg-[#1616b4]"> {solutions.map((item) => ( - <ListItem key={item.title} title={item.title} href={item.href}> - {item.description} - </ListItem> + <MenubarItem + key={item.href} + className="text-white hover:bg-[#c9b3f5] hover:bg-opacity-20"> + <Link href={item.href}>{item.title}</Link> + </MenubarItem> ))} - </ul> - </NavigationMenuContent> - </NavigationMenuItem> - <NavigationMenuItem> - <NavigationMenuTrigger>Products</NavigationMenuTrigger> - <NavigationMenuContent> - <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> + </MenubarContent> + </MenubarMenu> + <MenubarMenu> + <MenubarTrigger className="text-white hover:bg-[#c9b3f5] hover:bg-opacity-20"> + Products + </MenubarTrigger> + <MenubarContent className="bg-[#1616b4]"> {products.map((item) => ( - <ListItem key={item.title} title={item.title} href={item.href}> - {item.description} - </ListItem> + <MenubarItem + key={item.href} + className="text-white hover:bg-[#c9b3f5] hover:bg-opacity-20"> + <Link href={item.href}>{item.title}</Link> + </MenubarItem> ))} - </ul> - </NavigationMenuContent> - </NavigationMenuItem> - <NavigationMenuItem> - <Link href="/docs" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}> + </MenubarContent> + </MenubarMenu> + <MenubarMenu> + <MenubarTrigger className="text-white hover:bg-[#c9b3f5] hover:bg-opacity-20"> + <Link href="/docs">Documentation</Link> + </MenubarTrigger> + </MenubarMenu> + <MenubarMenu> + <MenubarTrigger className="text-white hover:bg-[#c9b3f5] hover:bg-opacity-20"> + <Link href="/blog">Blog</Link> + </MenubarTrigger> + </MenubarMenu> + </Menubar> + </nav> + </div> + <div className="md:hidden"> + <Sheet> + <SheetTrigger asChild> + <Button variant="ghost" size="icon" className="text-white"> + <Menu className="h-6 w-6" /> + <span className="sr-only">Open menu</span> + </Button> + </SheetTrigger> + <SheetContent side="left" className="w-[300px] bg-[#1616b4] text-white"> + <nav className="flex flex-col space-y-4"> + <Link href="/" className="text-lg font-semibold"> + Manifold Finance + </Link> + <MobileNavItem title="Solutions" items={solutions} /> + <MobileNavItem title="Products" items={products} /> + <Link href="/docs" className="py-2"> Documentation - </NavigationMenuLink> - </Link> - </NavigationMenuItem> - <NavigationMenuItem> - <Link href="/blog" legacyBehavior passHref> - <NavigationMenuLink className={navigationMenuTriggerStyle()}> + </Link> + <Link href="/blog" className="py-2"> Blog - </NavigationMenuLink> - </Link> - </NavigationMenuItem> - </NavigationMenuList> - </NavigationMenu> + </Link> + </nav> + </SheetContent> + </Sheet> + </div> </div> - </> + </header> ); } -const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>( - ({ className, title, children, ...props }, ref) => { - return ( - <li> - <NavigationMenuLink asChild> - <a - ref={ref} - className={cn( - "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", - className, - )} - {...props}> - <div className="text-sm font-medium leading-none">{title}</div> - <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> - </a> - </NavigationMenuLink> - </li> - ); - }, -); -ListItem.displayName = "ListItem"; - function MobileNavItem({ title, items, @@ -164,7 +147,7 @@ function MobileNavItem({ onClick={() => setIsOpen(!isOpen)} className="flex w-full items-center justify-between py-2 text-left"> {title} - <Icons.chevronDown className={cn("h-4 w-4 transition-transform", isOpen && "rotate-180")} /> + <CaretDownIcon className={cn("h-4 w-4 transition-transform", isOpen && "rotate-180")} /> </button> {isOpen && ( <div className="pl-4 space-y-2"> diff --git a/bun.lockb b/bun.lockb old mode 100644 new mode 100755 index cea8324d10c4f66f63990fb6a25f357e1a6afe9f..1cdd236549859ba9dda3877a3f45bedaf6d024ac GIT binary patch delta 24093 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 M8W$ve!^TwoAE1gGEdT%j delta 23180 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 diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx old mode 100644 new mode 100755 index 7f5d4c8..ac7b619 --- a/components/ui/accordion.tsx +++ b/components/ui/accordion.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import * as AccordionPrimitive from "@radix-ui/react-accordion"; -import { ChevronDown } from "lucide-react"; +import { CaretDownIcon } from "@radix-ui/react-icons"; import { cn } from "@/lib/utils"; @@ -29,7 +29,7 @@ const AccordionTrigger = React.forwardRef< )} {...props}> {children} - <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> + <CaretDownIcon className="h-4 w-4 shrink-0 transition-transform duration-200" /> </AccordionPrimitive.Trigger> </AccordionPrimitive.Header> )); @@ -41,12 +41,14 @@ const AccordionContent = React.forwardRef< >(({ className, children, ...props }, ref) => ( <AccordionPrimitive.Content ref={ref} - className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" + className={cn( + "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down", + className, + )} {...props}> - <div className={cn("pb-4 pt-0", className)}>{children}</div> + <div className="pb-4 pt-0">{children}</div> </AccordionPrimitive.Content> )); - AccordionContent.displayName = AccordionPrimitive.Content.displayName; export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/components/ui/menubar.tsx b/components/ui/menubar.tsx index 815aeec..116072d 100644 --- a/components/ui/menubar.tsx +++ b/components/ui/menubar.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import * as MenubarPrimitive from "@radix-ui/react-menubar"; -import { Check, ChevronRight, Circle } from "lucide-react"; +import { CaretDownIcon } from "@radix-ui/react-icons"; import { cn } from "@/lib/utils"; @@ -61,7 +61,7 @@ const MenubarSubTrigger = React.forwardRef< )} {...props}> {children} - <ChevronRight className="ml-auto h-4 w-4" /> + <CaretDownIcon className="ml-auto h-4 w-4" /> </MenubarPrimitive.SubTrigger> )); MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName; @@ -133,7 +133,7 @@ const MenubarCheckboxItem = React.forwardRef< {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <MenubarPrimitive.ItemIndicator> - <Check className="h-4 w-4" /> + <CaretDownIcon className="h-4 w-4" /> </MenubarPrimitive.ItemIndicator> </span> {children} @@ -154,7 +154,7 @@ const MenubarRadioItem = React.forwardRef< {...props}> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <MenubarPrimitive.ItemIndicator> - <Circle className="h-2 w-2 fill-current" /> + <CaretDownIcon className="h-2 w-2 fill-current" /> </MenubarPrimitive.ItemIndicator> </span> {children} diff --git a/components/ui/navigation-menu.tsx b/components/ui/navigation-menu.tsx old mode 100644 new mode 100755 index 083eb5f..9068bb6 --- a/components/ui/navigation-menu.tsx +++ b/components/ui/navigation-menu.tsx @@ -3,7 +3,7 @@ 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 { CaretDownIcon } from "@radix-ui/react-icons"; import { cn } from "@/lib/utils"; @@ -48,7 +48,7 @@ const NavigationMenuTrigger = React.forwardRef< className={cn(navigationMenuTriggerStyle(), "group", className)} {...props}> {children}{" "} - <ChevronDown + <CaretDownIcon className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180" aria-hidden="true" /> diff --git a/next-sitemap.config.js b/next-sitemap.config.js index 1c4cb18..f79bdc5 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,6 +1,6 @@ /** @type {import('next-sitemap').IConfig} */ module.exports = { - siteUrl: process.env.SITE_URL || "https://securerpc.com", + siteUrl: process.env.SITE_URL || "https://manifoldfinance.com", generateRobotsTxt: true, // (optional) // ...other options }; diff --git a/package.json b/package.json index 76c27f3..377fda6 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "lint": "next lint" }, "dependencies": { + "@emotion/is-prop-valid": "latest", "@hookform/resolvers": "^3.10.0", + "@radix-ui/colors": "latest", "@radix-ui/react-accordion": "^1.2.2", "@radix-ui/react-alert-dialog": "^1.1.5", "@radix-ui/react-aspect-ratio": "^1.1.1", @@ -20,6 +22,7 @@ "@radix-ui/react-dialog": "latest", "@radix-ui/react-dropdown-menu": "^2.1.5", "@radix-ui/react-hover-card": "^1.1.5", + "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-label": "^2.1.1", "@radix-ui/react-menubar": "^1.1.5", "@radix-ui/react-navigation-menu": "latest", @@ -37,42 +40,39 @@ "@radix-ui/react-toggle": "^1.1.1", "@radix-ui/react-toggle-group": "^1.1.1", "@radix-ui/react-tooltip": "latest", + "@tailwindcss/typography": "latest", "autoprefixer": "^10.4.20", + "browserslist": "^4.24.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "latest", "date-fns": "4.1.0", "embla-carousel-react": "8.5.1", + "framer-motion": "latest", "input-otp": "1.4.1", "lucide-react": "0.454.0", "next": "14.2.23", + "next-sitemap": "^4.2.3", "next-themes": "^0.4.4", - "react": "^18", + "react": "^18.3.1", "react-day-picker": "8.10.1", - "react-dom": "^18", - "react-hook-form": "^7.54.1", + "react-dom": "^18.3.1", + "react-hook-form": "^7.54.2", "react-resizable-panels": "^2.1.7", "recharts": "latest", "sonner": "^1.7.4", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "vaul": "^1.1.2", - "zod": "^3.24.1", - "@types/react": "latest", - "@types/react-dom": "latest", - "tailwindcss": "latest", - "@emotion/is-prop-valid": "latest", - "@radix-ui/colors": "latest", - "@tailwindcss/typography": "latest", - "framer-motion": "latest" + "zod": "^3.24.1" }, "devDependencies": { "@biomejs/biome": "1.9.4", - "@types/node": "^22", - "@types/react": "^18", - "@types/react-dom": "^18", - "postcss": "^8", + "@types/node": "^22.13.1", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "postcss": "^8.5.1", "tailwindcss": "^3.4.17", - "typescript": "^5" + "typescript": "^5.7.3" } -} \ No newline at end of file +} diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100755 index 0000000000000000000000000000000000000000..50243caa4e76b49fa3387693d5e748885dc6f60e GIT binary patch literal 8642 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 UUCZ-lUjP6A07*qoM6N<$f&pJ#ng9R* literal 0 HcmV?d00001 diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100755 index 0000000000000000000000000000000000000000..521c1a7e34e283be4c2aeabc40a777fa02b7e45b GIT binary patch literal 28815 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 BiX8v| literal 0 HcmV?d00001 diff --git a/public/apple-touch-icon-180x180.png b/public/apple-touch-icon-180x180.png new file mode 100755 index 0000000000000000000000000000000000000000..9e84865ad1313ad6eecb3e537a698bb1e2a01863 GIT binary patch literal 7752 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 O0000<MNUMnLSTX^V)z6A literal 0 HcmV?d00001 diff --git a/public/apple-touch-icon-192x192.png b/public/apple-touch-icon-192x192.png new file mode 100755 index 0000000000000000000000000000000000000000..50243caa4e76b49fa3387693d5e748885dc6f60e GIT binary patch literal 8642 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 UUCZ-lUjP6A07*qoM6N<$f&pJ#ng9R* literal 0 HcmV?d00001 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..96295111b027881efb0e8b84ec0882e552b4c59c GIT binary patch literal 1369 zcmV-f1*ZCmP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00001b5ch_0Itp) z=>Px)6G=otRCr$Hn@Q+?Qy9lTe?*z*G0CjRkTMku3koYGHuP7PQdnSvD6&A3g#}?_ zqm-do*dRkBB16WMIWw7u_xt+YxAQ;0d+vFjbI!f*i)Z!gz0dG{zRz>dxo7xo;D0U~ zM#%p~;8>&Ivw%m9x}&JIBH(9Wt4f4B17BDAaGTc>@RvJc-ay^+QeLf%MkxWm09&?! zkn~cD%>}C@$QV^mfxaHN+Le)0*+an1z-3PVE!2N)Fuqi`**n02EwZWb;VG6mjK%4j zz@cW3<0<|DY|+|%j)04S+gk^%@b@5ac7^>q(;NX)4tUnQa+s}t=6XZURx$Z5xn?A! z9Ie8jH&n@uz`bh<Cjrm6${r}E2w3In_jN&s_h{f14;g&~`~Ym@aT4gB3p@>c9Q?Ky za2RkWaB!jDKC`WXpMnQr(af(%pQ5MwHLJOgfW0dT3Gv6cp9S=K3`$JEnZP4Cqs-uG zFyBPwc;Gp&(VBjYzpr?M-C%JLV%rSxbciRf$AHs420evHVM~%=CE$JF04KOobq~QB zYxW5O?FoF62;578g@B!aZ;aWT2s{MrX4Frqc}TG2&^L3;e+!KTKAul=qv?6Gb;A8o z7RLZDR}vue$7gs>Gx+fk@LRl(5gI=XXjD(K6+HVL*t`eag}^-q&{h?-v)Xz{JOs$k ze!z!)Nrr6~&#|5Ux4`xTXmTB6O+3`gy$*5A3xco2RJ?^v-#n`JRU60R1yYi1$(Rrm zpbCGG3H~;4NIV8~3C0d@0WQrr)H+@3^)baW#pQ~%$UW|Wc%J_Z*xiuT7_D#Zz|ybT zD}kFrV@-8C22npZPG?gj-@&qe=~+5p-UTV}Hv(eFB2yBe^MY`E(vnz9<4`n!|7Za| zM1YmSQ-G(8!CI;1R(+=ePZ)!3EPa1E|5H}K?=|R)|2?p+k$`nuVy^;6SdAO63aw!^ zPU#Hsi^KqJ?cRAj?^jd|av2>U3`#N;yO;pY0y|jC02~Co>(FnhItl?U=9bj{ITF1& zEZXQ~;K`i#==rkRe+XtV0dB(;>;Ro$=_Jb~T^0We1eD~kcm+y~SLqcf!M~UWwF#ol z5U;EX0o%>)Eqvz%AAZR_4;)wEKsz;BEiPM%t3O-p-JvR$I(Qv8e976DVqY{s4FP>$ zl2h_goBSOAzm<R%$=?NBBm%wywD(^k+AY$eWJ+m~{GxkBz}<khvrA>F+2D+Z*J>9h zN&>G%jdn>(WeNgXRXv>j=6~0G35JA?MMCSuh4}<PQ~$~mpv#!LlsT4cQmj@T5Oz}x zysP4SYqv)}1@-`r0(7NiN?F&b-4D75sSA-ca^38s>Y9XuF<RM+wf8lR4@SIBWBs8M zqCc0ogiel8;RBrssx50}Xh3|cJCmyo;;<hapldfpQ#gi#>hgq6oyL|gfn9S!VxYIp zz6>wP85y7J{(#y(C1bu4=4rW4vE_iJDecw_VJ+inSKGBW&}47j&=Ho3XlebL!B?#E zLg9YK+)oPFzTq{J0#JP>T6FE=^mPTGyNlX<(G6A&qPnl3q?^c4Wi+Q>+a$_*Cu80> zbV1Iw<_*AAE{}fY2Y_?@W^F8T1SpCwI=|5-oY{-6>$kjEoeXRtpfhecS`RVd!DMDM zrRWWI-|Rs2{OYLv4)k5nclU6laR0dV63~Is%5MLL$VzckL#PdWr1w8G0>qcEO=;Ch b)HwJXZCt@BctJ-}00000NkvXXu0mjft<sKX literal 0 HcmV?d00001 diff --git a/public/og-image.jpg b/public/og-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7db36ee3959f5112431c07c4587cceb6843f22bc GIT binary patch literal 49109 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 literal 0 HcmV?d00001 diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100755 index 0000000..94570e3 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "Manifold Finance", + "short_name": "Manifold Finance", + "description": "Manifold Finance, Inc.", + "start_url": "/", + "display": "standalone", + "background_color": "#FFFFFF", + "theme_color": "#FFFFFF", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} From 646216f29999eac82453c66b652dfbeff8558769 Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 07:26:04 -0800 Subject: [PATCH 4/7] fix(types): fixup --- components/icons.tsx | 5 ++--- components/ui/badge.tsx | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/components/icons.tsx b/components/icons.tsx index 04bc958..333c582 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -12,12 +12,11 @@ export const Icons = { sun: SunMedium, moon: Moon, twitter: Twitter, - logo: (props: LucideProps) => ( + logo: (props: typeof LucideProps) => ( <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}> <path fill="currentColor" d="M11.572 0c-.176 0-.31.001-.358.007a19.76 19.76 0 0 1-.364.033C7.443.346 4.25 2.185 2.228 5.012a11.875 11.875 0 0 0-2.119 5.243c-.096.659-.108.854-.108 1.747s.012 1.089.108 1.748c.652 4.506 3.86 8.292 8.209 9.695.779.25 1.6.422 2.534.525.363.04 1.935.04 2.299 0 1.611-.178 2.977-.577 4.323-1.264.207-.106.247-.134.219-.158-.02-.013-.9-1.193-1.955-2.62l-1.919-2.592-2.404-3.558a338.739 338.739 0 0 0-2.422-3.556c-.009-.002-.018 1.579-.023 3.51-.007 3.38-.01 3.515-.052 3.595a.426.426 0 0 1-.206.214c-.075.037-.14.044-.495.044H7.81l-.108-.068a.438.438 0 0 1-.157-.171l-.05-.106.006-4.703.007-4.705.072-.092a.645.645 0 0 1 .174-.143c.096-.047.134-.051.54-.051.478 0 .558.018.682.154.035.038 1.337 1.999 2.895 4.361a10760.433 10760.433 0 0 0 4.735 7.17l1.9 2.879.096-.063a12.317 12.317 0 0 0 2.466-2.163 11.944 11.944 0 0 0 2.824-6.134c.096-.66.108-.854.108-1.748 0-.893-.012-1.088-.108-1.747-.652-4.506-3.859-8.292-8.208-9.695a12.597 12.597 0 0 0-2.499-.523A33.119 33.119 0 0 0 11.573 0zm4.069 7.217c.347 0 .408.005.486.047a.473.473 0 0 1 .237.277c.018.06.023 1.365.018 4.304l-.006 4.218-.744-1.14-.746-1.14v-3.066c0-1.982.01-3.097.023-3.15a.478.478 0 0 1 .233-.296c.096-.05.13-.054.5-.054z" /> </svg> - ), -}; + ),}; diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx index 9ab4cc0..01e1852 100644 --- a/components/ui/badge.tsx +++ b/components/ui/badge.tsx @@ -32,12 +32,10 @@ const badgeVariants = cva( }, ); -export interface BadgeProps - extends React.HTMLAttributes<HTMLDivElement>, - VariantProps<typeof badgeVariants> {} +export interface BadgeProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>, VariantProps<typeof badgeVariants> {} function Badge({ className, variant, color, radius, ...props }: BadgeProps) { return <div className={cn(badgeVariants({ variant, color, radius }), className)} {...props} />; } -export { Badge, badgeVariants }; +export { Badge, badgeVariants }; \ No newline at end of file From 17dfc88cf820abb7ae464c0178c3e77d3b196376 Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 07:40:08 -0800 Subject: [PATCH 5/7] fix(types): two step cast type fix --- app/components/header.tsx | 27 +++++++++++++++------------ components/icons.tsx | 3 ++- components/ui/badge.tsx | 6 ++++-- package.json | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/components/header.tsx b/app/components/header.tsx index 7095728..e2066c0 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -90,17 +90,20 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit ({ className, title, children, ...props }, ref) => { return ( <li> - <NavigationMenuLink asChild> - <a - ref={ref} - className={cn( - "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", - className, - )} - {...props}> - <div className="text-sm font-medium leading-none">{title}</div> - <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> - </a> + <NavigationMenuLink + ref={ref} + className={cn( + "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", + className, + )} + {...props} + onSelect={(event) => { + if (props.onSelect) { + props.onSelect(event as unknown as React.SyntheticEvent<HTMLAnchorElement, Event>); + } + }}> + <div className="text-sm font-medium leading-none">{title}</div> + <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> </NavigationMenuLink> </li> ); @@ -140,7 +143,7 @@ function MobileMenu() { export function Header() { return ( - <header className="fixed top-0 w-full z-50 bg-background border-b border-border"> + <header className="fixed top-0 w-full z-50 bg-black border-b border-border"> <div className="container mx-auto px-4"> <div className="flex items-center justify-between h-16 md:h-20"> <Link href="/" className="flex items-center"> diff --git a/components/icons.tsx b/components/icons.tsx index 333c582..7aab4bf 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -19,4 +19,5 @@ export const Icons = { d="M11.572 0c-.176 0-.31.001-.358.007a19.76 19.76 0 0 1-.364.033C7.443.346 4.25 2.185 2.228 5.012a11.875 11.875 0 0 0-2.119 5.243c-.096.659-.108.854-.108 1.747s.012 1.089.108 1.748c.652 4.506 3.86 8.292 8.209 9.695.779.25 1.6.422 2.534.525.363.04 1.935.04 2.299 0 1.611-.178 2.977-.577 4.323-1.264.207-.106.247-.134.219-.158-.02-.013-.9-1.193-1.955-2.62l-1.919-2.592-2.404-3.558a338.739 338.739 0 0 0-2.422-3.556c-.009-.002-.018 1.579-.023 3.51-.007 3.38-.01 3.515-.052 3.595a.426.426 0 0 1-.206.214c-.075.037-.14.044-.495.044H7.81l-.108-.068a.438.438 0 0 1-.157-.171l-.05-.106.006-4.703.007-4.705.072-.092a.645.645 0 0 1 .174-.143c.096-.047.134-.051.54-.051.478 0 .558.018.682.154.035.038 1.337 1.999 2.895 4.361a10760.433 10760.433 0 0 0 4.735 7.17l1.9 2.879.096-.063a12.317 12.317 0 0 0 2.466-2.163 11.944 11.944 0 0 0 2.824-6.134c.096-.66.108-.854.108-1.748 0-.893-.012-1.088-.108-1.747-.652-4.506-3.859-8.292-8.208-9.695a12.597 12.597 0 0 0-2.499-.523A33.119 33.119 0 0 0 11.573 0zm4.069 7.217c.347 0 .408.005.486.047a.473.473 0 0 1 .237.277c.018.06.023 1.365.018 4.304l-.006 4.218-.744-1.14-.746-1.14v-3.066c0-1.982.01-3.097.023-3.15a.478.478 0 0 1 .233-.296c.096-.05.13-.054.5-.054z" /> </svg> - ),}; + ), +}; diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx index 01e1852..18cdf3c 100644 --- a/components/ui/badge.tsx +++ b/components/ui/badge.tsx @@ -32,10 +32,12 @@ const badgeVariants = cva( }, ); -export interface BadgeProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>, VariantProps<typeof badgeVariants> {} +export interface BadgeProps + extends Omit<React.HTMLAttributes<HTMLDivElement>, "color">, + VariantProps<typeof badgeVariants> {} function Badge({ className, variant, color, radius, ...props }: BadgeProps) { return <div className={cn(badgeVariants({ variant, color, radius }), className)} {...props} />; } -export { Badge, badgeVariants }; \ No newline at end of file +export { Badge, badgeVariants }; diff --git a/package.json b/package.json index 377fda6..ffb333f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@manifoldfinance/www-frontend", - "version": "0.1.0", + "version": "0.1.1", "private": true, "scripts": { "dev": "next dev", From da59a90dfa10621f5f8e3750ec131acc6b1af479 Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 08:28:13 -0800 Subject: [PATCH 6/7] fix(site): enforce black bg css --- app/components/footer.tsx | 25 +++++++++--------- app/components/header.tsx | 53 ++++++++++++++++++--------------------- app/globals.css | 10 ++++---- app/layout.tsx | 51 ++++++++++++++++--------------------- public/eth_frame.svg | 21 ++++++++++++++++ tailwind.config.js | 2 +- 6 files changed, 87 insertions(+), 75 deletions(-) create mode 100644 public/eth_frame.svg diff --git a/app/components/footer.tsx b/app/components/footer.tsx index 7dbc4d2..6bfd76d 100644 --- a/app/components/footer.tsx +++ b/app/components/footer.tsx @@ -1,14 +1,14 @@ -import Link from "next/link"; -import { Twitter, Github } from "lucide-react"; -import { Logo } from "./logo"; -import { HoverCard, HoverCardTrigger, HoverCardContent } from "@/components/ui/hover-card"; +import Link from "next/link" +import { Twitter, Github } from "lucide-react" +import { Logo } from "./logo" +import { HoverCard, HoverCardTrigger, HoverCardContent } from "@/components/ui/hover-card" // This would typically come from an environment variable or build-time constant -const GIT_VERSION_HASH = "a1b2c3d"; +const GIT_VERSION_HASH = "a1b2c3d" export function Footer() { return ( - <footer className="bg-black border-t border-gray-800 py-6"> + <footer className="bg-background border-t border-gray-800 py-6"> <div className="container mx-auto px-4"> <div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0"> <div className="flex flex-col items-center md:items-start space-y-2"> @@ -24,14 +24,16 @@ export function Footer() { href="https://twitter.com/manifoldfinance" target="_blank" rel="noopener noreferrer" - className="text-gray-400 hover:text-white transition-colors"> + className="text-gray-400 hover:text-white transition-colors" + > <Twitter className="w-5 h-5" /> </Link> <Link href="https://github.com/manifoldfinance" target="_blank" rel="noopener noreferrer" - className="text-gray-400 hover:text-white transition-colors"> + className="text-gray-400 hover:text-white transition-colors" + > <Github className="w-5 h-5" /> </Link> </div> @@ -50,9 +52,7 @@ export function Footer() { <h4 className="text-sm font-semibold">System Status</h4> <p className="text-sm">All systems are operational.</p> <div className="flex items-center pt-2"> - <span className="text-xs text-muted-foreground"> - Last checked: {new Date().toLocaleString()} - </span> + <span className="text-xs text-muted-foreground">Last checked: {new Date().toLocaleString()}</span> </div> </div> </div> @@ -62,5 +62,6 @@ export function Footer() { </div> </div> </footer> - ); + ) } + diff --git a/app/components/header.tsx b/app/components/header.tsx index e2066c0..e33ae80 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -19,24 +19,24 @@ import { Menu } from "lucide-react"; const solutions: { title: string; href: string; description: string }[] = [ { - title: "High-Performance Staking", + title: "High-Yield Staking", href: "/solutions/staking", - description: "Build and manage efficient staking solutions for maximum returns.", + description: "Maximum returns, natively.", }, { - title: "Secure Restaking", + title: "AVS Restaking", href: "/solutions/restaking", - description: "Leverage restaking protocols while ensuring top-notch security.", + description: "AVS Operations", }, { - title: "MEV Optimization", + title: "MEV Relay", href: "/solutions/mev", - description: "Maximize MEV earnings with our advanced strategies and tools.", + description: "Maximize MEV earnings as a Validator. Protect yourself as a user.", }, { title: "Enterprise SecureRPC", href: "/solutions/securerpc", - description: "Stable and reliable blockchain interactions for your applications.", + description: "MEV Protection and RPC as a Service", }, ]; @@ -49,12 +49,12 @@ const products: { title: string; href: string; description: string }[] = [ { title: "SecureRPC", href: "/products/securerpc", - description: "Enterprise-grade RPC service for secure blockchain interactions.", + description: "MEV Protection as a Service", }, { title: "XGA", - href: "/products/xga", - description: "Cross-chain Governance Aggregator for decentralized decision-making.", + href: "https://xga.com", + description: "Hello World Auction.", }, { title: "mevETH", @@ -90,20 +90,17 @@ const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWit ({ className, title, children, ...props }, ref) => { return ( <li> - <NavigationMenuLink - ref={ref} - className={cn( - "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", - className, - )} - {...props} - onSelect={(event) => { - if (props.onSelect) { - props.onSelect(event as unknown as React.SyntheticEvent<HTMLAnchorElement, Event>); - } - }}> - <div className="text-sm font-medium leading-none">{title}</div> - <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> + <NavigationMenuLink asChild> + <a + ref={ref} + className={cn( + "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", + className, + )} + {...props}> + <div className="text-sm font-medium leading-none">{title}</div> + <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p> + </a> </NavigationMenuLink> </li> ); @@ -143,7 +140,7 @@ function MobileMenu() { export function Header() { return ( - <header className="fixed top-0 w-full z-50 bg-black border-b border-border"> + <header className="fixed top-0 w-full z-50 bg-background border-b border-border"> <div className="container mx-auto px-4"> <div className="flex items-center justify-between h-16 md:h-20"> <Link href="/" className="flex items-center"> @@ -164,17 +161,17 @@ export function Header() { href="/solutions/staking"> <div> <Image - src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Ethereum2_Logo-G7XZRKQfQ3ujqhgs1ZKjTpoe3zVqab.png" + src="/eth_frame.svg" alt="Ethereum Logo" width={38} height={38} className="mb-3" /> <div className="text-lg font-medium text-foreground mb-2"> - High-Performance Staking + High Yield Staking </div> <p className="text-sm text-muted-foreground"> - Build and manage efficient staking solutions for maximum returns. + +4.5% Without any Restaking </p> </div> <div className="text-sm font-medium text-primary mt-4">Learn more →</div> diff --git a/app/globals.css b/app/globals.css index 59e819b..cdec42b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -10,9 +10,8 @@ @layer base { :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - + --background: 200 0% 0%; + --foreground: 0 0% 100%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; @@ -43,8 +42,8 @@ } .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; + --background: 200 0% 0%; + --foreground: 0 0% 100%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; @@ -90,3 +89,4 @@ @apply font-heading; } } + diff --git a/app/layout.tsx b/app/layout.tsx index f03af9d..add501e 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,22 +1,22 @@ -import { Space_Grotesk, Noto_Sans } from "next/font/google"; -import ErrorBoundary from "./components/error-boundary"; -import "./globals.css"; -import type { Metadata } from "next"; -import { CommandMenu } from "./components/command-menu"; -import { Header } from "./components/header"; -import type React from "react"; -import { LayoutWrapper } from "./components/layout-wrapper"; +import { Space_Grotesk, Noto_Sans } from "next/font/google" +import ErrorBoundary from "./components/error-boundary" +import "./globals.css" +import type { Metadata } from "next" +import { CommandMenu } from "./components/command-menu" +import { Header } from "./components/header" +import type React from "react" +import { LayoutWrapper } from "./components/layout-wrapper" const spaceGrotesk = Space_Grotesk({ subsets: ["latin"], variable: "--font-space-grotesk", -}); +}) const notoSans = Noto_Sans({ subsets: ["latin"], weight: ["400", "700"], variable: "--font-noto-sans", -}); +}) export const metadata: Metadata = { metadataBase: new URL("https://manifoldfinance.com"), @@ -26,14 +26,7 @@ export const metadata: Metadata = { }, description: "Manifold Finance provides optimized infrastructure for the next generation of Ethereum, offering high-performance staking, MEV optimization, and enterprise-grade SecureRPC.", - keywords: [ - "Manifold Finance", - "Ethereum", - "Staking", - "MEV", - "SecureRPC", - "Blockchain Infrastructure", - ], + keywords: ["Manifold Finance", "Ethereum", "Staking", "MEV", "SecureRPC", "Blockchain Infrastructure"], authors: [{ name: "Manifold Finance" }], creator: "Manifold Finance", publisher: "Manifold Finance", @@ -47,25 +40,25 @@ export const metadata: Metadata = { locale: "en_US", url: "https://manifoldfinance.com", siteName: "Manifold Finance", - title: "Manifold Finance - Optimized Infrastructure for Ethereum", + title: "Manifold Finance - Powering markets across networks.", description: - "Build high-performance staking solutions, maximize MEV earnings, and leverage enterprise-grade SecureRPC with Manifold Finance.", + "High-yielding staking solutions, maximize MEV earnings, and more with Manifold Finance.", images: [ { url: "https://manifoldfinance.com/og-image.jpg", width: 1200, height: 630, - alt: "Manifold Finance - Optimized Ethereum Infrastructure", + alt: "Manifold Finance - Powering markets across networks", }, ], }, twitter: { card: "summary_large_image", - title: "Manifold Finance - Optimized Infrastructure for Ethereum", + title: "Manifold Finance - Powering markets across networks", description: - "Build high-performance staking solutions, maximize MEV earnings, and leverage enterprise-grade SecureRPC with Manifold Finance.", + "High-yielding staking solutions, maximize MEV earnings, and more with Manifold Finance.", images: ["https://manifoldfinance.com/og-image.jpg"], - creator: "@manifoldfinance", + creator: "@foldfinance", }, icons: { icon: "/favicon.ico", @@ -73,20 +66,19 @@ export const metadata: Metadata = { apple: "/apple-touch-icon.png", }, manifest: "https://manifoldfinance.com/site.webmanifest", -}; +} export default function RootLayout({ children, }: { - children: React.ReactNode; + children: React.ReactNode }) { //const pathname = usePathname() //const isHomePage = pathname === "/" return ( <html lang="en" className={`dark ${spaceGrotesk.variable} ${notoSans.variable}`}> - <body - className={`min-h-screen bg-background text-foreground flex flex-col ${notoSans.className}`}> + <body className={`min-h-screen bg-background text-foreground flex flex-col ${notoSans.className}`}> <ErrorBoundary> <Header /> <LayoutWrapper> @@ -96,5 +88,6 @@ export default function RootLayout({ </ErrorBoundary> </body> </html> - ); + ) } + diff --git a/public/eth_frame.svg b/public/eth_frame.svg new file mode 100644 index 0000000..5789225 --- /dev/null +++ b/public/eth_frame.svg @@ -0,0 +1,21 @@ +<svg width="24" height="38" viewBox="0 0 24 38" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1_2)"> +<path d="M11.9203 37.9666V28.4495L0.168273 21.5648L11.9203 37.9666Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M0.143513 21.5424C0.15417 21.5306 0.171552 21.528 0.185203 21.5359L11.9372 28.4206C11.9475 28.4267 11.9538 28.4377 11.9538 28.4495V37.9666C11.9538 37.981 11.9444 37.9939 11.9305 37.9985C11.9167 38.0029 11.9015 37.9979 11.893 37.9859L0.141043 21.5844C0.131825 21.5717 0.132855 21.554 0.143513 21.5424ZM0.287301 21.6735L11.8868 37.8622V28.4687L0.287301 21.6735Z" fill="black"/> +<path d="M11.9592 37.9666V28.4495L23.7112 21.5648L11.9592 37.9666Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M23.7358 21.5424C23.7465 21.554 23.7476 21.5717 23.7383 21.5844L11.9865 37.9859C11.978 37.9979 11.9628 38.0029 11.949 37.9985C11.9351 37.9939 11.9257 37.981 11.9257 37.9666V28.4495C11.9257 28.4377 11.932 28.4267 11.9423 28.4206L23.6943 21.5359C23.7079 21.528 23.7252 21.5306 23.7358 21.5424ZM11.9927 28.4687V37.8622L23.5921 21.6735L11.9927 28.4687Z" fill="black"/> +<path d="M11.9203 26.084V13.9378L0.0335064 19.27L11.9203 26.084Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9385 13.9096C11.948 13.9158 11.9538 13.9264 11.9538 13.9378V26.084C11.9538 26.0959 11.9474 26.1069 11.9371 26.113C11.9268 26.1189 11.914 26.1189 11.9036 26.113L0.0168506 19.2991C0.00591382 19.2928 -0.000581375 19.281 4.10489e-05 19.2683C0.000663474 19.2557 0.00829821 19.2445 0.0197997 19.2394L11.9066 13.9072C11.9169 13.9025 11.929 13.9034 11.9385 13.9096ZM0.107277 19.2736L11.8868 26.0262V13.9895L0.107277 19.2736Z" fill="black"/> +<path d="M11.9592 26.084V13.9378L23.846 19.27L11.9592 26.084Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M11.941 13.9096C11.9505 13.9034 11.9625 13.9025 11.9729 13.9072L23.8597 19.2394C23.8712 19.2445 23.8788 19.2557 23.8794 19.2683C23.8802 19.281 23.8735 19.2928 23.8627 19.2991L11.9758 26.113C11.9655 26.1189 11.9527 26.1189 11.9424 26.113C11.932 26.1069 11.9257 26.0959 11.9257 26.084V13.9378C11.9257 13.9264 11.9314 13.9158 11.941 13.9096ZM11.9927 13.9895V26.0262L23.7721 19.2736L11.9927 13.9895Z" fill="black"/> +<path d="M0.0335179 19.27L11.9203 0.0335297V13.9378L0.0335179 19.27Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9294 0.00127978C11.9438 0.00537647 11.9538 0.0185428 11.9538 0.0335295V13.9378C11.9538 13.951 11.946 13.9629 11.934 13.9684L0.0472146 19.3006C0.033784 19.3067 0.0179966 19.303 0.00829987 19.292C-0.00139692 19.281 -0.00273249 19.2649 0.00500781 19.2523L11.8918 0.0158982C11.8996 0.00315125 11.915 -0.0028169 11.9294 0.00127978ZM0.11942 19.1947L11.8867 13.9161V0.151506L0.11942 19.1947Z" fill="black"/> +<path d="M23.846 19.27L11.9592 0.0335297V13.9378L23.846 19.27Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9501 0.00127978C11.9645 -0.0028169 11.9798 0.00315124 11.9877 0.0158981L23.8745 19.2523C23.8823 19.2649 23.8809 19.281 23.8712 19.292C23.8616 19.303 23.8456 19.3067 23.8323 19.3006L11.9455 13.9684C11.9335 13.9629 11.9257 13.951 11.9257 13.9378V0.0335295C11.9257 0.0185428 11.9357 0.00537647 11.9501 0.00127978ZM11.9927 0.151506V13.9161L23.7602 19.1947L11.9927 0.151506Z" fill="black"/> +</g> +<defs> +<clipPath id="clip0_1_2"> +<rect width="23.9259" height="38" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/tailwind.config.js b/tailwind.config.js index 90ae598..4705d7d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -72,4 +72,4 @@ module.exports = { }, }, plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")], -}; +}; \ No newline at end of file From d29e180e9ff76e69cd4b6a9da0c6b6f31769a0dd Mon Sep 17 00:00:00 2001 From: sam bacha <sam@manifoldfinance.com> Date: Tue, 4 Feb 2025 09:14:53 -0800 Subject: [PATCH 7/7] chore(site): sitemap --- app/layout.tsx | 2 +- public/robots.txt | 9 +++++++++ public/sitemap-0.xml | 30 ++++++++++++++++++++++++++++++ public/sitemap.xml | 4 ++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 public/robots.txt create mode 100644 public/sitemap-0.xml create mode 100644 public/sitemap.xml diff --git a/app/layout.tsx b/app/layout.tsx index add501e..0f2451f 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -21,7 +21,7 @@ const notoSans = Noto_Sans({ export const metadata: Metadata = { metadataBase: new URL("https://manifoldfinance.com"), title: { - default: "Manifold Finance - Optimized Infrastructure for Ethereum", + default: "Manifold Finance - Powering markets across networks.", template: "%s | Manifold Finance", }, description: diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..1c7fb27 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,9 @@ +# * +User-agent: * +Allow: / + +# Host +Host: https://manifoldfinance.com + +# Sitemaps +Sitemap: https://manifoldfinance.com/sitemap.xml diff --git a/public/sitemap-0.xml b/public/sitemap-0.xml new file mode 100644 index 0000000..cb25116 --- /dev/null +++ b/public/sitemap-0.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"> +<url><loc>https://manifoldfinance.com/blog</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/products/meveth</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/docs/securerpc/api-reference</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/changelog</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/docs</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/products/xga</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/products/securerpc</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/auction-markets</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/docs/getting-started/introduction</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/avs-operations</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/hedging-execution</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/mev</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/mev-relay-protection</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/relay-protect</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/technology</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/fold-token</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/products/fold-staking</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/docs/getting-started/installation</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/restaking</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/blog/future-of-ethereum-scaling</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/blog/introducing-mev-protection</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/blog/optimizing-defi-strategies</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/case-studies</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/products/captive-insurance</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +<url><loc>https://manifoldfinance.com/solutions/staking</loc><lastmod>2025-02-04T17:10:14.018Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> +</urlset> \ No newline at end of file diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..c8c4ac4 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> +<sitemap><loc>https://manifoldfinance.com/sitemap-0.xml</loc></sitemap> +</sitemapindex> \ No newline at end of file