another update

This commit is contained in:
2025-07-24 00:48:27 +03:00
parent dfc8e21db1
commit e0217cbbcb
75 changed files with 5331 additions and 4457 deletions

View File

@@ -1,12 +1,8 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true root = true
[*] [*]
charset = utf-8
indent_style = tab indent_style = tab
indent_size = 4 indent_size = 4
end_of_line = lf insert_final_newline = true
charset = utf-8 trim_trailing_whitespace = true
trim_trailing_whitespace = false
insert_final_newline = false

2
.prettierignore Normal file
View File

@@ -0,0 +1,2 @@
bun.lockb
bun.lock

View File

@@ -1,5 +1,7 @@
{ {
"tabWidth": 4, "trailingComma": "none",
"useTabs": true, "tabWidth": 4,
"semi": true "useTabs": true,
"semi": true,
"singleQuote": false
} }

View File

@@ -7,7 +7,7 @@ async function proxyRequest(request: Request, method: string) {
JSON.stringify({ error: "Missing `url` query parameter." }), JSON.stringify({ error: "Missing `url` query parameter." }),
{ {
status: 400, status: 400,
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" }
} }
); );
} }
@@ -21,7 +21,7 @@ async function proxyRequest(request: Request, method: string) {
const init: RequestInit = { const init: RequestInit = {
method, method,
headers, headers,
body: method === "GET" || method === "HEAD" ? undefined : request.body, body: method === "GET" || method === "HEAD" ? undefined : request.body
}; };
if (init.body !== undefined) { if (init.body !== undefined) {
@@ -35,7 +35,7 @@ async function proxyRequest(request: Request, method: string) {
return new Response(response.body, { return new Response(response.body, {
status: response.status, status: response.status,
headers: responseHeaders, headers: responseHeaders
}); });
} }

View File

@@ -3,7 +3,7 @@
@tailwind utilities; @tailwind utilities;
body { body {
font-family: Arial, Helvetica, sans-serif; font-family: Geist;
} }
@layer base { @layer base {

View File

@@ -3,32 +3,32 @@ import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css"; import "./globals.css";
const geistSans = Geist({ const geistSans = Geist({
variable: "--font-geist-sans", variable: "--font-geist-sans",
subsets: ["latin"], subsets: ["latin"]
}); });
const geistMono = Geist_Mono({ const geistMono = Geist_Mono({
variable: "--font-geist-mono", variable: "--font-geist-mono",
subsets: ["latin"], subsets: ["latin"]
}); });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Create Next App", title: "Create Next App",
description: "Generated by create next app", description: "Generated by create next app"
}; };
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">
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased`} className={`${geistSans.variable} ${geistMono.variable} antialiased`}
> >
{children} {children}
</body> </body>
</html> </html>
); );
} }

View File

@@ -5,7 +5,7 @@ import { HomeLoggedInHeader } from "@/components/loggedInHeader";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { import {
getOmniRecommendationsHome, getOmniRecommendationsHome,
OmniRecommendation, OmniRecommendation
} from "@/lib/omniRecommendation"; } from "@/lib/omniRecommendation";
import { loadThumbnails } from "@/lib/thumbnailLoader"; import { loadThumbnails } from "@/lib/thumbnailLoader";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -14,7 +14,7 @@ export default function Home() {
const SORTS_ALLOWED_IDS = [100000003, 100000001]; const SORTS_ALLOWED_IDS = [100000003, 100000001];
const [rec, setRec] = useState<OmniRecommendation | null>(null); const [rec, setRec] = useState<OmniRecommendation | null>(null);
useEffect(() => { useEffect(() => {
(async () => { setTimeout(async () => {
const r = await getOmniRecommendationsHome(); const r = await getOmniRecommendationsHome();
setRec(r); setRec(r);
loadThumbnails( loadThumbnails(
@@ -22,52 +22,51 @@ export default function Home() {
type: "GameThumbnail", type: "GameThumbnail",
targetId: Number(a[1].rootPlaceId), targetId: Number(a[1].rootPlaceId),
format: "webp", format: "webp",
size: "384x216", size: "384x216"
})) }))
).catch((a) => {}); ).catch((a) => {});
})(); }, 1000);
}, []); }, []);
if (!rec) {
return (
<div className="p-4">
<Card>
<CardContent className="p-4">
<div className="h-[200px] flex items-center justify-center">
<div className="animate-pulse text-muted-foreground">
{"Loading..."}
</div>
</div>
</CardContent>
</Card>
</div>
);
}
return ( return (
<div className="overflow-scroll no-scrollbar w-screen max-h-screen h-screen"> <div className="overflow-scroll no-scrollbar w-screen max-h-screen h-screen">
<HomeLoggedInHeader /> <HomeLoggedInHeader />
<div className="p-4 space-y-8 no-scrollbar"> <div className="p-4 space-y-8 no-scrollbar">
{rec.sorts {!rec ? (
.filter((a) => SORTS_ALLOWED_IDS.includes(a.topicId)) <Card>
.map((sort, idx) => ( <CardContent className="p-4">
<div key={idx}> <div className="h-[200px] flex items-center justify-center">
<h1 className="text-2xl pb-2">{sort.topic}</h1> <div className="animate-pulse text-muted-foreground">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"> {"Loading..."}
{(sort.recommendationList || []).map( </div>
(recommendation, idxb) => {
const game =
rec.contentMetadata.Game[
recommendation.contentId.toString()
];
return (
<GameCard key={idxb} game={game} />
);
}
)}
</div> </div>
</div> </CardContent>
))} </Card>
) : (
rec.sorts
.filter((a) => SORTS_ALLOWED_IDS.includes(a.topicId))
.map((sort, idx) => (
<div key={idx}>
<h1 className="text-2xl pb-2">{sort.topic}</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{(sort.recommendationList || []).map(
(recommendation, idxb) => {
const game =
rec.contentMetadata.Game[
recommendation.contentId.toString()
];
return (
<GameCard
key={idxb}
game={game}
/>
);
}
)}
</div>
</div>
))
)}
</div> </div>
</div> </div>
); );

700
bun.lock Normal file
View File

@@ -0,0 +1,700 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "roblox",
"dependencies": {
"@catppuccin/tailwindcss": "^0.1.6",
"@hookform/resolvers": "^4.0.0",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-alert-dialog": "^1.1.6",
"@radix-ui/react-aspect-ratio": "^1.1.2",
"@radix-ui/react-avatar": "^1.1.3",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.3",
"@radix-ui/react-context-menu": "^2.2.6",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-hover-card": "^1.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-menubar": "^1.1.6",
"@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-radio-group": "^1.2.3",
"@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slider": "^1.2.3",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toast": "^1.2.6",
"@radix-ui/react-toggle": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.5.2",
"input-otp": "^1.4.2",
"lucide-react": "^0.475.0",
"next": "15.1.6",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-day-picker": "8.10.1",
"react-dom": "^19.0.0",
"react-hook-form": "^7.54.2",
"react-resizable-panels": "^2.1.7",
"recharts": "^2.15.1",
"sonner": "^1.7.4",
"tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7",
"vaul": "^1.1.2",
"zod": "^3.24.2",
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5",
},
},
},
"packages": {
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
"@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="],
"@catppuccin/tailwindcss": ["@catppuccin/tailwindcss@0.1.6", "", { "peerDependencies": { "tailwindcss": ">=3.0.0" } }, "sha512-V+Y0AwZ5SSyvOVAcDl7Ng30xy+m82OKnEJ+9+kcZZ7lRyXuZrAb2GScdq9XR3v+ggt8qiZ/G4TvaC9cJ88AAXA=="],
"@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="],
"@floating-ui/core": ["@floating-ui/core@1.7.2", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw=="],
"@floating-ui/dom": ["@floating-ui/dom@1.7.2", "", { "dependencies": { "@floating-ui/core": "^1.7.2", "@floating-ui/utils": "^0.2.10" } }, "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA=="],
"@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.4", "", { "dependencies": { "@floating-ui/dom": "^1.7.2" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw=="],
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
"@hookform/resolvers": ["@hookform/resolvers@4.1.3", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
"@next/env": ["@next/env@15.1.6", "", {}, "sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w=="],
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw=="],
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg=="],
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg=="],
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ=="],
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ=="],
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ=="],
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg=="],
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="],
"@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collapsible": "1.1.11", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A=="],
"@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dialog": "1.1.14", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IOZfZ3nPvN6lXpJTBCunFQPRSvK8MDgSc1FB85xnIpUKOw9en0dJj8JmCAxV7BiZdtYlUpmrQjoTFkVYtdoWzQ=="],
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
"@radix-ui/react-aspect-ratio": ["@radix-ui/react-aspect-ratio@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g=="],
"@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.10", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog=="],
"@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.2", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA=="],
"@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="],
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
"@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
"@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.2.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-menu": "2.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UsQUMjcYTsBjTSXw0P3GO0werEQvUY2plgRQuKoCTtkNr45q1DiL51j4m7gxhABzZ0BadoXNsIbg7F3KwiUBbw=="],
"@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw=="],
"@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ=="],
"@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ=="],
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA=="],
"@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
"@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-CPYZ24Mhirm+g6D8jArmLzjYu4Eyg3TTUHswR26QgzXBHBe64BO/RHOJKzmF/Dxb4y4f9PKyJdwm/O/AhNkb+Q=="],
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
"@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
"@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew=="],
"@radix-ui/react-menubar": ["@radix-ui/react-menubar@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Z71C7LGD+YDYo3TV81paUs8f3Zbmkvg6VLRQpKYfzioOE6n7fOhA3ApK/V/2Odolxjoc4ENk8AYCjohCNayd5A=="],
"@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WG8wWfDiJlSF5hELjwfjSGOXcBR/ZMhBFCGYe8vERpC39CQYZeq1PQ2kaYHdye3V95d06H89KGMsVCIE4LWo3g=="],
"@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw=="],
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ=="],
"@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
"@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA=="],
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.7", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="],
"@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.3.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g=="],
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="],
"@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.9", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A=="],
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.5", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA=="],
"@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
"@radix-ui/react-slider": ["@radix-ui/react-slider@1.3.5", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ=="],
"@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw=="],
"@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg=="],
"@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.9", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ZoFkBBz9zv9GWer7wIjvdRxmh2wyc2oKWw6C6CseWd6/yq1DK/l5lJ+wnsmFwJZbBYqr02mrf8A2q/CVCuM3ZA=="],
"@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-toggle": "1.1.9", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kiU694Km3WFLTC75DdqgM/3Jauf3rD9wxeS9XtyWFKsBUeZA337lC+6uUazT7I1DhanZ5gyD5Stf8uf2dbQxOQ=="],
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw=="],
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
"@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
"@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
"@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
"@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="],
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
"@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="],
"@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
"@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
"@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="],
"@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
"@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
"@types/d3-array": ["@types/d3-array@3.2.1", "", {}, "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="],
"@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
"@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="],
"@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
"@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
"@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
"@types/d3-shape": ["@types/d3-shape@3.1.7", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg=="],
"@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
"@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
"@types/node": ["@types/node@20.19.9", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw=="],
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
"@types/react-dom": ["@types/react-dom@19.1.6", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw=="],
"ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
"arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
"aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
"caniuse-lite": ["caniuse-lite@1.0.30001727", "", {}, "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q=="],
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"cmdk": ["cmdk@1.0.0", "", { "dependencies": { "@radix-ui/react-dialog": "1.0.5", "@radix-ui/react-primitive": "1.0.3" }, "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } }, "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q=="],
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
"commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
"d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
"d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
"d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="],
"d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
"d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
"d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
"d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
"d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
"d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
"d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
"date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
"decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
"didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
"dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
"embla-carousel-react": ["embla-carousel-react@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA=="],
"embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="],
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
"fast-equals": ["fast-equals@5.2.2", "", {}, "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw=="],
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
"glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
"input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
"internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
"is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
"jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"lucide-react": ["lucide-react@0.475.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg=="],
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"next": ["next@15.1.6", "", { "dependencies": { "@next/env": "15.1.6", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.1.6", "@next/swc-darwin-x64": "15.1.6", "@next/swc-linux-arm64-gnu": "15.1.6", "@next/swc-linux-arm64-musl": "15.1.6", "@next/swc-linux-x64-gnu": "15.1.6", "@next/swc-linux-x64-musl": "15.1.6", "@next/swc-win32-arm64-msvc": "15.1.6", "@next/swc-win32-x64-msvc": "15.1.6", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q=="],
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
"object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="],
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="],
"postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="],
"postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="],
"postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
"postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
"react-day-picker": ["react-day-picker@8.10.1", "", { "peerDependencies": { "date-fns": "^2.28.0 || ^3.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA=="],
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
"react-hook-form": ["react-hook-form@7.60.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A=="],
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
"react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="],
"react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
"react-resizable-panels": ["react-resizable-panels@2.1.9", "", { "peerDependencies": { "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-z77+X08YDIrgAes4jl8xhnUu1LNIRp4+E7cv4xHmLOxxUPO/ML7PSrE813b90vj7xvQ1lcf7g2uA9GeMZonjhQ=="],
"react-smooth": ["react-smooth@4.0.4", "", { "dependencies": { "fast-equals": "^5.0.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q=="],
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
"react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
"recharts": ["recharts@2.15.4", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.4", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw=="],
"recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="],
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
"sonner": ["sonner@1.7.4", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
"string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
"sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="],
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
"tailwindcss": ["tailwindcss@3.4.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.6", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="],
"tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
"use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
"use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="],
"victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="],
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"cmdk/@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.0.5", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", "@radix-ui/react-compose-refs": "1.0.1", "@radix-ui/react-context": "1.0.1", "@radix-ui/react-dismissable-layer": "1.0.5", "@radix-ui/react-focus-guards": "1.0.1", "@radix-ui/react-focus-scope": "1.0.4", "@radix-ui/react-id": "1.0.1", "@radix-ui/react-portal": "1.0.4", "@radix-ui/react-presence": "1.0.1", "@radix-ui/react-primitive": "1.0.3", "@radix-ui/react-slot": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.1", "aria-hidden": "^1.1.1", "react-remove-scroll": "2.5.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q=="],
"cmdk/@radix-ui/react-primitive": ["@radix-ui/react-primitive@1.0.3", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-slot": "1.0.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/primitive": ["@radix-ui/primitive@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" } }, "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.0.5", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", "@radix-ui/react-compose-refs": "1.0.1", "@radix-ui/react-primitive": "1.0.3", "@radix-ui/react-use-callback-ref": "1.0.1", "@radix-ui/react-use-escape-keydown": "1.0.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.0.4", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1", "@radix-ui/react-primitive": "1.0.3", "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-id": ["@radix-ui/react-id@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-portal": ["@radix-ui/react-portal@1.0.4", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-primitive": "1.0.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-presence": ["@radix-ui/react-presence@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1", "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.0.2", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA=="],
"cmdk/@radix-ui/react-dialog/react-remove-scroll": ["react-remove-scroll@2.5.5", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.3", "react-style-singleton": "^2.2.1", "tslib": "^2.1.0", "use-callback-ref": "^1.3.0", "use-sidecar": "^1.1.2" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw=="],
"cmdk/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.0.2", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg=="],
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.0.3", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-focus-scope/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ=="],
"cmdk/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ=="],
"cmdk/@radix-ui/react-primitive/@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw=="],
}
}

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,21 +1,21 @@
{ {
"$schema": "https://ui.shadcn.com/schema.json", "$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york", "style": "new-york",
"rsc": true, "rsc": true,
"tsx": true, "tsx": true,
"tailwind": { "tailwind": {
"config": "tailwind.config.ts", "config": "tailwind.config.ts",
"css": "app/globals.css", "css": "app/globals.css",
"baseColor": "neutral", "baseColor": "neutral",
"cssVariables": true, "cssVariables": true,
"prefix": "" "prefix": ""
}, },
"aliases": { "aliases": {
"components": "@/components", "components": "@/components",
"utils": "@/lib/utils", "utils": "@/lib/utils",
"ui": "@/components/ui", "ui": "@/components/ui",
"lib": "@/lib", "lib": "@/lib",
"hooks": "@/hooks" "hooks": "@/hooks"
}, },
"iconLibrary": "lucide" "iconLibrary": "lucide"
} }

View File

@@ -1,26 +1,60 @@
import React from 'react'; import React from "react";
const PremiumIcon = (props: React.SVGProps<SVGSVGElement>) => ( export const PremiumIconSmall = (props: React.SVGProps<SVGSVGElement>) => (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink" xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox="0 0 16 16" viewBox="0 0 16 16"
{...props} {...props}
> >
<defs> <defs>
<clipPath id="clip-path"> <clipPath id="clip-path">
<path <path d="M14,14V2H2V16a2,2,0,0,1-2-2V2A2,2,0,0,1,2,0H14a2,2,0,0,1,2,2V14a2,2,0,0,1-2,2H8V14ZM12,6v6H8V10h2V6H6V16H4V4h8Z" />
d="M14,14V2H2V16a2,2,0,0,1-2-2V2A2,2,0,0,1,2,0H14a2,2,0,0,1,2,2V14a2,2,0,0,1-2,2H8V14ZM12,6v6H8V10h2V6H6V16H4V4h8Z" </clipPath>
/> </defs>
</clipPath> <title>premium_small</title>
</defs> <g id="premium">
<title>premium_small</title> <g clipPath="url(#clip-path)">
<g id="premium"> <rect
<g clipPath="url(#clip-path)"> x="-5"
<rect x="-5" y="-5" width="26" height="26" fill="currentColor" /> y="-5"
</g> width="26"
</g> height="26"
</svg> fill="currentColor"
/>
</g>
</g>
</svg>
); );
export default PremiumIcon; export const VerifiedIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
viewBox="0 0 28 28"
fill="none"
{...props}
>
<g clipPath="url(#clip0_8_46)">
<rect
x="5.88818"
width="22.89"
height="22.89"
transform="rotate(15 5.88818 0)"
fill="currentFill" /* #0066FF */
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20.543 8.7508L20.549 8.7568C21.15 9.3578 21.15 10.3318 20.549 10.9328L11.817 19.6648L7.45 15.2968C6.85 14.6958 6.85 13.7218 7.45 13.1218L7.457 13.1148C8.058 12.5138 9.031 12.5138 9.633 13.1148L11.817 15.2998L18.367 8.7508C18.968 8.1498 19.942 8.1498 20.543 8.7508Z"
fill="currentColor" /* white */
/>
</g>
<defs>
<clipPath id="clip0_8_46">
<rect width="28" height="28" fill="white" />
</clipPath>
</defs>
</svg>
);

View File

@@ -2,7 +2,12 @@
import { ContentMetadata } from "@/lib/omniRecommendation"; import { ContentMetadata } from "@/lib/omniRecommendation";
import LazyLoadedImage from "./lazyLoadedImage"; import LazyLoadedImage from "./lazyLoadedImage";
import { ContextMenu, ContextMenuContent, ContextMenuSeparator, ContextMenuTrigger } from "./ui/context-menu"; import {
ContextMenu,
ContextMenuContent,
ContextMenuSeparator,
ContextMenuTrigger
} from "./ui/context-menu";
import { ContextMenuItem } from "@radix-ui/react-context-menu"; import { ContextMenuItem } from "@radix-ui/react-context-menu";
import React from "react"; import React from "react";
@@ -18,40 +23,76 @@ export const GameCard = React.memo(function GameCard({ game }: GameCardProps) {
<div className="overflow-hidden"> <div className="overflow-hidden">
{game.primaryMediaAsset ? ( {game.primaryMediaAsset ? (
<LazyLoadedImage <LazyLoadedImage
imgId={'GameThumbnail_'+game.rootPlaceId.toString()} imgId={
"GameThumbnail_" +
game.rootPlaceId.toString()
}
alt={game.name} alt={game.name}
className="object-cover w-full h-full" className="object-fill w-full h-full"
/> />
) : ( ) : (
<div className="w-full h-full flex items-center justify-center bg-muted"> <div className="w-full h-full flex items-center justify-center bg-muted">
<span className="text-muted-foreground">{":("}</span> <span className="text-muted-foreground">
{":("}
</span>
</div> </div>
)} )}
</div> </div>
<div className="bg-base flex right-2 bottom-2 absolute rounded-lg p-1 py-0"> <div className="text-blue bg-base font-mono flex right-2 bottom-2 absolute rounded-lg px-2 py-1">
{game.playerCount.toLocaleString()} {game.playerCount.toLocaleString()}
</div> </div>
</div> </div>
</ContextMenuTrigger> </ContextMenuTrigger>
<ContextMenuContent className="w-64 p-2 space-y-1"> <ContextMenuContent className="max-w-[512px] p-2 space-y-1">
<ContextMenuItem disabled className="text-xs text-muted-foreground"> <ContextMenuItem
disabled
className="text-s font-bold text-muted-foreground"
>
{game.name} {game.name}
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem disabled className="text-xs text-muted-foreground"> <ContextMenuItem
{Math.round((game.totalUpVotes/(game.totalUpVotes+game.totalDownVotes))*100)}% rating - {game.playerCount.toLocaleString()} playing disabled
className="text-xs text-subtext0 text-muted-foreground"
>
{Math.round(
(game.totalUpVotes /
(game.totalUpVotes + game.totalDownVotes)) *
100
)}
% rating - {game.playerCount.toLocaleString()} playing
</ContextMenuItem> </ContextMenuItem>
<ContextMenuSeparator/> <ContextMenuItem
disabled
className="pb-1 text-xs text-subtext0 text-muted-foreground"
>
{game.ageRecommendationDisplayName || ""}
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem> <ContextMenuItem>
<a href={`https://roblox.com/games/${game.rootPlaceId}`}>Open URL</a> <a href={`https://roblox.com/games/${game.rootPlaceId}`}>
Open URL
</a>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem onClick={()=>{window.location.href = (`roblox://placeId=${game.rootPlaceId}`)}}> <ContextMenuItem
onClick={() => {
window.location.href = `roblox://placeId=${game.rootPlaceId}`;
}}
>
Play Play
</ContextMenuItem> </ContextMenuItem>
<ContextMenuSeparator/> <ContextMenuSeparator />
<ContextMenuItem onClick={()=>{navigator.clipboard.writeText(`${game.rootPlaceId}`)}}> <ContextMenuItem
onClick={() => {
navigator.clipboard.writeText(`${game.rootPlaceId}`);
}}
>
Copy rootPlaceId Copy rootPlaceId
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem onClick={()=>{navigator.clipboard.writeText(`${game.universeId}`)}}> <ContextMenuItem
onClick={() => {
navigator.clipboard.writeText(`${game.universeId}`);
}}
>
Copy universeId Copy universeId
</ContextMenuItem> </ContextMenuItem>
</ContextMenuContent> </ContextMenuContent>

View File

@@ -1,24 +1,23 @@
import React from 'react'; import React from "react";
import { useThumbnailURL } from '@/hooks/use-lazy-load'; import { useThumbnailURL } from "@/hooks/use-lazy-load";
import { Skeleton } from './ui/skeleton'; import { Skeleton } from "./ui/skeleton";
import Image from "next/image";
interface LazyLoadedImageProps { interface LazyLoadedImageProps {
imgId: string; imgId: string;
alt: string; alt: string;
[prop: string]: string [prop: string]: string;
} }
const LazyLoadedImage: React.FC<React.ImgHTMLAttributes<HTMLImageElement> & LazyLoadedImageProps> = ({ const LazyLoadedImage: React.FC<
imgId, LazyLoadedImageProps
alt, > = ({ imgId, alt, ...props }) => {
...props
}) => {
const imgUrl = useThumbnailURL(imgId); const imgUrl = useThumbnailURL(imgId);
return ( return (
<div> <div>
{imgUrl ? ( {imgUrl ? (
<img src={imgUrl} alt={alt} {...props} /> <Image src={imgUrl as any} width={1024} height={1024} alt={alt} {...props} />
) : ( ) : (
<Skeleton {...props} /> <Skeleton {...props} />
)} )}
@@ -26,4 +25,4 @@ const LazyLoadedImage: React.FC<React.ImgHTMLAttributes<HTMLImageElement> & Lazy
); );
}; };
export default LazyLoadedImage; export default LazyLoadedImage;

View File

@@ -3,12 +3,12 @@
import { import {
getLoggedInUser, getLoggedInUser,
getUserByUserId, getUserByUserId,
UserProfileDetails, UserProfileDetails
} from "@/lib/profile"; } from "@/lib/profile";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import LazyLoadedImage from "./lazyLoadedImage"; import LazyLoadedImage from "./lazyLoadedImage";
import { loadThumbnails } from "@/lib/thumbnailLoader"; import { loadThumbnails } from "@/lib/thumbnailLoader";
import PremiumIcon from "./RobloxIcons"; import { PremiumIconSmall, VerifiedIcon } from "./RobloxIcons";
export const HomeLoggedInHeader = React.memo(function HomeLoggedInHeader() { export const HomeLoggedInHeader = React.memo(function HomeLoggedInHeader() {
const [profileDetails, setProfileDetails] = const [profileDetails, setProfileDetails] =
@@ -30,23 +30,25 @@ export const HomeLoggedInHeader = React.memo(function HomeLoggedInHeader() {
type: "AvatarHeadShot", type: "AvatarHeadShot",
targetId: profileDetails.id, targetId: profileDetails.id,
format: "webp", format: "webp",
size: "720x720", size: "720x720"
}, }
]).catch(a => {}); ]).catch((a) => {});
return ( return (
<div className="flex items-center gap-6 bg-base rounded-xl px-8 py-6 w-fit mt-8 ml-0"> <div className="flex items-center gap-6 bg-base rounded-xl px-8 py-6 w-fit mt-8 ml-0">
<LazyLoadedImage <LazyLoadedImage
imgId={`AvatarHeadShot_${profileDetails.id}`} imgId={`AvatarHeadShot_${profileDetails.id}`}
alt="" alt=""
className="w-28 h-28 rounded-full border-4 border-base bg-base shadow-lg" className="w-28 h-28 rounded-full shadow-2xl"
/> />
<div className="flex flex-col justify-center"> <div className="flex flex-col justify-center">
<span className="text-3xl font-bold text-text flex items-center gap-2"> <span className="text-3xl font-bold text-text flex items-center gap-2">
Hello, {profileDetails.displayName} Hello, {profileDetails.displayName}
<PremiumIcon className="w-6 h-6 fill-transparent"/> {/* TODO: Fetch the User's Roblox Premium subscription state */}
<PremiumIconSmall className="w-6 h-6 fill-transparent" />
<VerifiedIcon className="w-6 h-6 fill-blue text-base" />
</span> </span>
<span className="text-base text-subtext0 mt-1"> <span className="text-base font-mono text-subtext0 mt-1">
@{profileDetails.name} @{profileDetails.name}
</span> </span>
</div> </div>

View File

@@ -1,57 +1,57 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion" import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { ChevronDown } from "lucide-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 <AccordionPrimitive.Item
ref={ref} ref={ref}
className={cn("border-b", className)} className={cn("border-b", className)}
{...props} {...props}
/> />
)) ));
AccordionItem.displayName = "AccordionItem" 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 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180", "flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
className className
)} )}
{...props} {...props}
> >
{children} {children}
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" /> <ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground 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 data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" className="overflow-hidden text-sm 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,141 +1,141 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button" 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( className={cn(
"flex flex-col space-y-2 text-center sm:text-left", "flex flex-col space-y-2 text-center sm:text-left",
className className
)} )}
{...props} {...props}
/> />
) );
AlertDialogHeader.displayName = "AlertDialogHeader" 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 = AlertDialogDescription.displayName =
AlertDialogPrimitive.Description.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( className={cn(
buttonVariants({ variant: "outline" }), buttonVariants({ variant: "outline" }),
"mt-2 sm:mt-0", "mt-2 sm:mt-0",
className className
)} )}
{...props} {...props}
/> />
)) ));
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName 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,59 +1,62 @@
import * as React from "react" import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority" 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 px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
{ {
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(
{...props} "mb-1 font-medium leading-none tracking-tight",
/> className
)) )}
AlertTitle.displayName = "AlertTitle" {...props}
/>
));
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 <div
ref={ref} ref={ref}
className={cn("text-sm [&_p]:leading-relaxed", className)} className={cn("text-sm [&_p]:leading-relaxed", className)}
{...props} {...props}
/> />
)) ));
AlertDescription.displayName = "AlertDescription" 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 React from "react" import * as React from "react";
import * as AvatarPrimitive from "@radix-ui/react-avatar" 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,36 +1,36 @@
import * as React from "react" import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority" 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-md 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-md 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 shadow hover:bg-primary/80", "border-transparent bg-primary text-primary-foreground shadow 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 shadow hover:bg-destructive/80", "border-transparent bg-destructive text-destructive-foreground shadow 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 ( return (
<div className={cn(badgeVariants({ variant }), className)} {...props} /> <div className={cn(badgeVariants({ variant }), className)} {...props} />
) );
} }
export { Badge, badgeVariants } export { Badge, badgeVariants };

