feat: progress (2/19) & clerk themes and extra theming

This commit is contained in:
dvelo 2025-02-19 14:31:59 -06:00
parent a0a139de02
commit a9d5ddf43d
32 changed files with 768 additions and 325 deletions

@ -71,6 +71,7 @@
"sonner": "^1.7.0", "sonner": "^1.7.0",
"stripe-gradient": "^1.0.1", "stripe-gradient": "^1.0.1",
"tailwind-merge": "^2.3.0", "tailwind-merge": "^2.3.0",
"tailwindcss": "^4.0.7",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"tailwindcss-patch": "^4.0.0", "tailwindcss-patch": "^4.0.0",
"turbo": "^2.4.0", "turbo": "^2.4.0",
@ -92,6 +93,7 @@
"@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3", "@radix-ui/react-tooltip": "^1.1.3",
"@tailwindcss/postcss": "^4.0.7",
"@tailwindcss/typography": "^0.5.13", "@tailwindcss/typography": "^0.5.13",
"@types/canvas-confetti": "^1.6.4", "@types/canvas-confetti": "^1.6.4",
"@types/node": "^20", "@types/node": "^20",

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

@ -31,18 +31,16 @@
"use client"; "use client";
import "../globals.css"; import "../globals.css";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { Inter } from "next/font/google";
import { Placeholder } from "@/components/ui/placeholder"; import { Placeholder } from "@/components/ui/placeholder";
import { X } from "lucide-react"; import { X } from "lucide-react";
import { IsScript } from "@/components/util/is-script"; import { IsScript } from "@/components/util/is-script";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { ClerkProvider } from "@clerk/nextjs";
import Link from "next/link"; import Link from "next/link";
import { NavBar } from "@/components/feat/navbar/navbar"; import { NavBar } from "@/components/feat/navbar/navbar";
import { TooltipProvider } from "@/components/ui/tooltip"; import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/util/theme-provider"; import { ThemeProvider } from "@/components/util/theme-provider";
import { FontBoundary } from "@/components/util/font-boundary";
const inter = Inter({ subsets: ["latin"] }); import { ClerkProvider } from "@/components/util/clerk-provider";
export default function RootLayout({ export default function RootLayout({
children, children,
@ -53,10 +51,7 @@ export default function RootLayout({
const search = searchParams?.get("theme") || "light"; const search = searchParams?.get("theme") || "light";
return ( return (
<ClerkProvider>
<html lang="en"> <html lang="en">
<body className={inter.className}>
<TooltipProvider>
<noscript> <noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max"> <main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder <Placeholder
@ -71,19 +66,22 @@ export default function RootLayout({
</main> </main>
</noscript> </noscript>
<IsScript> <IsScript>
<FontBoundary>
<TooltipProvider>
<ThemeProvider <ThemeProvider
attribute="class" attribute="class"
defaultTheme="system" defaultTheme="system"
enableSystem enableSystem
disableTransitionOnChange disableTransitionOnChange
> >
<ClerkProvider>
<NavBar /> <NavBar />
<div className="pt-16">{children}</div> <div className="pt-16">{children}</div>
</ThemeProvider>
</IsScript>
</TooltipProvider>
</body>
</html>
</ClerkProvider> </ClerkProvider>
</ThemeProvider>
</TooltipProvider>
</FontBoundary>
</IsScript>
</html>
); );
} }

@ -1,9 +1,142 @@
@tailwind base; @import "tailwindcss";
@tailwind components;
@tailwind utilities;
body { @plugin 'tailwindcss-animate';
@custom-variant dark (&:is(.dark *));
@theme {
--animate-spin: spin 1s linear infinite;
--animate-scale-in: scaleIn 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
--color-border: hsl(var(--border));
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-shadcn-primary: hsl(var(--primary));
--color-shadcn-primary-foreground: hsl(var(--primary-foreground));
--color-secondary: hsl(var(--secondary));
--color-secondary-foreground: hsl(var(--secondary-foreground));
--color-destructive: hsl(var(--destructive));
--color-destructive-foreground: hsl(var(--destructive-foreground));
--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));
--color-accent: hsl(var(--accent));
--color-accent-foreground: hsl(var(--accent-foreground));
--color-popover: hsl(var(--popover));
--color-popover-foreground: hsl(var(--popover-foreground));
--color-card: hsl(var(--card));
--color-card-foreground: hsl(var(--card-foreground));
--color-slate-25: rgb(var(--c-s-25, 252 253 254));
--color-slate-50: rgb(var(--c-s-50, 248 250 252));
--color-slate-100: rgb(var(--c-s-100, 241 245 249));
--color-slate-200: rgb(var(--c-s-200, 226 232 240));
--color-slate-300: rgb(var(--c-s-300, 203 213 225));
--color-slate-400: rgb(var(--c-s-400, 148 163 184));
--color-slate-500: rgb(var(--c-s-500, 100 116 139));
--color-slate-600: rgb(var(--c-s-600, 71 85 105));
--color-slate-700: rgb(var(--c-s-700, 51 65 85));
--color-slate-800: rgb(var(--c-s-800, 30 41 59));
--color-slate-900: rgb(var(--c-s-900, 15 23 42));
--color-slate-950: rgb(var(--c-s-950, 2 6 23));
--color-zinc-50: rgb(var(--c-z-50, 249 250 251));
--color-zinc-100: rgb(var(--c-z-100, 243 244 246));
--color-zinc-200: rgb(var(--c-z-200, 229 231 235));
--color-zinc-300: rgb(var(--c-z-300, 209 213 219));
--color-zinc-400: rgb(var(--c-z-400, 156 163 175));
--color-zinc-500: rgb(var(--c-z-500, 107 114 128));
--color-zinc-600: rgb(var(--c-z-600, 75 85 99));
--color-zinc-700: rgb(var(--c-z-700, 50 60 76));
--color-zinc-800: rgb(var(--c-z-800, 22 31 45));
--color-zinc-900: rgb(var(--c-z-900, 17 24 39));
--color-zinc-925: rgb(var(--c-z-925, 8 12 25));
--color-zinc-950: rgb(var(--c-z-950, 5 9 16));
--color-primary-100: rgb(var(--c-p-100, 241 245 249));
--color-primary-900: rgb(var(--c-p-900, 15 23 42));
--color-black: rgb(var(--c-o-black, 0 0 0));
--color-white: rgb(var(--c-o-white, 255 255 255));
--color-sidebar: hsl(var(--sidebar-background));
--color-sidebar-foreground: hsl(var(--sidebar-foreground));
--color-sidebar-primary: hsl(var(--sidebar-primary));
--color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
--color-sidebar-accent: hsl(var(--sidebar-accent));
--color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
--color-sidebar-border: hsl(var(--sidebar-border));
--color-sidebar-ring: hsl(var(--sidebar-ring));
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes scaleIn {
0% {
transform: scale(0.95);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
}
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
@layer utilities {
body {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
}
}
.system-ui-font--font-boundary {
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
"Open Sans",
"Helvetica Neue",
sans-serif;
} }
@layer base { @layer base {
@ -93,8 +226,10 @@ body {
} }
} }
body { @layer utilities {
body {
@apply bg-slate-50 text-slate-900 dark:bg-zinc-950 dark:text-zinc-100 accent-slate-950 dark:accent-zinc-50; @apply bg-slate-50 text-slate-900 dark:bg-zinc-950 dark:text-zinc-100 accent-slate-950 dark:accent-zinc-50;
}
} }
@layer base { @layer base {
@ -106,6 +241,29 @@ body {
} }
} }
.cl-headerTitle {
@apply bg-linear-to-r from-[#3b82f6] to-[#ef4444] bg-clip-text text-transparent;
}
.cl-socialButtonsBlockButtonText__discord {
@apply text-[#5865f2];
}
.cl-socialButtonsBlockButtonText__github {
@apply text-black dark:text-white;
}
.cl-footer {
background: white !important;
&:is(.dark *) {
background: #1e1e24 !important;
}
}
.cl-card {
box-shadow: none !important;
}
@layer base { @layer base {
::view-transition-old(root), ::view-transition-old(root),
::view-transition-new(root) { ::view-transition-new(root) {

@ -31,6 +31,8 @@
"use client"; "use client";
import "./globals.css"; import "./globals.css";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { ThemeProvider } from "@/components/util/theme-provider";
import { ClerkProvider } from "@/components/util/clerk-provider";
import { Inter } from "next/font/google"; import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });
@ -45,7 +47,17 @@ export default function RootLayout({
return ( return (
<html lang="en"> <html lang="en">
<body className={inter.className}>{children}</body> <body className={inter.className}>
<noscript>{children}</noscript>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<ClerkProvider>{children}</ClerkProvider>
</ThemeProvider>
</body>
</html> </html>
); );
} }

@ -90,9 +90,9 @@ export default function Embed({ params }: { params: { server: string } }) {
> >
<ServerCrash <ServerCrash
size={16} size={16}
className="group-hover:text-white p-[4px] group-hover:p-[3px] w-[24px] h-[24px] transition-all bg-gradient-to-r group-hover:from-blue-600 group-hover:to-purple-500 group-hover:rounded" className="group-hover:text-white p-[4px] group-hover:p-[3px] w-[24px] h-[24px] transition-all bg-linear-to-r group-hover:from-blue-600 group-hover:to-purple-500 group-hover:rounded"
/> />
<span className="transition-colors ml-2 group-hover:bg-clip-text group-hover:text-transparent bg-gradient-to-r group-hover:from-blue-600 group-hover:to-purple-500"> <span className="transition-colors ml-2 group-hover:bg-clip-text group-hover:text-transparent bg-linear-to-r group-hover:from-blue-600 group-hover:to-purple-500">
Powered by MHSF Powered by MHSF
</span> </span>
</Link> </Link>

@ -1,5 +1,73 @@
import { Material } from "@/components/ui/material"; import { Material } from "@/components/ui/material";
import {
Setting,
SettingContent,
SettingDescription,
SettingMeta,
SettingTitle,
} from "./setting";
import { ModeToggle } from "@/components/util/mode-toggle";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useEffect, useState } from "react";
import { useSettingsStore } from "@/lib/hooks/use-settings-store";
export function BrowserSettings() { export function BrowserSettings() {
return <Material></Material>; const settingsStore = useSettingsStore();
const [fontFamily, setFontFamily] = useState("inter");
useEffect(() => {
setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
}, [settingsStore]);
return (
<Material className="mt-6 grid gap-4">
<h2 className="text-xl font-semibold text-inherit">Appearance</h2>
<Setting>
<SettingContent>
<SettingMeta>
<SettingTitle>Color Scheme</SettingTitle>
<SettingDescription>
Change the MHSF color scheme
</SettingDescription>
</SettingMeta>
<ModeToggle />
</SettingContent>
</Setting>
<Setting>
<SettingContent>
<SettingMeta>
<SettingTitle>Font</SettingTitle>
<SettingDescription>
Change the default font used in the interface.
</SettingDescription>
</SettingMeta>
<Select
defaultValue="inter"
value={fontFamily}
onValueChange={(c) => {
settingsStore.set("font-family", c, false);
window.dispatchEvent(new Event("font-family-change"));
setFontFamily(c);
}}
>
<SelectTrigger className="max-w-[180px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="inter">Inter</SelectItem>
<SelectItem value="geist-sans">Geist Sans</SelectItem>
<SelectItem value="system-ui">System UI</SelectItem>
<SelectItem value="roboto">Roboto</SelectItem>
</SelectContent>
</Select>
</SettingContent>
</Setting>
</Material>
);
} }

@ -0,0 +1,78 @@
import { cn } from "@/lib/utils";
import type { ReactNode } from "react";
export function Setting({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<div
className={cn(
"flex flex-col w-full justify-between gap-2 max-w-full @container/setting",
className
)}
>
{children}
</div>
);
}
export function SettingContent({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<div className="flex flex-col @md/setting:flex-row items-center gap-2">
{children}
</div>
);
}
export function SettingMeta({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<div
className={cn(
"flex flex-col gap-0.5 flex-[2] w-full flex-shrink-0 min-w-48",
className
)}
>
{children}
</div>
);
}
export function SettingTitle({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return <h1 className={cn("font-medium text-base", className)}>{children}</h1>;
}
export function SettingDescription({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<p className={cn("text-slate-800 dark:text-zinc-200 text-sm", className)}>
{children}
</p>
);
}

@ -16,7 +16,7 @@ export function Settings() {
<h1 className="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-4xl mb-3"> <h1 className="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-4xl mb-3">
Settings Settings
</h1> </h1>
<Tabs defaultValue="account" className="mt-3"> <Tabs defaultValue="browser-settings" className="mt-3">
<TabsList> <TabsList>
<TabsTrigger <TabsTrigger
value="browser-settings" value="browser-settings"
@ -47,10 +47,10 @@ export function Settings() {
</TabsContent> </TabsContent>
<TabsContent value="user-settings"> <TabsContent value="user-settings">
<SignedOut> <SignedOut>
<Material className="mt-6 grid gap-4"> <Material className="mt-6 grid gap-4 py-6">
<h3 <h3
className={cn( className={cn(
"scroll-m-20 text-2xl font-semibold tracking-tight bg-gradient-to-r from-[#3b82f6] to-[#ef4444] bg-clip-text text-transparent", "scroll-m-20 text-2xl font-semibold tracking-tight bg-linear-to-r from-[#3b82f6] to-[#ef4444] bg-clip-text text-transparent",
"w-full flex items-center text-center justify-center" "w-full flex items-center text-center justify-center"
)} )}
> >

@ -13,35 +13,35 @@ const buttonVariants = cva(
variant: { variant: {
default: `border border-transparent bg-primary-900 text-white default: `border border-transparent bg-primary-900 text-white
dark:bg-primary-100 dark:text-black hover:brightness-125 dark:hover:brightness-90 active:brightness-90 dark:bg-primary-100 dark:text-black hover:brightness-125 dark:hover:brightness-90 active:brightness-90
active:dark:brightness-75`, dark:active:brightness-75`,
secondary: `border border-slate-200 border-b-slate-300 dark:border-zinc-800 dark:border-t-zinc-700/50 bg-white dark:bg-zinc-900 secondary: `border border-slate-200 border-b-slate-300 dark:border-zinc-800 dark:border-t-zinc-700/50 bg-white dark:bg-zinc-900
hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 hover:dark:border-zinc-700 active:dark:bg-zinc-900 active:bg-slate-200`, hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:hover:border-zinc-700 dark:active:bg-zinc-900 active:bg-slate-200`,
tertiary: tertiary:
"border border-transparent bg-transparent hover:bg-slate-100 hover:dark:bg-zinc-700/30 dark:text-zinc-200", "border border-transparent bg-transparent hover:bg-slate-100 dark:hover:bg-zinc-700/30 dark:text-zinc-200",
danger: danger:
"border border-red-500 bg-red-500 hover:text-red-500 hover:bg-transparent text-white", "border border-red-500 bg-red-500 hover:text-red-500 hover:bg-transparent text-white",
"danger-subtle": "text-red-500 hover:bg-red-500 hover:!text-inherit", "danger-subtle": "text-red-500 hover:bg-red-500 hover:text-inherit!",
"success-subtle": "success-subtle":
"text-green-500 hover:bg-green-500 hover:!text-inherit", "text-green-500 hover:bg-green-500 hover:text-inherit!",
"warning-subtle": "warning-subtle":
"text-yellow-500 hover:bg-yellow-500 hover:!text-inherit", "text-yellow-500 hover:bg-yellow-500 hover:text-inherit!",
ghost: `border border-slate-200 dark:border-zinc-800 bg-transparent ghost: `border border-slate-200 dark:border-zinc-800 bg-transparent
hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 dark:text-zinc-400 hover:text-inherit hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:text-zinc-400 hover:text-inherit
hover:dark:text-inherit`, dark:hover:text-inherit`,
elevated: `bg-slate-100 dark:bg-zinc-800 border border-slate-200 elevated: `bg-slate-100 dark:bg-zinc-800 border border-slate-200
dark:border-zinc-700 hover:bg-zinc-200 hover:dark:bg-zinc-700 hover:border-slate-300 dark:border-zinc-700 hover:bg-zinc-200 dark:hover:bg-zinc-700 hover:border-slate-300
hover:dark:border-zinc-600`, dark:hover:border-zinc-600`,
elevatedLow: `bg-slate-100 dark:bg-zinc-900 border border-slate-200 elevatedLow: `bg-slate-100 dark:bg-zinc-900 border border-slate-200
dark:border-zinc-800 hover:bg-slate-200 hover:dark:bg-zinc-800 hover:border-slate-300 dark:border-zinc-800 hover:bg-slate-200 dark:hover:bg-zinc-800 hover:border-slate-300
hover:dark:border-zinc-700`, dark:hover:border-zinc-700`,
none: "", none: "",
}, },
@ -63,7 +63,7 @@ const buttonVariants = cva(
right: "justify-end text-right origin-right", right: "justify-end text-right origin-right",
}, },
shadow: { shadow: {
sm: "shadow-sm", sm: "shadow-xs",
none: "shadow-none", none: "shadow-none",
}, },
rounding: { rounding: {

@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root <CheckboxPrimitive.Root
ref={ref} ref={ref}
className={cn( className={cn(
"peer h-5 w-5 shrink-0 rounded-sm border border-slate-200 border-b-slate-300 border-primary transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-shadcn-primary data-[state=checked]:text-shadcn-primary-foreground", "peer h-5 w-5 shrink-0 rounded-sm border border-slate-200 border-b-slate-300 border-primary transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-shadcn-primary data-[state=checked]:text-shadcn-primary-foreground",
className className
)} )}
{...props} {...props}

@ -28,7 +28,7 @@ const ContextMenuSubTrigger = React.forwardRef<
<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-hidden 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
)} )}
@ -63,7 +63,7 @@ const ContextMenuContent = React.forwardRef<
<ContextMenuPrimitive.Content <ContextMenuPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"backdrop-blur-xl w-max max-w-[280px] z-[100] origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl", "backdrop-blur-xl w-max max-w-[280px] z-100 origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl",
className className
)} )}
data-align="end" data-align="end"
@ -94,7 +94,7 @@ const ContextMenuItem = React.forwardRef<
<ContextMenuPrimitive.Item <ContextMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"w-full px-2 rounded-lg z-[100] min-h-[36px] font-normal flex items-center cursor-pointer hover:dark:bg-zinc-800/70", "w-full px-2 rounded-lg z-100 min-h-[36px] font-normal flex items-center cursor-pointer dark:hover:bg-zinc-800/70",
props.disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "", props.disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "",
"duration-100 border border-transparent bg-transparent hover:bg-slate-100 dark:text-zinc-200", "duration-100 border border-transparent bg-transparent hover:bg-slate-100 dark:text-zinc-200",
className className
@ -111,7 +111,7 @@ const ContextMenuCheckboxItem = React.forwardRef<
<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-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className className
)} )}
checked={checked} checked={checked}
@ -135,7 +135,7 @@ const ContextMenuRadioItem = React.forwardRef<
<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-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className className
)} )}
{...props} {...props}

