Compare commits

..

No commits in common. "3dfee64e8e4c26b506fafcc6f4d2154dc0f35c1d" and "4d00d4b936551d87eb9f35e3673f9f51b5888db2" have entirely different histories.

70 changed files with 3460 additions and 3486 deletions

View File

@ -1,37 +0,0 @@
{
"$schema": "https://biomejs.dev/schemas/1.6.4/schema.json",
"organizeImports": {
"enabled": true
},
"files": {
"include": [
"./src/**/*.ts",
"./src/**/*.tsx"
]
},
"vcs": {
"enabled": true,
"clientKind": "git"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"performance": {
"recommended": true,
"noDelete": "off"
},
"suspicious": {
"noExplicitAny": "warn"
},
"complexity": {
"useLiteralKeys": "off"
}
}
},
"formatter": {
"indentStyle": "tab",
"indentWidth": 2,
"lineWidth": 90
}
}

View File

@ -6,8 +6,7 @@
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint"
"check": "biome check --skip-errors --apply src"
}, },
"dependencies": { "dependencies": {
"@fontsource-variable/kode-mono": "^5.0.3", "@fontsource-variable/kode-mono": "^5.0.3",
@ -63,7 +62,6 @@
"zod": "^3.23.8" "zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.8.1",
"@types/jest": "^29.5.12", "@types/jest": "^29.5.12",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^18", "@types/react": "^18",

91
pnpm-lock.yaml generated
View File

@ -162,9 +162,6 @@ importers:
specifier: ^3.23.8 specifier: ^3.23.8
version: 3.23.8 version: 3.23.8
devDependencies: devDependencies:
'@biomejs/biome':
specifier: 1.8.1
version: 1.8.1
'@types/jest': '@types/jest':
specifier: ^29.5.12 specifier: ^29.5.12
version: 29.5.12 version: 29.5.12
@ -371,59 +368,6 @@ packages:
'@bcoe/v8-coverage@0.2.3': '@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
'@biomejs/biome@1.8.1':
resolution: {integrity: sha512-fQXGfvq6DIXem12dGQCM2tNF+vsNHH1qs3C7WeOu75Pd0trduoTmoO7G4ntLJ2qDs5wuw981H+cxQhi1uHnAtA==}
engines: {node: '>=14.21.3'}
hasBin: true
'@biomejs/cli-darwin-arm64@1.8.1':
resolution: {integrity: sha512-XLiB7Uu6GALIOBWzQ2aMD0ru4Ly5/qSeQF7kk3AabzJ/kwsEWSe33iVySBP/SS2qv25cgqNiLksjGcw2bHT3mw==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [darwin]
'@biomejs/cli-darwin-x64@1.8.1':
resolution: {integrity: sha512-uMTSxVLMfqkBVqyc25hSn83jBbp+wtWjzM/pHFlKXt3htJuw7FErVGW0nmQ9Sxa9vJ7GcqoltLMl28VQRIMYzg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [darwin]
'@biomejs/cli-linux-arm64-musl@1.8.1':
resolution: {integrity: sha512-UQ8Wc01J0wQL+5AYOc7qkJn20B4PZmQL1KrmDZh7ot0DvD6aX4+8mmfd/dG5b6Zjo/44QvCKcvkFGCMRYuhWZA==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
'@biomejs/cli-linux-arm64@1.8.1':
resolution: {integrity: sha512-3SzZRuC/9Oi2P2IBNPsEj0KXxSXUEYRR2kfRF/Ve8QAfGgrt4qnwuWd6QQKKN5R+oYH691qjm+cXBKEcrP1v/Q==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
'@biomejs/cli-linux-x64-musl@1.8.1':
resolution: {integrity: sha512-fYbP/kNu/rtZ4kKzWVocIdqZOtBSUEg9qUhZaao3dy3CRzafR6u6KDtBeSCnt47O+iLnks1eOR1TUxzr5+QuqA==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
'@biomejs/cli-linux-x64@1.8.1':
resolution: {integrity: sha512-AeBycVdNrTzsyYKEOtR2R0Ph0hCD0sCshcp2aOnfGP0hCZbtFg09D0SdKLbyzKntisY41HxKVrydYiaApp+2uw==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
'@biomejs/cli-win32-arm64@1.8.1':
resolution: {integrity: sha512-6tEd1H/iFKpgpE3OIB7oNgW5XkjiVMzMRPL8zYoZ036YfuJ5nMYm9eB9H/y81+8Z76vL48fiYzMPotJwukGPqQ==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [win32]
'@biomejs/cli-win32-x64@1.8.1':
resolution: {integrity: sha512-g2H31jJzYmS4jkvl6TiyEjEX+Nv79a5km/xn+5DARTp5MBFzC9gwceusSSB2AkJKqZzY131AiACAWjKrVt5Ijw==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [win32]
'@floating-ui/core@1.6.2': '@floating-ui/core@1.6.2':
resolution: {integrity: sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==} resolution: {integrity: sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==}
@ -2850,41 +2794,6 @@ snapshots:
'@bcoe/v8-coverage@0.2.3': {} '@bcoe/v8-coverage@0.2.3': {}
'@biomejs/biome@1.8.1':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 1.8.1
'@biomejs/cli-darwin-x64': 1.8.1
'@biomejs/cli-linux-arm64': 1.8.1
'@biomejs/cli-linux-arm64-musl': 1.8.1
'@biomejs/cli-linux-x64': 1.8.1
'@biomejs/cli-linux-x64-musl': 1.8.1
'@biomejs/cli-win32-arm64': 1.8.1
'@biomejs/cli-win32-x64': 1.8.1
'@biomejs/cli-darwin-arm64@1.8.1':
optional: true
'@biomejs/cli-darwin-x64@1.8.1':
optional: true
'@biomejs/cli-linux-arm64-musl@1.8.1':
optional: true
'@biomejs/cli-linux-arm64@1.8.1':
optional: true
'@biomejs/cli-linux-x64-musl@1.8.1':
optional: true
'@biomejs/cli-linux-x64@1.8.1':
optional: true
'@biomejs/cli-win32-arm64@1.8.1':
optional: true
'@biomejs/cli-win32-x64@1.8.1':
optional: true
'@floating-ui/core@1.6.2': '@floating-ui/core@1.6.2':
dependencies: dependencies:
'@floating-ui/utils': 0.2.2 '@floating-ui/utils': 0.2.2

View File

@ -1,38 +1,37 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import "@fontsource-variable/kode-mono"; import '@fontsource-variable/kode-mono';
import "./globals.css"; import "./globals.css";
import { Footer } from "@/components/footer"; import {ThemeProvider} from "@/components/providers/theme-provider";
import { Header } from "@/components/header";
import { PrimaryNavigationMenu } from "@/components/primary-nav";
import { Providers } from "@/components/providers/providers";
import { ThemeProvider } from "@/components/providers/theme-provider";
import type React from "react"; import type React from "react";
import {Footer} from "@/components/footer";
import {Header} from "@/components/header";
import {PrimaryNavigationMenu} from "@/components/primary-nav";
import {Providers} from "@/components/providers/providers";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "YeloBit", title: "YeloBit",
description: "Generated by create next app", description: "Generated by create next app",
icons: "yellow-bit.svg", icons: "yellow-bit.svg"};
};
export default function RootLayout({ export default function RootLayout({
children, children,
}: Readonly<{ }: Readonly<{
children: React.ReactNode; children: React.ReactNode;
}>) { }>) {
return ( return (
<html lang="en"> <html lang="en">
<head> <head>
<link rel="icon" href="/public/favicon.ico" sizes="any" /> <link rel="icon" href="/public/favicon.ico" sizes="any"/>
</head> </head>
<body className={"w-full min-h-screen flex flex-col items-center justify-between"}> <body className={"w-full min-h-screen flex flex-col items-center justify-between"}>
<Providers> <Providers>
<Header> <Header>
<PrimaryNavigationMenu /> <PrimaryNavigationMenu/>
</Header> </Header>
{children} {children}
<Footer /> <Footer/>
</Providers> </Providers>
</body> </body>
</html> </html>
); );
} }

View File

@ -1,9 +1,9 @@
import Image from "next/image"; import Image from "next/image";
export default function Home() { export default function Home() {
return ( return (
<main className="flex flex-col items-center justify-end h-full w-2/4"> <main className="flex flex-col items-center justify-end h-full w-2/4">
<h1>Hello world !</h1> <h1>Hello world !</h1>
</main> </main>
); );
} }

View File

@ -1,15 +1,16 @@
"use client"; "use client"
import {useContext} from "react";
import {UserDataContext} from "@/components/providers/userdata-provider";
import {AccountInfo} from "@/components/account-info";
import { AccountInfo } from "@/components/account-info";
import { UserDataContext } from "@/components/providers/userdata-provider";
import { useContext } from "react";
export function AccountDialog() { export function AccountDialog() {
const userContext = useContext(UserDataContext); const userContext = useContext(UserDataContext)
if (!userContext?.userData) { if (!userContext?.userData) {
userContext?.setUserData({ name: "Mathis" }); userContext?.setUserData({name: "Mathis"})
return <p>Loading...</p>; return (<p>Loading...</p>)
} }
//TODO No account context //TODO No account context
@ -17,5 +18,5 @@ export function AccountDialog() {
//TODO Loading context //TODO Loading context
//TODO Account context //TODO Account context
return <AccountInfo userData={userContext.userData} />; return (<AccountInfo userData={userContext.userData}/>)
} }

View File

@ -1,8 +1,9 @@
"use client"; "use client"
import { Button } from "@/components/ui/button"; import {IUserData} from "@/interfaces/userdata.interface";
import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { import {
Sheet, Sheet,
SheetClose, SheetClose,
@ -12,11 +13,11 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from "@/components/ui/sheet"; } from "@/components/ui/sheet"
import type { IUserData } from "@/interfaces/userdata.interface"; import {User} from "lucide-react";
import { User } from "lucide-react";
export function AccountInfo({ userData }: { userData: IUserData }) {
export function AccountInfo({userData}: {userData: IUserData}) {
return ( return (
<Sheet> <Sheet>
<SheetTrigger asChild> <SheetTrigger asChild>
@ -37,14 +38,7 @@ export function AccountInfo({ userData }: { userData: IUserData }) {
<Label htmlFor="name" className="text-right"> <Label htmlFor="name" className="text-right">
Name Name
</Label> </Label>
<Input <Input id="name" placeholder={userData.firstName} className="col-span-3" onChange={(event)=>{console.log(event.target.value)}} />
id="name"
placeholder={userData.firstName}
className="col-span-3"
onChange={(event) => {
console.log(event.target.value);
}}
/>
</div> </div>
<div className="grid grid-cols-4 items-center gap-4"> <div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="username" className="text-right"> <Label htmlFor="username" className="text-right">
@ -60,5 +54,5 @@ export function AccountInfo({ userData }: { userData: IUserData }) {
</SheetFooter> </SheetFooter>
</SheetContent> </SheetContent>
</Sheet> </Sheet>
); )
} }

View File

@ -1,59 +1,33 @@
import { Copyright } from "lucide-react"; import {Copyright} from "lucide-react";
import Link from "next/link"; import Link from "next/link";
export function Footer() { export function Footer() {
return ( return (
<footer <footer className={"flex flex-col-reverse md:flex-row justify-between gap-2 md:gap-1 items-center p-2 border-t-2 w-full"}>
className={ <div className={"flex flex-row gap-1 items-center justify-center md:justify-start md:w-1/3 opacity-50"}>
"flex flex-col-reverse md:flex-row justify-between gap-2 md:gap-1 items-center p-2 border-t-2 w-full" <Copyright className={"w-4"}/>
}
>
<div
className={
"flex flex-row gap-1 items-center justify-center md:justify-start md:w-1/3 opacity-50"
}
>
<Copyright className={"w-4"} />
<h4 className={"pr-2"}>Yidhra Studio</h4> <h4 className={"pr-2"}>Yidhra Studio</h4>
<p> <p>MIT <em>2024</em></p>
MIT <em>2024</em>
</p>
</div> </div>
<div <div className={"flex flex-col flex-wrap md:flex-row max-h-24 md:flex-nowrap gap-1 md:gap-2 items-center justify-evenly w-full md:w-1/3"}>
className={ <Link href={"#"} className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}>
"flex flex-col flex-wrap md:flex-row max-h-24 md:flex-nowrap gap-1 md:gap-2 items-center justify-evenly w-full md:w-1/3"
}
>
<Link
href={"#"}
className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}
>
<h3 className={"text-nowrap text-center"}>Data privacy</h3> <h3 className={"text-nowrap text-center"}>Data privacy</h3>
</Link> </Link>
<Link <Link href={"#"} className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}>
href={"#"}
className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}
>
<h3 className={"text-nowrap text-center"}>Terms and conditions</h3> <h3 className={"text-nowrap text-center"}>Terms and conditions</h3>
</Link> </Link>
<Link <Link href={"#"} className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}>
href={"#"}
className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}
>
<h3 className={"text-nowrap text-center"}>Legal notice</h3> <h3 className={"text-nowrap text-center"}>Legal notice</h3>
</Link> </Link>
<Link <Link href={"#"} className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}>
href={"#"}
className={"p-1 hover:-translate-y-1.5 hover:text-primary w-1/2"}
>
<h3 className={"text-nowrap text-center"}>Support Center</h3> <h3 className={"text-nowrap text-center"}>Support Center</h3>
</Link> </Link>
</div> </div>
<div <div className={"flex flex-row gap-1 items-center justify-center md:justify-end md:w-1/3"}>
className={ </div>
"flex flex-row gap-1 items-center justify-center md:justify-end md:w-1/3"
}
></div>
</footer> </footer>
); )
} }

View File

@ -1,33 +1,26 @@
import { AccountDialog } from "@/components/account-dialog";
import { ThemeBtnSelector } from "@/components/theme-btn-selector";
import Image from "next/image"; import Image from "next/image";
import type React from "react"; import React from "react";
import {ThemeBtnSelector} from "@/components/theme-btn-selector";
import {AccountDialog} from "@/components/account-dialog";
export function Header({title, children}: {title?: string, children?: React.ReactNode}) {
export function Header({
title,
children,
}: { title?: string; children?: React.ReactNode }) {
return ( return (
<header <header className={"flex flex-col md:flex-row justify-between items-center w-full p-1 md:px-3 md:py-2 border-b-2"}>
className={ <div className={"flex flex-row justify-center md:justify-start items-center gap-2 md:w-1/3"}>
"flex flex-col md:flex-row justify-between items-center w-full p-1 md:px-3 md:py-2 border-b-2" <Image src={'yellow-bit.svg'} alt={'Logo of YeloBit'} width={42} height={42}/>
} <h1 className={"font-bold text-xl align-middle text-center text-wrap"}>{title || 'YeloBit'}</h1>
> </div>
<div <div className={"w-1/3 flex flex-row justify-center items-center"}>
className={ {children}
"flex flex-row justify-center md:justify-start items-center gap-2 md:w-1/3"
}
>
<Image src={"yellow-bit.svg"} alt={"Logo of YeloBit"} width={42} height={42} />
<h1 className={"font-bold text-xl align-middle text-center text-wrap"}>
{title || "YeloBit"}
</h1>
</div> </div>
<div className={"w-1/3 flex flex-row justify-center items-center"}>{children}</div>
<div className={"w-1/3 flex flex-row justify-end gap-2 items-center"}> <div className={"w-1/3 flex flex-row justify-end gap-2 items-center"}>
<AccountDialog /> <AccountDialog/>
<ThemeBtnSelector /> <ThemeBtnSelector/>
</div> </div>
</header> </header>
); )
} }

View File

@ -1,8 +1,9 @@
"use client"; "use client"
import Link from "next/link"; import * as React from "react"
import * as React from "react"; import Link from "next/link"
import { cn } from "@/lib/utils"
import { import {
NavigationMenu, NavigationMenu,
NavigationMenuContent, NavigationMenuContent,
@ -11,10 +12,9 @@ import {
NavigationMenuList, NavigationMenuList,
NavigationMenuTrigger, NavigationMenuTrigger,
navigationMenuTriggerStyle, navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"; } from "@/components/ui/navigation-menu"
import { cn } from "@/lib/utils";
import { Boxes, Info } from "lucide-react";
import Image from "next/image"; import Image from "next/image";
import {Boxes, Info} from "lucide-react";
const components: { title: string; href: string; description: string }[] = [ const components: { title: string; href: string; description: string }[] = [
{ {
@ -26,7 +26,8 @@ const components: { title: string; href: string; description: string }[] = [
{ {
title: "Hover Card", title: "Hover Card",
href: "/docs/primitives/hover-card", href: "/docs/primitives/hover-card",
description: "For sighted users to preview content available behind a link.", description:
"For sighted users to preview content available behind a link.",
}, },
{ {
title: "Progress", title: "Progress",
@ -51,17 +52,14 @@ const components: { title: string; href: string; description: string }[] = [
description: description:
"A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.", "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
}, },
]; ]
export function PrimaryNavigationMenu() { export function PrimaryNavigationMenu() {
return ( return (
<NavigationMenu> <NavigationMenu>
<NavigationMenuList className={"flex flex-row flex-wrap md:flex-nowrap"}> <NavigationMenuList className={"flex flex-row flex-wrap md:flex-nowrap"}>
<NavigationMenuItem className={"relative"}> <NavigationMenuItem className={"relative"}>
<NavigationMenuTrigger className={"gap-1"}> <NavigationMenuTrigger className={"gap-1"}><Info className={"w-4"} />Getting started</NavigationMenuTrigger>
<Info className={"w-4"} />
Getting started
</NavigationMenuTrigger>
<NavigationMenuContent className={""}> <NavigationMenuContent className={""}>
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]"> <ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-3"> <li className="row-span-3">
@ -70,16 +68,14 @@ export function PrimaryNavigationMenu() {
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md" className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
href="/" href="/"
> >
<Image <Image src={'logo-red.svg'} alt={'Logo of Yidhra Studio'} width={64} height={64}/>
src={"logo-red.svg"} <div className="mb-2 mt-4 text-lg font-medium">
alt={"Logo of Yidhra Studio"} shadcn/ui
width={64} </div>
height={64}
/>
<div className="mb-2 mt-4 text-lg font-medium">shadcn/ui</div>
<p className="text-sm leading-tight text-muted-foreground"> <p className="text-sm leading-tight text-muted-foreground">
Beautifully designed components that you can copy and paste into Beautifully designed components that you can copy and
your apps. Accessible. Customizable. Open Source. paste into your apps. Accessible. Customizable. Open
Source.
</p> </p>
</a> </a>
</NavigationMenuLink> </NavigationMenuLink>
@ -97,10 +93,7 @@ export function PrimaryNavigationMenu() {
</NavigationMenuContent> </NavigationMenuContent>
</NavigationMenuItem> </NavigationMenuItem>
<NavigationMenuItem> <NavigationMenuItem>
<NavigationMenuTrigger className={"gap-1"}> <NavigationMenuTrigger className={"gap-1"}><Boxes className={"w-4"} />Features</NavigationMenuTrigger>
<Boxes className={"w-4"} />
Features
</NavigationMenuTrigger>
<NavigationMenuContent> <NavigationMenuContent>
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] "> <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ">
{components.map((component) => ( {components.map((component) => (
@ -124,7 +117,7 @@ export function PrimaryNavigationMenu() {
</NavigationMenuItem> </NavigationMenuItem>
</NavigationMenuList> </NavigationMenuList>
</NavigationMenu> </NavigationMenu>
); )
} }
const ListItem = React.forwardRef< const ListItem = React.forwardRef<
@ -138,7 +131,7 @@ const ListItem = React.forwardRef<
ref={ref} ref={ref}
className={cn( 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", "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, className
)} )}
{...props} {...props}
> >
@ -149,6 +142,6 @@ const ListItem = React.forwardRef<
</a> </a>
</NavigationMenuLink> </NavigationMenuLink>
</li> </li>
); )
}); })
ListItem.displayName = "ListItem"; ListItem.displayName = "ListItem"

View File

@ -1,14 +1,23 @@
"use client"; "use client"
import { Footer } from "@/components/footer"; import React from "react";
import { Header } from "@/components/header"; import {Header} from "@/components/header";
import { ThemeProvider } from "@/components/providers/theme-provider"; import {Footer} from "@/components/footer";
import { UserDataProvider } from "@/components/providers/userdata-provider"; import {ThemeProvider} from "@/components/providers/theme-provider";
import type React from "react"; import {UserDataProvider} from "@/components/providers/userdata-provider";
export function Providers({children}: { children: React.ReactNode }) {
export function Providers({ children }: { children: React.ReactNode }) {
return ( return (
<ThemeProvider attribute="class" defaultTheme="system" enableSystem> <ThemeProvider
<UserDataProvider>{children}</UserDataProvider> attribute="class"
defaultTheme="system"
enableSystem
>
<UserDataProvider>
{children}
</UserDataProvider>
</ThemeProvider> </ThemeProvider>
); )
} }

View File

@ -1,9 +1,9 @@
"use client"; "use client"
import { ThemeProvider as NextThemesProvider } from "next-themes"; import * as React from "react"
import type { ThemeProviderProps } from "next-themes/dist/types"; import { ThemeProvider as NextThemesProvider } from "next-themes"
import * as React from "react"; import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) { export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>; return <NextThemesProvider {...props}>{children}</NextThemesProvider>
} }

View File

@ -1,25 +1,21 @@
import type { IUserData } from "@/interfaces/userdata.interface"; import React from 'react';
import { useEncodedLocalStorage } from "@/services/localStorage"; import {IUserData} from "@/interfaces/userdata.interface";
import React from "react"; import {useEncodedLocalStorage} from "@/services/localStorage";
export interface IUserDataProvider { export interface IUserDataProvider {
userData: IUserData | undefined; userData: IUserData | undefined;
setUserData: React.Dispatch<React.SetStateAction<IUserData | undefined>>; setUserData: React.Dispatch<React.SetStateAction<IUserData | undefined>>
} }
export const UserDataContext = React.createContext<IUserDataProvider | undefined>( export const UserDataContext = React.createContext<IUserDataProvider | undefined>(undefined);
undefined,
); export const UserDataProvider = ({children}: {children: React.ReactNode}) => {
const [userData, setUserData] = useEncodedLocalStorage<IUserData | undefined>("user_data", undefined);
export const UserDataProvider = ({ children }: { children: React.ReactNode }) => {
const [userData, setUserData] = useEncodedLocalStorage<IUserData | undefined>(
"user_data",
undefined,
);
return ( return (
<UserDataContext.Provider value={{ userData, setUserData }}> <UserDataContext.Provider value={{userData, setUserData}}>
{children} {children}
</UserDataContext.Provider> </UserDataContext.Provider>
); );
}; };

View File

@ -1,19 +1,19 @@
"use client"; "use client"
import { MoonStar, Sun } from "lucide-react"; import * as React from "react"
import { useTheme } from "next-themes"; import {MoonStar, Sun} from "lucide-react";
import * as React from "react"; import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button"
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu"
export function ThemeBtnSelector() { export function ThemeBtnSelector() {
const { setTheme } = useTheme(); const { setTheme } = useTheme()
return ( return (
<DropdownMenu> <DropdownMenu>
@ -25,10 +25,16 @@ export function ThemeBtnSelector() {
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem> <DropdownMenuItem onClick={() => setTheme("light")}>
<DropdownMenuItem onClick={() => setTheme("dark")}>Dark</DropdownMenuItem> Light
<DropdownMenuItem onClick={() => setTheme("system")}>System</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
System
</DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
); )
} }

View File

@ -1,54 +1,58 @@
"use client"; "use client"
import * as AccordionPrimitive from "@radix-ui/react-accordion"; import * as React from "react"
import { ChevronDown } from "lucide-react"; import * as AccordionPrimitive from "@radix-ui/react-accordion"
import * as React from "react"; 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< const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>, React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} /> <AccordionPrimitive.Item
)); ref={ref}
AccordionItem.displayName = "AccordionItem"; className={cn("border-b", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
const AccordionTrigger = React.forwardRef< const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>, React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex"> <AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger <AccordionPrimitive.Trigger
ref={ref} ref={ref}
className={cn( className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180", "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} {children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger> </AccordionPrimitive.Trigger>
</AccordionPrimitive.Header> </AccordionPrimitive.Header>
)); ))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef< const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>, React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content <AccordionPrimitive.Content
ref={ref} ref={ref}
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" 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> <div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content> </AccordionPrimitive.Content>
)); ))
AccordionContent.displayName = AccordionPrimitive.Content.displayName; AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }

View File

@ -1,133 +1,141 @@
"use client"; "use client"
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; import * as React from "react"
import * as React from "react"; import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
import { buttonVariants } from "@/components/ui/button"; import { cn } from "@/lib/utils"
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< const AlertDialogOverlay = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Overlay>, React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay> React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Overlay <AlertDialogPrimitive.Overlay
className={cn( 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", "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} {...props}
ref={ref} ref={ref}
/> />
)); ))
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
const AlertDialogContent = React.forwardRef< const AlertDialogContent = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Content>, React.ElementRef<typeof AlertDialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AlertDialogPortal> <AlertDialogPortal>
<AlertDialogOverlay /> <AlertDialogOverlay />
<AlertDialogPrimitive.Content <AlertDialogPrimitive.Content
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
</AlertDialogPortal> </AlertDialogPortal>
)); ))
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
const AlertDialogHeader = ({ const AlertDialogHeader = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} className={cn(
{...props} "flex flex-col space-y-2 text-center sm:text-left",
/> className
); )}
AlertDialogHeader.displayName = "AlertDialogHeader"; {...props}
/>
)
AlertDialogHeader.displayName = "AlertDialogHeader"
const AlertDialogFooter = ({ const AlertDialogFooter = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn( className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className, className
)} )}
{...props} {...props}
/> />
); )
AlertDialogFooter.displayName = "AlertDialogFooter"; AlertDialogFooter.displayName = "AlertDialogFooter"
const AlertDialogTitle = React.forwardRef< const AlertDialogTitle = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Title>, React.ElementRef<typeof AlertDialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title> React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Title <AlertDialogPrimitive.Title
ref={ref} ref={ref}
className={cn("text-lg font-semibold", className)} className={cn("text-lg font-semibold", className)}
{...props} {...props}
/> />
)); ))
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
const AlertDialogDescription = React.forwardRef< const AlertDialogDescription = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Description>, React.ElementRef<typeof AlertDialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description> React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Description <AlertDialogPrimitive.Description
ref={ref} ref={ref}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)); ))
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; AlertDialogDescription.displayName =
AlertDialogPrimitive.Description.displayName
const AlertDialogAction = React.forwardRef< const AlertDialogAction = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Action>, React.ElementRef<typeof AlertDialogPrimitive.Action>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Action <AlertDialogPrimitive.Action
ref={ref} ref={ref}
className={cn(buttonVariants(), className)} className={cn(buttonVariants(), className)}
{...props} {...props}
/> />
)); ))
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
const AlertDialogCancel = React.forwardRef< const AlertDialogCancel = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Cancel>, React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel> React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Cancel <AlertDialogPrimitive.Cancel
ref={ref} ref={ref}
className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)} className={cn(
{...props} buttonVariants({ variant: "outline" }),
/> "mt-2 sm:mt-0",
)); className
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; )}
{...props}
/>
))
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
export { export {
AlertDialog, AlertDialog,
AlertDialogPortal, AlertDialogPortal,
AlertDialogOverlay, AlertDialogOverlay,
AlertDialogTrigger, AlertDialogTrigger,
AlertDialogContent, AlertDialogContent,
AlertDialogHeader, AlertDialogHeader,
AlertDialogFooter, AlertDialogFooter,
AlertDialogTitle, AlertDialogTitle,
AlertDialogDescription, AlertDialogDescription,
AlertDialogAction, AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
}; }

