From a9d5ddf43df5d9d4ab1c7febcba6299515815611 Mon Sep 17 00:00:00 2001
From: dvelo <52332868+DeveloLongScript@users.noreply.github.com>
Date: Wed, 19 Feb 2025 14:31:59 -0600
Subject: [PATCH] feat: progress (2/19) & clerk themes and extra theming
---
apps/www/package.json | 2 +
apps/www/postcss.config.mjs | 2 +-
apps/www/src/app/(main)/layout.tsx | 62 +++---
apps/www/src/app/globals.css | 172 ++++++++++++++++-
apps/www/src/app/layout.tsx | 14 +-
apps/www/src/components/feat/embeds/embed.tsx | 4 +-
.../feat/settings/browser-settings.tsx | 70 ++++++-
.../src/components/feat/settings/setting.tsx | 78 ++++++++
.../src/components/feat/settings/settings.tsx | 6 +-
apps/www/src/components/ui/button.tsx | 26 +--
apps/www/src/components/ui/checkbox.tsx | 2 +-
apps/www/src/components/ui/context-menu.tsx | 10 +-
apps/www/src/components/ui/dialog.tsx | 4 +-
apps/www/src/components/ui/dropdown-menu.tsx | 12 +-
apps/www/src/components/ui/input.tsx | 6 +-
apps/www/src/components/ui/material.tsx | 4 +-
apps/www/src/components/ui/radio-group.tsx | 2 +-
apps/www/src/components/ui/select.tsx | 8 +-
apps/www/src/components/ui/sheet.tsx | 2 +-
apps/www/src/components/ui/sidebar.tsx | 44 ++---
apps/www/src/components/ui/switch.tsx | 6 +-
apps/www/src/components/ui/tabs.tsx | 4 +-
apps/www/src/components/ui/text-area.tsx | 2 +-
.../src/components/util/clerk-provider.tsx | 25 +++
.../www/src/components/util/font-boundary.tsx | 47 +++++
apps/www/src/components/util/link.tsx | 1 +
apps/www/src/components/util/mode-toggle.tsx | 16 +-
.../src/components/util/theme-provider.tsx | 20 +-
apps/www/src/lib/hooks/use-settings-store.tsx | 38 ++++
.../www/src/pages/api/v0/account-sl/change.ts | 71 +++----
apps/www/tailwind.config.ts | 153 ---------------
yarn.lock | 180 +++++++++++++++++-
32 files changed, 768 insertions(+), 325 deletions(-)
create mode 100644 apps/www/src/components/feat/settings/setting.tsx
create mode 100644 apps/www/src/components/util/clerk-provider.tsx
create mode 100644 apps/www/src/components/util/font-boundary.tsx
create mode 100644 apps/www/src/lib/hooks/use-settings-store.tsx
delete mode 100644 apps/www/tailwind.config.ts
diff --git a/apps/www/package.json b/apps/www/package.json
index 8df5147..3bc82a9 100644
--- a/apps/www/package.json
+++ b/apps/www/package.json
@@ -71,6 +71,7 @@
"sonner": "^1.7.0",
"stripe-gradient": "^1.0.1",
"tailwind-merge": "^2.3.0",
+ "tailwindcss": "^4.0.7",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-patch": "^4.0.0",
"turbo": "^2.4.0",
@@ -92,6 +93,7 @@
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
+ "@tailwindcss/postcss": "^4.0.7",
"@tailwindcss/typography": "^0.5.13",
"@types/canvas-confetti": "^1.6.4",
"@types/node": "^20",
diff --git a/apps/www/postcss.config.mjs b/apps/www/postcss.config.mjs
index d6a28d6..898209d 100644
--- a/apps/www/postcss.config.mjs
+++ b/apps/www/postcss.config.mjs
@@ -31,7 +31,7 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
- tailwindcss: {},
+ '@tailwindcss/postcss': {},
},
};
diff --git a/apps/www/src/app/(main)/layout.tsx b/apps/www/src/app/(main)/layout.tsx
index 2eff33f..55c5b88 100644
--- a/apps/www/src/app/(main)/layout.tsx
+++ b/apps/www/src/app/(main)/layout.tsx
@@ -31,18 +31,16 @@
"use client";
import "../globals.css";
import { useSearchParams } from "next/navigation";
-import { Inter } from "next/font/google";
import { Placeholder } from "@/components/ui/placeholder";
import { X } from "lucide-react";
import { IsScript } from "@/components/util/is-script";
import { Button } from "@/components/ui/button";
-import { ClerkProvider } from "@clerk/nextjs";
import Link from "next/link";
import { NavBar } from "@/components/feat/navbar/navbar";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/util/theme-provider";
-
-const inter = Inter({ subsets: ["latin"] });
+import { FontBoundary } from "@/components/util/font-boundary";
+import { ClerkProvider } from "@/components/util/clerk-provider";
export default function RootLayout({
children,
@@ -53,37 +51,37 @@ export default function RootLayout({
const search = searchParams?.get("theme") || "light";
return (
-
-
-
+
+
+
+
-
-
-
+
+
{children}
-
-
+
+
-
-
-
+
+
+
);
}
diff --git a/apps/www/src/app/globals.css b/apps/www/src/app/globals.css
index 0fddd1b..9eeab6b 100644
--- a/apps/www/src/app/globals.css
+++ b/apps/www/src/app/globals.css
@@ -1,9 +1,142 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+@import "tailwindcss";
-body {
- font-family: Arial, Helvetica, sans-serif;
+@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;
+ }
+}
+
+.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 {
@@ -93,8 +226,10 @@ body {
}
}
-body {
- @apply bg-slate-50 text-slate-900 dark:bg-zinc-950 dark:text-zinc-100 accent-slate-950 dark:accent-zinc-50;
+@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;
+ }
}
@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 {
::view-transition-old(root),
::view-transition-new(root) {
diff --git a/apps/www/src/app/layout.tsx b/apps/www/src/app/layout.tsx
index 0cb2762..b0d6958 100644
--- a/apps/www/src/app/layout.tsx
+++ b/apps/www/src/app/layout.tsx
@@ -31,6 +31,8 @@
"use client";
import "./globals.css";
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";
const inter = Inter({ subsets: ["latin"] });
@@ -45,7 +47,17 @@ export default function RootLayout({
return (
-
{children}
+
+
+
+ {children}
+
+
);
}
diff --git a/apps/www/src/components/feat/embeds/embed.tsx b/apps/www/src/components/feat/embeds/embed.tsx
index 3b9e552..89b97d8 100644
--- a/apps/www/src/components/feat/embeds/embed.tsx
+++ b/apps/www/src/components/feat/embeds/embed.tsx
@@ -90,9 +90,9 @@ export default function Embed({ params }: { params: { server: string } }) {
>
-
+
Powered by MHSF
diff --git a/apps/www/src/components/feat/settings/browser-settings.tsx b/apps/www/src/components/feat/settings/browser-settings.tsx
index 6201b43..60de69a 100644
--- a/apps/www/src/components/feat/settings/browser-settings.tsx
+++ b/apps/www/src/components/feat/settings/browser-settings.tsx
@@ -1,5 +1,73 @@
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() {
- return ;
+ const settingsStore = useSettingsStore();
+ const [fontFamily, setFontFamily] = useState("inter");
+
+ useEffect(() => {
+ setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
+ }, [settingsStore]);
+
+ return (
+
+ Appearance
+
+
+
+ Color Scheme
+
+ Change the MHSF color scheme
+
+
+
+
+
+
+
+
+ Font
+
+ Change the default font used in the interface.
+
+
+
+
+
+
+ );
}
diff --git a/apps/www/src/components/feat/settings/setting.tsx b/apps/www/src/components/feat/settings/setting.tsx
new file mode 100644
index 0000000..2570d8d
--- /dev/null
+++ b/apps/www/src/components/feat/settings/setting.tsx
@@ -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 (
+
+ {children}
+
+ );
+}
+
+export function SettingContent({
+ className,
+ children,
+}: {
+ className?: string;
+ children: ReactNode | ReactNode[] | undefined;
+}) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function SettingMeta({
+ className,
+ children,
+}: {
+ className?: string;
+ children: ReactNode | ReactNode[] | undefined;
+}) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function SettingTitle({
+ className,
+ children,
+}: {
+ className?: string;
+ children: ReactNode | ReactNode[] | undefined;
+}) {
+ return {children}
;
+}
+
+export function SettingDescription({
+ className,
+ children,
+}: {
+ className?: string;
+ children: ReactNode | ReactNode[] | undefined;
+}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/apps/www/src/components/feat/settings/settings.tsx b/apps/www/src/components/feat/settings/settings.tsx
index 89c178e..13fdbac 100644
--- a/apps/www/src/components/feat/settings/settings.tsx
+++ b/apps/www/src/components/feat/settings/settings.tsx
@@ -16,7 +16,7 @@ export function Settings() {
Settings
-
+
-
+
diff --git a/apps/www/src/components/ui/button.tsx b/apps/www/src/components/ui/button.tsx
index f848e61..873c407 100644
--- a/apps/www/src/components/ui/button.tsx
+++ b/apps/www/src/components/ui/button.tsx
@@ -13,35 +13,35 @@ const buttonVariants = cva(
variant: {
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
- 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
- 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:
- "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:
"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":
- "text-green-500 hover:bg-green-500 hover:!text-inherit",
+ "text-green-500 hover:bg-green-500 hover:text-inherit!",
"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
- hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 dark:text-zinc-400 hover:text-inherit
- hover:dark:text-inherit`,
+ hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:text-zinc-400 hover:text-inherit
+ dark:hover:text-inherit`,
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
- hover:dark:border-zinc-600`,
+ dark:border-zinc-700 hover:bg-zinc-200 dark:hover:bg-zinc-700 hover:border-slate-300
+ dark:hover:border-zinc-600`,
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
- hover:dark:border-zinc-700`,
+ dark:border-zinc-800 hover:bg-slate-200 dark:hover:bg-zinc-800 hover:border-slate-300
+ dark:hover:border-zinc-700`,
none: "",
},
@@ -63,7 +63,7 @@ const buttonVariants = cva(
right: "justify-end text-right origin-right",
},
shadow: {
- sm: "shadow-sm",
+ sm: "shadow-xs",
none: "shadow-none",
},
rounding: {
diff --git a/apps/www/src/components/ui/checkbox.tsx b/apps/www/src/components/ui/checkbox.tsx
index f678b95..9d31e01 100644
--- a/apps/www/src/components/ui/checkbox.tsx
+++ b/apps/www/src/components/ui/checkbox.tsx
@@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
{props.children}
-
+
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
diff --git a/apps/www/src/components/ui/input.tsx b/apps/www/src/components/ui/input.tsx
index 3cf7698..93975ab 100644
--- a/apps/www/src/components/ui/input.tsx
+++ b/apps/www/src/components/ui/input.tsx
@@ -14,7 +14,7 @@ const sizeClass = {
};
const shadowClass = {
- sm: "shadow-sm",
+ sm: "shadow-xs",
none: "shadow-none",
};
@@ -63,7 +63,7 @@ const Input: React.FC = ({
)}
{prefix && (
= ({
disabled={disabled}
value={value}
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 && (
-
+
Close
diff --git a/apps/www/src/components/ui/sidebar.tsx b/apps/www/src/components/ui/sidebar.tsx
index 5e9f37b..0c7a091 100644
--- a/apps/www/src/components/ui/sidebar.tsx
+++ b/apps/www/src/components/ui/sidebar.tsx
@@ -141,7 +141,7 @@ const SidebarProvider = React.forwardRef<
} as React.CSSProperties
}
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
)}
ref={ref}
@@ -181,7 +181,7 @@ const Sidebar = React.forwardRef<
return (
{children}
@@ -301,9 +301,9 @@ const SidebarRail = React.forwardRef<
title="Toggle Sidebar"
className={cn(
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
- "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
+ "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",
- "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=right][data-collapsible=offcanvas]_&]:-left-2",
className
@@ -323,7 +323,7 @@ const SidebarInset = React.forwardRef<
ref={ref}
className={cn(
"relative flex min-h-svh flex-1 flex-col bg-background",
- "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
+ "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
)}
{...props}
@@ -439,7 +439,7 @@ const SidebarGroupLabel = React.forwardRef<
ref={ref}
data-sidebar="group-label"
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",
className
)}
@@ -460,9 +460,9 @@ const SidebarGroupAction = React.forwardRef<
ref={ref}
data-sidebar="group-action"
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.
- "after:absolute after:-inset-2 after:md:hidden",
+ "after:absolute after:-inset-2 md:after:hidden",
"group-data-[collapsible=icon]:hidden",
className
)}
@@ -512,7 +512,7 @@ const SidebarMenuItem = React.forwardRef<
SidebarMenuItem.displayName = "SidebarMenuItem"
const sidebarMenuButtonVariants = cva(
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
+ "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: {
variant: {
@@ -523,7 +523,7 @@ const sidebarMenuButtonVariants = cva(
size: {
default: "h-8 text-sm",
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: {
@@ -606,9 +606,9 @@ const SidebarMenuAction = React.forwardRef<
ref={ref}
data-sidebar="menu-action"
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.
- "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=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
@@ -669,7 +669,7 @@ const SidebarMenuSkeleton = React.forwardRef<
/>
)}
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",
size === "sm" && "text-xs",
size === "md" && "text-sm",
diff --git a/apps/www/src/components/ui/switch.tsx b/apps/www/src/components/ui/switch.tsx
index fd475bd..1c4bbcb 100644
--- a/apps/www/src/components/ui/switch.tsx
+++ b/apps/www/src/components/ui/switch.tsx
@@ -11,8 +11,8 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
diff --git a/apps/www/src/components/ui/tabs.tsx b/apps/www/src/components/ui/tabs.tsx
index dffca9d..94c51d0 100644
--- a/apps/www/src/components/ui/tabs.tsx
+++ b/apps/www/src/components/ui/tabs.tsx
@@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<
= ({
value={value}
onChange={(e) => restProps.onChange?.(e)}
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}`}
/>
{restProps.children}
diff --git a/apps/www/src/components/util/clerk-provider.tsx b/apps/www/src/components/util/clerk-provider.tsx
new file mode 100644
index 0000000..0b9b67a
--- /dev/null
+++ b/apps/www/src/components/util/clerk-provider.tsx
@@ -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 (
+
+ {children}
+
+ );
+ }
+ console.log("a");
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/apps/www/src/components/util/font-boundary.tsx b/apps/www/src/components/util/font-boundary.tsx
new file mode 100644
index 0000000..265a7de
--- /dev/null
+++ b/apps/www/src/components/util/font-boundary.tsx
@@ -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 (
+ {
+ 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}
+
+ );
+}
diff --git a/apps/www/src/components/util/link.tsx b/apps/www/src/components/util/link.tsx
index 6e8721c..bf0ebf3 100644
--- a/apps/www/src/components/util/link.tsx
+++ b/apps/www/src/components/util/link.tsx
@@ -4,6 +4,7 @@ import { Book, ExternalLink, NotebookText } from "lucide-react";
export function Link(
props: LinkProps & {
children?: React.ReactNode;
+ className?: string;
}
) {
const href = props.href as string;
diff --git a/apps/www/src/components/util/mode-toggle.tsx b/apps/www/src/components/util/mode-toggle.tsx
index c7eee35..7629521 100644
--- a/apps/www/src/components/util/mode-toggle.tsx
+++ b/apps/www/src/components/util/mode-toggle.tsx
@@ -11,19 +11,17 @@ import {
} from "../ui/dropdown-menu";
export function ModeToggle() {
- const { setTheme } = useTheme();
+ const { setTheme, resolvedTheme } = useTheme();
return (
-
diff --git a/apps/www/src/components/util/theme-provider.tsx b/apps/www/src/components/util/theme-provider.tsx
index 8bf430b..f3ce3bf 100644
--- a/apps/www/src/components/util/theme-provider.tsx
+++ b/apps/www/src/components/util/theme-provider.tsx
@@ -1,11 +1,17 @@
"use client";
-import type * as React from "react";
-import { ThemeProvider as NextThemesProvider } from "next-themes";
+import * as React from "react";
+import { ThemeProvider as NextThemeProvider } from "next-themes";
+import type { ThemeProviderProps } from "next-themes";
-export function ThemeProvider({
- children,
- ...props
-}: React.ComponentProps) {
- return {children};
+export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+ const [mounted, setMounted] = React.useState(false);
+
+ React.useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ if (!mounted) return null;
+
+ return {children};
}
diff --git a/apps/www/src/lib/hooks/use-settings-store.tsx b/apps/www/src/lib/hooks/use-settings-store.tsx
new file mode 100644
index 0000000..b4df1af
--- /dev/null
+++ b/apps/www/src/lib/hooks/use-settings-store.tsx
@@ -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);
+ }
+ },
+ };
+}
diff --git a/apps/www/src/pages/api/v0/account-sl/change.ts b/apps/www/src/pages/api/v0/account-sl/change.ts
index 9a2611f..c37e5b8 100644
--- a/apps/www/src/pages/api/v0/account-sl/change.ts
+++ b/apps/www/src/pages/api/v0/account-sl/change.ts
@@ -30,52 +30,41 @@
import type { NextApiRequest, NextApiResponse } from "next";
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(
- req: NextApiRequest,
- res: NextApiResponse
+ req: NextApiRequest,
+ res: NextApiResponse,
) {
- const { userId } = getAuth(req);
+ const { userId } = getAuth(req);
- if (!userId) {
- return res.status(401).json({ error: "Unauthorized" });
- }
- const { data } = req.body;
+ if (!userId) {
+ return res.status(401).json({ error: "Unauthorized" });
+ }
+ const { data } = req.body;
- if (data === undefined) {
- res.status(400).send({ message: "Couldn't find data" });
- return;
- }
- const { type } = req.body;
+ if (data === undefined) {
+ res.status(400).send({ message: "Couldn't find data" });
+ return;
+ }
- 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" });
+ const v = obj.parse(data);
+ for (const [key, value] of Object.entries(v)) {
+ (await clerkClient()).users.updateUserMetadata(userId, {
+ publicMetadata: {
+ [key]: typeof value === "number" ? value.toString() : value,
+ },
+ });
+ }
- 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" });
-
- (await clerkClient()).users.updateUserMetadata(userId, {
- publicMetadata: {
- [type]: typeof data === "number" ? data.toString() : data,
- },
- });
- res.status(200).send({ message: "Success" });
+ res.status(200).send({ message: "Success" });
}
diff --git a/apps/www/tailwind.config.ts b/apps/www/tailwind.config.ts
deleted file mode 100644
index e73e5e7..0000000
--- a/apps/www/tailwind.config.ts
+++ /dev/null
@@ -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) / )",
- "50": "rgb(var(--c-s-50,248 250 252) / )",
- "100": "rgb(var(--c-s-100,241 245 249) / )",
- "200": "rgb(var(--c-s-200,226 232 240) / )",
- "300": "rgb(var(--c-s-300,203 213 225) / )",
- "400": "rgb(var(--c-s-400,148 163 184) / )",
- "500": "rgb(var(--c-s-500,100 116 139) / )",
- "600": "rgb(var(--c-s-600,71 85 105) / )",
- "700": "rgb(var(--c-s-700,51 65 85) / )",
- "800": "rgb(var(--c-s-800,30 41 59) / )",
- "900": "rgb(var(--c-s-900,15 23 42) / )",
- "950": "rgb(var(--c-s-950,2 6 23) / )",
- },
- zinc: {
- "50": "rgb(var(--c-z-50,249 250 251) / )",
- "100": "rgb(var(--c-z-100,243 244 246) / )",
- "200": "rgb(var(--c-z-200,229 231 235) / )",
- "300": "rgb(var(--c-z-300,209 213 219) / )",
- "400": "rgb(var(--c-z-400,156 163 175) / )",
- "500": "rgb(var(--c-z-500,107 114 128) / )",
- "600": "rgb(var(--c-z-600,75 85 99) / )",
- "700": "rgb(var(--c-z-700,50 60 76) / )",
- "800": "rgb(var(--c-z-800,22 31 45) / )",
- "900": "rgb(var(--c-z-900,17 24 39) / )",
- "925": "rgb(var(--c-z-925,8 12 25) / )",
- "950": "rgb(var(--c-z-950,5 9 16) / )",
- },
- primary: {
- "100": "rgb(var(--c-p-100,241 245 249) / )",
- "900": "rgb(var(--c-p-900,15 23 42) / )",
- },
- black: "rgb(var(--c-o-black,0 0 0) / )",
- white: "rgb(var(--c-o-white,255 255 255) / )",
- 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;
diff --git a/yarn.lock b/yarn.lock
index 500da7c..818e31f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2588,6 +2588,99 @@
resolved "https://registry.yarnpkg.com/@tailwindcss-mangle/shared/-/shared-3.0.0.tgz#8a60fa4168da0069c62fba75f212864ac796c54b"
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":
version "0.5.16"
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"
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:
version "2.0.3"
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"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
-enhanced-resolve@^5.15.0:
+enhanced-resolve@^5.15.0, enhanced-resolve@^5.18.1:
version "5.18.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf"
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"
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:
version "3.0.5"
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"
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:
version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
@@ -8056,7 +8227,7 @@ postcss@8.4.31:
picocolors "^1.0.0"
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"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.2.tgz#e7b99cb9d2ec3e8dd424002e7c16517cb2b846bd"
integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==
@@ -9240,6 +9411,11 @@ tailwindcss@3.3.2:
resolve "^1.22.2"
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:
version "3.4.17"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63"