@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay ref={ref} asChild {...props}> <DialogPrimitive.Overlay ref={ref} asChild {...props}>
<motion.div <motion.div
className={cn( className={cn(
"fixed bg-[#ffffff]/50 dark:bg-black/50 inset-0 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "fixed bg-[#ffffff]/50 dark:bg-black/50 inset-0 backdrop-blur-xs data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className className
)} )}
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
@ -65,7 +65,7 @@ const DialogContent = React.forwardRef<
ref={ref} ref={ref}
{...props} {...props}
className={cn( className={cn(
"top-[50%] left-[50%] max-h-[85vh] translate-x-[-50%] translate-y-[-50%] focus:outline-none", "top-[50%] left-[50%] max-h-[85vh] translate-x-[-50%] translate-y-[-50%] focus:outline-hidden",
"w-full border border-slate-200 border-b-slate-300", "w-full border border-slate-200 border-b-slate-300",
"dark:border-zinc-900 dark:border-t-zinc-800 dark:border-b-zinc-900", "dark:border-zinc-900 dark:border-t-zinc-800 dark:border-b-zinc-900",
"rounded-2xl max-w-lg box-border mx-auto overscroll-contain shadow-lg overflow-auto", "rounded-2xl max-w-lg box-border mx-auto overscroll-contain shadow-lg overflow-auto",

@ -28,7 +28,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
<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-hidden 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
)} )}
@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef<
<DropdownMenuPrimitive.Content <DropdownMenuPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"backdrop-blur-xl w-max z-[100] max-w-[280px] origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl select-none outline-none", "backdrop-blur-xl w-max z-100 max-w-[280px] origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl select-none outline-hidden",
className className
)} )}
{...props} {...props}
@ -96,7 +96,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item <DropdownMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"w-full px-2 rounded-lg z-[100] outline-none min-h-[36px] font-normal flex items-center cursor-pointer hover:dark:bg-zinc-800/70", "w-full px-2 rounded-lg z-100 outline-hidden min-h-[36px] font-normal flex items-center cursor-pointer dark:hover:bg-zinc-800/70",
props.disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "", props.disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "",
"duration-100 border border-transparent bg-transparent hover:bg-slate-100 dark:text-zinc-200", "duration-100 border border-transparent bg-transparent hover:bg-slate-100 dark:text-zinc-200",
className className
@ -113,7 +113,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<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-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className className
)} )}
checked={checked} checked={checked}
@ -137,7 +137,7 @@ const DropdownMenuRadioItem = React.forwardRef<
<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-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className className
)} )}
{...props} {...props}
@ -183,7 +183,7 @@ const DropdownMenuSeparator = React.forwardRef<
{...props} {...props}
> >
<div>{props.children}</div> <div>{props.children}</div>
<hr className="flex-shrink flex-1 border-slate-200 dark:border-zinc-800 border-opacity-70" /> <hr className="shrink flex-1 border-slate-200 dark:border-zinc-800 border-opacity-70" />
</DropdownMenuPrimitive.Separator> </DropdownMenuPrimitive.Separator>
)); ));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;