View File

@ -1,55 +1,59 @@
import { type VariantProps, cva } from "class-variance-authority"; import * as React from "react"
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( 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", "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",
{ {
variants: { variants: {
variant: { variant: {
default: "bg-background text-foreground", default: "bg-background text-foreground",
destructive: destructive:
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
}, },
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
}, },
}, }
); )
const Alert = React.forwardRef< const Alert = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants> React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
>(({ className, variant, ...props }, ref) => ( >(({ className, variant, ...props }, ref) => (
<div <div
ref={ref} ref={ref}
role="alert" role="alert"
className={cn(alertVariants({ variant }), className)} className={cn(alertVariants({ variant }), className)}
{...props} {...props}
/> />
)); ))
Alert.displayName = "Alert"; Alert.displayName = "Alert"
const AlertTitle = React.forwardRef< const AlertTitle = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement> React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<h5 <h5
ref={ref} ref={ref}
className={cn("mb-1 font-medium leading-none tracking-tight", className)} className={cn("mb-1 font-medium leading-none tracking-tight", className)}
{...props} {...props}
/> />
)); ))
AlertTitle.displayName = "AlertTitle"; AlertTitle.displayName = "AlertTitle"
const AlertDescription = React.forwardRef< const AlertDescription = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement> React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div ref={ref} className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} /> <div
)); ref={ref}
AlertDescription.displayName = "AlertDescription"; className={cn("text-sm [&_p]:leading-relaxed", className)}
{...props}
/>
))
AlertDescription.displayName = "AlertDescription"
export { Alert, AlertTitle, AlertDescription }; export { Alert, AlertTitle, AlertDescription }

View File

@ -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 }

View File

@ -1,50 +1,50 @@
"use client"; "use client"
import * as AvatarPrimitive from "@radix-ui/react-avatar"; import * as React from "react"
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< const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>, React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root> React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AvatarPrimitive.Root <AvatarPrimitive.Root
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className, className
)} )}
{...props} {...props}
/> />
)); ))
Avatar.displayName = AvatarPrimitive.Root.displayName; Avatar.displayName = AvatarPrimitive.Root.displayName
const AvatarImage = React.forwardRef< const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>, React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AvatarPrimitive.Image <AvatarPrimitive.Image
ref={ref} ref={ref}
className={cn("aspect-square h-full w-full", className)} className={cn("aspect-square h-full w-full", className)}
{...props} {...props}
/> />
)); ))
AvatarImage.displayName = AvatarPrimitive.Image.displayName; AvatarImage.displayName = AvatarPrimitive.Image.displayName
const AvatarFallback = React.forwardRef< const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>, React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback <AvatarPrimitive.Fallback
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted", "flex h-full w-full items-center justify-center rounded-full bg-muted",
className, className
)} )}
{...props} {...props}
/> />
)); ))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
export { Avatar, AvatarImage, AvatarFallback }; export { Avatar, AvatarImage, AvatarFallback }

View File

@ -1,34 +1,36 @@
import { type VariantProps, cva } from "class-variance-authority"; import * as React from "react"
import type * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const badgeVariants = cva( const badgeVariants = cva(
"inline-flex items-center rounded-full border 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", "inline-flex items-center rounded-full border 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",
{ {
variants: { variants: {
variant: { variant: {
default: default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80", "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary: secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive: destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground", outline: "text-foreground",
}, },
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
}, },
}, }
); )
export interface BadgeProps export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>, extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {} VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) { function Badge({ className, variant, ...props }: BadgeProps) {
return <div className={cn(badgeVariants({ variant }), className)} {...props} />; return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
} }
export { Badge, badgeVariants }; export { Badge, badgeVariants }

View File

@ -1,112 +1,115 @@
import { Slot } from "@radix-ui/react-slot"; import * as React from "react"
import { ChevronRight, MoreHorizontal } from "lucide-react"; import { Slot } from "@radix-ui/react-slot"
import * as React from "react"; import { ChevronRight, MoreHorizontal } from "lucide-react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const Breadcrumb = React.forwardRef< const Breadcrumb = React.forwardRef<
HTMLElement, HTMLElement,
React.ComponentPropsWithoutRef<"nav"> & { React.ComponentPropsWithoutRef<"nav"> & {
separator?: React.ReactNode; separator?: React.ReactNode
} }
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />); >(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
Breadcrumb.displayName = "Breadcrumb"; Breadcrumb.displayName = "Breadcrumb"
const BreadcrumbList = React.forwardRef< const BreadcrumbList = React.forwardRef<
HTMLOListElement, HTMLOListElement,
React.ComponentPropsWithoutRef<"ol"> React.ComponentPropsWithoutRef<"ol">
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ol <ol
ref={ref} ref={ref}
className={cn( className={cn(
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
className, className
)} )}
{...props} {...props}
/> />
)); ))
BreadcrumbList.displayName = "BreadcrumbList"; BreadcrumbList.displayName = "BreadcrumbList"
const BreadcrumbItem = React.forwardRef< const BreadcrumbItem = React.forwardRef<
HTMLLIElement, HTMLLIElement,
React.ComponentPropsWithoutRef<"li"> React.ComponentPropsWithoutRef<"li">
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<li <li
ref={ref} ref={ref}
className={cn("inline-flex items-center gap-1.5", className)} className={cn("inline-flex items-center gap-1.5", className)}
{...props} {...props}
/> />
)); ))
BreadcrumbItem.displayName = "BreadcrumbItem"; BreadcrumbItem.displayName = "BreadcrumbItem"
const BreadcrumbLink = React.forwardRef< const BreadcrumbLink = React.forwardRef<
HTMLAnchorElement, HTMLAnchorElement,
React.ComponentPropsWithoutRef<"a"> & { React.ComponentPropsWithoutRef<"a"> & {
asChild?: boolean; asChild?: boolean
} }
>(({ asChild, className, ...props }, ref) => { >(({ asChild, className, ...props }, ref) => {
const Comp = asChild ? Slot : "a"; const Comp = asChild ? Slot : "a"
return ( return (
<Comp <Comp
ref={ref} ref={ref}
className={cn("transition-colors hover:text-foreground", className)} className={cn("transition-colors hover:text-foreground", className)}
{...props} {...props}
/> />
); )
}); })
BreadcrumbLink.displayName = "BreadcrumbLink"; BreadcrumbLink.displayName = "BreadcrumbLink"
const BreadcrumbPage = React.forwardRef< const BreadcrumbPage = React.forwardRef<
HTMLSpanElement, HTMLSpanElement,
React.ComponentPropsWithoutRef<"span"> React.ComponentPropsWithoutRef<"span">
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<span <span
ref={ref} ref={ref}
role="link" role="link"
aria-disabled="true" aria-disabled="true"
aria-current="page" aria-current="page"
className={cn("font-normal text-foreground", className)} className={cn("font-normal text-foreground", className)}
{...props} {...props}
/> />
)); ))
BreadcrumbPage.displayName = "BreadcrumbPage"; BreadcrumbPage.displayName = "BreadcrumbPage"
const BreadcrumbSeparator = ({ const BreadcrumbSeparator = ({
children, children,
className, className,
...props ...props
}: React.ComponentProps<"li">) => ( }: React.ComponentProps<"li">) => (
<li <li
role="presentation" role="presentation"
aria-hidden="true" aria-hidden="true"
className={cn("[&>svg]:size-3.5", className)} className={cn("[&>svg]:size-3.5", className)}
{...props} {...props}
> >
{children ?? <ChevronRight />} {children ?? <ChevronRight />}
</li> </li>
); )
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"; BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => ( const BreadcrumbEllipsis = ({
<span className,
role="presentation" ...props
aria-hidden="true" }: React.ComponentProps<"span">) => (
className={cn("flex h-9 w-9 items-center justify-center", className)} <span
{...props} role="presentation"
> aria-hidden="true"
<MoreHorizontal className="h-4 w-4" /> className={cn("flex h-9 w-9 items-center justify-center", className)}
<span className="sr-only">More</span> {...props}
</span> >
); <MoreHorizontal className="h-4 w-4" />
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"; <span className="sr-only">More</span>
</span>
)
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
export { export {
Breadcrumb, Breadcrumb,
BreadcrumbList, BreadcrumbList,
BreadcrumbItem, BreadcrumbItem,
BreadcrumbLink, BreadcrumbLink,
BreadcrumbPage, BreadcrumbPage,
BreadcrumbSeparator, BreadcrumbSeparator,
BreadcrumbEllipsis, BreadcrumbEllipsis,
}; }

View File