View File

@@ -1,115 +1,115 @@
import * as React from "react" import * as React from "react";
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot";
import { ChevronRight, MoreHorizontal } from "lucide-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]:w-3.5 [&>svg]:h-3.5", className)} className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)}
{...props} {...props}
> >
{children ?? <ChevronRight />} {children ?? <ChevronRight />}
</li> </li>
) );
BreadcrumbSeparator.displayName = "BreadcrumbSeparator" BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
const BreadcrumbEllipsis = ({ const BreadcrumbEllipsis = ({
className, className,
...props ...props
}: React.ComponentProps<"span">) => ( }: React.ComponentProps<"span">) => (
<span <span
role="presentation" role="presentation"
aria-hidden="true" aria-hidden="true"
className={cn("flex h-9 w-9 items-center justify-center", className)} className={cn("flex h-9 w-9 items-center justify-center", className)}
{...props} {...props}
> >
<MoreHorizontal className="h-4 w-4" /> <MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span> <span className="sr-only">More</span>
</span> </span>
) );
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis" BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";
export { export {
Breadcrumb, Breadcrumb,
BreadcrumbList, BreadcrumbList,
BreadcrumbItem, BreadcrumbItem,
BreadcrumbLink, BreadcrumbLink,
BreadcrumbPage, BreadcrumbPage,
BreadcrumbSeparator, BreadcrumbSeparator,
BreadcrumbEllipsis, BreadcrumbEllipsis
} };