@ -14,7 +14,7 @@ const sizeClass = {
}; };
const shadowClass = { const shadowClass = {
sm: "shadow-sm", sm: "shadow-xs",
none: "shadow-none", none: "shadow-none",
}; };
@ -63,7 +63,7 @@ const Input: React.FC<InputWithLabelProps> = ({
</Label> </Label>
)} )}
<div <div
className={`${shadowClass[shadow]} border ${borderClass} focus-within:border-primary-900 focus-within:dark:border-primary-100 focus-within:ring-2 ring-slate-300 dark:ring-zinc-700 transition-colors rounded-lg flex flex-row items-center text-sm ${className}`} className={`${shadowClass[shadow-sm]} border ${borderClass} focus-within:border-primary-900 dark:focus-within:border-primary-100 focus-within:ring-2 ring-slate-300 dark:ring-zinc-700 transition-colors rounded-lg flex flex-row items-center text-sm ${className}`}
> >
{prefix && ( {prefix && (
<div <div
@ -79,7 +79,7 @@ const Input: React.FC<InputWithLabelProps> = ({
disabled={disabled} disabled={disabled}
value={value} value={value}
onChange={onChange} onChange={onChange}
className={`${sizeClass[size]} bg-white dark:bg-zinc-950 focus:outline-none rounded-lg text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:!border-red-500 peer invalid:text-red-500 z-10 ${className}`} className={`${sizeClass[size]} bg-white dark:bg-zinc-950 focus:outline-hidden rounded-lg text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:border-red-500! peer invalid:text-red-500 z-10 ${className}`}
/> />
{suffix && ( {suffix && (
<div <div

@ -7,8 +7,8 @@ const cardVariants = cva("text-sm", {
variants: { variants: {
elevation: { elevation: {
flat: "", flat: "",
low: "shadow-xs", low: "shadow-2xs",
medium: "shadow-sm", medium: "shadow-xs",
high: "shadow-md", high: "shadow-md",
xhigh: "shadow-lg", xhigh: "shadow-lg",
max: "shadow-xl", max: "shadow-xl",

@ -28,7 +28,7 @@ const RadioGroupItem = React.forwardRef<
<RadioGroupPrimitive.Item <RadioGroupPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"aspect-square h-4 w-4 rounded-full border border-shadcn-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-shadcn-primary text-primary shadow-sm focus:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className className
)} )}
{...props} {...props}

@ -20,11 +20,11 @@ const SelectTrigger = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
// Select Specific // Select Specific
"appearance-none transition-colors rounded-lg text-sm w-full min-w-full cursor-pointer px-3", "appearance-none transition-colors rounded-lg text-sm w-full cursor-pointer px-3",
"flex items-center h-9 justify-between", "flex items-center h-9 justify-between",
// Secondary Button Props // Secondary Button Props
"border border-slate-200 border-b-slate-300 dark:border-zinc-800 dark:border-t-zinc-700/50 bg-white dark:bg-zinc-900", "border border-slate-200 border-b-slate-300 dark:border-zinc-800 dark:border-t-zinc-700/50 bg-white dark:bg-zinc-900",
"hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 active:dark:bg-zinc-900 active:bg-slate-200", "hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:active:bg-zinc-900 active:bg-slate-200",
className className
)} )}
{...props} {...props}
@ -133,8 +133,8 @@ const SelectItem = React.forwardRef<
ref={ref} ref={ref}
{...props} {...props}
className={cn( className={cn(
"relative flex w-full select-none items-center data-[state=checked]:!bg-slate-100 data-[state=checked]:dark:!bg-zinc-800 rounded-lg py-1.5 pl-2 pr-8 text-sm outline-none focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", "relative flex w-full select-none items-center data-[state=checked]:bg-slate-100! dark:data-[state=checked]:bg-zinc-800! rounded-lg py-1.5 pl-2 pr-8 text-sm outline-hidden focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"w-full px-2 rounded-lg cursor-pointer min-h-[36px] font-normal flex items-center hover:dark:bg-zinc-800/70 hover:bg-slate-100", "w-full px-2 rounded-lg cursor-pointer min-h-[36px] font-normal flex items-center dark:hover:bg-zinc-800/70 hover:bg-slate-100",
disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "", disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "",
"duration-100", "duration-100",
className className

@ -64,7 +64,7 @@ const SheetContent = React.forwardRef<
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-hidden 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>

@ -141,7 +141,7 @@ const SidebarProvider = React.forwardRef<
} as React.CSSProperties } as React.CSSProperties
} }
className={cn( className={cn(
"group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar", "group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
className className
)} )}
ref={ref} ref={ref}
@ -181,7 +181,7 @@ const Sidebar = React.forwardRef<
return ( return (
<div <div
className={cn( className={cn(
"flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground", "flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
className className
)} )}
ref={ref} ref={ref}
@ -198,7 +198,7 @@ const Sidebar = React.forwardRef<
<SheetContent <SheetContent
data-sidebar="sidebar" data-sidebar="sidebar"
data-mobile="true" data-mobile="true"
className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden" className="w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
style={ style={
{ {
"--sidebar-width": SIDEBAR_WIDTH_MOBILE, "--sidebar-width": SIDEBAR_WIDTH_MOBILE,
@ -224,31 +224,31 @@ const Sidebar = React.forwardRef<
{/* This is what handles the sidebar gap on desktop */} {/* This is what handles the sidebar gap on desktop */}
<div <div
className={cn( className={cn(
"relative h-svh w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear", "relative h-svh w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
"group-data-[collapsible=offcanvas]:w-0", "group-data-[collapsible=offcanvas]:w-0",
"group-data-[side=right]:rotate-180", "group-data-[side=right]:rotate-180",
variant === "floating" || variant === "inset" variant === "floating" || variant === "inset"
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
)} )}
/> />
<div <div
className={cn( className={cn(
"fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex", "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
side === "left" side === "left"
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
// Adjust the padding for floating and inset variants. // Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset" variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l", : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
className className
)} )}
{...props} {...props}
> >
<div <div
data-sidebar="sidebar" data-sidebar="sidebar"
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow" className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
> >
{children} {children}
</div> </div>
@ -301,9 +301,9 @@ const SidebarRail = React.forwardRef<
title="Toggle Sidebar" title="Toggle Sidebar"
className={cn( className={cn(
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
"[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
className className
@ -323,7 +323,7 @@ const SidebarInset = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex min-h-svh flex-1 flex-col bg-background", "relative flex min-h-svh flex-1 flex-col bg-background",
"peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow", "peer-data-[variant=inset]:min-h-[calc(100svh-(--spacing(4)))] md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm",
className className
)} )}
{...props} {...props}
@ -439,7 +439,7 @@ const SidebarGroupLabel = React.forwardRef<
ref={ref} ref={ref}
data-sidebar="group-label" data-sidebar="group-label"
className={cn( className={cn(
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-hidden ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
className className
)} )}
@ -460,9 +460,9 @@ const SidebarGroupAction = React.forwardRef<
ref={ref} ref={ref}
data-sidebar="group-action" data-sidebar="group-action"
className={cn( className={cn(
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-hidden ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile. // Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden", "after:absolute after:-inset-2 md:after:hidden",
"group-data-[collapsible=icon]:hidden", "group-data-[collapsible=icon]:hidden",
className className
)} )}
@ -512,7 +512,7 @@ const SidebarMenuItem = React.forwardRef<
SidebarMenuItem.displayName = "SidebarMenuItem" SidebarMenuItem.displayName = "SidebarMenuItem"
const sidebarMenuButtonVariants = cva( const sidebarMenuButtonVariants = cva(
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
{ {
variants: { variants: {
variant: { variant: {
@ -523,7 +523,7 @@ const sidebarMenuButtonVariants = cva(
size: { size: {
default: "h-8 text-sm", default: "h-8 text-sm",
sm: "h-7 text-xs", sm: "h-7 text-xs",
lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0", lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
}, },
}, },
defaultVariants: { defaultVariants: {
@ -606,9 +606,9 @@ const SidebarMenuAction = React.forwardRef<
ref={ref} ref={ref}
data-sidebar="menu-action" data-sidebar="menu-action"
className={cn( className={cn(
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0", "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-hidden ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile. // Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden", "after:absolute after:-inset-2 md:after:hidden",
"peer-data-[size=sm]/menu-button:top-1", "peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5", "peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5", "peer-data-[size=lg]/menu-button:top-2.5",
@ -669,7 +669,7 @@ const SidebarMenuSkeleton = React.forwardRef<
/> />
)} )}
<Skeleton <Skeleton
className="h-4 max-w-[--skeleton-width] flex-1" className="h-4 max-w-(--skeleton-width) flex-1"
data-sidebar="menu-skeleton-text" data-sidebar="menu-skeleton-text"
style={ style={
{ {
@ -722,7 +722,7 @@ const SidebarMenuSubButton = React.forwardRef<
data-size={size} data-size={size}
data-active={isActive} data-active={isActive}
className={cn( className={cn(
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs", size === "sm" && "text-xs",
size === "md" && "text-sm", size === "md" && "text-sm",

@ -11,8 +11,8 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SwitchPrimitives.Root <SwitchPrimitives.Root
className={cn( className={cn(
"peer inline-flex w-11 h-6 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm", "peer inline-flex w-11 h-6 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs",
"transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "transition-colors focus-visible:outline-hidden 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-shadcn-primary", "focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-shadcn-primary",
"data-[state=unchecked]:bg-input", "data-[state=unchecked]:bg-input",
className className
@ -22,7 +22,7 @@ const Switch = React.forwardRef<
> >
<SwitchPrimitives.Thumb <SwitchPrimitives.Thumb
className={cn( className={cn(
"box-border w-5 h-full bg-white dark:bg-black rounded-full shadow-sm", "box-border w-5 h-full bg-white dark:bg-black rounded-full shadow-xs",
"transition data-[state=checked]:translate-x-5" "transition data-[state=checked]:translate-x-5"
)} )}
/> />

@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger <TabsPrimitive.Trigger
ref={ref} ref={ref}
className={cn( className={cn(
"font-medium rounded-full px-4 py-1 hover:bg-slate-200/40 hover:dark:bg-zinc-700/40 group transition-colors duration-100 relative z-0 flex-shrink-0", "font-medium rounded-full px-4 py-1 hover:bg-slate-200/40 dark:hover:bg-zinc-700/40 group transition-colors duration-100 relative z-0 shrink-0",
className className
)} )}
{...props} {...props}
@ -50,7 +50,7 @@ const TabsContent = React.forwardRef<
<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-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className className
)} )}
{...props} {...props}

@ -65,7 +65,7 @@ const TextArea: React.FC<TextAreaProps> = ({
value={value} value={value}
onChange={(e) => restProps.onChange?.(e)} onChange={(e) => restProps.onChange?.(e)}
ref={elementRef} ref={elementRef}
className={`${sizeClass[size]} ${borderClass} focus:border-slate-800 focus:dark:border-zinc-200 bg-white dark:bg-zinc-950 focus:outline-none focus:ring-2 ring-slate-800/50 rounded-xl dark:ring-zinc-200/50 transition-all text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:!border-red-500 peer invalid:text-red-500 z-10 ${className}`} className={`${sizeClass[size]} ${borderClass} focus:border-slate-800 dark:focus:border-zinc-200 bg-white dark:bg-zinc-950 focus:outline-hidden focus:ring-2 ring-slate-800/50 rounded-xl dark:ring-zinc-200/50 transition-all text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:border-red-500! peer invalid:text-red-500 z-10 ${className}`}
/> />
</div> </div>
{restProps.children} {restProps.children}

@ -0,0 +1,25 @@
"use client";
import { ClerkProvider as ImportedClerkProvider } from "@clerk/nextjs";
import { dark } from "@clerk/themes";
import { useTheme } from "next-themes";
import { MultisessionAppSupport } from "@clerk/nextjs/internal";
export const ClerkProvider = ({ children }: { children: React.ReactNode }) => {
const { resolvedTheme } = useTheme();
if (resolvedTheme === "dark") {
console.log(resolvedTheme);
return (
<ImportedClerkProvider appearance={{ baseTheme: dark }}>
<MultisessionAppSupport>{children}</MultisessionAppSupport>
</ImportedClerkProvider>
);
}
console.log("a");
return (
<ImportedClerkProvider>
<MultisessionAppSupport>{children}</MultisessionAppSupport>
</ImportedClerkProvider>
);
};

@ -0,0 +1,47 @@
"use client";
import { useSettingsStore } from "@/lib/hooks/use-settings-store";
import { Inter, Roboto } from "next/font/google";
import { useEffect, useState, type ReactNode } from "react";
import { GeistSans } from "geist/font/sans";
const inter = Inter({ subsets: ["latin"] });
const roboto = Roboto({
subsets: ["latin"],
weight: ["100", "300", "400", "500", "700", "900"],
});
export function FontBoundary({
children,
}: {
children?: ReactNode | ReactNode[];
}) {
const settingsStore = useSettingsStore();
const [fontFamily, setFontFamily] = useState("inter");
useEffect(() => {
setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
window.addEventListener("font-family-change", () => {
setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
});
}, [settingsStore]);
return (
<body
className={`font-${fontFamily} ${(() => {
switch (fontFamily) {
case "geist-sans":
return GeistSans.className;
case "roboto":
return roboto.className;
case "inter":
return inter.className;
default:
return "system-ui-font--font-boundary";
}
})()}`}
>
{children}
</body>
);
}

@ -4,6 +4,7 @@ import { Book, ExternalLink, NotebookText } from "lucide-react";
export function Link( export function Link(
props: LinkProps & { props: LinkProps & {
children?: React.ReactNode; children?: React.ReactNode;
className?: string;
} }
) { ) {
const href = props.href as string; const href = props.href as string;

@ -11,19 +11,17 @@ import {
} from "../ui/dropdown-menu"; } from "../ui/dropdown-menu";
export function ModeToggle() { export function ModeToggle() {
const { setTheme } = useTheme(); const { setTheme, resolvedTheme } = useTheme();
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button <Button className="flex items-center gap-2">
variant="tertiary" <span className="flex items-center">
className="flex items-center"
size="square-lg"
>
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /> <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /> <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span> </span>
{resolvedTheme === "dark" ? "Dark Mode" : "Light Mode"}
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">

@ -1,11 +1,17 @@
"use client"; "use client";
import type * as React from "react"; import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes"; import { ThemeProvider as NextThemeProvider } from "next-themes";
import type { ThemeProviderProps } from "next-themes";
export function ThemeProvider({ export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
children, const [mounted, setMounted] = React.useState(false);
...props
}: React.ComponentProps<typeof NextThemesProvider>) { React.useEffect(() => {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>; setMounted(true);
}, []);
if (!mounted) return null;
return <NextThemeProvider {...props}>{children}</NextThemeProvider>;
} }

@ -0,0 +1,38 @@
import { useUser } from "@clerk/nextjs";
export function useSettingsStore() {
const { isSignedIn, user } = useUser();
/* Get: (key: string) =>
check if the user is signed in, if so, check user storage & grab entry
if not or if the entry couldn't be found, check browser storage
Set: (key: string, value: string, userEntry: boolean) =>
if user signed in & userEntry === true, send to user storage
if user signed out & userEntry === true, do nothing
if userEntry === false, send to browser
*/
return {
get: (key: string) => {
if (isSignedIn) {
const value = user.publicMetadata[key] as string | boolean;
if (value === undefined) return localStorage.getItem(key);
return value;
}
return localStorage.getItem(key);
},
set: async (key: string, value: string, userEntry: boolean) => {
if (isSignedIn && userEntry === true) {
await fetch("/api/v0/account-sl/change", {
body: JSON.stringify({ [key]: value }),
});
}
if (!isSignedIn && userEntry)
throw new Error("How is this even possible?!?!");
if (userEntry === false) {
localStorage.setItem(key, value);
}
},
};
}

@ -30,10 +30,20 @@
import type { NextApiRequest, NextApiResponse } from "next"; import type { NextApiRequest, NextApiResponse } from "next";
import { clerkClient, getAuth } from "@clerk/nextjs/server"; import { clerkClient, getAuth } from "@clerk/nextjs/server";
import z from "zod";
const obj = z.object({
// Use padding on the sides of only the servers, not the whole server list
srv: z.boolean(),
// Items per row (4-6 rows)
ipr: z.number().min(4).max(6),
// Padding of server list (0-120px)
pad: z.number().min(0).max(120),
});
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse res: NextApiResponse,
) { ) {
const { userId } = getAuth(req); const { userId } = getAuth(req);
@ -46,36 +56,15 @@ export default async function handler(
res.status(400).send({ message: "Couldn't find data" }); res.status(400).send({ message: "Couldn't find data" });
return; return;
} }
const { type } = req.body;
if (type === undefined) {
res.status(400).send({ message: "Couldn't find data" });
return;
}
if (data === null) {
await (
await clerkClient()
).users.updateUserMetadata(userId, {
publicMetadata: { [type]: null },
});
res.status(200).send({ message: "Success" });
}
if (type !== "srv" && type !== "ipr" && type !== "pad")
return res.status(400).send({ message: "Couldn't find data" });
if (type === "srv" && typeof data !== "boolean")
return res.status(400).send({ message: "Couldn't find data" });
if (type === "ipr" && typeof data !== "number")
return res.status(400).send({ message: "Couldn't find data" });
if (type === "pad" && typeof data !== "number")
return res.status(400).send({ message: "Couldn't find data" });
const v = obj.parse(data);
for (const [key, value] of Object.entries(v)) {
(await clerkClient()).users.updateUserMetadata(userId, { (await clerkClient()).users.updateUserMetadata(userId, {
publicMetadata: { publicMetadata: {
[type]: typeof data === "number" ? data.toString() : data, [key]: typeof value === "number" ? value.toString() : value,
}, },
}); });
}
res.status(200).send({ message: "Success" }); res.status(200).send({ message: "Success" });
} }

@ -1,153 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
import type { Config } from "tailwindcss";
export default {
darkMode: ["class"],
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
keyframes: {
spin: {
"0%": {
transform: "rotate(0deg)",
},
"100%": {
transform: "rotate(360deg)",
},
},
scaleIn: {
"0%": {
transform: "scale(0.95)",
opacity: "0",
},
"100%": {
transform: "scale(1)",
opacity: "1",
},
},
},
animation: {
spin: "spin 1s linear infinite",
"scale-in": "scaleIn 0.2s cubic-bezier(0.34, 1.56, 0.64, 1)",
},
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
"shadcn-primary": {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
slate: {
"25": "rgb(var(--c-s-25,252 253 254) / <alpha-value>)",
"50": "rgb(var(--c-s-50,248 250 252) / <alpha-value>)",
"100": "rgb(var(--c-s-100,241 245 249) / <alpha-value>)",
"200": "rgb(var(--c-s-200,226 232 240) / <alpha-value>)",
"300": "rgb(var(--c-s-300,203 213 225) / <alpha-value>)",
"400": "rgb(var(--c-s-400,148 163 184) / <alpha-value>)",
"500": "rgb(var(--c-s-500,100 116 139) / <alpha-value>)",
"600": "rgb(var(--c-s-600,71 85 105) / <alpha-value>)",
"700": "rgb(var(--c-s-700,51 65 85) / <alpha-value>)",
"800": "rgb(var(--c-s-800,30 41 59) / <alpha-value>)",
"900": "rgb(var(--c-s-900,15 23 42) / <alpha-value>)",
"950": "rgb(var(--c-s-950,2 6 23) / <alpha-value>)",
},
zinc: {
"50": "rgb(var(--c-z-50,249 250 251) / <alpha-value>)",
"100": "rgb(var(--c-z-100,243 244 246) / <alpha-value>)",
"200": "rgb(var(--c-z-200,229 231 235) / <alpha-value>)",
"300": "rgb(var(--c-z-300,209 213 219) / <alpha-value>)",
"400": "rgb(var(--c-z-400,156 163 175) / <alpha-value>)",
"500": "rgb(var(--c-z-500,107 114 128) / <alpha-value>)",
"600": "rgb(var(--c-z-600,75 85 99) / <alpha-value>)",
"700": "rgb(var(--c-z-700,50 60 76) / <alpha-value>)",
"800": "rgb(var(--c-z-800,22 31 45) / <alpha-value>)",
"900": "rgb(var(--c-z-900,17 24 39) / <alpha-value>)",
"925": "rgb(var(--c-z-925,8 12 25) / <alpha-value>)",
"950": "rgb(var(--c-z-950,5 9 16) / <alpha-value>)",
},
primary: {
"100": "rgb(var(--c-p-100,241 245 249) / <alpha-value>)",
"900": "rgb(var(--c-p-900,15 23 42) / <alpha-value>)",
},
black: "rgb(var(--c-o-black,0 0 0) / <alpha-value>)",
white: "rgb(var(--c-o-white,255 255 255) / <alpha-value>)",
sidebar: {
DEFAULT: "hsl(var(--sidebar-background))",
foreground: "hsl(var(--sidebar-foreground))",
primary: "hsl(var(--sidebar-primary))",
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
accent: "hsl(var(--sidebar-accent))",
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
border: "hsl(var(--sidebar-border))",
ring: "hsl(var(--sidebar-ring))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [require("tailwindcss-animate")],
} satisfies Config;

180
yarn.lock

@ -2588,6 +2588,99 @@
resolved "https://registry.yarnpkg.com/@tailwindcss-mangle/shared/-/shared-3.0.0.tgz#8a60fa4168da0069c62fba75f212864ac796c54b" resolved "https://registry.yarnpkg.com/@tailwindcss-mangle/shared/-/shared-3.0.0.tgz#8a60fa4168da0069c62fba75f212864ac796c54b"
integrity sha512-h1ateiRm/o0JvRsD5755dyS4H1RPE5sgeyEAOorLGVkGvNawkACtM+0MsiD/ZFNgrfQ7aYDD+DF/dV/8LN5Lmw== integrity sha512-h1ateiRm/o0JvRsD5755dyS4H1RPE5sgeyEAOorLGVkGvNawkACtM+0MsiD/ZFNgrfQ7aYDD+DF/dV/8LN5Lmw==
"@tailwindcss/node@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.0.7.tgz#11211457bbe83ff3656c74bf0276e27e9ce87410"
integrity sha512-dkFXufkbRB2mu3FPsW5xLAUWJyexpJA+/VtQj18k3SUiJVLdpgzBd1v1gRRcIpEJj7K5KpxBKfOXlZxT3ZZRuA==
dependencies:
enhanced-resolve "^5.18.1"
jiti "^2.4.2"
tailwindcss "4.0.7"
"@tailwindcss/oxide-android-arm64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.7.tgz#a0864f4831a4eca1a92207fd5ae726343fbb0554"
integrity sha512-5iQXXcAeOHBZy8ASfHFm1k0O/9wR2E3tKh6+P+ilZZbQiMgu+qrnfpBWYPc3FPuQdWiWb73069WT5D+CAfx/tg==
"@tailwindcss/oxide-darwin-arm64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.7.tgz#a25e3831cfb0a9ab5b77ada620b8c714e0f41eab"
integrity sha512-7yGZtEc5IgVYylqK/2B0yVqoofk4UAbkn1ygNpIJZyrOhbymsfr8uUFCueTu2fUxmAYIfMZ8waWo2dLg/NgLgg==
"@tailwindcss/oxide-darwin-x64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.7.tgz#1dae8648aa03c9783cd01cfd1249c781aaa49dd1"
integrity sha512-tPQDV20fBjb26yWbPqT1ZSoDChomMCiXTKn4jupMSoMCFyU7+OJvIY1ryjqBuY622dEBJ8LnCDDWsnj1lX9nNQ==
"@tailwindcss/oxide-freebsd-x64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.7.tgz#904aaa135e5a2500faf729290b12133f15273500"
integrity sha512-sZqJpTyTZiknU9LLHuByg5GKTW+u3FqM7q7myequAXxKOpAFiOfXpY710FuMY+gjzSapyRbDXJlsTQtCyiTo5w==
"@tailwindcss/oxide-linux-arm-gnueabihf@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.7.tgz#27b6483303218f545a971ec68f468417cab1f6be"
integrity sha512-PBgvULgeSswjd8cbZ91gdIcIDMdc3TUHV5XemEpxlqt9M8KoydJzkuB/Dt910jYdofOIaTWRL6adG9nJICvU4A==
"@tailwindcss/oxide-linux-arm64-gnu@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.7.tgz#98126af54ff0262756e9a4f730a8b6f6585e13c2"
integrity sha512-By/a2yeh+e9b+C67F88ndSwVJl2A3tcUDb29FbedDi+DZ4Mr07Oqw9Y1DrDrtHIDhIZ3bmmiL1dkH2YxrtV+zw==
"@tailwindcss/oxide-linux-arm64-musl@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.7.tgz#55f0183a8521473cab1ca0414b57079efc145952"
integrity sha512-WHYs3cpPEJb/ccyT20NOzopYQkl7JKncNBUbb77YFlwlXMVJLLV3nrXQKhr7DmZxz2ZXqjyUwsj2rdzd9stYdw==
"@tailwindcss/oxide-linux-x64-gnu@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.7.tgz#053b019201892b339c0d975092bfc8024be54226"
integrity sha512-7bP1UyuX9kFxbOwkeIJhBZNevKYPXB6xZI37v09fqi6rqRJR8elybwjMUHm54GVP+UTtJ14ueB1K54Dy1tIO6w==
"@tailwindcss/oxide-linux-x64-musl@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.7.tgz#c4d753acf3d6ef617e91b53880b7c1b966677ca6"
integrity sha512-gBQIV8nL/LuhARNGeroqzXymMzzW5wQzqlteVqOVoqwEfpHOP3GMird5pGFbnpY+NP0fOlsZGrxxOPQ4W/84bQ==
"@tailwindcss/oxide-win32-arm64-msvc@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.7.tgz#cceea5857939092d5149e6afc8da1b8d3a7464b2"
integrity sha512-aH530NFfx0kpQpvYMfWoeG03zGnRCMVlQG8do/5XeahYydz+6SIBxA1tl/cyITSJyWZHyVt6GVNkXeAD30v0Xg==
"@tailwindcss/oxide-win32-x64-msvc@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.7.tgz#500cf333326a45078ca5b0fd68b56b1f0b434bfa"
integrity sha512-8Cva6bbJN7ZJx320k7vxGGdU0ewmpfS5A4PudyzUuofdi8MgeINuiiWiPQ0VZCda/GX88K6qp+6UpDZNVr8HMQ==
"@tailwindcss/oxide@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.0.7.tgz#b53573fc01b8b61af195ad36957d05c78278761d"
integrity sha512-yr6w5YMgjy+B+zkJiJtIYGXW+HNYOPfRPtSs+aqLnKwdEzNrGv4ZuJh9hYJ3mcA+HMq/K1rtFV+KsEr65S558g==
optionalDependencies:
"@tailwindcss/oxide-android-arm64" "4.0.7"
"@tailwindcss/oxide-darwin-arm64" "4.0.7"
"@tailwindcss/oxide-darwin-x64" "4.0.7"
"@tailwindcss/oxide-freebsd-x64" "4.0.7"
"@tailwindcss/oxide-linux-arm-gnueabihf" "4.0.7"
"@tailwindcss/oxide-linux-arm64-gnu" "4.0.7"
"@tailwindcss/oxide-linux-arm64-musl" "4.0.7"
"@tailwindcss/oxide-linux-x64-gnu" "4.0.7"
"@tailwindcss/oxide-linux-x64-musl" "4.0.7"
"@tailwindcss/oxide-win32-arm64-msvc" "4.0.7"
"@tailwindcss/oxide-win32-x64-msvc" "4.0.7"
"@tailwindcss/postcss@^4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/postcss/-/postcss-4.0.7.tgz#b8bc02b5e23248ac7cbac1970ed807850e03261c"
integrity sha512-zXcKs1uGssVDlnsQ+iwrkul5GPKvsXPynGCuk/eXLx3DVhHlQKMpA6tXN2oO28x2ki1xRBTfadKiHy2taVvp7g==
dependencies:
"@alloc/quick-lru" "^5.2.0"
"@tailwindcss/node" "4.0.7"
"@tailwindcss/oxide" "4.0.7"
lightningcss "^1.29.1"
postcss "^8.4.41"
tailwindcss "4.0.7"
"@tailwindcss/typography@^0.5.13": "@tailwindcss/typography@^0.5.13":
version "0.5.16" version "0.5.16"
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.16.tgz#a926c8f44d5c439b2915e231cad80058850047c6" resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.16.tgz#a926c8f44d5c439b2915e231cad80058850047c6"
@ -4130,6 +4223,11 @@ destroy@1.2.0:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
detect-libc@^2.0.3: detect-libc@^2.0.3:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
@ -4326,7 +4424,7 @@ encodeurl@~2.0.0:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
enhanced-resolve@^5.15.0: enhanced-resolve@^5.15.0, enhanced-resolve@^5.18.1:
version "5.18.1" version "5.18.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf"
integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg== integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==
@ -6119,6 +6217,11 @@ jiti@^1.18.2, jiti@^1.21.6:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9"
integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==
jiti@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
js-cookie@3.0.5: js-cookie@3.0.5:
version "3.0.5" version "3.0.5"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc"
@ -6275,6 +6378,74 @@ levn@^0.4.1:
prelude-ls "^1.2.1" prelude-ls "^1.2.1"
type-check "~0.4.0" type-check "~0.4.0"
lightningcss-darwin-arm64@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.1.tgz#dce17349c7b9f968f396ec240503de14e7b4870b"
integrity sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==
lightningcss-darwin-x64@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.1.tgz#e79c984180c57d00ee114210ceced83473d72dfc"
integrity sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==
lightningcss-freebsd-x64@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.1.tgz#4b3aec9620684a60c45266d50fd843869320f42f"
integrity sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==
lightningcss-linux-arm-gnueabihf@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.1.tgz#b80e9c4dd75652bec451ffd4d5779492a01791ff"
integrity sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==
lightningcss-linux-arm64-gnu@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.1.tgz#7825eb119ddf580a4a4f011c6f384a3f9c992060"
integrity sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==
lightningcss-linux-arm64-musl@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.1.tgz#389efccf80088dce2bb00e28bd7d1cfe36a71669"
integrity sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==
lightningcss-linux-x64-gnu@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.1.tgz#98fc5df5e39ac8ddc51e51f785849eb21131f789"
integrity sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==
lightningcss-linux-x64-musl@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.1.tgz#fb4f80895ba7dfa8048ee32e9716a1684fefd6b2"
integrity sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==
lightningcss-win32-arm64-msvc@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.1.tgz#fd4409fd1505d89d0ff66511c36df5a1379eb7cd"
integrity sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==
lightningcss-win32-x64-msvc@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.1.tgz#54dcd52884f6cbf205a53d49239559603f194927"
integrity sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==
lightningcss@^1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.29.1.tgz#1d4d62332fc5ba4b6c28e04a8c5638c76019702b"
integrity sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==
dependencies:
detect-libc "^1.0.3"
optionalDependencies:
lightningcss-darwin-arm64 "1.29.1"
lightningcss-darwin-x64 "1.29.1"
lightningcss-freebsd-x64 "1.29.1"
lightningcss-linux-arm-gnueabihf "1.29.1"
lightningcss-linux-arm64-gnu "1.29.1"
lightningcss-linux-arm64-musl "1.29.1"
lightningcss-linux-x64-gnu "1.29.1"
lightningcss-linux-x64-musl "1.29.1"
lightningcss-win32-arm64-msvc "1.29.1"
lightningcss-win32-x64-msvc "1.29.1"
lilconfig@^2.1.0: lilconfig@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
@ -8056,7 +8227,7 @@ postcss@8.4.31:
picocolors "^1.0.0" picocolors "^1.0.0"
source-map-js "^1.0.2" source-map-js "^1.0.2"
postcss@^8, postcss@^8.4.23, postcss@^8.4.38, postcss@^8.4.39, postcss@^8.4.40, postcss@^8.4.47: postcss@^8, postcss@^8.4.23, postcss@^8.4.38, postcss@^8.4.39, postcss@^8.4.40, postcss@^8.4.41, postcss@^8.4.47:
version "8.5.2" version "8.5.2"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.2.tgz#e7b99cb9d2ec3e8dd424002e7c16517cb2b846bd" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.2.tgz#e7b99cb9d2ec3e8dd424002e7c16517cb2b846bd"
integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA== integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==
@ -9240,6 +9411,11 @@ tailwindcss@3.3.2:
resolve "^1.22.2" resolve "^1.22.2"
sucrase "^3.32.0" sucrase "^3.32.0"
tailwindcss@4.0.7, tailwindcss@^4.0.7:
version "4.0.7"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.0.7.tgz#b3e26a5dda77651808a873f1b535cc8c39fcb0ae"
integrity sha512-yH5bPPyapavo7L+547h3c4jcBXcrKwybQRjwdEIVAd9iXRvy/3T1CC6XSQEgZtRySjKfqvo3Cc0ZF1DTheuIdA==
tailwindcss@^3.4.1: tailwindcss@^3.4.1:
version "3.4.17" version "3.4.17"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63"