@ -1,54 +1,56 @@
import { Slot } from "@radix-ui/react-slot"; import * as React from "react"
import { type VariantProps, cva } from "class-variance-authority"; import { Slot } from "@radix-ui/react-slot"
import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const buttonVariants = cva( const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{ {
variants: { variants: {
variant: { variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90", default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", destructive:
outline: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
"border border-input bg-background hover:bg-accent hover:text-accent-foreground", outline:
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
ghost: "hover:bg-accent hover:text-accent-foreground", secondary:
link: "text-primary underline-offset-4 hover:underline", "bg-secondary text-secondary-foreground hover:bg-secondary/80",
}, ghost: "hover:bg-accent hover:text-accent-foreground",
size: { link: "text-primary underline-offset-4 hover:underline",
default: "h-10 px-4 py-2", },
sm: "h-9 rounded-md px-3", size: {
lg: "h-11 rounded-md px-8", default: "h-10 px-4 py-2",
icon: "h-10 w-10", sm: "h-9 rounded-md px-3",
}, lg: "h-11 rounded-md px-8",
}, icon: "h-10 w-10",
defaultVariants: { },
variant: "default", },
size: "default", defaultVariants: {
}, variant: "default",
}, size: "default",
); },
}
)
export interface ButtonProps export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>, extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> { VariantProps<typeof buttonVariants> {
asChild?: boolean; asChild?: boolean
} }
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => { ({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"; const Comp = asChild ? Slot : "button"
return ( return (
<Comp <Comp
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}
ref={ref} ref={ref}
{...props} {...props}
/> />
); )
}, }
); )
Button.displayName = "Button"; Button.displayName = "Button"
export { Button, buttonVariants }; export { Button, buttonVariants }

View File

@ -1,64 +1,66 @@
"use client"; "use client"
import { ChevronLeft, ChevronRight } from "lucide-react"; import * as React from "react"
import type * as React from "react"; import { ChevronLeft, ChevronRight } from "lucide-react"
import { DayPicker } from "react-day-picker"; import { DayPicker } from "react-day-picker"
import { buttonVariants } from "@/components/ui/button"; import { cn } from "@/lib/utils"
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({ function Calendar({
className, className,
classNames, classNames,
showOutsideDays = true, showOutsideDays = true,
...props ...props
}: CalendarProps) { }: CalendarProps) {
return ( return (
<DayPicker <DayPicker
showOutsideDays={showOutsideDays} showOutsideDays={showOutsideDays}
className={cn("p-3", className)} className={cn("p-3", className)}
classNames={{ classNames={{
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0", months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
month: "space-y-4", month: "space-y-4",
caption: "flex justify-center pt-1 relative items-center", caption: "flex justify-center pt-1 relative items-center",
caption_label: "text-sm font-medium", caption_label: "text-sm font-medium",
nav: "space-x-1 flex items-center", nav: "space-x-1 flex items-center",
nav_button: cn( nav_button: cn(
buttonVariants({ variant: "outline" }), 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_previous: "absolute left-1",
nav_button_next: "absolute right-1", nav_button_next: "absolute right-1",
table: "w-full border-collapse space-y-1", table: "w-full border-collapse space-y-1",
head_row: "flex", head_row: "flex",
head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", head_cell:
row: "flex w-full mt-2", "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
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", row: "flex w-full mt-2",
day: cn( 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",
buttonVariants({ variant: "ghost" }), day: cn(
"h-9 w-9 p-0 font-normal aria-selected:opacity-100", buttonVariants({ variant: "ghost" }),
), "h-9 w-9 p-0 font-normal aria-selected:opacity-100"
day_range_end: "day-range-end", ),
day_selected: day_range_end: "day-range-end",
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", day_selected:
day_today: "bg-accent text-accent-foreground", "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_outside: day_today: "bg-accent text-accent-foreground",
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30", day_outside:
day_disabled: "text-muted-foreground opacity-50", "day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground", day_disabled: "text-muted-foreground opacity-50",
day_hidden: "invisible", day_range_middle:
...classNames, "aria-selected:bg-accent aria-selected:text-accent-foreground",
}} day_hidden: "invisible",
components={{ ...classNames,
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />, }}
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />, components={{
}} IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />,
{...props} IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />,
/> }}
); {...props}
/>
)
} }
Calendar.displayName = "Calendar"; Calendar.displayName = "Calendar"
export { Calendar }; export { Calendar }

View File

@ -1,65 +1,79 @@
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>>( const Card = React.forwardRef<
({ className, ...props }, ref) => ( HTMLDivElement,
<div React.HTMLAttributes<HTMLDivElement>
ref={ref} >(({ className, ...props }, ref) => (
className={cn( <div
"rounded-lg border bg-card text-card-foreground shadow-sm", ref={ref}
className, className={cn(
)} "rounded-lg border bg-card text-card-foreground shadow-sm",
{...props} className
/> )}
), {...props}
); />
Card.displayName = "Card"; ))
Card.displayName = "Card"
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( const CardHeader = React.forwardRef<
({ className, ...props }, ref) => ( HTMLDivElement,
<div React.HTMLAttributes<HTMLDivElement>
ref={ref} >(({ className, ...props }, ref) => (
className={cn("flex flex-col space-y-1.5 p-6", className)} <div
{...props} 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< const CardTitle = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement> React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<h3 <h3
ref={ref} ref={ref}
className={cn("text-2xl font-semibold leading-none tracking-tight", className)} className={cn(
{...props} "text-2xl font-semibold leading-none tracking-tight",
/> className
)); )}
CardTitle.displayName = "CardTitle"; {...props}
/>
))
CardTitle.displayName = "CardTitle"
const CardDescription = React.forwardRef< const CardDescription = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement> React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> <p
)); ref={ref}
CardDescription.displayName = "CardDescription"; className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"
const CardContent = React.forwardRef< const CardContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} /> <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
)); ))
CardContent.displayName = "CardContent"; CardContent.displayName = "CardContent"
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( const CardFooter = React.forwardRef<
({ className, ...props }, ref) => ( HTMLDivElement,
<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} /> React.HTMLAttributes<HTMLDivElement>
), >(({ className, ...props }, ref) => (
); <div
CardFooter.displayName = "CardFooter"; ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

View File

@ -1,251 +1,262 @@
"use client"; "use client"
import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react"; import * as React from "react"
import { ArrowLeft, ArrowRight } from "lucide-react"; import useEmblaCarousel, {
import * as React from "react"; type UseEmblaCarouselType,
} from "embla-carousel-react"
import { ArrowLeft, ArrowRight } from "lucide-react"
import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"
type CarouselApi = UseEmblaCarouselType[1]; type CarouselApi = UseEmblaCarouselType[1]
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>; type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
type CarouselOptions = UseCarouselParameters[0]; type CarouselOptions = UseCarouselParameters[0]
type CarouselPlugin = UseCarouselParameters[1]; type CarouselPlugin = UseCarouselParameters[1]
type CarouselProps = { type CarouselProps = {
opts?: CarouselOptions; opts?: CarouselOptions
plugins?: CarouselPlugin; plugins?: CarouselPlugin
orientation?: "horizontal" | "vertical"; orientation?: "horizontal" | "vertical"
setApi?: (api: CarouselApi) => void; setApi?: (api: CarouselApi) => void
}; }
type CarouselContextProps = { type CarouselContextProps = {
carouselRef: ReturnType<typeof useEmblaCarousel>[0]; carouselRef: ReturnType<typeof useEmblaCarousel>[0]
api: ReturnType<typeof useEmblaCarousel>[1]; api: ReturnType<typeof useEmblaCarousel>[1]
scrollPrev: () => void; scrollPrev: () => void
scrollNext: () => void; scrollNext: () => void
canScrollPrev: boolean; canScrollPrev: boolean
canScrollNext: boolean; canScrollNext: boolean
} & CarouselProps; } & CarouselProps
const CarouselContext = React.createContext<CarouselContextProps | null>(null); const CarouselContext = React.createContext<CarouselContextProps | null>(null)
function useCarousel() { function useCarousel() {
const context = React.useContext(CarouselContext); const context = React.useContext(CarouselContext)
if (!context) { 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< const Carousel = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & CarouselProps React.HTMLAttributes<HTMLDivElement> & CarouselProps
>( >(
( (
{ orientation = "horizontal", opts, setApi, plugins, className, children, ...props }, {
ref, orientation = "horizontal",
) => { opts,
const [carouselRef, api] = useEmblaCarousel( setApi,
{ plugins,
...opts, className,
axis: orientation === "horizontal" ? "x" : "y", children,
}, ...props
plugins, },
); ref
const [canScrollPrev, setCanScrollPrev] = React.useState(false); ) => {
const [canScrollNext, setCanScrollNext] = React.useState(false); 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) => { const onSelect = React.useCallback((api: CarouselApi) => {
if (!api) { if (!api) {
return; return
} }
setCanScrollPrev(api.canScrollPrev()); setCanScrollPrev(api.canScrollPrev())
setCanScrollNext(api.canScrollNext()); setCanScrollNext(api.canScrollNext())
}, []); }, [])
const scrollPrev = React.useCallback(() => { const scrollPrev = React.useCallback(() => {
api?.scrollPrev(); api?.scrollPrev()
}, [api]); }, [api])
const scrollNext = React.useCallback(() => { const scrollNext = React.useCallback(() => {
api?.scrollNext(); api?.scrollNext()
}, [api]); }, [api])
const handleKeyDown = React.useCallback( const handleKeyDown = React.useCallback(
(event: React.KeyboardEvent<HTMLDivElement>) => { (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "ArrowLeft") { if (event.key === "ArrowLeft") {
event.preventDefault(); event.preventDefault()
scrollPrev(); scrollPrev()
} else if (event.key === "ArrowRight") { } else if (event.key === "ArrowRight") {
event.preventDefault(); event.preventDefault()
scrollNext(); scrollNext()
} }
}, },
[scrollPrev, scrollNext], [scrollPrev, scrollNext]
); )
React.useEffect(() => { React.useEffect(() => {
if (!api || !setApi) { if (!api || !setApi) {
return; return
} }
setApi(api); setApi(api)
}, [api, setApi]); }, [api, setApi])
React.useEffect(() => { React.useEffect(() => {
if (!api) { if (!api) {
return; return
} }
onSelect(api); onSelect(api)
api.on("reInit", onSelect); api.on("reInit", onSelect)
api.on("select", onSelect); api.on("select", onSelect)
return () => { return () => {
api?.off("select", onSelect); api?.off("select", onSelect)
}; }
}, [api, onSelect]); }, [api, onSelect])
return ( return (
<CarouselContext.Provider <CarouselContext.Provider
value={{ value={{
carouselRef, carouselRef,
api: api, api: api,
opts, opts,
orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), orientation:
scrollPrev, orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
scrollNext, scrollPrev,
canScrollPrev, scrollNext,
canScrollNext, canScrollPrev,
}} canScrollNext,
> }}
<div >
ref={ref} <div
onKeyDownCapture={handleKeyDown} ref={ref}
className={cn("relative", className)} onKeyDownCapture={handleKeyDown}
role="region" className={cn("relative", className)}
aria-roledescription="carousel" role="region"
{...props} aria-roledescription="carousel"
> {...props}
{children} >
</div> {children}
</CarouselContext.Provider> </div>
); </CarouselContext.Provider>
}, )
); }
Carousel.displayName = "Carousel"; )
Carousel.displayName = "Carousel"
const CarouselContent = React.forwardRef< const CarouselContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
const { carouselRef, orientation } = useCarousel(); const { carouselRef, orientation } = useCarousel()
return ( return (
<div ref={carouselRef} className="overflow-hidden"> <div ref={carouselRef} className="overflow-hidden">
<div <div
ref={ref} ref={ref}
className={cn( className={cn(
"flex", "flex",
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
className, className
)} )}
{...props} {...props}
/> />
</div> </div>
); )
}); })
CarouselContent.displayName = "CarouselContent"; CarouselContent.displayName = "CarouselContent"
const CarouselItem = React.forwardRef< const CarouselItem = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
const { orientation } = useCarousel(); const { orientation } = useCarousel()
return ( return (
<div <div
ref={ref} ref={ref}
role="group" role="group"
aria-roledescription="slide" aria-roledescription="slide"
className={cn( className={cn(
"min-w-0 shrink-0 grow-0 basis-full", "min-w-0 shrink-0 grow-0 basis-full",
orientation === "horizontal" ? "pl-4" : "pt-4", orientation === "horizontal" ? "pl-4" : "pt-4",
className, className
)} )}
{...props} {...props}
/> />
); )
}); })
CarouselItem.displayName = "CarouselItem"; CarouselItem.displayName = "CarouselItem"
const CarouselPrevious = React.forwardRef< const CarouselPrevious = React.forwardRef<
HTMLButtonElement, HTMLButtonElement,
React.ComponentProps<typeof Button> React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => { >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
const { orientation, scrollPrev, canScrollPrev } = useCarousel(); const { orientation, scrollPrev, canScrollPrev } = useCarousel()
return ( return (
<Button <Button
ref={ref} ref={ref}
variant={variant} variant={variant}
size={size} size={size}
className={cn( className={cn(
"absolute h-8 w-8 rounded-full", "absolute h-8 w-8 rounded-full",
orientation === "horizontal" orientation === "horizontal"
? "-left-12 top-1/2 -translate-y-1/2" ? "-left-12 top-1/2 -translate-y-1/2"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90", : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
className, className
)} )}
disabled={!canScrollPrev} disabled={!canScrollPrev}
onClick={scrollPrev} onClick={scrollPrev}
{...props} {...props}
> >
<ArrowLeft className="h-4 w-4" /> <ArrowLeft className="h-4 w-4" />
<span className="sr-only">Previous slide</span> <span className="sr-only">Previous slide</span>
</Button> </Button>
); )
}); })
CarouselPrevious.displayName = "CarouselPrevious"; CarouselPrevious.displayName = "CarouselPrevious"
const CarouselNext = React.forwardRef< const CarouselNext = React.forwardRef<
HTMLButtonElement, HTMLButtonElement,
React.ComponentProps<typeof Button> React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => { >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
const { orientation, scrollNext, canScrollNext } = useCarousel(); const { orientation, scrollNext, canScrollNext } = useCarousel()
return ( return (
<Button <Button
ref={ref} ref={ref}
variant={variant} variant={variant}
size={size} size={size}
className={cn( className={cn(
"absolute h-8 w-8 rounded-full", "absolute h-8 w-8 rounded-full",
orientation === "horizontal" orientation === "horizontal"
? "-right-12 top-1/2 -translate-y-1/2" ? "-right-12 top-1/2 -translate-y-1/2"
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
className, className
)} )}
disabled={!canScrollNext} disabled={!canScrollNext}
onClick={scrollNext} onClick={scrollNext}
{...props} {...props}
> >
<ArrowRight className="h-4 w-4" /> <ArrowRight className="h-4 w-4" />
<span className="sr-only">Next slide</span> <span className="sr-only">Next slide</span>
</Button> </Button>
); )
}); })
CarouselNext.displayName = "CarouselNext"; CarouselNext.displayName = "CarouselNext"
export { export {
type CarouselApi, type CarouselApi,
Carousel, Carousel,
CarouselContent, CarouselContent,
CarouselItem, CarouselItem,
CarouselPrevious, CarouselPrevious,
CarouselNext, CarouselNext,
}; }

View File

@ -1,30 +1,30 @@
"use client"; "use client"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; import * as React from "react"
import { Check } from "lucide-react"; import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import * as React from "react"; import { Check } from "lucide-react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const Checkbox = React.forwardRef< const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>, React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root <CheckboxPrimitive.Root
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
> >
<CheckboxPrimitive.Indicator <CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")} className={cn("flex items-center justify-center text-current")}
> >
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</CheckboxPrimitive.Indicator> </CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root> </CheckboxPrimitive.Root>
)); ))
Checkbox.displayName = CheckboxPrimitive.Root.displayName; Checkbox.displayName = CheckboxPrimitive.Root.displayName
export { Checkbox }; export { Checkbox }

View File

@ -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 }

View File

@ -1,148 +1,155 @@
"use client"; "use client"
import type { DialogProps } from "@radix-ui/react-dialog"; import * as React from "react"
import { Command as CommandPrimitive } from "cmdk"; import { type DialogProps } from "@radix-ui/react-dialog"
import { Search } from "lucide-react"; import { Command as CommandPrimitive } from "cmdk"
import * as React from "react"; import { Search } from "lucide-react"
import { Dialog, DialogContent } from "@/components/ui/dialog"; import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils"; import { Dialog, DialogContent } from "@/components/ui/dialog"
const Command = React.forwardRef< const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>, React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive> React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<CommandPrimitive <CommandPrimitive
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className, className
)} )}
{...props} {...props}
/> />
)); ))
Command.displayName = CommandPrimitive.displayName; Command.displayName = CommandPrimitive.displayName
interface CommandDialogProps extends DialogProps {} interface CommandDialogProps extends DialogProps {}
const CommandDialog = ({ children, ...props }: CommandDialogProps) => { const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
return ( return (
<Dialog {...props}> <Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-lg"> <DialogContent className="overflow-hidden p-0 shadow-lg">
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"> <Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
{children} {children}
</Command> </Command>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); )
}; }
const CommandInput = React.forwardRef< const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>, React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper=""> <div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" /> <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input <CommandPrimitive.Input
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
</div> </div>
)); ))
CommandInput.displayName = CommandPrimitive.Input.displayName; CommandInput.displayName = CommandPrimitive.Input.displayName
const CommandList = React.forwardRef< const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>, React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List> React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<CommandPrimitive.List <CommandPrimitive.List
ref={ref} ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
{...props} {...props}
/> />
)); ))
CommandList.displayName = CommandPrimitive.List.displayName; CommandList.displayName = CommandPrimitive.List.displayName
const CommandEmpty = React.forwardRef< const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>, React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => ( >((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< const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>, React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group> React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<CommandPrimitive.Group <CommandPrimitive.Group
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
CommandGroup.displayName = CommandPrimitive.Group.displayName; CommandGroup.displayName = CommandPrimitive.Group.displayName
const CommandSeparator = React.forwardRef< const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>, React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator> React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<CommandPrimitive.Separator <CommandPrimitive.Separator
ref={ref} ref={ref}
className={cn("-mx-1 h-px bg-border", className)} className={cn("-mx-1 h-px bg-border", className)}
{...props} {...props}
/> />
)); ))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName; CommandSeparator.displayName = CommandPrimitive.Separator.displayName
const CommandItem = React.forwardRef< const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>, React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item> React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<CommandPrimitive.Item <CommandPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex cursor-default 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", "relative flex cursor-default 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",
className, className
)} )}
{...props} {...props}
/> />
)); ))
CommandItem.displayName = CommandPrimitive.Item.displayName; CommandItem.displayName = CommandPrimitive.Item.displayName
const CommandShortcut = ({ const CommandShortcut = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLSpanElement>) => { }: React.HTMLAttributes<HTMLSpanElement>) => {
return ( return (
<span <span
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} className={cn(
{...props} "ml-auto text-xs tracking-widest text-muted-foreground",
/> className
); )}
}; {...props}
CommandShortcut.displayName = "CommandShortcut"; />
)
}
CommandShortcut.displayName = "CommandShortcut"
export { export {
Command, Command,
CommandDialog, CommandDialog,
CommandInput, CommandInput,
CommandList, CommandList,
CommandEmpty, CommandEmpty,
CommandGroup, CommandGroup,
CommandItem, CommandItem,
CommandShortcut, CommandShortcut,
CommandSeparator, CommandSeparator,
}; }