View File

@@ -1,57 +1,57 @@
import * as React from "react" import * as React from "react";
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority" 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 gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{ {
variants: { variants: {
variant: { variant: {
default: default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90", "bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive: destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline: outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary: secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground", ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline", link: "text-primary underline-offset-4 hover:underline"
}, },
size: { size: {
default: "h-9 px-4 py-2", default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs", sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8", lg: "h-10 rounded-md px-8",
icon: "h-9 w-9", icon: "h-9 w-9"
}, }
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
size: "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,76 +1,82 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import { ChevronLeft, ChevronRight } from "lucide-react" import { ChevronLeft, ChevronRight } from "lucide-react";
import { DayPicker } from "react-day-picker" import { DayPicker } from "react-day-picker";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button" 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: head_cell:
"text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]", "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
row: "flex w-full mt-2", row: "flex w-full mt-2",
cell: cn( cell: cn(
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md", "relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
props.mode === "range" props.mode === "range"
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
: "[&:has([aria-selected])]:rounded-md" : "[&:has([aria-selected])]:rounded-md"
), ),
day: cn( day: cn(
buttonVariants({ variant: "ghost" }), buttonVariants({ variant: "ghost" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100" "h-8 w-8 p-0 font-normal aria-selected:opacity-100"
), ),
day_range_start: "day-range-start", day_range_start: "day-range-start",
day_range_end: "day-range-end", day_range_end: "day-range-end",
day_selected: day_selected:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_today: "bg-accent text-accent-foreground", day_today: "bg-accent text-accent-foreground",
day_outside: day_outside:
"day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground", "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
day_disabled: "text-muted-foreground opacity-50", day_disabled: "text-muted-foreground opacity-50",
day_range_middle: day_range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground", "aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible", day_hidden: "invisible",
...classNames, ...classNames
}} }}
components={{ components={{
IconLeft: ({ className, ...props }) => ( IconLeft: ({ className, ...props }) => (
<ChevronLeft className={cn("h-4 w-4", className)} {...props} /> <ChevronLeft
), className={cn("h-4 w-4", className)}
IconRight: ({ className, ...props }) => ( {...props}
<ChevronRight className={cn("h-4 w-4", className)} {...props} /> />
), ),
}} IconRight: ({ className, ...props }) => (
{...props} <ChevronRight
/> className={cn("h-4 w-4", className)}
) {...props}
/>
)
}}
{...props}
/>
);
} }
Calendar.displayName = "Calendar" Calendar.displayName = "Calendar";
export { Calendar } export { Calendar };

View File

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

View File

@@ -1,262 +1,263 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import useEmblaCarousel, { import useEmblaCarousel, {
type UseEmblaCarouselType, type UseEmblaCarouselType
} from "embla-carousel-react" } from "embla-carousel-react";
import { ArrowLeft, ArrowRight } from "lucide-react" import { ArrowLeft, ArrowRight } from "lucide-react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button" 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", orientation = "horizontal",
opts, opts,
setApi, setApi,
plugins, plugins,
className, className,
children, children,
...props ...props
}, },
ref ref
) => { ) => {
const [carouselRef, api] = useEmblaCarousel( const [carouselRef, api] = useEmblaCarousel(
{ {
...opts, ...opts,
axis: orientation === "horizontal" ? "x" : "y", axis: orientation === "horizontal" ? "x" : "y"
}, },
plugins plugins
) );
const [canScrollPrev, setCanScrollPrev] = React.useState(false) const [canScrollPrev, setCanScrollPrev] = React.useState(false);
const [canScrollNext, setCanScrollNext] = 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:
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), orientation ||
scrollPrev, (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,365 +1,405 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as RechartsPrimitive from "recharts" import * as RechartsPrimitive from "recharts";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
// Format: { THEME_NAME: CSS_SELECTOR } // Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const const THEMES = { light: "", dark: ".dark" } as const;
export type ChartConfig = { export type ChartConfig = {
[k in string]: { [k in string]: {
label?: React.ReactNode label?: React.ReactNode;
icon?: React.ComponentType icon?: React.ComponentType;
} & ( } & (
| { color?: string; theme?: never } | { color?: string; theme?: never }
| { color?: never; theme: Record<keyof typeof THEMES, string> } | { color?: never; theme: Record<keyof typeof THEMES, string> }
) );
} };
type ChartContextProps = { type ChartContextProps = {
config: ChartConfig config: ChartConfig;
} };
const ChartContext = React.createContext<ChartContextProps | null>(null) const ChartContext = React.createContext<ChartContextProps | null>(null);
function useChart() { function useChart() {
const context = React.useContext(ChartContext) const context = React.useContext(ChartContext);
if (!context) { if (!context) {
throw new Error("useChart must be used within a <ChartContainer />") throw new Error("useChart must be used within a <ChartContainer />");
} }
return context return context;
} }
const ChartContainer = React.forwardRef< const ChartContainer = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.ComponentProps<"div"> & { React.ComponentProps<"div"> & {
config: ChartConfig config: ChartConfig;
children: React.ComponentProps< children: React.ComponentProps<
typeof RechartsPrimitive.ResponsiveContainer typeof RechartsPrimitive.ResponsiveContainer
>["children"] >["children"];
} }
>(({ id, className, children, config, ...props }, ref) => { >(({ id, className, children, config, ...props }, ref) => {
const uniqueId = React.useId() const uniqueId = React.useId();
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
return ( return (
<ChartContext.Provider value={{ config }}> <ChartContext.Provider value={{ config }}>
<div <div
data-chart={chartId} data-chart={chartId}
ref={ref} ref={ref}
className={cn( className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
className className
)} )}
{...props} {...props}
> >
<ChartStyle id={chartId} config={config} /> <ChartStyle id={chartId} config={config} />
<RechartsPrimitive.ResponsiveContainer> <RechartsPrimitive.ResponsiveContainer>
{children} {children}
</RechartsPrimitive.ResponsiveContainer> </RechartsPrimitive.ResponsiveContainer>
</div> </div>
</ChartContext.Provider> </ChartContext.Provider>
) );
}) });
ChartContainer.displayName = "Chart" ChartContainer.displayName = "Chart";
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter( const colorConfig = Object.entries(config).filter(
([, config]) => config.theme || config.color ([, config]) => config.theme || config.color
) );
if (!colorConfig.length) { if (!colorConfig.length) {
return null return null;
} }
return ( return (
<style <style
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: Object.entries(THEMES) __html: Object.entries(THEMES)
.map( .map(
([theme, prefix]) => ` ([theme, prefix]) => `
${prefix} [data-chart=${id}] { ${prefix} [data-chart=${id}] {
${colorConfig ${colorConfig
.map(([key, itemConfig]) => { .map(([key, itemConfig]) => {
const color = const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color itemConfig.color;
return color ? ` --color-${key}: ${color};` : null return color ? ` --color-${key}: ${color};` : null;
}) })
.join("\n")} .join("\n")}
} }
` `
) )
.join("\n"), .join("\n")
}} }}
/> />
) );
} };
const ChartTooltip = RechartsPrimitive.Tooltip const ChartTooltip = RechartsPrimitive.Tooltip;
const ChartTooltipContent = React.forwardRef< const ChartTooltipContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
React.ComponentProps<"div"> & { React.ComponentProps<"div"> & {
hideLabel?: boolean hideLabel?: boolean;
hideIndicator?: boolean hideIndicator?: boolean;
indicator?: "line" | "dot" | "dashed" indicator?: "line" | "dot" | "dashed";
nameKey?: string nameKey?: string;
labelKey?: string labelKey?: string;
} }
>( >(
( (
{ {
active, active,
payload, payload,
className, className,
indicator = "dot", indicator = "dot",
hideLabel = false, hideLabel = false,
hideIndicator = false, hideIndicator = false,
label, label,
labelFormatter, labelFormatter,
labelClassName, labelClassName,
formatter, formatter,
color, color,
nameKey, nameKey,
labelKey, labelKey
}, },
ref ref
) => { ) => {
const { config } = useChart() const { config } = useChart();
const tooltipLabel = React.useMemo(() => { const tooltipLabel = React.useMemo(() => {
if (hideLabel || !payload?.length) { if (hideLabel || !payload?.length) {
return null return null;
} }
const [item] = payload const [item] = payload;
const key = `${labelKey || item.dataKey || item.name || "value"}` const key = `${labelKey || item.dataKey || item.name || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key) const itemConfig = getPayloadConfigFromPayload(config, item, key);
const value = const value =
!labelKey && typeof label === "string" !labelKey && typeof label === "string"
? config[label as keyof typeof config]?.label || label ? config[label as keyof typeof config]?.label || label
: itemConfig?.label : itemConfig?.label;
if (labelFormatter) { if (labelFormatter) {
return ( return (
<div className={cn("font-medium", labelClassName)}> <div className={cn("font-medium", labelClassName)}>
{labelFormatter(value, payload)} {labelFormatter(value, payload)}
</div> </div>
) );
} }
if (!value) { if (!value) {
return null return null;
} }
return <div className={cn("font-medium", labelClassName)}>{value}</div> return (
}, [ <div className={cn("font-medium", labelClassName)}>{value}</div>
label, );
labelFormatter, }, [
payload, label,
hideLabel, labelFormatter,
labelClassName, payload,
config, hideLabel,
labelKey, labelClassName,
]) config,
labelKey
]);
if (!active || !payload?.length) { if (!active || !payload?.length) {
return null return null;
} }
const nestLabel = payload.length === 1 && indicator !== "dot" const nestLabel = payload.length === 1 && indicator !== "dot";
return ( return (
<div <div
ref={ref} ref={ref}
className={cn( className={cn(
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl", "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
className className
)} )}
> >
{!nestLabel ? tooltipLabel : null} {!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5"> <div className="grid gap-1.5">
{payload.map((item, index) => { {payload.map((item, index) => {
const key = `${nameKey || item.name || item.dataKey || "value"}` const key = `${nameKey || item.name || item.dataKey || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key) const itemConfig = getPayloadConfigFromPayload(
const indicatorColor = color || item.payload.fill || item.color config,
item,
key
);
const indicatorColor =
color || item.payload.fill || item.color;
return ( return (
<div <div
key={item.dataKey} key={item.dataKey}
className={cn( className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
indicator === "dot" && "items-center" indicator === "dot" && "items-center"
)} )}
> >
{formatter && item?.value !== undefined && item.name ? ( {formatter &&
formatter(item.value, item.name, item, index, item.payload) item?.value !== undefined &&
) : ( item.name ? (
<> formatter(
{itemConfig?.icon ? ( item.value,
<itemConfig.icon /> item.name,
) : ( item,
!hideIndicator && ( index,
<div item.payload
className={cn( )
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]", ) : (
{ <>
"h-2.5 w-2.5": indicator === "dot", {itemConfig?.icon ? (
"w-1": indicator === "line", <itemConfig.icon />
"w-0 border-[1.5px] border-dashed bg-transparent": ) : (
indicator === "dashed", !hideIndicator && (
"my-0.5": nestLabel && indicator === "dashed", <div
} className={cn(
)} "shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
style={ {
{ "h-2.5 w-2.5":
"--color-bg": indicatorColor, indicator ===
"--color-border": indicatorColor, "dot",
} as React.CSSProperties "w-1":
} indicator ===
/> "line",
) "w-0 border-[1.5px] border-dashed bg-transparent":
)} indicator ===
<div "dashed",
className={cn( "my-0.5":
"flex flex-1 justify-between leading-none", nestLabel &&
nestLabel ? "items-end" : "items-center" indicator ===
)} "dashed"
> }
<div className="grid gap-1.5"> )}
{nestLabel ? tooltipLabel : null} style={
<span className="text-muted-foreground"> {
{itemConfig?.label || item.name} "--color-bg":
</span> indicatorColor,
</div> "--color-border":
{item.value && ( indicatorColor
<span className="font-mono font-medium tabular-nums text-foreground"> } as React.CSSProperties
{item.value.toLocaleString()} }
</span> />
)} )
</div> )}
</> <div
)} className={cn(
</div> "flex flex-1 justify-between leading-none",
) nestLabel
})} ? "items-end"
</div> : "items-center"
</div> )}
) >
} <div className="grid gap-1.5">
) {nestLabel
ChartTooltipContent.displayName = "ChartTooltip" ? tooltipLabel
: null}
<span className="text-muted-foreground">
{itemConfig?.label ||
item.name}
</span>
</div>
{item.value && (
<span className="font-mono font-medium tabular-nums text-foreground">
{item.value.toLocaleString()}
</span>
)}
</div>
</>
)}
</div>
);
})}
</div>
</div>
);
}
);
ChartTooltipContent.displayName = "ChartTooltip";
const ChartLegend = RechartsPrimitive.Legend const ChartLegend = RechartsPrimitive.Legend;
const ChartLegendContent = React.forwardRef< const ChartLegendContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.ComponentProps<"div"> & React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & { Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean hideIcon?: boolean;
nameKey?: string nameKey?: string;
} }
>( >(
( (
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, {
ref className,
) => { hideIcon = false,
const { config } = useChart() payload,
verticalAlign = "bottom",
nameKey
},
ref
) => {
const { config } = useChart();
if (!payload?.length) { if (!payload?.length) {
return null return null;
} }
return ( return (
<div <div
ref={ref} ref={ref}
className={cn( className={cn(
"flex items-center justify-center gap-4", "flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3", verticalAlign === "top" ? "pb-3" : "pt-3",
className className
)} )}
> >
{payload.map((item) => { {payload.map((item) => {
const key = `${nameKey || item.dataKey || "value"}` const key = `${nameKey || item.dataKey || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key) const itemConfig = getPayloadConfigFromPayload(
config,
item,
key
);
return ( return (
<div <div
key={item.value} key={item.value}
className={cn( className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
)} )}
> >
{itemConfig?.icon && !hideIcon ? ( {itemConfig?.icon && !hideIcon ? (
<itemConfig.icon /> <itemConfig.icon />
) : ( ) : (
<div <div
className="h-2 w-2 shrink-0 rounded-[2px]" className="h-2 w-2 shrink-0 rounded-[2px]"
style={{ style={{
backgroundColor: item.color, backgroundColor: item.color
}} }}
/> />
)} )}
{itemConfig?.label} {itemConfig?.label}
</div> </div>
) );
})} })}
</div> </div>
) );
} }
) );
ChartLegendContent.displayName = "ChartLegend" ChartLegendContent.displayName = "ChartLegend";
// Helper to extract item config from a payload. // Helper to extract item config from a payload.
function getPayloadConfigFromPayload( function getPayloadConfigFromPayload(
config: ChartConfig, config: ChartConfig,
payload: unknown, payload: unknown,
key: string key: string
) { ) {
if (typeof payload !== "object" || payload === null) { if (typeof payload !== "object" || payload === null) {
return undefined return undefined;
} }
const payloadPayload = const payloadPayload =
"payload" in payload && "payload" in payload &&
typeof payload.payload === "object" && typeof payload.payload === "object" &&
payload.payload !== null payload.payload !== null
? payload.payload ? payload.payload
: undefined : undefined;
let configLabelKey: string = key let configLabelKey: string = key;
if ( if (
key in payload && key in payload &&
typeof payload[key as keyof typeof payload] === "string" typeof payload[key as keyof typeof payload] === "string"
) { ) {
configLabelKey = payload[key as keyof typeof payload] as string configLabelKey = payload[key as keyof typeof payload] as string;
} else if ( } else if (
payloadPayload && payloadPayload &&
key in payloadPayload && key in payloadPayload &&
typeof payloadPayload[key as keyof typeof payloadPayload] === "string" typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
) { ) {
configLabelKey = payloadPayload[ configLabelKey = payloadPayload[
key as keyof typeof payloadPayload key as keyof typeof payloadPayload
] as string ] as string;
} }
return configLabelKey in config return configLabelKey in config
? config[configLabelKey] ? config[configLabelKey]
: config[key as keyof typeof config] : config[key as keyof typeof config];
} }
export { export {
ChartContainer, ChartContainer,
ChartTooltip, ChartTooltip,
ChartTooltipContent, ChartTooltipContent,
ChartLegend, ChartLegend,
ChartLegendContent, ChartLegendContent,
ChartStyle, ChartStyle
} };

View File

@@ -1,30 +1,30 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox" import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check } from "lucide-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 shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring 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 shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring 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,153 +1,156 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import { type DialogProps } from "@radix-ui/react-dialog" import { type DialogProps } from "@radix-ui/react-dialog";
import { Command as CommandPrimitive } from "cmdk" import { Command as CommandPrimitive } from "cmdk";
import { Search } from "lucide-react" import { Search } from "lucide-react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { Dialog, DialogContent } from "@/components/ui/dialog" 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;
const CommandDialog = ({ children, ...props }: DialogProps) => { const CommandDialog = ({ children, ...props }: DialogProps) => {
return ( return (
<Dialog {...props}> <Dialog {...props}>
<DialogContent className="overflow-hidden p-0"> <DialogContent className="overflow-hidden p-0">
<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-10 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-10 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(
{...props} "max-h-[300px] overflow-y-auto overflow-x-hidden",
/> className
)) )}
{...props}
/>
));
CommandList.displayName = CommandPrimitive.List.displayName CommandList.displayName = CommandPrimitive.List.displayName;
const CommandEmpty = React.forwardRef< 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 <CommandPrimitive.Empty
ref={ref} ref={ref}
className="py-6 text-center text-sm" className="py-6 text-center text-sm"
{...props} {...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 gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
className className
)} )}
{...props} {...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( className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground", "ml-auto text-xs tracking-widest text-muted-foreground",
className className
)} )}
{...props} {...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,200 +1,200 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
import { Check, ChevronRight, Circle } from "lucide-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-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}
/> />
)) ));
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 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}
/> />
</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 = ContextMenuCheckboxItem.displayName =
ContextMenuPrimitive.CheckboxItem.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-4 w-4 fill-current" /> <Circle className="h-4 w-4 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( className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground", "ml-auto text-xs tracking-widest text-muted-foreground",
className className
)} )}
{...props} {...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,122 +1,122 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog" import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-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 = ({ const DialogHeader = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn( className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left", "flex flex-col space-y-1.5 text-center sm:text-left",
className className
)} )}
{...props} {...props}
/> />
) );
DialogHeader.displayName = "DialogHeader" DialogHeader.displayName = "DialogHeader";
const DialogFooter = ({ const DialogFooter = ({
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}
/> />
) );
DialogFooter.displayName = "DialogFooter" 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( className={cn(
"text-lg font-semibold leading-none tracking-tight", "text-lg font-semibold leading-none tracking-tight",
className className
)} )}
{...props} {...props}
/> />
)) ));
DialogTitle.displayName = DialogPrimitive.Title.displayName 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,
DialogTrigger, DialogTrigger,
DialogClose, DialogClose,
DialogContent, DialogContent,
DialogHeader, DialogHeader,
DialogFooter, DialogFooter,
DialogTitle, DialogTitle,
DialogDescription, DialogDescription
} };

View File

@@ -1,118 +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 <DrawerPrimitive.Root
shouldScaleBackground={shouldScaleBackground} shouldScaleBackground={shouldScaleBackground}
{...props} {...props}
/> />
) );
Drawer.displayName = "Drawer" 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 = ({ const DrawerHeader = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
{...props} {...props}
/> />
) );
DrawerHeader.displayName = "DrawerHeader" DrawerHeader.displayName = "DrawerHeader";
const DrawerFooter = ({ const DrawerFooter = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn("mt-auto flex flex-col gap-2 p-4", className)} className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props} {...props}
/> />
) );
DrawerFooter.displayName = "DrawerFooter" 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( className={cn(
"text-lg font-semibold leading-none tracking-tight", "text-lg font-semibold leading-none tracking-tight",
className className
)} )}
{...props} {...props}
/> />
)) ));
DrawerTitle.displayName = DrawerPrimitive.Title.displayName 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,201 +1,204 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check, ChevronRight, Circle } from "lucide-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 gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", "flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
inset && "pl-8", inset && "pl-8",
className className
)} )}
{...props} {...props}
> >
{children} {children}
<ChevronRight className="ml-auto" /> <ChevronRight className="ml-auto" />
</DropdownMenuPrimitive.SubTrigger> </DropdownMenuPrimitive.SubTrigger>
)) ));
DropdownMenuSubTrigger.displayName = DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.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 = DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.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", "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", "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 gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0", "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
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 = DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.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( className={cn(
"px-2 py-1.5 text-sm font-semibold", "px-2 py-1.5 text-sm font-semibold",
inset && "pl-8", inset && "pl-8",
className className
)} )}
{...props} {...props}
/> />
)) ));
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName 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(
{...props} "ml-auto text-xs tracking-widest opacity-60",
/> className
) )}
} {...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,178 +1,182 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label" import * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot";
import { import {
Controller, Controller,
ControllerProps, ControllerProps,
FieldPath, FieldPath,
FieldValues, FieldValues,
FormProvider, FormProvider,
useFormContext, useFormContext
} from "react-hook-form" } from "react-hook-form";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { Label } from "@/components/ui/label" 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< const FormItem = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
const id = React.useId() 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 !error
? `${formDescriptionId}` ? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}` : `${formDescriptionId} ${formMessageId}`
} }
aria-invalid={!!error} aria-invalid={!!error}
{...props} {...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-[0.8rem] text-muted-foreground", className)} className={cn("text-[0.8rem] 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-[0.8rem] font-medium text-destructive", className)} className={cn(
{...props} "text-[0.8rem] font-medium text-destructive",
> className
{body} )}
</p> {...props}
) >
}) {body}
FormMessage.displayName = "FormMessage" </p>
);
});
FormMessage.displayName = "FormMessage";
export { export {
useFormField, useFormField,
Form, Form,
FormItem, FormItem,
FormLabel, FormLabel,
FormControl, FormControl,
FormDescription, FormDescription,
FormMessage, FormMessage,
FormField, FormField
} };

View File

@@ -1,29 +1,29 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as HoverCardPrimitive from "@radix-ui/react-hover-card" 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 * as React from "react" import * as React from "react";
import { OTPInput, OTPInputContext } from "input-otp" import { OTPInput, OTPInputContext } from "input-otp";
import { Minus } from "lucide-react" import { Minus } 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-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md", "relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
isActive && "z-10 ring-1 ring-ring", isActive && "z-10 ring-1 ring-ring",
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}>
<Minus /> <Minus />
</div> </div>
)) ));
InputOTPSeparator.displayName = "InputOTPSeparator" InputOTPSeparator.displayName = "InputOTPSeparator";
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };

View File

@@ -1,22 +1,22 @@
import * as React from "react" import * as React from "react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => { ({ className, type, ...props }, ref) => {
return ( return (
<input <input
type={type} type={type}
className={cn( className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className className
)} )}
ref={ref} ref={ref}
{...props} {...props}
/> />
) );
} }
) );
Input.displayName = "Input" Input.displayName = "Input";
export { Input } export { Input };

View File

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

View File

@@ -1,256 +1,262 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as MenubarPrimitive from "@radix-ui/react-menubar" import * as MenubarPrimitive from "@radix-ui/react-menubar";
import { Check, ChevronRight, Circle } from "lucide-react" import { Check, ChevronRight, Circle } from "lucide-react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
function MenubarMenu({ function MenubarMenu({
...props ...props
}: React.ComponentProps<typeof MenubarPrimitive.Menu>) { }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
return <MenubarPrimitive.Menu {...props} /> return <MenubarPrimitive.Menu {...props} />;
} }
function MenubarGroup({ function MenubarGroup({
...props ...props
}: React.ComponentProps<typeof MenubarPrimitive.Group>) { }: React.ComponentProps<typeof MenubarPrimitive.Group>) {
return <MenubarPrimitive.Group {...props} /> return <MenubarPrimitive.Group {...props} />;
} }
function MenubarPortal({ function MenubarPortal({
...props ...props
}: React.ComponentProps<typeof MenubarPrimitive.Portal>) { }: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
return <MenubarPrimitive.Portal {...props} /> return <MenubarPrimitive.Portal {...props} />;
} }
function MenubarRadioGroup({ function MenubarRadioGroup({
...props ...props
}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) { }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
return <MenubarPrimitive.RadioGroup {...props} /> return <MenubarPrimitive.RadioGroup {...props} />;
} }
function MenubarSub({ function MenubarSub({
...props ...props
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) { }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} /> return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
} }
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-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm", "flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm",
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 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 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 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}
/> />
)) ));
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 className,
) => ( align = "start",
<MenubarPrimitive.Portal> alignOffset = -4,
<MenubarPrimitive.Content sideOffset = 8,
ref={ref} ...props
align={align} },
alignOffset={alignOffset} ref
sideOffset={sideOffset} ) => (
className={cn( <MenubarPrimitive.Portal>
"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.Content
className ref={ref}
)} align={align}
{...props} alignOffset={alignOffset}
/> sideOffset={sideOffset}
</MenubarPrimitive.Portal> className={cn(
) "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
) className
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-4 w-4 fill-current" /> <Circle className="h-4 w-4 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( className={cn(
"px-2 py-1.5 text-sm font-semibold", "px-2 py-1.5 text-sm font-semibold",
inset && "pl-8", inset && "pl-8",
className className
)} )}
{...props} {...props}
/> />
)) ));
MenubarLabel.displayName = MenubarPrimitive.Label.displayName 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( className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground", "ml-auto text-xs tracking-widest text-muted-foreground",
className className
)} )}
{...props} {...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,128 +1,128 @@
import * as React from "react" import * as React from "react";
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
import { cva } from "class-variance-authority" import { cva } from "class-variance-authority";
import { ChevronDown } from "lucide-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-9 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-9 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-300 group-data-[state=open]:rotate-180" className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 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(
"left-0 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 ", "left-0 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 left-0 top-full flex justify-center")}> <div className={cn("absolute 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-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow 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-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow 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 = NavigationMenuViewport.displayName =
NavigationMenuPrimitive.Viewport.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 = NavigationMenuIndicator.displayName =
NavigationMenuPrimitive.Indicator.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,117 +1,117 @@
import * as React from "react" import * as React from "react";
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react" import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { ButtonProps, buttonVariants } from "@/components/ui/button" 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< const PaginationContent = React.forwardRef<
HTMLUListElement, HTMLUListElement,
React.ComponentProps<"ul"> React.ComponentProps<"ul">
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<ul <ul
ref={ref} ref={ref}
className={cn("flex flex-row items-center gap-1", className)} className={cn("flex flex-row items-center gap-1", className)}
{...props} {...props}
/> />
)) ));
PaginationContent.displayName = "PaginationContent" PaginationContent.displayName = "PaginationContent";
const PaginationItem = React.forwardRef< const PaginationItem = React.forwardRef<
HTMLLIElement, HTMLLIElement,
React.ComponentProps<"li"> React.ComponentProps<"li">
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<li ref={ref} className={cn("", className)} {...props} /> <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 = ({ const PaginationEllipsis = ({
className, className,
...props ...props
}: React.ComponentProps<"span">) => ( }: React.ComponentProps<"span">) => (
<span <span
aria-hidden aria-hidden
className={cn("flex h-9 w-9 items-center justify-center", className)} className={cn("flex h-9 w-9 items-center justify-center", className)}
{...props} {...props}
> >
<MoreHorizontal className="h-4 w-4" /> <MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More pages</span> <span className="sr-only">More pages</span>
</span> </span>
) );
PaginationEllipsis.displayName = "PaginationEllipsis" PaginationEllipsis.displayName = "PaginationEllipsis";
export { export {
Pagination, Pagination,
PaginationContent, PaginationContent,
PaginationLink, PaginationLink,
PaginationItem, PaginationItem,
PaginationPrevious, PaginationPrevious,
PaginationNext, PaginationNext,
PaginationEllipsis, PaginationEllipsis
} };