View File

@ -1,196 +1,200 @@
"use client"; "use client"
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"; import * as React from "react"
import { Check, ChevronRight, Circle } from "lucide-react"; import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
import * as React from "react"; 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< const ContextMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>, React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & { React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, children, ...props }, ref) => ( >(({ className, inset, children, ...props }, ref) => (
<ContextMenuPrimitive.SubTrigger <ContextMenuPrimitive.SubTrigger
ref={ref} ref={ref}
className={cn( 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", "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", inset && "pl-8",
className, className
)} )}
{...props} {...props}
> >
{children} {children}
<ChevronRight className="ml-auto h-4 w-4" /> <ChevronRight className="ml-auto h-4 w-4" />
</ContextMenuPrimitive.SubTrigger> </ContextMenuPrimitive.SubTrigger>
)); ))
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName; ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
const ContextMenuSubContent = React.forwardRef< const ContextMenuSubContent = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.SubContent>, React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent> React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ContextMenuPrimitive.SubContent <ContextMenuPrimitive.SubContent
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName; ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
const ContextMenuContent = React.forwardRef< const ContextMenuContent = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.Content>, React.ElementRef<typeof ContextMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content> React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ContextMenuPrimitive.Portal> <ContextMenuPrimitive.Portal>
<ContextMenuPrimitive.Content <ContextMenuPrimitive.Content
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
</ContextMenuPrimitive.Portal> </ContextMenuPrimitive.Portal>
)); ))
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName; ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
const ContextMenuItem = React.forwardRef< const ContextMenuItem = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.Item>, React.ElementRef<typeof ContextMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & { React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, ...props }, ref) => ( >(({ className, inset, ...props }, ref) => (
<ContextMenuPrimitive.Item <ContextMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( 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", "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", inset && "pl-8",
className, className
)} )}
{...props} {...props}
/> />
)); ))
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName; ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
const ContextMenuCheckboxItem = React.forwardRef< const ContextMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>, React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem> React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => ( >(({ className, children, checked, ...props }, ref) => (
<ContextMenuPrimitive.CheckboxItem <ContextMenuPrimitive.CheckboxItem
ref={ref} ref={ref}
className={cn( 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", "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} checked={checked}
{...props} {...props}
> >
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuPrimitive.ItemIndicator> <ContextMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</ContextMenuPrimitive.ItemIndicator> </ContextMenuPrimitive.ItemIndicator>
</span> </span>
{children} {children}
</ContextMenuPrimitive.CheckboxItem> </ContextMenuPrimitive.CheckboxItem>
)); ))
ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName; ContextMenuCheckboxItem.displayName =
ContextMenuPrimitive.CheckboxItem.displayName
const ContextMenuRadioItem = React.forwardRef< const ContextMenuRadioItem = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>, React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem> React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<ContextMenuPrimitive.RadioItem <ContextMenuPrimitive.RadioItem
ref={ref} ref={ref}
className={cn( 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", "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"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuPrimitive.ItemIndicator> <ContextMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" /> <Circle className="h-2 w-2 fill-current" />
</ContextMenuPrimitive.ItemIndicator> </ContextMenuPrimitive.ItemIndicator>
</span> </span>
{children} {children}
</ContextMenuPrimitive.RadioItem> </ContextMenuPrimitive.RadioItem>
)); ))
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName; ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
const ContextMenuLabel = React.forwardRef< const ContextMenuLabel = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.Label>, React.ElementRef<typeof ContextMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & { React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, ...props }, ref) => ( >(({ className, inset, ...props }, ref) => (
<ContextMenuPrimitive.Label <ContextMenuPrimitive.Label
ref={ref} ref={ref}
className={cn( className={cn(
"px-2 py-1.5 text-sm font-semibold text-foreground", "px-2 py-1.5 text-sm font-semibold text-foreground",
inset && "pl-8", inset && "pl-8",
className, className
)} )}
{...props} {...props}
/> />
)); ))
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName; ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
const ContextMenuSeparator = React.forwardRef< const ContextMenuSeparator = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.Separator>, React.ElementRef<typeof ContextMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator> React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ContextMenuPrimitive.Separator <ContextMenuPrimitive.Separator
ref={ref} ref={ref}
className={cn("-mx-1 my-1 h-px bg-border", className)} className={cn("-mx-1 my-1 h-px bg-border", className)}
{...props} {...props}
/> />
)); ))
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName; ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
const ContextMenuShortcut = ({ const ContextMenuShortcut = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLSpanElement>) => { }: React.HTMLAttributes<HTMLSpanElement>) => {
return ( return (
<span <span
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} className={cn(
{...props} "ml-auto text-xs tracking-widest text-muted-foreground",
/> className
); )}
}; {...props}
ContextMenuShortcut.displayName = "ContextMenuShortcut"; />
)
}
ContextMenuShortcut.displayName = "ContextMenuShortcut"
export { export {
ContextMenu, ContextMenu,
ContextMenuTrigger, ContextMenuTrigger,
ContextMenuContent, ContextMenuContent,
ContextMenuItem, ContextMenuItem,
ContextMenuCheckboxItem, ContextMenuCheckboxItem,
ContextMenuRadioItem, ContextMenuRadioItem,
ContextMenuLabel, ContextMenuLabel,
ContextMenuSeparator, ContextMenuSeparator,
ContextMenuShortcut, ContextMenuShortcut,
ContextMenuGroup, ContextMenuGroup,
ContextMenuPortal, ContextMenuPortal,
ContextMenuSub, ContextMenuSub,
ContextMenuSubContent, ContextMenuSubContent,
ContextMenuSubTrigger, ContextMenuSubTrigger,
ContextMenuRadioGroup, ContextMenuRadioGroup,
}; }

View File

@ -1,110 +1,122 @@
"use client"; "use client"
import * as DialogPrimitive from "@radix-ui/react-dialog"; import * as React from "react"
import { X } from "lucide-react"; import * as DialogPrimitive from "@radix-ui/react-dialog"
import * as React from "react"; 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< const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>, React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay <DialogPrimitive.Overlay
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
const DialogContent = React.forwardRef< const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>, React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<DialogPortal> <DialogPortal>
<DialogOverlay /> <DialogOverlay />
<DialogPrimitive.Content <DialogPrimitive.Content
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
> >
{children} {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"> <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" /> <X className="h-4 w-4" />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</DialogPrimitive.Close> </DialogPrimitive.Close>
</DialogPrimitive.Content> </DialogPrimitive.Content>
</DialogPortal> </DialogPortal>
)); ))
DialogContent.displayName = DialogPrimitive.Content.displayName; DialogContent.displayName = DialogPrimitive.Content.displayName
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const DialogHeader = ({
<div className,
className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} ...props
{...props} }: React.HTMLAttributes<HTMLDivElement>) => (
/> <div
); className={cn(
DialogHeader.displayName = "DialogHeader"; "flex flex-col space-y-1.5 text-center sm:text-left",
className
)}
{...props}
/>
)
DialogHeader.displayName = "DialogHeader"
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const DialogFooter = ({
<div className,
className={cn( ...props
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", }: React.HTMLAttributes<HTMLDivElement>) => (
className, <div
)} className={cn(
{...props} "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
/> className
); )}
DialogFooter.displayName = "DialogFooter"; {...props}
/>
)
DialogFooter.displayName = "DialogFooter"
const DialogTitle = React.forwardRef< const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>, React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DialogPrimitive.Title <DialogPrimitive.Title
ref={ref} ref={ref}
className={cn("text-lg font-semibold leading-none tracking-tight", className)} className={cn(
{...props} "text-lg font-semibold leading-none tracking-tight",
/> className
)); )}
DialogTitle.displayName = DialogPrimitive.Title.displayName; {...props}
/>
))
DialogTitle.displayName = DialogPrimitive.Title.displayName
const DialogDescription = React.forwardRef< const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>, React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DialogPrimitive.Description <DialogPrimitive.Description
ref={ref} ref={ref}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)); ))
DialogDescription.displayName = DialogPrimitive.Description.displayName; DialogDescription.displayName = DialogPrimitive.Description.displayName
export { export {
Dialog, Dialog,
DialogPortal, DialogPortal,
DialogOverlay, DialogOverlay,
DialogClose, DialogClose,
DialogTrigger, DialogTrigger,
DialogContent, DialogContent,
DialogHeader, DialogHeader,
DialogFooter, DialogFooter,
DialogTitle, DialogTitle,
DialogDescription, DialogDescription,
}; }

View File

@ -1,103 +1,118 @@
"use client"; "use client"
import * as React from "react"; import * as React from "react"
import { Drawer as DrawerPrimitive } from "vaul"; import { Drawer as DrawerPrimitive } from "vaul"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const Drawer = ({ const Drawer = ({
shouldScaleBackground = true, shouldScaleBackground = true,
...props ...props
}: React.ComponentProps<typeof DrawerPrimitive.Root>) => ( }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
<DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} /> <DrawerPrimitive.Root
); shouldScaleBackground={shouldScaleBackground}
Drawer.displayName = "Drawer"; {...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< const DrawerOverlay = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Overlay>, React.ElementRef<typeof DrawerPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay> React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DrawerPrimitive.Overlay <DrawerPrimitive.Overlay
ref={ref} ref={ref}
className={cn("fixed inset-0 z-50 bg-black/80", className)} className={cn("fixed inset-0 z-50 bg-black/80", className)}
{...props} {...props}
/> />
)); ))
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName; DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
const DrawerContent = React.forwardRef< const DrawerContent = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Content>, React.ElementRef<typeof DrawerPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content> React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<DrawerPortal> <DrawerPortal>
<DrawerOverlay /> <DrawerOverlay />
<DrawerPrimitive.Content <DrawerPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background", "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" /> <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
{children} {children}
</DrawerPrimitive.Content> </DrawerPrimitive.Content>
</DrawerPortal> </DrawerPortal>
)); ))
DrawerContent.displayName = "DrawerContent"; DrawerContent.displayName = "DrawerContent"
const DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const DrawerHeader = ({
<div className,
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} ...props
{...props} }: React.HTMLAttributes<HTMLDivElement>) => (
/> <div
); className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
DrawerHeader.displayName = "DrawerHeader"; {...props}
/>
)
DrawerHeader.displayName = "DrawerHeader"
const DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const DrawerFooter = ({
<div className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} /> className,
); ...props
DrawerFooter.displayName = "DrawerFooter"; }: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props}
/>
)
DrawerFooter.displayName = "DrawerFooter"
const DrawerTitle = React.forwardRef< const DrawerTitle = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Title>, React.ElementRef<typeof DrawerPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title> React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DrawerPrimitive.Title <DrawerPrimitive.Title
ref={ref} ref={ref}
className={cn("text-lg font-semibold leading-none tracking-tight", className)} className={cn(
{...props} "text-lg font-semibold leading-none tracking-tight",
/> className
)); )}
DrawerTitle.displayName = DrawerPrimitive.Title.displayName; {...props}
/>
))
DrawerTitle.displayName = DrawerPrimitive.Title.displayName
const DrawerDescription = React.forwardRef< const DrawerDescription = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Description>, React.ElementRef<typeof DrawerPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description> React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DrawerPrimitive.Description <DrawerPrimitive.Description
ref={ref} ref={ref}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)); ))
DrawerDescription.displayName = DrawerPrimitive.Description.displayName; DrawerDescription.displayName = DrawerPrimitive.Description.displayName
export { export {
Drawer, Drawer,
DrawerPortal, DrawerPortal,
DrawerOverlay, DrawerOverlay,
DrawerTrigger, DrawerTrigger,
DrawerClose, DrawerClose,
DrawerContent, DrawerContent,
DrawerHeader, DrawerHeader,
DrawerFooter, DrawerFooter,
DrawerTitle, DrawerTitle,
DrawerDescription, DrawerDescription,
}; }

View File

@ -1,193 +1,200 @@
"use client"; "use client"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; import * as React from "react"
import { Check, ChevronRight, Circle } from "lucide-react"; import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import * as React from "react"; 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< const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>, React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & { React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, children, ...props }, ref) => ( >(({ className, inset, children, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger <DropdownMenuPrimitive.SubTrigger
ref={ref} ref={ref}
className={cn( className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent", "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8", inset && "pl-8",
className, className
)} )}
{...props} {...props}
> >
{children} {children}
<ChevronRight className="ml-auto h-4 w-4" /> <ChevronRight className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger> </DropdownMenuPrimitive.SubTrigger>
)); ))
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName
const DropdownMenuSubContent = React.forwardRef< const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>, React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent> React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent <DropdownMenuPrimitive.SubContent
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName
const DropdownMenuContent = React.forwardRef< const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>, React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => ( >(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal> <DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content <DropdownMenuPrimitive.Content
ref={ref} ref={ref}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( 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", "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} {...props}
/> />
</DropdownMenuPrimitive.Portal> </DropdownMenuPrimitive.Portal>
)); ))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
const DropdownMenuItem = React.forwardRef< const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>, React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, ...props }, ref) => ( >(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item <DropdownMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex cursor-default select-none items-center 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", "relative flex cursor-default select-none items-center 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",
inset && "pl-8", inset && "pl-8",
className, className
)} )}
{...props} {...props}
/> />
)); ))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
const DropdownMenuCheckboxItem = React.forwardRef< const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>, React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem> React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => ( >(({ className, children, checked, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem <DropdownMenuPrimitive.CheckboxItem
ref={ref} ref={ref}
className={cn( 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", "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} checked={checked}
{...props} {...props}
> >
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator> <DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator> </DropdownMenuPrimitive.ItemIndicator>
</span> </span>
{children} {children}
</DropdownMenuPrimitive.CheckboxItem> </DropdownMenuPrimitive.CheckboxItem>
)); ))
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName
const DropdownMenuRadioItem = React.forwardRef< const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>, React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem <DropdownMenuPrimitive.RadioItem
ref={ref} ref={ref}
className={cn( 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", "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"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator> <DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" /> <Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator> </DropdownMenuPrimitive.ItemIndicator>
</span> </span>
{children} {children}
</DropdownMenuPrimitive.RadioItem> </DropdownMenuPrimitive.RadioItem>
)); ))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
const DropdownMenuLabel = React.forwardRef< const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>, React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, ...props }, ref) => ( >(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label <DropdownMenuPrimitive.Label
ref={ref} ref={ref}
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} className={cn(
{...props} "px-2 py-1.5 text-sm font-semibold",
/> inset && "pl-8",
)); className
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; )}
{...props}
/>
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
const DropdownMenuSeparator = React.forwardRef< const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>, React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator> React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator <DropdownMenuPrimitive.Separator
ref={ref} ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)} className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props} {...props}
/> />
)); ))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
const DropdownMenuShortcut = ({ const DropdownMenuShortcut = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLSpanElement>) => { }: React.HTMLAttributes<HTMLSpanElement>) => {
return ( return (
<span <span
className={cn("ml-auto text-xs tracking-widest opacity-60", className)} className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
{...props} {...props}
/> />
); )
}; }
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
export { export {
DropdownMenu, DropdownMenu,
DropdownMenuTrigger, DropdownMenuTrigger,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuItem, DropdownMenuItem,
DropdownMenuCheckboxItem, DropdownMenuCheckboxItem,
DropdownMenuRadioItem, DropdownMenuRadioItem,
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuShortcut, DropdownMenuShortcut,
DropdownMenuGroup, DropdownMenuGroup,
DropdownMenuPortal, DropdownMenuPortal,
DropdownMenuSub, DropdownMenuSub,
DropdownMenuSubContent, DropdownMenuSubContent,
DropdownMenuSubTrigger, DropdownMenuSubTrigger,
DropdownMenuRadioGroup, DropdownMenuRadioGroup,
}; }

View File