View File

@@ -1,33 +1,33 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as PopoverPrimitive from "@radix-ui/react-popover" 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 PopoverAnchor = PopoverPrimitive.Anchor const PopoverAnchor = PopoverPrimitive.Anchor;
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, PopoverAnchor } export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };

View File

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

View File

@@ -1,44 +1,44 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { Circle } from "lucide-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 shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", "aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring 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-3.5 w-3.5 fill-primary" /> <Circle className="h-3.5 w-3.5 fill-primary" />
</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,48 +1,50 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" 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" && orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]", "h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" && orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]", "h-2.5 flex-col border-t border-t-transparent p-[1px]",
className className
)} )}
{...props} {...props}
> >
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" /> <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar> </ScrollAreaPrimitive.ScrollAreaScrollbar>
)) ));
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
export { ScrollArea, ScrollBar } export { ScrollArea, ScrollBar };

View File

@@ -1,159 +1,159 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as SelectPrimitive from "@radix-ui/react-select" import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown, ChevronUp } from "lucide-react" import { Check, ChevronDown, ChevronUp } from "lucide-react";
import { 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-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring 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( className={cn(
"flex cursor-default items-center justify-center py-1", "flex cursor-default items-center justify-center py-1",
className className
)} )}
{...props} {...props}
> >
<ChevronUp className="h-4 w-4" /> <ChevronUp className="h-4 w-4" />
</SelectPrimitive.ScrollUpButton> </SelectPrimitive.ScrollUpButton>
)) ));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
const SelectScrollDownButton = React.forwardRef< const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>, React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
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( className={cn(
"flex cursor-default items-center justify-center py-1", "flex cursor-default items-center justify-center py-1",
className className
)} )}
{...props} {...props}
> >
<ChevronDown className="h-4 w-4" /> <ChevronDown className="h-4 w-4" />
</SelectPrimitive.ScrollDownButton> </SelectPrimitive.ScrollDownButton>
)) ));
SelectScrollDownButton.displayName = SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName SelectPrimitive.ScrollDownButton.displayName;
const SelectContent = React.forwardRef< const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>, React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => ( >(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal> <SelectPrimitive.Portal>
<SelectPrimitive.Content <SelectPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" && position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className className
)} )}
position={position} position={position}
{...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("px-2 py-1.5 text-sm font-semibold", className)} className={cn("px-2 py-1.5 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-2 pr-8 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-2 pr-8 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 right-2 flex h-3.5 w-3.5 items-center justify-center"> <span className="absolute right-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,31 +1,33 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as SeparatorPrimitive from "@radix-ui/react-separator" 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 }, { className, orientation = "horizontal", decorative = true, ...props },
ref ref
) => ( ) => (
<SeparatorPrimitive.Root <SeparatorPrimitive.Root
ref={ref} ref={ref}
decorative={decorative} decorative={decorative}
orientation={orientation} orientation={orientation}
className={cn( className={cn(
"shrink-0 bg-border", "shrink-0 bg-border",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", orientation === "horizontal"
className ? "h-[1px] w-full"
)} : "h-full w-[1px]",
{...props} className
/> )}
) {...props}
) />
Separator.displayName = SeparatorPrimitive.Root.displayName )
);
Separator.displayName = SeparatorPrimitive.Root.displayName;
export { Separator } export { Separator };

View File

@@ -1,140 +1,138 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as SheetPrimitive from "@radix-ui/react-dialog" import * as SheetPrimitive from "@radix-ui/react-dialog";
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-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=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out", "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
{ {
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: "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"
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", },
}, defaultVariants: {
}, side: "right"
defaultVariants: { }
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}
> >
<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>
{children} {children}
</SheetPrimitive.Content> </SheetPrimitive.Content>
</SheetPortal> </SheetPortal>
)) ));
SheetContent.displayName = SheetPrimitive.Content.displayName SheetContent.displayName = SheetPrimitive.Content.displayName;
const SheetHeader = ({ const SheetHeader = ({
className, className,
...props ...props
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn( className={cn(
"flex flex-col space-y-2 text-center sm:text-left", "flex flex-col space-y-2 text-center sm:text-left",
className className
)} )}
{...props} {...props}
/> />
) );
SheetHeader.displayName = "SheetHeader" SheetHeader.displayName = "SheetHeader";
const SheetFooter = ({ const SheetFooter = ({
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}
/> />
) );
SheetFooter.displayName = "SheetFooter" 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
} };

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,28 +1,28 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as SliderPrimitive from "@radix-ui/react-slider" 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( className={cn(
"relative flex w-full touch-none select-none items-center", "relative flex w-full touch-none select-none items-center",
className className
)} )}
{...props} {...props}
> >
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20"> <SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" /> <SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track> </SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" /> <SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root> </SliderPrimitive.Root>
)) ));
Slider.displayName = SliderPrimitive.Root.displayName Slider.displayName = SliderPrimitive.Root.displayName;
export { Slider } export { Slider };

View File

@@ -1,31 +1,30 @@
"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:
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground"
"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 React from "react" import * as React from "react";
import * as SwitchPrimitives from "@radix-ui/react-switch" 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-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm 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-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm 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-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0" "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 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,120 +1,120 @@
import * as React from "react" import * as React from "react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
const Table = React.forwardRef< const Table = React.forwardRef<
HTMLTableElement, HTMLTableElement,
React.HTMLAttributes<HTMLTableElement> React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto"> <div className="relative w-full overflow-auto">
<table <table
ref={ref} ref={ref}
className={cn("w-full caption-bottom text-sm", className)} className={cn("w-full caption-bottom text-sm", className)}
{...props} {...props}
/> />
</div> </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 <tbody
ref={ref} ref={ref}
className={cn("[&_tr:last-child]:border-0", className)} className={cn("[&_tr:last-child]:border-0", className)}
{...props} {...props}
/> />
)) ));
TableBody.displayName = "TableBody" 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( className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className className
)} )}
{...props} {...props}
/> />
)) ));
TableFooter.displayName = "TableFooter" 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-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", "h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
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( className={cn(
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className 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 React from "react" import * as React from "react";
import * as TabsPrimitive from "@radix-ui/react-tabs" 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-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground", "inline-flex h-9 items-center justify-center rounded-lg 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-md px-3 py-1 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", "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 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",
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,22 +1,22 @@
import * as React from "react" import * as React from "react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
const Textarea = React.forwardRef< const Textarea = React.forwardRef<
HTMLTextAreaElement, HTMLTextAreaElement,
React.ComponentProps<"textarea"> React.ComponentProps<"textarea">
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
return ( return (
<textarea <textarea
className={cn( className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className className
)} )}
ref={ref} ref={ref}
{...props} {...props}
/> />
) );
}) });
Textarea.displayName = "Textarea" Textarea.displayName = "Textarea";
export { Textarea } export { Textarea };

View File

@@ -1,129 +1,129 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as ToastPrimitives from "@radix-ui/react-toast" import * as ToastPrimitives from "@radix-ui/react-toast";
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-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-2 overflow-hidden rounded-md border p-4 pr-6 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-2 overflow-hidden rounded-md border p-4 pr-6 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 transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring 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 transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring 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-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 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-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 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 [&+div]:text-xs", className)} className={cn("text-sm font-semibold [&+div]:text-xs", 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,35 +1,43 @@
"use client" "use client";
import { useToast } from "@/hooks/use-toast" import { useToast } from "@/hooks/use-toast";
import { import {
Toast, Toast,
ToastClose, ToastClose,
ToastDescription, ToastDescription,
ToastProvider, ToastProvider,
ToastTitle, ToastTitle,
ToastViewport, ToastViewport
} from "@/components/ui/toast" } from "@/components/ui/toast";
export function Toaster() { export function Toaster() {
const { toasts } = useToast() const { toasts } = useToast();
return ( return (
<ToastProvider> <ToastProvider>
{toasts.map(function ({ id, title, description, action, ...props }) { {toasts.map(function ({
return ( id,
<Toast key={id} {...props}> title,
<div className="grid gap-1"> description,
{title && <ToastTitle>{title}</ToastTitle>} action,
{description && ( ...props
<ToastDescription>{description}</ToastDescription> }) {
)} return (
</div> <Toast key={id} {...props}>
{action} <div className="grid gap-1">
<ToastClose /> {title && <ToastTitle>{title}</ToastTitle>}
</Toast> {description && (
) <ToastDescription>
})} {description}
<ToastViewport /> </ToastDescription>
</ToastProvider> )}
) </div>
{action}
<ToastClose />
</Toast>
);
})}
<ToastViewport />
</ToastProvider>
);
} }

View File

@@ -1,61 +1,61 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
import { type VariantProps } from "class-variance-authority" import { type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { toggleVariants } from "@/components/ui/toggle" import { toggleVariants } from "@/components/ui/toggle";
const ToggleGroupContext = React.createContext< const ToggleGroupContext = React.createContext<
VariantProps<typeof toggleVariants> VariantProps<typeof toggleVariants>
>({ >({
size: "default", size: "default",
variant: "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 React from "react" import * as React from "react";
import * as TogglePrimitive from "@radix-ui/react-toggle" import * as TogglePrimitive from "@radix-ui/react-toggle";
import { cva, type VariantProps } from "class-variance-authority" 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 gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{ {
variants: { variants: {
variant: { variant: {
default: "bg-transparent", default: "bg-transparent",
outline: outline:
"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground", "border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground"
}, },
size: { size: {
default: "h-9 px-2 min-w-9", default: "h-9 px-2 min-w-9",
sm: "h-8 px-1.5 min-w-8", sm: "h-8 px-1.5 min-w-8",
lg: "h-10 px-2.5 min-w-10", lg: "h-10 px-2.5 min-w-10"
}, }
}, },
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,32 +1,32 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip" 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.Portal> <TooltipPrimitive.Portal>
<TooltipPrimitive.Content <TooltipPrimitive.Content
ref={ref} ref={ref}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground 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 bg-primary px-3 py-1.5 text-xs text-primary-foreground 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}
/> />
</TooltipPrimitive.Portal> </TooltipPrimitive.Portal>
)) ));
TooltipContent.displayName = TooltipPrimitive.Content.displayName TooltipContent.displayName = TooltipPrimitive.Content.displayName;
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from "react";
// Shared cache and listeners // Shared cache and listeners
const gameImages: { [id: string]: string } = {}; const gameImages: { [id: string]: string } = {};
@@ -27,6 +27,6 @@ export function useThumbnailURL(img: string) {
export function addThumbnail(id: string, url: string) { export function addThumbnail(id: string, url: string) {
gameImages[id] = url; gameImages[id] = url;
if (listeners[id]) { if (listeners[id]) {
listeners[id].forEach(cb => cb(url)); listeners[id].forEach((cb) => cb(url));
} }
} }

View File

@@ -1,19 +1,23 @@
import * as React from "react" import * as React from "react";
const MOBILE_BREAKPOINT = 768 const MOBILE_BREAKPOINT = 768;
export function useIsMobile() { export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
undefined
);
React.useEffect(() => { React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) const mql = window.matchMedia(
const onChange = () => { `(max-width: ${MOBILE_BREAKPOINT - 1}px)`
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) );
} const onChange = () => {
mql.addEventListener("change", onChange) setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) };
return () => mql.removeEventListener("change", onChange) mql.addEventListener("change", onChange);
}, []) setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
return () => mql.removeEventListener("change", onChange);
}, []);
return !!isMobile return !!isMobile;
} }

View File

@@ -1,194 +1,192 @@
"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 { import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
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 => { export const reducer = (state: State, action: Action): State => {
switch (action.type) { switch (action.type) {
case "ADD_TOAST": case "ADD_TOAST":
return { return {
...state, ...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
} };
case "UPDATE_TOAST": case "UPDATE_TOAST":
return { return {
...state, ...state,
toasts: state.toasts.map((t) => toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t t.id === action.toast.id ? { ...t, ...action.toast } : t
), )
} };
case "DISMISS_TOAST": { case "DISMISS_TOAST": {
const { toastId } = action const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action, // ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity // but I'll keep it here for simplicity
if (toastId) { if (toastId) {
addToRemoveQueue(toastId) addToRemoveQueue(toastId);
} else { } else {
state.toasts.forEach((toast) => { state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id) addToRemoveQueue(toast.id);
}) });
} }
return { return {
...state, ...state,
toasts: state.toasts.map((t) => toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined t.id === toastId || toastId === undefined
? { ? {
...t, ...t,
open: false, open: false
} }
: t : t
), )
} };
} }
case "REMOVE_TOAST": case "REMOVE_TOAST":
if (action.toastId === undefined) { if (action.toastId === undefined) {
return { return {
...state, ...state,
toasts: [], toasts: []
} };
} }
return { return {
...state, ...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId), toasts: state.toasts.filter((t) => t.id !== action.toastId)
} };
} }
} };
const listeners: Array<(state: State) => void> = [] const listeners: Array<(state: State) => void> = [];
let memoryState: State = { toasts: [] } let memoryState: State = { toasts: [] };
function dispatch(action: Action) { function dispatch(action: Action) {
memoryState = reducer(memoryState, action) memoryState = reducer(memoryState, action);
listeners.forEach((listener) => { listeners.forEach((listener) => {
listener(memoryState) listener(memoryState);
}) });
} }
type Toast = Omit<ToasterToast, "id"> 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,81 +1,83 @@
"use client"; "use client";
import { getCookie } from "./roblox";
import { proxyFetch } from "./utils"; import { proxyFetch } from "./utils";
type RecommendationEntry = { type RecommendationEntry = {
contentType: "Game"|string, contentType: "Game" | string;
contentId: number, contentId: number;
contentStringId: string, contentStringId: string;
contentMetadata: { contentMetadata: {
Score: string Score: string;
} };
} };
type RecommendationSort = { type RecommendationSort = {
topic: string, topic: string;
topicId: number, topicId: number;
treatmentType: string, treatmentType: string;
recommendationList: RecommendationEntry[], recommendationList: RecommendationEntry[];
nextPageTokenForTopic: null, nextPageTokenForTopic: null;
numberOfRows: number, numberOfRows: number;
topicLayoutData: any topicLayoutData: any;
} };
export type ContentMetadata = { export type ContentMetadata = {
totalUpVotes: number, totalUpVotes: number;
totalDownVotes: number, totalDownVotes: number;
universeId: number, universeId: number;
name: string, name: string;
rootPlaceId: number, rootPlaceId: number;
description: null, description: null;
playerCount: number, playerCount: number;
primaryMediaAsset: any, primaryMediaAsset: any;
under9: boolean, under9: boolean;
under13: boolean, under13: boolean;
minimumAge: number, minimumAge: number;
ageRecommendationDisplayName: string, ageRecommendationDisplayName: string;
friendVisits: any[], friendVisits: any[];
friendVisitedString: string, friendVisitedString: string;
layoutDataBySort: any layoutDataBySort: any;
} };
export type OmniRecommendation = { export type OmniRecommendation = {
pageType: "Home" | string, pageType: "Home" | string;
requestId: string, requestId: string;
sortsRefreshInterval: number, sortsRefreshInterval: number;
contentMetadata: { contentMetadata: {
Game: {[id: string]: ContentMetadata}, Game: { [id: string]: ContentMetadata };
CatalogAsset: any, CatalogAsset: any;
CatalogBundle: any, CatalogBundle: any;
RecommendedFriend: any, RecommendedFriend: any;
GameCoPlay: any GameCoPlay: any;
}, };
nextPageToken: string, nextPageToken: string;
isSessionExpired: boolean, isSessionExpired: boolean;
globalLayoutData: any, globalLayoutData: any;
isPartialFeed: boolean, isPartialFeed: boolean;
DebugInfoGroups: boolean, DebugInfoGroups: boolean;
sorts: RecommendationSort[] sorts: RecommendationSort[];
} };
export async function getOmniRecommendationsHome(): Promise<OmniRecommendation> { export async function getOmniRecommendationsHome(): Promise<OmniRecommendation> {
const data = await proxyFetch(`https://apis.roblox.com/discovery-api/omni-recommendation`,{ const data = await proxyFetch(
method: "POST", `https://apis.roblox.com/discovery-api/omni-recommendation`,
body: JSON.stringify({ {
pageType: "Home", method: "POST",
sessionId: crypto.randomUUID(), body: JSON.stringify({
supportedTreatmentTypes: ["SortlessGrid"], pageType: "Home",
authIntentData: null, sessionId: crypto.randomUUID(),
cpuCores: 4, supportedTreatmentTypes: ["SortlessGrid"],
maxResolution: "1920x1080", authIntentData: null,
maxMemory: 8192 cpuCores: 4,
}), maxResolution: "1920x1080",
headers: { maxMemory: 8192
"Content-Type": "application/json" }),
headers: {
"Content-Type": "application/json"
}
} }
}) );
return await data.json() as OmniRecommendation return (await data.json()) as OmniRecommendation;
} }
// https://apis.roblox.com/discovery-api/omni-recommendation // https://apis.roblox.com/discovery-api/omni-recommendation

View File