@ -1,13 +1,13 @@
"use client"; "use client";
import { cn } from "@/lib/utils";
import { AnimatePresence, LayoutGroup, motion } from "framer-motion";
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import { AnimatePresence, motion, LayoutGroup } from "framer-motion";
import { cn } from "@/lib/utils";
export const FlipWords = ({ export const FlipWords = ({
words, words,
duration = 3000, duration = 3000,
className, className,
}: { }: {
words: string[]; words: string[];
duration?: number; duration?: number;
className?: string; className?: string;
@ -60,7 +60,7 @@ export const FlipWords = ({
}} }}
className={cn( className={cn(
"z-10 inline-block relative text-left text-neutral-900 dark:text-neutral-100 px-2", "z-10 inline-block relative text-left text-neutral-900 dark:text-neutral-100 px-2",
className, className
)} )}
key={currentWord} key={currentWord}
> >

View File

@ -1,173 +1,176 @@
import type * as LabelPrimitive from "@radix-ui/react-label"; import * as React from "react"
import { Slot } from "@radix-ui/react-slot"; import * as LabelPrimitive from "@radix-ui/react-label"
import * as React from "react"; import { Slot } from "@radix-ui/react-slot"
import { import {
Controller, Controller,
type ControllerProps, ControllerProps,
type FieldPath, FieldPath,
type FieldValues, FieldValues,
FormProvider, FormProvider,
useFormContext, useFormContext,
} from "react-hook-form"; } from "react-hook-form"
import { Label } from "@/components/ui/label"; import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils"; import { Label } from "@/components/ui/label"
const Form = FormProvider; const Form = FormProvider
type FormFieldContextValue< type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues, 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>( const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue, {} as FormFieldContextValue
); )
const FormField = < const FormField = <
TFieldValues extends FieldValues = FieldValues, TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({ >({
...props ...props
}: ControllerProps<TFieldValues, TName>) => { }: ControllerProps<TFieldValues, TName>) => {
return ( return (
<FormFieldContext.Provider value={{ name: props.name }}> <FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} /> <Controller {...props} />
</FormFieldContext.Provider> </FormFieldContext.Provider>
); )
}; }
const useFormField = () => { const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext); const fieldContext = React.useContext(FormFieldContext)
const itemContext = React.useContext(FormItemContext); const itemContext = React.useContext(FormItemContext)
const { getFieldState, formState } = useFormContext(); const { getFieldState, formState } = useFormContext()
const fieldState = getFieldState(fieldContext.name, formState); const fieldState = getFieldState(fieldContext.name, formState)
if (!fieldContext) { 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 { return {
id, id,
name: fieldContext.name, name: fieldContext.name,
formItemId: `${id}-form-item`, formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`, formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`, formMessageId: `${id}-form-item-message`,
...fieldState, ...fieldState,
}; }
}; }
type FormItemContextValue = { type FormItemContextValue = {
id: string; id: string
}; }
const FormItemContext = React.createContext<FormItemContextValue>( const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue, {} as FormItemContextValue
); )
const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( const FormItem = React.forwardRef<
({ className, ...props }, ref) => { HTMLDivElement,
const id = React.useId(); React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
const id = React.useId()
return ( return (
<FormItemContext.Provider value={{ id }}> <FormItemContext.Provider value={{ id }}>
<div ref={ref} className={cn("space-y-2", className)} {...props} /> <div ref={ref} className={cn("space-y-2", className)} {...props} />
</FormItemContext.Provider> </FormItemContext.Provider>
); )
}, })
); FormItem.displayName = "FormItem"
FormItem.displayName = "FormItem";
const FormLabel = React.forwardRef< const FormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>, React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField(); const { error, formItemId } = useFormField()
return ( return (
<Label <Label
ref={ref} ref={ref}
className={cn(error && "text-destructive", className)} className={cn(error && "text-destructive", className)}
htmlFor={formItemId} htmlFor={formItemId}
{...props} {...props}
/> />
); )
}); })
FormLabel.displayName = "FormLabel"; FormLabel.displayName = "FormLabel"
const FormControl = React.forwardRef< const FormControl = React.forwardRef<
React.ElementRef<typeof Slot>, React.ElementRef<typeof Slot>,
React.ComponentPropsWithoutRef<typeof Slot> React.ComponentPropsWithoutRef<typeof Slot>
>(({ ...props }, ref) => { >(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField(); const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
return ( return (
<Slot <Slot
ref={ref} ref={ref}
id={formItemId} id={formItemId}
aria-describedby={ aria-describedby={
!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}` !error
} ? `${formDescriptionId}`
aria-invalid={!!error} : `${formDescriptionId} ${formMessageId}`
{...props} }
/> aria-invalid={!!error}
); {...props}
}); />
FormControl.displayName = "FormControl"; )
})
FormControl.displayName = "FormControl"
const FormDescription = React.forwardRef< const FormDescription = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement> React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
const { formDescriptionId } = useFormField(); const { formDescriptionId } = useFormField()
return ( return (
<p <p
ref={ref} ref={ref}
id={formDescriptionId} id={formDescriptionId}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
); )
}); })
FormDescription.displayName = "FormDescription"; FormDescription.displayName = "FormDescription"
const FormMessage = React.forwardRef< const FormMessage = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement> React.HTMLAttributes<HTMLParagraphElement>
>(({ className, children, ...props }, ref) => { >(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField(); const { error, formMessageId } = useFormField()
const body = error ? String(error?.message) : children; const body = error ? String(error?.message) : children
if (!body) { if (!body) {
return null; return null
} }
return ( return (
<p <p
ref={ref} ref={ref}
id={formMessageId} id={formMessageId}
className={cn("text-sm font-medium text-destructive", className)} className={cn("text-sm font-medium text-destructive", className)}
{...props} {...props}
> >
{body} {body}
</p> </p>
); )
}); })
FormMessage.displayName = "FormMessage"; FormMessage.displayName = "FormMessage"
export { export {
useFormField, useFormField,
Form, Form,
FormItem, FormItem,
FormLabel, FormLabel,
FormControl, FormControl,
FormDescription, FormDescription,
FormMessage, FormMessage,
FormField, FormField,
}; }

View File

@ -1,18 +1,18 @@
"use client"; "use client";
import React from "react";
import { import {
type MotionValue,
motion, motion,
useScroll, useScroll,
useSpring,
useTransform, useTransform,
useSpring,
MotionValue,
} from "framer-motion"; } from "framer-motion";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import React from "react";
interface HeroParallaxProps { interface HeroParallaxProps {
products: product[]; products: product[];
children?: React.ReactNode; children?: React.ReactNode
} }
interface product { interface product {
@ -21,7 +21,7 @@ interface product {
thumbnail: string; thumbnail: string;
} }
export const HeroParallax = ({ products, children }: HeroParallaxProps) => { export const HeroParallax = ({ products, children }: HeroParallaxProps ) => {
const firstRow = products.slice(0, 5); const firstRow = products.slice(0, 5);
const secondRow = products.slice(5, 10); const secondRow = products.slice(5, 10);
const thirdRow = products.slice(10, 15); const thirdRow = products.slice(10, 15);
@ -35,27 +35,27 @@ export const HeroParallax = ({ products, children }: HeroParallaxProps) => {
const translateX = useSpring( const translateX = useSpring(
useTransform(scrollYProgress, [0, 1], [0, 1000]), useTransform(scrollYProgress, [0, 1], [0, 1000]),
springConfig, springConfig
); );
const translateXReverse = useSpring( const translateXReverse = useSpring(
useTransform(scrollYProgress, [0, 1], [0, -1000]), useTransform(scrollYProgress, [0, 1], [0, -1000]),
springConfig, springConfig
); );
const rotateX = useSpring( const rotateX = useSpring(
useTransform(scrollYProgress, [0, 0.2], [15, 0]), useTransform(scrollYProgress, [0, 0.2], [15, 0]),
springConfig, springConfig
); );
const opacity = useSpring( const opacity = useSpring(
useTransform(scrollYProgress, [0, 0.2], [0.2, 1]), useTransform(scrollYProgress, [0, 0.2], [0.2, 1]),
springConfig, springConfig
); );
const rotateZ = useSpring( const rotateZ = useSpring(
useTransform(scrollYProgress, [0, 0.2], [20, 0]), useTransform(scrollYProgress, [0, 0.2], [20, 0]),
springConfig, springConfig
); );
const translateY = useSpring( const translateY = useSpring(
useTransform(scrollYProgress, [0, 0.2], [-700, 500]), useTransform(scrollYProgress, [0, 0.2], [-700, 500]),
springConfig, springConfig
); );
return ( return (
<div <div
@ -74,7 +74,11 @@ export const HeroParallax = ({ products, children }: HeroParallaxProps) => {
> >
<motion.div className="flex flex-row-reverse space-x-reverse space-x-20 mb-20"> <motion.div className="flex flex-row-reverse space-x-reverse space-x-20 mb-20">
{firstRow.map((product) => ( {firstRow.map((product) => (
<ProductCard product={product} translate={translateX} key={product.title} /> <ProductCard
product={product}
translate={translateX}
key={product.title}
/>
))} ))}
</motion.div> </motion.div>
<motion.div className="flex flex-row mb-20 space-x-20 "> <motion.div className="flex flex-row mb-20 space-x-20 ">
@ -88,7 +92,11 @@ export const HeroParallax = ({ products, children }: HeroParallaxProps) => {
</motion.div> </motion.div>
<motion.div className="flex flex-row-reverse space-x-reverse space-x-20"> <motion.div className="flex flex-row-reverse space-x-reverse space-x-20">
{thirdRow.map((product) => ( {thirdRow.map((product) => (
<ProductCard product={product} translate={translateX} key={product.title} /> <ProductCard
product={product}
translate={translateX}
key={product.title}
/>
))} ))}
</motion.div> </motion.div>
</motion.div> </motion.div>
@ -97,9 +105,9 @@ export const HeroParallax = ({ products, children }: HeroParallaxProps) => {
}; };
export const ProductCard = ({ export const ProductCard = ({
product, product,
translate, translate,
}: { }: {
product: { product: {
title: string; title: string;
link: string; link: string;
@ -118,7 +126,10 @@ export const ProductCard = ({
key={product.title} key={product.title}
className="group/product h-96 w-[30rem] relative flex-shrink-0" className="group/product h-96 w-[30rem] relative flex-shrink-0"
> >
<Link href={product.link} className="block group-hover/product:shadow-2xl "> <Link
href={product.link}
className="block group-hover/product:shadow-2xl "
>
<Image <Image
src={product.thumbnail} src={product.thumbnail}
height="600" height="600"

View File

@ -1,29 +1,29 @@
"use client"; "use client"
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"; import * as React from "react"
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< const HoverCardContent = React.forwardRef<
React.ElementRef<typeof HoverCardPrimitive.Content>, React.ElementRef<typeof HoverCardPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content> React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<HoverCardPrimitive.Content <HoverCardPrimitive.Content
ref={ref} ref={ref}
align={align} align={align}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"z-50 w-64 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", "z-50 w-64 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} {...props}
/> />
)); ))
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName; HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
export { HoverCard, HoverCardTrigger, HoverCardContent }; export { HoverCard, HoverCardTrigger, HoverCardContent }

View File

@ -1,71 +1,71 @@
"use client"; "use client"
import { OTPInput, OTPInputContext } from "input-otp"; import * as React from "react"
import { Dot } from "lucide-react"; import { OTPInput, OTPInputContext } from "input-otp"
import * as React from "react"; import { Dot } from "lucide-react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const InputOTP = React.forwardRef< const InputOTP = React.forwardRef<
React.ElementRef<typeof OTPInput>, React.ElementRef<typeof OTPInput>,
React.ComponentPropsWithoutRef<typeof OTPInput> React.ComponentPropsWithoutRef<typeof OTPInput>
>(({ className, containerClassName, ...props }, ref) => ( >(({ className, containerClassName, ...props }, ref) => (
<OTPInput <OTPInput
ref={ref} ref={ref}
containerClassName={cn( containerClassName={cn(
"flex items-center gap-2 has-[:disabled]:opacity-50", "flex items-center gap-2 has-[:disabled]:opacity-50",
containerClassName, containerClassName
)} )}
className={cn("disabled:cursor-not-allowed", className)} className={cn("disabled:cursor-not-allowed", className)}
{...props} {...props}
/> />
)); ))
InputOTP.displayName = "InputOTP"; InputOTP.displayName = "InputOTP"
const InputOTPGroup = React.forwardRef< const InputOTPGroup = React.forwardRef<
React.ElementRef<"div">, React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div"> React.ComponentPropsWithoutRef<"div">
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div ref={ref} className={cn("flex items-center", className)} {...props} /> <div ref={ref} className={cn("flex items-center", className)} {...props} />
)); ))
InputOTPGroup.displayName = "InputOTPGroup"; InputOTPGroup.displayName = "InputOTPGroup"
const InputOTPSlot = React.forwardRef< const InputOTPSlot = React.forwardRef<
React.ElementRef<"div">, React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div"> & { index: number } React.ComponentPropsWithoutRef<"div"> & { index: number }
>(({ index, className, ...props }, ref) => { >(({ index, className, ...props }, ref) => {
const inputOTPContext = React.useContext(OTPInputContext); const inputOTPContext = React.useContext(OTPInputContext)
const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]; const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
return ( return (
<div <div
ref={ref} ref={ref}
className={cn( 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", "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", isActive && "z-10 ring-2 ring-ring ring-offset-background",
className, className
)} )}
{...props} {...props}
> >
{char} {char}
{hasFakeCaret && ( {hasFakeCaret && (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center"> <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" /> <div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
</div> </div>
)} )}
</div> </div>
); )
}); })
InputOTPSlot.displayName = "InputOTPSlot"; InputOTPSlot.displayName = "InputOTPSlot"
const InputOTPSeparator = React.forwardRef< const InputOTPSeparator = React.forwardRef<
React.ElementRef<"div">, React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div"> React.ComponentPropsWithoutRef<"div">
>(({ ...props }, ref) => ( >(({ ...props }, ref) => (
<div ref={ref} role="separator" {...props}> <div ref={ref} role="separator" {...props}>
<Dot /> <Dot />
</div> </div>
)); ))
InputOTPSeparator.displayName = "InputOTPSeparator"; InputOTPSeparator.displayName = "InputOTPSeparator"
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }

View File

@ -1,24 +1,25 @@
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> {} export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>( const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => { ({ className, type, ...props }, ref) => {
return ( return (
<input <input
type={type} type={type}
className={cn( 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", "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, className
)} )}
ref={ref} ref={ref}
{...props} {...props}
/> />
); )
}, }
); )
Input.displayName = "Input"; Input.displayName = "Input"
export { Input }; export { Input }

View File

@ -1,22 +1,26 @@
"use client"; "use client"
import * as LabelPrimitive from "@radix-ui/react-label"; import * as React from "react"
import { type VariantProps, cva } from "class-variance-authority"; import * as LabelPrimitive from "@radix-ui/react-label"
import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const labelVariants = cva( 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< const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>, React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants> VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} /> <LabelPrimitive.Root
)); ref={ref}
Label.displayName = LabelPrimitive.Root.displayName; className={cn(labelVariants(), className)}
{...props}
/>
))
Label.displayName = LabelPrimitive.Root.displayName
export { Label }; export { Label }

View File

@ -1,224 +1,236 @@
"use client"; "use client"
import * as MenubarPrimitive from "@radix-ui/react-menubar"; import * as React from "react"
import { Check, ChevronRight, Circle } from "lucide-react"; import * as MenubarPrimitive from "@radix-ui/react-menubar"
import * as React from "react"; 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< const Menubar = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Root>, React.ElementRef<typeof MenubarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<MenubarPrimitive.Root <MenubarPrimitive.Root
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-10 items-center space-x-1 rounded-md border bg-background p-1", "flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
className, className
)} )}
{...props} {...props}
/> />
)); ))
Menubar.displayName = MenubarPrimitive.Root.displayName; Menubar.displayName = MenubarPrimitive.Root.displayName
const MenubarTrigger = React.forwardRef< const MenubarTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Trigger>, React.ElementRef<typeof MenubarPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<MenubarPrimitive.Trigger <MenubarPrimitive.Trigger
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName; MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
const MenubarSubTrigger = React.forwardRef< const MenubarSubTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubTrigger>, React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & { React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, children, ...props }, ref) => ( >(({ className, inset, children, ...props }, ref) => (
<MenubarPrimitive.SubTrigger <MenubarPrimitive.SubTrigger
ref={ref} ref={ref}
className={cn( 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", "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", inset && "pl-8",
className, className
)} )}
{...props} {...props}
> >
{children} {children}
<ChevronRight className="ml-auto h-4 w-4" /> <ChevronRight className="ml-auto h-4 w-4" />
</MenubarPrimitive.SubTrigger> </MenubarPrimitive.SubTrigger>
)); ))
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName; MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
const MenubarSubContent = React.forwardRef< const MenubarSubContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubContent>, React.ElementRef<typeof MenubarPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<MenubarPrimitive.SubContent <MenubarPrimitive.SubContent
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName; MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
const MenubarContent = React.forwardRef< const MenubarContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Content>, React.ElementRef<typeof MenubarPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
>(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => ( >(
<MenubarPrimitive.Portal> (
<MenubarPrimitive.Content { className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
ref={ref} ref
align={align} ) => (
alignOffset={alignOffset} <MenubarPrimitive.Portal>
sideOffset={sideOffset} <MenubarPrimitive.Content
className={cn( ref={ref}
"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", align={align}
className, alignOffset={alignOffset}
)} sideOffset={sideOffset}
{...props} 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",
</MenubarPrimitive.Portal> className
)); )}
MenubarContent.displayName = MenubarPrimitive.Content.displayName; {...props}
/>
</MenubarPrimitive.Portal>
)
)
MenubarContent.displayName = MenubarPrimitive.Content.displayName
const MenubarItem = React.forwardRef< const MenubarItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Item>, React.ElementRef<typeof MenubarPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & { React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, ...props }, ref) => ( >(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Item <MenubarPrimitive.Item
ref={ref} ref={ref}
className={cn( 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", "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", inset && "pl-8",
className, className
)} )}
{...props} {...props}
/> />
)); ))
MenubarItem.displayName = MenubarPrimitive.Item.displayName; MenubarItem.displayName = MenubarPrimitive.Item.displayName
const MenubarCheckboxItem = React.forwardRef< const MenubarCheckboxItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>, React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => ( >(({ className, children, checked, ...props }, ref) => (
<MenubarPrimitive.CheckboxItem <MenubarPrimitive.CheckboxItem
ref={ref} ref={ref}
className={cn( 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", "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} checked={checked}
{...props} {...props}
> >
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator> <MenubarPrimitive.ItemIndicator>
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</MenubarPrimitive.ItemIndicator> </MenubarPrimitive.ItemIndicator>
</span> </span>
{children} {children}
</MenubarPrimitive.CheckboxItem> </MenubarPrimitive.CheckboxItem>
)); ))
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName; MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
const MenubarRadioItem = React.forwardRef< const MenubarRadioItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.RadioItem>, React.ElementRef<typeof MenubarPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<MenubarPrimitive.RadioItem <MenubarPrimitive.RadioItem
ref={ref} ref={ref}
className={cn( 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", "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"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator> <MenubarPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" /> <Circle className="h-2 w-2 fill-current" />
</MenubarPrimitive.ItemIndicator> </MenubarPrimitive.ItemIndicator>
</span> </span>
{children} {children}
</MenubarPrimitive.RadioItem> </MenubarPrimitive.RadioItem>
)); ))
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName; MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
const MenubarLabel = React.forwardRef< const MenubarLabel = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Label>, React.ElementRef<typeof MenubarPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & { React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
inset?: boolean; inset?: boolean
} }
>(({ className, inset, ...props }, ref) => ( >(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Label <MenubarPrimitive.Label
ref={ref} ref={ref}
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} className={cn(
{...props} "px-2 py-1.5 text-sm font-semibold",
/> inset && "pl-8",
)); className
MenubarLabel.displayName = MenubarPrimitive.Label.displayName; )}
{...props}
/>
))
MenubarLabel.displayName = MenubarPrimitive.Label.displayName
const MenubarSeparator = React.forwardRef< const MenubarSeparator = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Separator>, React.ElementRef<typeof MenubarPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator> React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<MenubarPrimitive.Separator <MenubarPrimitive.Separator
ref={ref} ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)} className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props} {...props}
/> />
)); ))
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName; MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
const MenubarShortcut = ({ const MenubarShortcut = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLSpanElement>) => { }: React.HTMLAttributes<HTMLSpanElement>) => {
return ( return (
<span <span
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} className={cn(
{...props} "ml-auto text-xs tracking-widest text-muted-foreground",
/> className
); )}
}; {...props}
MenubarShortcut.displayname = "MenubarShortcut"; />
)
}
MenubarShortcut.displayname = "MenubarShortcut"
export { export {
Menubar, Menubar,
MenubarMenu, MenubarMenu,
MenubarTrigger, MenubarTrigger,
MenubarContent, MenubarContent,
MenubarItem, MenubarItem,
MenubarSeparator, MenubarSeparator,
MenubarLabel, MenubarLabel,
MenubarCheckboxItem, MenubarCheckboxItem,
MenubarRadioGroup, MenubarRadioGroup,
MenubarRadioItem, MenubarRadioItem,
MenubarPortal, MenubarPortal,
MenubarSubContent, MenubarSubContent,
MenubarSubTrigger, MenubarSubTrigger,
MenubarGroup, MenubarGroup,
MenubarSub, MenubarSub,
MenubarShortcut, MenubarShortcut,
}; }

View File

@ -1,126 +1,128 @@
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"; import * as React from "react"
import { cva } from "class-variance-authority"; import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { ChevronDown } from "lucide-react"; import { cva } from "class-variance-authority"
import * as React from "react"; import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const NavigationMenu = React.forwardRef< const NavigationMenu = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Root>, React.ElementRef<typeof NavigationMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Root <NavigationMenuPrimitive.Root
ref={ref} ref={ref}
className={cn( className={cn(
"relative z-10 flex max-w-max flex-1 items-center justify-center", "relative z-10 flex max-w-max flex-1 items-center justify-center",
className, className
)} )}
{...props} {...props}
> >
{children} {children}
<NavigationMenuViewport /> <NavigationMenuViewport />
</NavigationMenuPrimitive.Root> </NavigationMenuPrimitive.Root>
)); ))
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName; NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
const NavigationMenuList = React.forwardRef< const NavigationMenuList = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.List>, React.ElementRef<typeof NavigationMenuPrimitive.List>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.List <NavigationMenuPrimitive.List
ref={ref} ref={ref}
className={cn( className={cn(
"group flex flex-1 list-none items-center justify-center space-x-1", "group flex flex-1 list-none items-center justify-center space-x-1",
className, className
)} )}
{...props} {...props}
/> />
)); ))
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName; NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
const NavigationMenuItem = NavigationMenuPrimitive.Item; const NavigationMenuItem = NavigationMenuPrimitive.Item
const navigationMenuTriggerStyle = cva( 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", "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< const NavigationMenuTrigger = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>, React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Trigger <NavigationMenuPrimitive.Trigger
ref={ref} ref={ref}
className={cn(navigationMenuTriggerStyle(), "group", className)} className={cn(navigationMenuTriggerStyle(), "group", className)}
{...props} {...props}
> >
{children}{" "} {children}{" "}
<ChevronDown <ChevronDown
className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180" className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
aria-hidden="true" aria-hidden="true"
/> />
</NavigationMenuPrimitive.Trigger> </NavigationMenuPrimitive.Trigger>
)); ))
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName; NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
const NavigationMenuContent = React.forwardRef< const NavigationMenuContent = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Content>, React.ElementRef<typeof NavigationMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Content <NavigationMenuPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"md:left-0 md:top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ", "md:left-0 md:top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
className, className
)} )}
{...props} {...props}
/> />
)); ))
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName; NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
const NavigationMenuLink = NavigationMenuPrimitive.Link; const NavigationMenuLink = NavigationMenuPrimitive.Link
const NavigationMenuViewport = React.forwardRef< const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>, React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport> React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div className={cn("absolute md:left-0 top-full flex justify-center")}> <div className={cn("absolute md:left-0 top-full flex justify-center")}>
<NavigationMenuPrimitive.Viewport <NavigationMenuPrimitive.Viewport
className={cn( className={cn(
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-screen md:w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]", "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-screen md:w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
className, className
)} )}
ref={ref} ref={ref}
{...props} {...props}
/> />
</div> </div>
)); ))
NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName; NavigationMenuViewport.displayName =
NavigationMenuPrimitive.Viewport.displayName
const NavigationMenuIndicator = React.forwardRef< const NavigationMenuIndicator = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>, React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator> React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Indicator <NavigationMenuPrimitive.Indicator
ref={ref} ref={ref}
className={cn( className={cn(
"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", "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, className
)} )}
{...props} {...props}
> >
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" /> <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
</NavigationMenuPrimitive.Indicator> </NavigationMenuPrimitive.Indicator>
)); ))
NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName; NavigationMenuIndicator.displayName =
NavigationMenuPrimitive.Indicator.displayName
export { export {
navigationMenuTriggerStyle, navigationMenuTriggerStyle,
NavigationMenu, NavigationMenu,
NavigationMenuList, NavigationMenuList,
NavigationMenuItem, NavigationMenuItem,
NavigationMenuContent, NavigationMenuContent,
NavigationMenuTrigger, NavigationMenuTrigger,
NavigationMenuLink, NavigationMenuLink,
NavigationMenuIndicator, NavigationMenuIndicator,
NavigationMenuViewport, NavigationMenuViewport,
}; }

View File

@ -1,112 +1,117 @@
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"; import * as React from "react"
import * as React from "react"; import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
import { type ButtonProps, buttonVariants } from "@/components/ui/button"; import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils"; import { ButtonProps, buttonVariants } from "@/components/ui/button"
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => ( const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
<nav <nav
role="navigation" role="navigation"
aria-label="pagination" aria-label="pagination"
className={cn("mx-auto flex w-full justify-center", className)} className={cn("mx-auto flex w-full justify-center", className)}
{...props} {...props}
/> />
); )
Pagination.displayName = "Pagination"; Pagination.displayName = "Pagination"
const PaginationContent = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>( const PaginationContent = React.forwardRef<
({ className, ...props }, ref) => ( HTMLUListElement,
<ul React.ComponentProps<"ul">
ref={ref} >(({ className, ...props }, ref) => (
className={cn("flex flex-row items-center gap-1", className)} <ul
{...props} ref={ref}
/> className={cn("flex flex-row items-center gap-1", className)}
), {...props}
); />
PaginationContent.displayName = "PaginationContent"; ))
PaginationContent.displayName = "PaginationContent"
const PaginationItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>( const PaginationItem = React.forwardRef<
({ className, ...props }, ref) => ( HTMLLIElement,
<li ref={ref} className={cn("", className)} {...props} /> React.ComponentProps<"li">
), >(({ className, ...props }, ref) => (
); <li ref={ref} className={cn("", className)} {...props} />
PaginationItem.displayName = "PaginationItem"; ))
PaginationItem.displayName = "PaginationItem"
type PaginationLinkProps = { type PaginationLinkProps = {
isActive?: boolean; isActive?: boolean
} & Pick<ButtonProps, "size"> & } & Pick<ButtonProps, "size"> &
React.ComponentProps<"a">; React.ComponentProps<"a">
const PaginationLink = ({ const PaginationLink = ({
className, className,
isActive, isActive,
size = "icon", size = "icon",
...props ...props
}: PaginationLinkProps) => ( }: PaginationLinkProps) => (
<a <a
aria-current={isActive ? "page" : undefined} aria-current={isActive ? "page" : undefined}
className={cn( className={cn(
buttonVariants({ buttonVariants({
variant: isActive ? "outline" : "ghost", variant: isActive ? "outline" : "ghost",
size, size,
}), }),
className, className
)} )}
{...props} {...props}
/> />
); )
PaginationLink.displayName = "PaginationLink"; PaginationLink.displayName = "PaginationLink"
const PaginationPrevious = ({ const PaginationPrevious = ({
className, className,
...props ...props
}: React.ComponentProps<typeof PaginationLink>) => ( }: React.ComponentProps<typeof PaginationLink>) => (
<PaginationLink <PaginationLink
aria-label="Go to previous page" aria-label="Go to previous page"
size="default" size="default"
className={cn("gap-1 pl-2.5", className)} className={cn("gap-1 pl-2.5", className)}
{...props} {...props}
> >
<ChevronLeft className="h-4 w-4" /> <ChevronLeft className="h-4 w-4" />
<span>Previous</span> <span>Previous</span>
</PaginationLink> </PaginationLink>
); )
PaginationPrevious.displayName = "PaginationPrevious"; PaginationPrevious.displayName = "PaginationPrevious"
const PaginationNext = ({ const PaginationNext = ({
className, className,
...props ...props
}: React.ComponentProps<typeof PaginationLink>) => ( }: React.ComponentProps<typeof PaginationLink>) => (
<PaginationLink <PaginationLink
aria-label="Go to next page" aria-label="Go to next page"
size="default" size="default"
className={cn("gap-1 pr-2.5", className)} className={cn("gap-1 pr-2.5", className)}
{...props} {...props}
> >
<span>Next</span> <span>Next</span>
<ChevronRight className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
</PaginationLink> </PaginationLink>
); )
PaginationNext.displayName = "PaginationNext"; PaginationNext.displayName = "PaginationNext"
const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => ( const PaginationEllipsis = ({
<span className,
aria-hidden ...props
className={cn("flex h-9 w-9 items-center justify-center", className)} }: React.ComponentProps<"span">) => (
{...props} <span
> aria-hidden
<MoreHorizontal className="h-4 w-4" /> className={cn("flex h-9 w-9 items-center justify-center", className)}
<span className="sr-only">More pages</span> {...props}
</span> >
); <MoreHorizontal className="h-4 w-4" />
PaginationEllipsis.displayName = "PaginationEllipsis"; <span className="sr-only">More pages</span>
</span>
)
PaginationEllipsis.displayName = "PaginationEllipsis"
export { export {
Pagination, Pagination,
PaginationContent, PaginationContent,
PaginationEllipsis, PaginationEllipsis,
PaginationItem, PaginationItem,
PaginationLink, PaginationLink,
PaginationNext, PaginationNext,
PaginationPrevious, PaginationPrevious,
}; }

View File

@ -1,31 +1,31 @@
"use client"; "use client"
import * as PopoverPrimitive from "@radix-ui/react-popover"; import * as React from "react"
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< const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>, React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal> <PopoverPrimitive.Portal>
<PopoverPrimitive.Content <PopoverPrimitive.Content
ref={ref} ref={ref}
align={align} align={align}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( 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", "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} {...props}
/> />
</PopoverPrimitive.Portal> </PopoverPrimitive.Portal>
)); ))
PopoverContent.displayName = PopoverPrimitive.Content.displayName; PopoverContent.displayName = PopoverPrimitive.Content.displayName
export { Popover, PopoverTrigger, PopoverContent }; export { Popover, PopoverTrigger, PopoverContent }

View File

@ -1,28 +1,28 @@
"use client"; "use client"
import * as ProgressPrimitive from "@radix-ui/react-progress"; import * as React from "react"
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< const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>, React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => ( >(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root <ProgressPrimitive.Root
ref={ref} ref={ref}
className={cn( className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary", "relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className, className
)} )}
{...props} {...props}
> >
<ProgressPrimitive.Indicator <ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all" className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }} style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/> />
</ProgressPrimitive.Root> </ProgressPrimitive.Root>
)); ))
Progress.displayName = ProgressPrimitive.Root.displayName; Progress.displayName = ProgressPrimitive.Root.displayName
export { Progress }; export { Progress }

View File

@ -1,44 +1,44 @@
"use client"; "use client"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; import * as React from "react"
import { Circle } from "lucide-react"; import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
import * as React from "react"; import { Circle } from "lucide-react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const RadioGroup = React.forwardRef< const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>, React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
return ( return (
<RadioGroupPrimitive.Root <RadioGroupPrimitive.Root
className={cn("grid gap-2", className)} className={cn("grid gap-2", className)}
{...props} {...props}
ref={ref} ref={ref}
/> />
); )
}); })
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName; RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
const RadioGroupItem = React.forwardRef< const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>, React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
return ( return (
<RadioGroupPrimitive.Item <RadioGroupPrimitive.Item
ref={ref} ref={ref}
className={cn( 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", "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"> <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-2.5 w-2.5 fill-current text-current" /> <Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator> </RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item> </RadioGroupPrimitive.Item>
); )
}); })
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
export { RadioGroup, RadioGroupItem }; export { RadioGroup, RadioGroupItem }

View File

@ -1,45 +1,45 @@
"use client"; "use client"
import { GripVertical } from "lucide-react"; import { GripVertical } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"; import * as ResizablePrimitive from "react-resizable-panels"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const ResizablePanelGroup = ({ const ResizablePanelGroup = ({
className, className,
...props ...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => ( }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
<ResizablePrimitive.PanelGroup <ResizablePrimitive.PanelGroup
className={cn( className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col", "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className, className
)} )}
{...props} {...props}
/> />
); )
const ResizablePanel = ResizablePrimitive.Panel; const ResizablePanel = ResizablePrimitive.Panel
const ResizableHandle = ({ const ResizableHandle = ({
withHandle, withHandle,
className, className,
...props ...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean; withHandle?: boolean
}) => ( }) => (
<ResizablePrimitive.PanelResizeHandle <ResizablePrimitive.PanelResizeHandle
className={cn( 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", "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 && ( {withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border"> <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" /> <GripVertical className="h-2.5 w-2.5" />
</div> </div>
)} )}
</ResizablePrimitive.PanelResizeHandle> </ResizablePrimitive.PanelResizeHandle>
); )
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; export { ResizablePanelGroup, ResizablePanel, ResizableHandle }

View File

@ -1,47 +1,48 @@
"use client"; "use client"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; import * as React from "react"
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< const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>, React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root <ScrollAreaPrimitive.Root
ref={ref} ref={ref}
className={cn("relative overflow-hidden", className)} className={cn("relative overflow-hidden", className)}
{...props} {...props}
> >
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]"> <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children} {children}
</ScrollAreaPrimitive.Viewport> </ScrollAreaPrimitive.Viewport>
<ScrollBar /> <ScrollBar />
<ScrollAreaPrimitive.Corner /> <ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root> </ScrollAreaPrimitive.Root>
)); ))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
const ScrollBar = React.forwardRef< const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>, React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar> React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => ( >(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar <ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref} ref={ref}
orientation={orientation} orientation={orientation}
className={cn( className={cn(
"flex touch-none select-none transition-colors", "flex touch-none select-none transition-colors",
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]", orientation === "vertical" &&
orientation === "horizontal" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
"h-2.5 flex-col border-t border-t-transparent p-[1px]", orientation === "horizontal" &&
className, "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> <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 }

View File

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

View File

@ -1,26 +1,31 @@
"use client"; "use client"
import * as SeparatorPrimitive from "@radix-ui/react-separator"; import * as React from "react"
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< const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>, React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => ( >(
<SeparatorPrimitive.Root (
ref={ref} { className, orientation = "horizontal", decorative = true, ...props },
decorative={decorative} ref
orientation={orientation} ) => (
className={cn( <SeparatorPrimitive.Root
"shrink-0 bg-border", ref={ref}
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", decorative={decorative}
className, orientation={orientation}
)} className={cn(
{...props} "shrink-0 bg-border",
/> orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
)); className
Separator.displayName = SeparatorPrimitive.Root.displayName; )}
{...props}
/>
)
)
Separator.displayName = SeparatorPrimitive.Root.displayName
export { Separator }; export { Separator }

View File

@ -1,131 +1,140 @@
"use client"; "use client"
import * as SheetPrimitive from "@radix-ui/react-dialog"; import * as React from "react"
import { type VariantProps, cva } from "class-variance-authority"; import * as SheetPrimitive from "@radix-ui/react-dialog"
import { X } from "lucide-react"; import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"; 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< const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>, React.ElementRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay> React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay <SheetPrimitive.Overlay
className={cn( 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", "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} {...props}
ref={ref} ref={ref}
/> />
)); ))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
const sheetVariants = cva( 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", "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",
{ {
variants: { variants: {
side: { side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
bottom: bottom:
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
right: right:
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
}, },
}, },
defaultVariants: { defaultVariants: {
side: "right", side: "right",
}, },
}, }
); )
interface SheetContentProps interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {} VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef< const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>, React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps SheetContentProps
>(({ side = "right", className, children, ...props }, ref) => ( >(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal> <SheetPortal>
<SheetOverlay /> <SheetOverlay />
<SheetPrimitive.Content <SheetPrimitive.Content
ref={ref} ref={ref}
className={cn(sheetVariants({ side }), className)} className={cn(sheetVariants({ side }), className)}
{...props} {...props}
> >
{children} {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"> <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" /> <X className="h-4 w-4" />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</SheetPrimitive.Close> </SheetPrimitive.Close>
</SheetPrimitive.Content> </SheetPrimitive.Content>
</SheetPortal> </SheetPortal>
)); ))
SheetContent.displayName = SheetPrimitive.Content.displayName; SheetContent.displayName = SheetPrimitive.Content.displayName
const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const SheetHeader = ({
<div className,
className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} ...props
{...props} }: React.HTMLAttributes<HTMLDivElement>) => (
/> <div
); className={cn(
SheetHeader.displayName = "SheetHeader"; "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 = ({
<div className,
className={cn( ...props
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", }: React.HTMLAttributes<HTMLDivElement>) => (
className, <div
)} className={cn(
{...props} "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
/> className
); )}
SheetFooter.displayName = "SheetFooter"; {...props}
/>
)
SheetFooter.displayName = "SheetFooter"
const SheetTitle = React.forwardRef< const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>, React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title> React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Title <SheetPrimitive.Title
ref={ref} ref={ref}
className={cn("text-lg font-semibold text-foreground", className)} className={cn("text-lg font-semibold text-foreground", className)}
{...props} {...props}
/> />
)); ))
SheetTitle.displayName = SheetPrimitive.Title.displayName; SheetTitle.displayName = SheetPrimitive.Title.displayName
const SheetDescription = React.forwardRef< const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>, React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description> React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Description <SheetPrimitive.Description
ref={ref} ref={ref}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)); ))
SheetDescription.displayName = SheetPrimitive.Description.displayName; SheetDescription.displayName = SheetPrimitive.Description.displayName
export { export {
Sheet, Sheet,
SheetPortal, SheetPortal,
SheetOverlay, SheetOverlay,
SheetTrigger, SheetTrigger,
SheetClose, SheetClose,
SheetContent, SheetContent,
SheetHeader, SheetHeader,
SheetFooter, SheetFooter,
SheetTitle, SheetTitle,
SheetDescription, SheetDescription,
}; }

View File

@ -1,9 +1,15 @@
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) { function Skeleton({
return ( className,
<div className={cn("animate-pulse rounded-md bg-muted", className)} {...props} /> ...props
); }: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
)
} }
export { Skeleton }; export { Skeleton }

View File

@ -1,25 +1,28 @@
"use client"; "use client"
import * as SliderPrimitive from "@radix-ui/react-slider"; import * as React from "react"
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< const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>, React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SliderPrimitive.Root <SliderPrimitive.Root
ref={ref} ref={ref}
className={cn("relative flex w-full touch-none select-none items-center", className)} className={cn(
{...props} "relative flex w-full touch-none select-none items-center",
> className
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> )}
<SliderPrimitive.Range className="absolute h-full bg-primary" /> {...props}
</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.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
</SliderPrimitive.Root> <SliderPrimitive.Range className="absolute h-full bg-primary" />
)); </SliderPrimitive.Track>
Slider.displayName = SliderPrimitive.Root.displayName; <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
export { Slider }; export { Slider }

View File

@ -1,30 +1,31 @@
"use client"; "use client"
import { useTheme } from "next-themes"; import { useTheme } from "next-themes"
import { Toaster as Sonner } from "sonner"; import { Toaster as Sonner } from "sonner"
type ToasterProps = React.ComponentProps<typeof Sonner>; type ToasterProps = React.ComponentProps<typeof Sonner>
const Toaster = ({ ...props }: ToasterProps) => { const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme(); const { theme = "system" } = useTheme()
return ( return (
<Sonner <Sonner
theme={theme as ToasterProps["theme"]} theme={theme as ToasterProps["theme"]}
className="toaster group" className="toaster group"
toastOptions={{ toastOptions={{
classNames: { classNames: {
toast: toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg", "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground", description: "group-[.toast]:text-muted-foreground",
actionButton: actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", cancelButton:
}, "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
}} },
{...props} }}
/> {...props}
); />
}; )
}
export { Toaster }; export { Toaster }

View File

@ -1,29 +1,29 @@
"use client"; "use client"
import * as SwitchPrimitives from "@radix-ui/react-switch"; import * as React from "react"
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< const Switch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>, React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root> React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SwitchPrimitives.Root <SwitchPrimitives.Root
className={cn( 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", "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} {...props}
ref={ref} ref={ref}
> >
<SwitchPrimitives.Thumb <SwitchPrimitives.Thumb
className={cn( 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> </SwitchPrimitives.Root>
)); ))
Switch.displayName = SwitchPrimitives.Root.displayName; Switch.displayName = SwitchPrimitives.Root.displayName
export { Switch }; export { Switch }

View File

@ -1,109 +1,117 @@
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>>( const Table = React.forwardRef<
({ className, ...props }, ref) => ( HTMLTableElement,
<div className="relative w-full overflow-auto"> React.HTMLAttributes<HTMLTableElement>
<table >(({ className, ...props }, ref) => (
ref={ref} <div className="relative w-full overflow-auto">
className={cn("w-full caption-bottom text-sm", className)} <table
{...props} ref={ref}
/> className={cn("w-full caption-bottom text-sm", className)}
</div> {...props}
), />
); </div>
Table.displayName = "Table"; ))
Table.displayName = "Table"
const TableHeader = React.forwardRef< const TableHeader = React.forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement> React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} /> <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
)); ))
TableHeader.displayName = "TableHeader"; TableHeader.displayName = "TableHeader"
const TableBody = React.forwardRef< const TableBody = React.forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement> React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} /> <tbody
)); ref={ref}
TableBody.displayName = "TableBody"; className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
))
TableBody.displayName = "TableBody"
const TableFooter = React.forwardRef< const TableFooter = React.forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement> React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<tfoot <tfoot
ref={ref} ref={ref}
className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)} className={cn(
{...props} "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
/> className
)); )}
TableFooter.displayName = "TableFooter"; {...props}
/>
))
TableFooter.displayName = "TableFooter"
const TableRow = React.forwardRef< const TableRow = React.forwardRef<
HTMLTableRowElement, HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement> React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<tr <tr
ref={ref} ref={ref}
className={cn( className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className, className
)} )}
{...props} {...props}
/> />
)); ))
TableRow.displayName = "TableRow"; TableRow.displayName = "TableRow"
const TableHead = React.forwardRef< const TableHead = React.forwardRef<
HTMLTableCellElement, HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement> React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<th <th
ref={ref} ref={ref}
className={cn( className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className, className
)} )}
{...props} {...props}
/> />
)); ))
TableHead.displayName = "TableHead"; TableHead.displayName = "TableHead"
const TableCell = React.forwardRef< const TableCell = React.forwardRef<
HTMLTableCellElement, HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement> React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<td <td
ref={ref} ref={ref}
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)} className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
{...props} {...props}
/> />
)); ))
TableCell.displayName = "TableCell"; TableCell.displayName = "TableCell"
const TableCaption = React.forwardRef< const TableCaption = React.forwardRef<
HTMLTableCaptionElement, HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement> React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<caption <caption
ref={ref} ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)} className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)); ))
TableCaption.displayName = "TableCaption"; TableCaption.displayName = "TableCaption"
export { export {
Table, Table,
TableHeader, TableHeader,
TableBody, TableBody,
TableFooter, TableFooter,
TableHead, TableHead,
TableRow, TableRow,
TableCell, TableCell,
TableCaption, TableCaption,
}; }

View File

@ -1,55 +1,55 @@
"use client"; "use client"
import * as TabsPrimitive from "@radix-ui/react-tabs"; import * as React from "react"
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< const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>, React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<TabsPrimitive.List <TabsPrimitive.List
ref={ref} ref={ref}
className={cn( className={cn(
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
className, className
)} )}
{...props} {...props}
/> />
)); ))
TabsList.displayName = TabsPrimitive.List.displayName; TabsList.displayName = TabsPrimitive.List.displayName
const TabsTrigger = React.forwardRef< const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>, React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger <TabsPrimitive.Trigger
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
const TabsContent = React.forwardRef< const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>, React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content> React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<TabsPrimitive.Content <TabsPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "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} {...props}
/> />
)); ))
TabsContent.displayName = TabsPrimitive.Content.displayName; TabsContent.displayName = TabsPrimitive.Content.displayName
export { Tabs, TabsList, TabsTrigger, TabsContent }; export { Tabs, TabsList, TabsTrigger, TabsContent }

View File

@ -1,24 +1,24 @@
import * as React from "react"; import * as React from "react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
export interface TextareaProps export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {} extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>( const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => { ({ className, ...props }, ref) => {
return ( return (
<textarea <textarea
className={cn( className={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm 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", "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm 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",
className, className
)} )}
ref={ref} ref={ref}
{...props} {...props}
/> />
); )
}, }
); )
Textarea.displayName = "Textarea"; Textarea.displayName = "Textarea"
export { Textarea }; export { Textarea }

View File

@ -1,77 +1,63 @@
import { import {Bug, CircleAlert, CircleCheckBig, CircleHelp, MessageSquareText, Minus, OctagonX, Plus} from "lucide-react";
Bug,
CircleAlert,
CircleCheckBig,
CircleHelp,
MessageSquareText,
Minus,
OctagonX,
Plus,
} from "lucide-react";
import React from "react"; import React from "react";
export enum toastType { export enum toastType {
info = "info", info = "info",
warn = "warn", warn = "warn",
error = "error", error = "error",
refused = "refused", refused= "refused",
success = "success", success = "success",
add = "add", add = "add",
del = "del", del = "del",
message = "message", message = "message"
} }
export function ToastBox({ export function ToastBox({title, message, type}: {title?: string, message: string, type: toastType}) {
title,
message,
type,
}: { title?: string; message: string; type: toastType }) {
let icon: any; let icon: any;
let bgColor: string; let bgColor: string;
switch (type) { switch (type) {
case toastType.message: case toastType.message :
icon = <MessageSquareText />; icon = <MessageSquareText />
bgColor = "bg-accent"; bgColor = 'bg-accent'
break; break
case toastType.add: case toastType.add:
icon = <Plus />; icon = <Plus />
bgColor = "bg-accent"; bgColor = 'bg-accent'
break; break
case toastType.del: case toastType.del:
icon = <Minus />; icon = <Minus />
bgColor = "bg-accent"; bgColor = 'bg-accent'
break; break
case toastType.info: case toastType.info:
icon = <CircleHelp />; icon = <CircleHelp />
bgColor = "bg-accent"; bgColor = 'bg-accent'
break; break
case toastType.warn: case toastType.warn:
icon = <CircleAlert />; icon = <CircleAlert />
bgColor = "bg-orange-500"; bgColor = 'bg-orange-500'
break; break
case toastType.error: case toastType.error:
icon = <Bug />; icon = <Bug />
bgColor = "bg-red-500"; bgColor = 'bg-red-500'
break; break
case toastType.success: case toastType.success:
icon = <CircleCheckBig />; icon = <CircleCheckBig />
bgColor = "bg-green-500"; bgColor = 'bg-green-500'
break; break
case toastType.refused: case toastType.refused:
icon = <OctagonX />; icon = <OctagonX />
bgColor = "bg-red-700"; bgColor = 'bg-red-700'
break; break
} }
return ( return (
<div <div className={`flex flex-row items-center gap-2 scale-90 md:scale-100 p-2 rounded border ${bgColor}`}>
className={`flex flex-row items-center gap-2 scale-90 md:scale-100 p-2 rounded border ${bgColor}`}
>
{icon} {icon}
<div className={"flex flex-col justify-center items-start"}> <div className={"flex flex-col justify-center items-start"}>
{title && <h3 className={"text-nowrap font-bold text-xl"}>{title}</h3>} {title && <h3 className={"text-nowrap font-bold text-xl"}>{title}</h3>}
<p className={"text-wrap"}>{message}</p> <p className={"text-wrap"}>{message}</p>
</div> </div>
</div> </div>
); )
} }

View File

@ -1,129 +1,129 @@
"use client"; "use client"
import * as ToastPrimitives from "@radix-ui/react-toast"; import * as React from "react"
import { type VariantProps, cva } from "class-variance-authority"; import * as ToastPrimitives from "@radix-ui/react-toast"
import { X } from "lucide-react"; import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"; 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< const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>, React.ElementRef<typeof ToastPrimitives.Viewport>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport> React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport <ToastPrimitives.Viewport
ref={ref} ref={ref}
className={cn( 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]", "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} {...props}
/> />
)); ))
ToastViewport.displayName = ToastPrimitives.Viewport.displayName; ToastViewport.displayName = ToastPrimitives.Viewport.displayName
const toastVariants = cva( 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", "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",
{ {
variants: { variants: {
variant: { variant: {
default: "border bg-background text-foreground", default: "border bg-background text-foreground",
destructive: destructive:
"destructive group border-destructive bg-destructive text-destructive-foreground", "destructive group border-destructive bg-destructive text-destructive-foreground",
}, },
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
}, },
}, }
); )
const Toast = React.forwardRef< const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>, React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants> VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => { >(({ className, variant, ...props }, ref) => {
return ( return (
<ToastPrimitives.Root <ToastPrimitives.Root
ref={ref} ref={ref}
className={cn(toastVariants({ variant }), className)} className={cn(toastVariants({ variant }), className)}
{...props} {...props}
/> />
); )
}); })
Toast.displayName = ToastPrimitives.Root.displayName; Toast.displayName = ToastPrimitives.Root.displayName
const ToastAction = React.forwardRef< const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>, React.ElementRef<typeof ToastPrimitives.Action>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action> React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ToastPrimitives.Action <ToastPrimitives.Action
ref={ref} ref={ref}
className={cn( 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", "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} {...props}
/> />
)); ))
ToastAction.displayName = ToastPrimitives.Action.displayName; ToastAction.displayName = ToastPrimitives.Action.displayName
const ToastClose = React.forwardRef< const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>, React.ElementRef<typeof ToastPrimitives.Close>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close> React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ToastPrimitives.Close <ToastPrimitives.Close
ref={ref} ref={ref}
className={cn( 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", "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="" toast-close=""
{...props} {...props}
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</ToastPrimitives.Close> </ToastPrimitives.Close>
)); ))
ToastClose.displayName = ToastPrimitives.Close.displayName; ToastClose.displayName = ToastPrimitives.Close.displayName
const ToastTitle = React.forwardRef< const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>, React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title> React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ToastPrimitives.Title <ToastPrimitives.Title
ref={ref} ref={ref}
className={cn("text-sm font-semibold", className)} className={cn("text-sm font-semibold", className)}
{...props} {...props}
/> />
)); ))
ToastTitle.displayName = ToastPrimitives.Title.displayName; ToastTitle.displayName = ToastPrimitives.Title.displayName
const ToastDescription = React.forwardRef< const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>, React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description> React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ToastPrimitives.Description <ToastPrimitives.Description
ref={ref} ref={ref}
className={cn("text-sm opacity-90", className)} className={cn("text-sm opacity-90", className)}
{...props} {...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 { export {
type ToastProps, type ToastProps,
type ToastActionElement, type ToastActionElement,
ToastProvider, ToastProvider,
ToastViewport, ToastViewport,
Toast, Toast,
ToastTitle, ToastTitle,
ToastDescription, ToastDescription,
ToastClose, ToastClose,
ToastAction, ToastAction,
}; }

View File

@ -1,31 +1,35 @@
"use client"; "use client"
import { import {
Toast, Toast,
ToastClose, ToastClose,
ToastDescription, ToastDescription,
ToastProvider, ToastProvider,
ToastTitle, ToastTitle,
ToastViewport, ToastViewport,
} from "@/components/ui/toast"; } from "@/components/ui/toast"
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast"
export function Toaster() { export function Toaster() {
const { toasts } = useToast(); const { toasts } = useToast()
return ( return (
<ToastProvider> <ToastProvider>
{toasts.map(({ id, title, description, action, ...props }) => ( {toasts.map(function ({ id, title, description, action, ...props }) {
<Toast key={id} {...props}> return (
<div className="grid gap-1"> <Toast key={id} {...props}>
{title && <ToastTitle>{title}</ToastTitle>} <div className="grid gap-1">
{description && <ToastDescription>{description}</ToastDescription>} {title && <ToastTitle>{title}</ToastTitle>}
</div> {description && (
{action} <ToastDescription>{description}</ToastDescription>
<ToastClose /> )}
</Toast> </div>
))} {action}
<ToastViewport /> <ToastClose />
</ToastProvider> </Toast>
); )
})}
<ToastViewport />
</ToastProvider>
)
} }

View File

@ -1,59 +1,61 @@
"use client"; "use client"
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"; import * as React from "react"
import type { VariantProps } from "class-variance-authority"; import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
import * as React from "react"; import { VariantProps } from "class-variance-authority"
import { toggleVariants } from "@/components/ui/toggle"; import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils"; import { toggleVariants } from "@/components/ui/toggle"
const ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants>>({ const ToggleGroupContext = React.createContext<
size: "default", VariantProps<typeof toggleVariants>
variant: "default", >({
}); size: "default",
variant: "default",
})
const ToggleGroup = React.forwardRef< const ToggleGroup = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Root>, React.ElementRef<typeof ToggleGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> & React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
VariantProps<typeof toggleVariants> VariantProps<typeof toggleVariants>
>(({ className, variant, size, children, ...props }, ref) => ( >(({ className, variant, size, children, ...props }, ref) => (
<ToggleGroupPrimitive.Root <ToggleGroupPrimitive.Root
ref={ref} ref={ref}
className={cn("flex items-center justify-center gap-1", className)} className={cn("flex items-center justify-center gap-1", className)}
{...props} {...props}
> >
<ToggleGroupContext.Provider value={{ variant, size }}> <ToggleGroupContext.Provider value={{ variant, size }}>
{children} {children}
</ToggleGroupContext.Provider> </ToggleGroupContext.Provider>
</ToggleGroupPrimitive.Root> </ToggleGroupPrimitive.Root>
)); ))
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName; ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
const ToggleGroupItem = React.forwardRef< const ToggleGroupItem = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Item>, React.ElementRef<typeof ToggleGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> & React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
VariantProps<typeof toggleVariants> VariantProps<typeof toggleVariants>
>(({ className, children, variant, size, ...props }, ref) => { >(({ className, children, variant, size, ...props }, ref) => {
const context = React.useContext(ToggleGroupContext); const context = React.useContext(ToggleGroupContext)
return ( return (
<ToggleGroupPrimitive.Item <ToggleGroupPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
toggleVariants({ toggleVariants({
variant: context.variant || variant, variant: context.variant || variant,
size: context.size || size, size: context.size || size,
}), }),
className, className
)} )}
{...props} {...props}
> >
{children} {children}
</ToggleGroupPrimitive.Item> </ToggleGroupPrimitive.Item>
); )
}); })
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName; ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
export { ToggleGroup, ToggleGroupItem }; export { ToggleGroup, ToggleGroupItem }

View File

@ -1,45 +1,45 @@
"use client"; "use client"
import * as TogglePrimitive from "@radix-ui/react-toggle"; import * as React from "react"
import { type VariantProps, cva } from "class-variance-authority"; import * as TogglePrimitive from "@radix-ui/react-toggle"
import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const toggleVariants = cva( 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", "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",
{ {
variants: { variants: {
variant: { variant: {
default: "bg-transparent", default: "bg-transparent",
outline: outline:
"border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
}, },
size: { size: {
default: "h-10 px-3", default: "h-10 px-3",
sm: "h-9 px-2.5", sm: "h-9 px-2.5",
lg: "h-11 px-5", lg: "h-11 px-5",
}, },
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
size: "default", size: "default",
}, },
}, }
); )
const Toggle = React.forwardRef< const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>, React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants> VariantProps<typeof toggleVariants>
>(({ className, variant, size, ...props }, ref) => ( >(({ className, variant, size, ...props }, ref) => (
<TogglePrimitive.Root <TogglePrimitive.Root
ref={ref} ref={ref}
className={cn(toggleVariants({ variant, size, className }))} className={cn(toggleVariants({ variant, size, className }))}
{...props} {...props}
/> />
)); ))
Toggle.displayName = TogglePrimitive.Root.displayName; Toggle.displayName = TogglePrimitive.Root.displayName
export { Toggle, toggleVariants }; export { Toggle, toggleVariants }

View File

@ -1,30 +1,30 @@
"use client"; "use client"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import * as React from "react"
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< const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>, React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => ( >(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content <TooltipPrimitive.Content
ref={ref} ref={ref}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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", "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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} {...props}
/> />
)); ))
TooltipContent.displayName = TooltipPrimitive.Content.displayName; TooltipContent.displayName = TooltipPrimitive.Content.displayName
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }

View File

@ -1,191 +1,194 @@
"use client"; "use client"
// Inspired by react-hot-toast library // 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_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000; const TOAST_REMOVE_DELAY = 1000000
type ToasterToast = ToastProps & { type ToasterToast = ToastProps & {
id: string; id: string
title?: React.ReactNode; title?: React.ReactNode
description?: React.ReactNode; description?: React.ReactNode
action?: ToastActionElement; action?: ToastActionElement
}; }
const actionTypes = { const actionTypes = {
ADD_TOAST: "ADD_TOAST", ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST", UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST", DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST", REMOVE_TOAST: "REMOVE_TOAST",
} as const; } as const
let count = 0; let count = 0
function genId() { function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER; count = (count + 1) % Number.MAX_SAFE_INTEGER
return count.toString(); return count.toString()
} }
type ActionType = typeof actionTypes; type ActionType = typeof actionTypes
type Action = type Action =
| { | {
type: ActionType["ADD_TOAST"]; type: ActionType["ADD_TOAST"]
toast: ToasterToast; toast: ToasterToast
} }
| { | {
type: ActionType["UPDATE_TOAST"]; type: ActionType["UPDATE_TOAST"]
toast: Partial<ToasterToast>; toast: Partial<ToasterToast>
} }
| { | {
type: ActionType["DISMISS_TOAST"]; type: ActionType["DISMISS_TOAST"]
toastId?: ToasterToast["id"]; toastId?: ToasterToast["id"]
} }
| { | {
type: ActionType["REMOVE_TOAST"]; type: ActionType["REMOVE_TOAST"]
toastId?: ToasterToast["id"]; toastId?: ToasterToast["id"]
}; }
interface State { 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) => { const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) { if (toastTimeouts.has(toastId)) {
return; return
} }
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
toastTimeouts.delete(toastId); toastTimeouts.delete(toastId)
dispatch({ dispatch({
type: "REMOVE_TOAST", type: "REMOVE_TOAST",
toastId: toastId, 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) {
case "ADD_TOAST":
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,
),
};
case "DISMISS_TOAST": {
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);
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id);
});
}
return {
...state,
toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined
? {
...t,
open: false,
}
: 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> = [];
let memoryState: State = { toasts: [] };
function dispatch(action: Action) {
memoryState = reducer(memoryState, action);
listeners.forEach((listener) => {
listener(memoryState);
});
} }
type Toast = Omit<ToasterToast, "id">; export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "ADD_TOAST":
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
}
case "UPDATE_TOAST":
return {
...state,
toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t
),
}
case "DISMISS_TOAST": {
const { toastId } = action
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId)
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id)
})
}
return {
...state,
toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined
? {
...t,
open: false,
}
: 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> = []
let memoryState: State = { toasts: [] }
function dispatch(action: Action) {
memoryState = reducer(memoryState, action)
listeners.forEach((listener) => {
listener(memoryState)
})
}
type Toast = Omit<ToasterToast, "id">
function toast({ ...props }: Toast) { function toast({ ...props }: Toast) {
const id = genId(); const id = genId()
const update = (props: ToasterToast) => const update = (props: ToasterToast) =>
dispatch({ dispatch({
type: "UPDATE_TOAST", type: "UPDATE_TOAST",
toast: { ...props, id }, toast: { ...props, id },
}); })
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
dispatch({ dispatch({
type: "ADD_TOAST", type: "ADD_TOAST",
toast: { toast: {
...props, ...props,
id, id,
open: true, open: true,
onOpenChange: (open) => { onOpenChange: (open) => {
if (!open) dismiss(); if (!open) dismiss()
}, },
}, },
}); })
return { return {
id: id, id: id,
dismiss, dismiss,
update, update,
}; }
} }
function useToast() { function useToast() {
const [state, setState] = React.useState<State>(memoryState); const [state, setState] = React.useState<State>(memoryState)
React.useEffect(() => { React.useEffect(() => {
listeners.push(setState); listeners.push(setState)
return () => { return () => {
const index = listeners.indexOf(setState); const index = listeners.indexOf(setState)
if (index > -1) { if (index > -1) {
listeners.splice(index, 1); listeners.splice(index, 1)
} }
}; }
}, [state]); }, [state])
return { return {
...state, ...state,
toast, toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
}; }
} }
export { useToast, toast }; export { useToast, toast }

View File

@ -1,15 +1,15 @@
import type { IUserData } from "@/interfaces/userdata.interface"; import {IUserData} from "@/interfaces/userdata.interface";
// ----- Request ----- // ----- Request -----
export interface IApiRegisterReq { export interface IApiRegisterReq {
firstName: string; firstName: string;
lastName: string; lastName: string;
pseudo: string; pseudo: string;
city: string; city: string;
email: string; email: string;
password: string; password: string;
age: number; age: number;
} }
export interface IApiLoginReq { export interface IApiLoginReq {
@ -17,19 +17,20 @@ export interface IApiLoginReq {
password: string; password: string;
} }
// ----- Response ----- // ----- Response -----
export interface IAbstractApiResponse { export interface IAbstractApiResponse {
message?: Array<string>; message?: Array<string>;
error?: string; error?: string;
statusCode?: number; statusCode?: number
} }
export interface IApiRegisterRes extends IAbstractApiResponse { export interface IApiRegisterRes extends IAbstractApiResponse {
access_token?: string; access_token?: string;
user?: IUserData; user?: IUserData
} }
export interface IApiLoginRes extends IAbstractApiResponse { export interface IApiLoginRes extends IAbstractApiResponse {
access_token?: string; access_token?: string
} }

View File

@ -1,14 +1,14 @@
export interface IUserData { export interface IUserData {
id: string; id: string;
firstName: string; firstName: string;
lastName: string; lastName: string;
pseudo: string; pseudo: string;
email: string; email: string;
roleId: string; roleId: string;
isActive: boolean; isActive: boolean;
city: string; city: string;
dollarAvailables: number; dollarAvailables: number;
age: number; age: number;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
} }

View File

@ -1,6 +1,6 @@
import { type ClassValue, clsx } from "clsx"; import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)); return twMerge(clsx(inputs))
} }

View File

@ -1,73 +1,55 @@
"use client"; "use client"
import type { import { createContext, useContext, useState } from 'react';
IApiLoginReq, import {IUserData} from "@/interfaces/userdata.interface";
IApiLoginRes, import {IApiLoginReq, IApiLoginRes, IApiRegisterReq, IApiRegisterRes} from "@/interfaces/api.interface";
IApiRegisterReq,
IApiRegisterRes,
} from "@/interfaces/api.interface";
import type { IUserData } from "@/interfaces/userdata.interface";
import ApiRequest from "@/services/apiRequest"; import ApiRequest from "@/services/apiRequest";
import { useEncodedLocalStorage } from "@/services/localStorage"; import {useEncodedLocalStorage} from "@/services/localStorage";
import { createContext, useContext, useState } from "react";
const UserDataContext = createContext<IUserData | null>(null); const UserDataContext = createContext<IUserData | null>(null)
const [userData, setUserData] = useEncodedLocalStorage<IUserData | null>( const [userData, setUserData] = useEncodedLocalStorage<IUserData | null>("user_data", null)
"user_data",
null,
);
//TODO Run register task //TODO Run register task
export async function doRegister( export async function doRegister(registerData: IApiRegisterReq): Promise<IApiRegisterRes | null> {
registerData: IApiRegisterReq, console.trace(registerData)
): Promise<IApiRegisterRes | null> {
console.trace(registerData);
try { try {
const ReqRes = await ApiRequest.standard.post.json<IApiRegisterReq, IApiRegisterRes>( const ReqRes = await ApiRequest.standard.post.json<IApiRegisterReq, IApiRegisterRes>("auth/signup", registerData)
"auth/signup", console.trace(ReqRes.data)
registerData,
);
console.trace(ReqRes.data);
if (ReqRes.data.user) { if (ReqRes.data.user) {
setUserData(ReqRes.data.user); setUserData(ReqRes.data.user)
} }
ReqRes.data.message?.forEach((err) => console.warn(err)); ReqRes.data.message?.forEach((err)=> console.warn(err))
return ReqRes.data; return ReqRes.data
} catch (error) { } catch (error) {
console.error("Error during registration:", error); console.error('Error during registration:', error);
return null; return null
} }
} }
//TODO Run login task //TODO Run login task
export async function doLogin(loginData: IApiLoginReq) { export async function doLogin(loginData: IApiLoginReq) {
try { try {
const ReqRes = await ApiRequest.standard.post.json<IApiLoginReq, IApiLoginRes>( const ReqRes = await ApiRequest.standard.post.json<IApiLoginReq, IApiLoginRes>("auth/login", loginData)
"auth/login", console.trace(ReqRes.data)
loginData,
);
console.trace(ReqRes.data);
//if (ReqRes.data.user) { //if (ReqRes.data.user) {
// setUserData(ReqRes.data.user) // setUserData(ReqRes.data.user)
//} //}
ReqRes.data.message?.forEach((err) => console.warn(err)); ReqRes.data.message?.forEach((err)=> console.warn(err))
return ReqRes.data; return ReqRes.data
} catch (err) { } catch (err) {
console.error("Error during login:", err); console.error('Error during login:', err);
return null; return null
} }
} }
//TODO Run disconnect task //TODO Run disconnect task
export function doDisconnect() { export function doDisconnect() {
if (typeof window !== "undefined") { if (typeof window !== 'undefined') {
window.localStorage.removeItem("sub"); window.localStorage.removeItem('sub')
return true; return true
} }
console.log( console.log('Whut ? Why trying to remove an item from the localStorage when runner in SSR ?')
"Whut ? Why trying to remove an item from the localStorage when runner in SSR ?", return false
);
return false;
} }
//TODO Run update user data //TODO Run update user data

View File

@ -1,83 +1,75 @@
"use client"; 'use client'
import axios, { type AxiosResponse } from "axios"; import axios, {type AxiosResponse} from "axios";
const baseUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3333/"; const baseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3333'
const AxiosConfigs = { const AxiosConfigs = {
authenticated: { authenticated: {
json: () => { json: () => {
return { return {
headers: { headers: {
"content-type": "application/json", 'content-type': 'application/json',
Authorization: `Bearer ${typeof window !== "undefined" ? window.localStorage.getItem("sub") : "not-ssr"}`, Authorization: `Bearer ${typeof window !== 'undefined' ? window.localStorage.getItem('sub') : "not-ssr"}`,
}, },
validateStatus: (status: number) => { validateStatus: function (status: number) {
return status < 500; // Resolve only if the status code is less than 500 return status < 500; // Resolve only if the status code is less than 500
}, }
}; }
}, }
}, },
standard: { standard: {
json: () => { json: () => {
return { return {
headers: { headers: {
"content-type": "application/json", 'content-type': 'application/json'
}, },
validateStatus: (status: number) => { validateStatus: function (status: number) {
return status < 500; // Resolve only if the status code is less than 500 return status < 500; // Resolve only if the status code is less than 500
}, }
}; }
}, }
}, }
};
async function doAuthenticatedJsonPostReq<ReqT, ResT>(
route: string,
body: ReqT,
): Promise<AxiosResponse<ResT>> {
return await axios.post(baseUrl + route, body, AxiosConfigs.authenticated.json());
} }
async function doAuthenticatedGetReq<ResT>(route: string): Promise<AxiosResponse<ResT>> { async function doAuthenticatedJsonPostReq<ReqT, ResT>(route:string, body:ReqT): Promise<AxiosResponse<ResT>> {
return await axios.get(baseUrl + route, AxiosConfigs.authenticated.json()); return await axios.post(baseUrl + route, body, AxiosConfigs.authenticated.json())
} }
async function doAuthenticatedPatchReq<ReqT, ResT>( async function doAuthenticatedGetReq<ResT>(route:string): Promise<AxiosResponse<ResT>> {
route: string, return await axios.get(baseUrl + route, AxiosConfigs.authenticated.json())
body: ReqT,
): Promise<AxiosResponse<ResT>> {
return await axios.patch(baseUrl + route, body, AxiosConfigs.authenticated.json());
} }
async function doAuthenticatedDelReq<ResT>(route: string): Promise<AxiosResponse<ResT>> { async function doAuthenticatedPatchReq<ReqT, ResT>(route:string, body: ReqT): Promise<AxiosResponse<ResT>> {
return await axios.delete(baseUrl + route, AxiosConfigs.authenticated.json()); return await axios.patch(baseUrl + route, body, AxiosConfigs.authenticated.json())
}
async function doAuthenticatedDelReq<ResT>(route:string): Promise<AxiosResponse<ResT>> {
return await axios.delete(baseUrl + route, AxiosConfigs.authenticated.json())
} }
//TODO form/multipart req //TODO form/multipart req
async function doJsonPostReq<ReqT, ResT>(
route: string, async function doJsonPostReq<ReqT, ResT>(route:string, body: ReqT): Promise<AxiosResponse<ResT>> {
body: ReqT, return await axios.post(baseUrl + route, body, AxiosConfigs.standard.json())
): Promise<AxiosResponse<ResT>> {
return await axios.post(baseUrl + route, body, AxiosConfigs.standard.json());
} }
async function doJsonGetReq<ResT>(route: string): Promise<AxiosResponse<ResT>> { async function doJsonGetReq<ResT>(route:string): Promise<AxiosResponse<ResT>> {
return await axios.get(baseUrl + route, AxiosConfigs.standard.json()); return await axios.get(baseUrl + route, AxiosConfigs.standard.json());
} }
const ApiRequest = { const ApiRequest = {
authenticated: { authenticated: {
post: { json: doAuthenticatedJsonPostReq }, post: {json: doAuthenticatedJsonPostReq},
patch: { json: doAuthenticatedPatchReq }, patch: {json: doAuthenticatedPatchReq},
delete: { json: doAuthenticatedDelReq }, delete: {json: doAuthenticatedDelReq},
get: { json: doAuthenticatedGetReq }, get: {json: doAuthenticatedGetReq}
}, },
standard: { standard: {
post: { json: doJsonPostReq }, post: {json: doJsonPostReq},
get: { json: doJsonGetReq }, get: {json: doJsonGetReq}
}, }
}; }
export default ApiRequest; export default ApiRequest;

View File

@ -1,9 +1,6 @@
"use client"; 'use client'
import type React from "react"; import React, {useEffect, useRef, useState} from "react";
import { useEffect, useRef, useState } from "react";
const localStorage = typeof window !== "undefined" ? window.localStorage : null;
/** /**
* A custom React hook that allows you to store and retrieve data in the browser's localStorage. * A custom React hook that allows you to store and retrieve data in the browser's localStorage.
@ -12,33 +9,34 @@ const localStorage = typeof window !== "undefined" ? window.localStorage : null;
* @param {T} initial - The initial value for the stored data. * @param {T} initial - The initial value for the stored data.
* @returns {[T, React.Dispatch<React.SetStateAction<T>>]} - An array containing the stored value and a function to update the stored value. * @returns {[T, React.Dispatch<React.SetStateAction<T>>]} - An array containing the stored value and a function to update the stored value.
*/ */
export function useLocalStorage<T>( export function useLocalStorage<T>(key: string, initial: T): [T, React.Dispatch<React.SetStateAction<T>>] {
key: string,
initial: T,
): [T, React.Dispatch<React.SetStateAction<T>>] {
const readValue = () => { const readValue = () => {
const item = localStorage?.getItem(key); const item = typeof window !== 'undefined' ? window.localStorage.getItem(key) : null
if (item) { if (item) {
try { try {
return JSON.parse(item); return JSON.parse(item)
} catch (error) { } catch(error) {
console.warn(`Error reading localStorage key “${key}”:`, error); console.warn(`Error reading localStorage key “${key}”:`, error)
} }
} }
return initial;
};
const [storedValue, setStoredValue] = useState<T>(readValue); return initial
}
const [storedValue, setStoredValue] = useState<T>(readValue)
useEffect(() => { useEffect(() => {
try { try {
localStorage?.setItem(key, JSON.stringify(storedValue)); typeof window !== 'undefined' && window.localStorage.setItem(key, JSON.stringify(storedValue))
} catch (error) { } catch (error) {
console.warn(`Error setting localStorage key “${key}”:`, error); console.warn(`Error setting localStorage key “${key}”:`, error)
} }
}, [key, storedValue]); }, [key, storedValue])
return [storedValue, setStoredValue];
return [storedValue, setStoredValue]
} }
/** /**
* Custom hook that provides a way to store and retrieve encoded values in local storage. * Custom hook that provides a way to store and retrieve encoded values in local storage.
* *
@ -49,22 +47,19 @@ export function useLocalStorage<T>(
* *
* @return {readonly [T, React.Dispatch<React.SetStateAction<T>>]} - An array containing the encoded value and a function to update the encoded value. * @return {readonly [T, React.Dispatch<React.SetStateAction<T>>]} - An array containing the encoded value and a function to update the encoded value.
*/ */
export function useEncodedLocalStorage<T>( export function useEncodedLocalStorage<T>(key: string, fallbackValue: T): readonly [T, React.Dispatch<React.SetStateAction<T>>] {
key: string, console.log("Pong !")
fallbackValue: T,
): readonly [T, React.Dispatch<React.SetStateAction<T>>] {
console.log("Pong !");
const [encodedValue, setEncodedValue] = useState<T>(() => { const [encodedValue, setEncodedValue] = useState<T>(() => {
const stored = localStorage?.getItem(key); const stored = localStorage.getItem(key);
return stored ? safelyParse(stored, fallbackValue) : fallbackValue; return stored ? safelyParse(stored, fallbackValue) : fallbackValue;
}); });
const prevValue = useRef(encodedValue); const prevValue = useRef(encodedValue);
useEffect(() => { useEffect(() => {
console.log({ encodedValue }); console.log({encodedValue})
if (!b64ValEqual(prevValue.current, encodedValue)) { if (!b64ValEqual(prevValue.current, encodedValue)) {
localStorage?.setItem(key, safelyStringify(encodedValue)); localStorage.setItem(key, safelyStringify(encodedValue));
} }
prevValue.current = encodedValue; // Set ref to current value prevValue.current = encodedValue; // Set ref to current value
}, [key, encodedValue]); }, [key, encodedValue]);
@ -82,6 +77,7 @@ export function useEncodedLocalStorage<T>(
return btoa(JSON.stringify(v1)) === btoa(JSON.stringify(v2)); return btoa(JSON.stringify(v1)) === btoa(JSON.stringify(v2));
} }
function safelyStringify(value: T): string { function safelyStringify(value: T): string {
try { try {
return btoa(JSON.stringify(value)); return btoa(JSON.stringify(value));
@ -89,4 +85,4 @@ export function useEncodedLocalStorage<T>(
return btoa(JSON.stringify(fallbackValue)); return btoa(JSON.stringify(fallbackValue));
} }
} }
} }