@@ -1,41 +1,48 @@
import { getCookie } from "./roblox" import { proxyFetch } from "./utils";
import { proxyFetch } from "./utils"
export type UserProfileDetails = { export type UserProfileDetails = {
description: string, description: string;
created: Date, created: Date;
isBanned: boolean, isBanned: boolean;
externalAppDisplayName: string, externalAppDisplayName: string;
hasVerifiedBadge: boolean, hasVerifiedBadge: boolean;
id: number, id: number;
name: string, name: string;
displayName: string displayName: string;
} };
export async function getLoggedInUser(): Promise<{ export async function getLoggedInUser(): Promise<{
id: number, id: number;
name: string, name: string;
displayName: string displayName: string;
}> { }> {
const data = await proxyFetch(`https://users.roblox.com/v1/users/authenticated`, { const data = await proxyFetch(
method: "GET", `https://users.roblox.com/v1/users/authenticated`,
headers: { {
"Content-Type": "application/json" method: "GET",
headers: {
"Content-Type": "application/json"
}
} }
}) );
return (await data.json() as any) as { return (await data.json()) as any as {
id: number, id: number;
name: string, name: string;
displayName: string displayName: string;
} };
} }
export async function getUserByUserId(userid: string): Promise<UserProfileDetails> { export async function getUserByUserId(
const data = await proxyFetch(`https://users.roblox.com/v1/users/${userid}`, { userid: string
method: "GET", ): Promise<UserProfileDetails> {
headers: { const data = await proxyFetch(
"Content-Type": "application/json" `https://users.roblox.com/v1/users/${userid}`,
{
method: "GET",
headers: {
"Content-Type": "application/json"
}
} }
}) );
return (await data.json() as any) as UserProfileDetails return (await data.json()) as any as UserProfileDetails;
} }

View File

@@ -1,5 +0,0 @@
export function setCookie(cookie: string): void {}
export async function getCookie(): Promise<string> {
return "";
}

View File

@@ -41,12 +41,12 @@ export async function getThumbnails(
targetId: a.targetId, targetId: a.targetId,
token: "", token: "",
format: a.format, format: a.format,
size: a.size, size: a.size
})) }))
), ),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json"
}, }
} }
); );
const json = await data.json(); const json = await data.json();

View File

@@ -13,8 +13,8 @@ export async function proxyFetch(
typeof input === "string" typeof input === "string"
? input ? input
: input instanceof Request : input instanceof Request
? input.url ? input.url
: ""; : "";
const proxyUrl = `/api/proxy?url=${encodeURIComponent(url)}`; const proxyUrl = `/api/proxy?url=${encodeURIComponent(url)}`;
// fix headers // fix headers
@@ -25,7 +25,7 @@ export async function proxyFetch(
...init, ...init,
method: init?.method || "GET", method: init?.method || "GET",
headers, headers,
body: init?.body, body: init?.body
}; };
return window.fetch(proxyUrl, fetchInit); return window.fetch(proxyUrl, fetchInit);

View File

@@ -1,7 +1,19 @@
import type { NextConfig } from "next"; import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
/* config options here */ /* config options here */
images: {
remotePatterns: [
{
protocol: "https",
hostname: "**"
},
{
protocol: "http",
hostname: "**"
},
],
},
}; };
export default nextConfig; export default nextConfig;

View File

@@ -1,70 +1,70 @@
{ {
"name": "roblox", "name": "roblox",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev --turbopack", "dev": "next dev --turbopack",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@catppuccin/tailwindcss": "^0.1.6", "@catppuccin/tailwindcss": "^0.1.6",
"@hookform/resolvers": "^4.0.0", "@hookform/resolvers": "^4.0.0",
"@radix-ui/react-accordion": "^1.2.3", "@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-alert-dialog": "^1.1.6", "@radix-ui/react-alert-dialog": "^1.1.6",
"@radix-ui/react-aspect-ratio": "^1.1.2", "@radix-ui/react-aspect-ratio": "^1.1.2",
"@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-avatar": "^1.1.3",
"@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.3", "@radix-ui/react-collapsible": "^1.1.3",
"@radix-ui/react-context-menu": "^2.2.6", "@radix-ui/react-context-menu": "^2.2.6",
"@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-hover-card": "^1.1.6", "@radix-ui/react-hover-card": "^1.1.6",
"@radix-ui/react-label": "^2.1.2", "@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-menubar": "^1.1.6", "@radix-ui/react-menubar": "^1.1.6",
"@radix-ui/react-navigation-menu": "^1.2.5", "@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-radio-group": "^1.2.3", "@radix-ui/react-radio-group": "^1.2.3",
"@radix-ui/react-scroll-area": "^1.2.3", "@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-select": "^2.1.6", "@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slider": "^1.2.3", "@radix-ui/react-slider": "^1.2.3",
"@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.3", "@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toast": "^1.2.6", "@radix-ui/react-toast": "^1.2.6",
"@radix-ui/react-toggle": "^1.1.2", "@radix-ui/react-toggle": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.1.2", "@radix-ui/react-toggle-group": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8", "@radix-ui/react-tooltip": "^1.1.8",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "1.0.0", "cmdk": "1.0.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"embla-carousel-react": "^8.5.2", "embla-carousel-react": "^8.5.2",
"input-otp": "^1.4.2", "input-otp": "^1.4.2",
"lucide-react": "^0.475.0", "lucide-react": "^0.475.0",
"next": "15.1.6", "next": "15.1.6",
"next-themes": "^0.4.4", "next-themes": "^0.4.4",
"react": "^19.0.0", "react": "^19.0.0",
"react-day-picker": "8.10.1", "react-day-picker": "8.10.1",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-resizable-panels": "^2.1.7", "react-resizable-panels": "^2.1.7",
"recharts": "^2.15.1", "recharts": "^2.15.1",
"sonner": "^1.7.4", "sonner": "^1.7.4",
"tailwind-merge": "^3.0.1", "tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"vaul": "^1.1.2", "vaul": "^1.1.2",
"zod": "^3.24.2" "zod": "^3.24.2"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^5", "typescript": "^5",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",
"postcss": "^8", "postcss": "^8",
"tailwindcss": "^3.4.1" "tailwindcss": "^3.4.1"
} }
} }

View File

@@ -1,8 +1,8 @@
/** @type {import('postcss-load-config').Config} */ /** @type {import('postcss-load-config').Config} */
const config = { const config = {
plugins: { plugins: {
tailwindcss: {}, tailwindcss: {}
}, }
}; };
export default config; export default config;

View File

@@ -5,88 +5,90 @@ export default {
content: [ content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}", "./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}", "./app/**/*.{js,ts,jsx,tsx,mdx}"
], ],
theme: { theme: {
extend: { extend: {
colors: { colors: {
background: 'hsl(var(--background))', background: "hsl(var(--background))",
foreground: 'hsl(var(--foreground))', foreground: "hsl(var(--foreground))",
card: { card: {
DEFAULT: 'hsl(var(--card))', DEFAULT: "hsl(var(--card))",
foreground: 'hsl(var(--card-foreground))' foreground: "hsl(var(--card-foreground))"
}, },
popover: { popover: {
DEFAULT: 'hsl(var(--popover))', DEFAULT: "hsl(var(--popover))",
foreground: 'hsl(var(--popover-foreground))' foreground: "hsl(var(--popover-foreground))"
}, },
primary: { primary: {
DEFAULT: 'hsl(var(--primary))', DEFAULT: "hsl(var(--primary))",
foreground: 'hsl(var(--primary-foreground))' foreground: "hsl(var(--primary-foreground))"
}, },
secondary: { secondary: {
DEFAULT: 'hsl(var(--secondary))', DEFAULT: "hsl(var(--secondary))",
foreground: 'hsl(var(--secondary-foreground))' foreground: "hsl(var(--secondary-foreground))"
}, },
muted: { muted: {
DEFAULT: 'hsl(var(--muted))', DEFAULT: "hsl(var(--muted))",
foreground: 'hsl(var(--muted-foreground))' foreground: "hsl(var(--muted-foreground))"
}, },
accent: { accent: {
DEFAULT: 'hsl(var(--accent))', DEFAULT: "hsl(var(--accent))",
foreground: 'hsl(var(--accent-foreground))' foreground: "hsl(var(--accent-foreground))"
}, },
destructive: { destructive: {
DEFAULT: 'hsl(var(--destructive))', DEFAULT: "hsl(var(--destructive))",
foreground: 'hsl(var(--destructive-foreground))' foreground: "hsl(var(--destructive-foreground))"
}, },
border: 'hsl(var(--border))', border: "hsl(var(--border))",
input: 'hsl(var(--input))', input: "hsl(var(--input))",
ring: 'hsl(var(--ring))', ring: "hsl(var(--ring))",
chart: { chart: {
'1': 'hsl(var(--chart-1))', "1": "hsl(var(--chart-1))",
'2': 'hsl(var(--chart-2))', "2": "hsl(var(--chart-2))",
'3': 'hsl(var(--chart-3))', "3": "hsl(var(--chart-3))",
'4': 'hsl(var(--chart-4))', "4": "hsl(var(--chart-4))",
'5': 'hsl(var(--chart-5))' "5": "hsl(var(--chart-5))"
}, },
sidebar: { sidebar: {
DEFAULT: 'hsl(var(--sidebar-background))', DEFAULT: "hsl(var(--sidebar-background))",
foreground: 'hsl(var(--sidebar-foreground))', foreground: "hsl(var(--sidebar-foreground))",
primary: 'hsl(var(--sidebar-primary))', primary: "hsl(var(--sidebar-primary))",
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))', "primary-foreground":
accent: 'hsl(var(--sidebar-accent))', "hsl(var(--sidebar-primary-foreground))",
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))', accent: "hsl(var(--sidebar-accent))",
border: 'hsl(var(--sidebar-border))', "accent-foreground":
ring: 'hsl(var(--sidebar-ring))' "hsl(var(--sidebar-accent-foreground))",
border: "hsl(var(--sidebar-border))",
ring: "hsl(var(--sidebar-ring))"
} }
}, },
borderRadius: { borderRadius: {
lg: 'var(--radius)', lg: "var(--radius)",
md: 'calc(var(--radius) - 2px)', md: "calc(var(--radius) - 2px)",
sm: 'calc(var(--radius) - 4px)' sm: "calc(var(--radius) - 4px)"
}, },
keyframes: { keyframes: {
'accordion-down': { "accordion-down": {
from: { from: {
height: '0' height: "0"
}, },
to: { to: {
height: 'var(--radix-accordion-content-height)' height: "var(--radix-accordion-content-height)"
} }
}, },
'accordion-up': { "accordion-up": {
from: { from: {
height: 'var(--radix-accordion-content-height)' height: "var(--radix-accordion-content-height)"
}, },
to: { to: {
height: '0' height: "0"
} }
} }
}, },
animation: { animation: {
'accordion-down': 'accordion-down 0.2s ease-out', "accordion-down": "accordion-down 0.2s ease-out",
'accordion-up': 'accordion-up 0.2s ease-out' "accordion-up": "accordion-up 0.2s ease-out"
} }
} }
}, },
@@ -96,5 +98,5 @@ export default {
prefix: false, prefix: false,
defaultFlavour: "mocha" defaultFlavour: "mocha"
}) })
], ]
} satisfies Config; } satisfies Config;

View File

@@ -1,27 +1,27 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2017", "target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"noEmit": true, "noEmit": true,
"esModuleInterop": true, "esModuleInterop": true,
"module": "esnext", "module": "esnext",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve", "jsx": "preserve",
"incremental": true, "incremental": true,
"plugins": [ "plugins": [
{ {
"name": "next" "name": "next"
} }
], ],
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./*"]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }