mirror of
https://github.com/YuzuZensai/Minikura.git
synced 2026-09-13 10:49:21 +00:00
✨ feat: add dark/light theme toggle
This commit is contained in:
@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { AuthFormCard, FormError } from "@/components/auth/auth-form-card";
|
import { AuthFormCard, FormError } from "@/components/auth/auth-form-card";
|
||||||
import { BrandMark } from "@/components/brand";
|
import { BrandMark } from "@/components/brand";
|
||||||
import { FullScreenLoader } from "@/components/page-layout";
|
import { FullScreenLoader } from "@/components/page-layout";
|
||||||
|
import { ThemeToggle } from "@/components/theme-toggle";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/lib/api-client";
|
import { api } from "@/lib/api-client";
|
||||||
@@ -82,7 +83,8 @@ export default function BootstrapPage() {
|
|||||||
if (checkingStatus) return <FullScreenLoader label="Checking setup" />;
|
if (checkingStatus) return <FullScreenLoader label="Checking setup" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="auth-grid flex min-h-screen items-center justify-center bg-sidebar p-5 sm:p-10">
|
<main className="auth-grid relative flex min-h-screen items-center justify-center bg-sidebar p-5 sm:p-10">
|
||||||
|
<ThemeToggle className="absolute top-5 right-5 sm:top-8 sm:right-8" />
|
||||||
<div className="grid w-full max-w-5xl overflow-hidden border border-sidebar-border bg-background text-foreground shadow-[12px_12px_0_color-mix(in_oklch,var(--sidebar-primary)_18%,transparent)] lg:grid-cols-[0.8fr_1.2fr]">
|
<div className="grid w-full max-w-5xl overflow-hidden border border-sidebar-border bg-background text-foreground shadow-[12px_12px_0_color-mix(in_oklch,var(--sidebar-primary)_18%,transparent)] lg:grid-cols-[0.8fr_1.2fr]">
|
||||||
<section className="flex flex-col justify-between bg-primary p-8 text-primary-foreground sm:p-10">
|
<section className="flex flex-col justify-between bg-primary p-8 text-primary-foreground sm:p-10">
|
||||||
<BrandMark inverted />
|
<BrandMark inverted />
|
||||||
|
|||||||
+39
-33
@@ -89,40 +89,46 @@
|
|||||||
--sidebar-accent-foreground: oklch(0.96 0.01 95);
|
--sidebar-accent-foreground: oklch(0.96 0.01 95);
|
||||||
--sidebar-border: oklch(0.31 0.025 80);
|
--sidebar-border: oklch(0.31 0.025 80);
|
||||||
--sidebar-ring: oklch(0.75 0.205 125);
|
--sidebar-ring: oklch(0.75 0.205 125);
|
||||||
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: oklch(0.145 0 0);
|
--background: oklch(0.16 0.018 75);
|
||||||
--foreground: oklch(0.985 0 0);
|
--foreground: oklch(0.94 0.012 95);
|
||||||
--card: oklch(0.205 0 0);
|
--card: oklch(0.21 0.018 75);
|
||||||
--card-foreground: oklch(0.985 0 0);
|
--card-foreground: oklch(0.94 0.012 95);
|
||||||
--popover: oklch(0.205 0 0);
|
--popover: oklch(0.19 0.018 75);
|
||||||
--popover-foreground: oklch(0.985 0 0);
|
--popover-foreground: oklch(0.94 0.012 95);
|
||||||
--primary: oklch(0.922 0 0);
|
--primary: oklch(0.75 0.205 125);
|
||||||
--primary-foreground: oklch(0.205 0 0);
|
--primary-foreground: oklch(0.15 0.025 125);
|
||||||
--secondary: oklch(0.269 0 0);
|
--secondary: oklch(0.26 0.02 80);
|
||||||
--secondary-foreground: oklch(0.985 0 0);
|
--secondary-foreground: oklch(0.94 0.012 95);
|
||||||
--muted: oklch(0.269 0 0);
|
--muted: oklch(0.24 0.016 80);
|
||||||
--muted-foreground: oklch(0.708 0 0);
|
--muted-foreground: oklch(0.72 0.018 90);
|
||||||
--accent: oklch(0.269 0 0);
|
--accent: oklch(0.28 0.04 112);
|
||||||
--accent-foreground: oklch(0.985 0 0);
|
--accent-foreground: oklch(0.92 0.03 110);
|
||||||
--destructive: oklch(0.704 0.191 22.216);
|
--destructive: oklch(0.68 0.19 28);
|
||||||
--border: oklch(1 0 0 / 10%);
|
--success: oklch(0.72 0.155 132);
|
||||||
--input: oklch(1 0 0 / 15%);
|
--success-foreground: oklch(0.22 0.06 132);
|
||||||
--ring: oklch(0.556 0 0);
|
--warning: oklch(0.78 0.14 76);
|
||||||
--chart-1: oklch(0.488 0.243 264.376);
|
--warning-foreground: oklch(0.28 0.08 66);
|
||||||
--chart-2: oklch(0.696 0.17 162.48);
|
--border: oklch(0.35 0.02 80);
|
||||||
--chart-3: oklch(0.769 0.188 70.08);
|
--input: oklch(0.32 0.02 80);
|
||||||
--chart-4: oklch(0.627 0.265 303.9);
|
--ring: oklch(0.75 0.205 125);
|
||||||
--chart-5: oklch(0.645 0.246 16.439);
|
--chart-1: oklch(0.75 0.205 125);
|
||||||
--sidebar: oklch(0.205 0 0);
|
--chart-2: oklch(0.66 0.16 205);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--chart-3: oklch(0.72 0.17 80);
|
||||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
--chart-4: oklch(0.62 0.16 50);
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
--chart-5: oklch(0.58 0.14 300);
|
||||||
--sidebar-accent: oklch(0.269 0 0);
|
--sidebar: oklch(0.13 0.018 75);
|
||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.91 0.015 95);
|
||||||
--sidebar-border: oklch(1 0 0 / 10%);
|
--sidebar-primary: oklch(0.75 0.205 125);
|
||||||
--sidebar-ring: oklch(0.556 0 0);
|
--sidebar-primary-foreground: oklch(0.15 0.025 125);
|
||||||
|
--sidebar-accent: oklch(0.22 0.022 80);
|
||||||
|
--sidebar-accent-foreground: oklch(0.96 0.01 95);
|
||||||
|
--sidebar-border: oklch(0.28 0.022 80);
|
||||||
|
--sidebar-ring: oklch(0.75 0.205 125);
|
||||||
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
@@ -174,8 +180,8 @@
|
|||||||
|
|
||||||
.auth-grid {
|
.auth-grid {
|
||||||
background-image:
|
background-image:
|
||||||
linear-gradient(to right, color-mix(in oklch, white 9%, transparent) 1px, transparent 1px),
|
linear-gradient(to right, color-mix(in oklch, var(--sidebar-foreground) 9%, transparent) 1px, transparent 1px),
|
||||||
linear-gradient(to bottom, color-mix(in oklch, white 9%, transparent) 1px, transparent 1px);
|
linear-gradient(to bottom, color-mix(in oklch, var(--sidebar-foreground) 9%, transparent) 1px, transparent 1px);
|
||||||
background-size: 36px 36px;
|
background-size: 36px 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -1,4 +1,5 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
|
import { ThemeProvider } from "@/components/theme-provider";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@@ -8,8 +9,17 @@ export const metadata: Metadata = {
|
|||||||
|
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" suppressHydrationWarning>
|
||||||
<body>{children}</body>
|
<body>
|
||||||
|
<ThemeProvider
|
||||||
|
attribute="class"
|
||||||
|
defaultTheme="system"
|
||||||
|
enableSystem
|
||||||
|
disableTransitionOnChange
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { AuthFormCard, FormError } from "@/components/auth/auth-form-card";
|
import { AuthFormCard, FormError } from "@/components/auth/auth-form-card";
|
||||||
import { BrandLockup } from "@/components/brand";
|
import { BrandLockup } from "@/components/brand";
|
||||||
import { FullScreenLoader } from "@/components/page-layout";
|
import { FullScreenLoader } from "@/components/page-layout";
|
||||||
|
import { ThemeToggle } from "@/components/theme-toggle";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { authClient, signIn, useSession } from "@/lib/auth-client";
|
import { authClient, signIn, useSession } from "@/lib/auth-client";
|
||||||
@@ -87,7 +88,8 @@ export default function LoginPage() {
|
|||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="flex items-center justify-center bg-background p-5 text-foreground sm:p-10">
|
<section className="relative flex items-center justify-center bg-background p-5 text-foreground sm:p-10">
|
||||||
|
<ThemeToggle className="absolute top-5 right-5 sm:top-8 sm:right-8" />
|
||||||
<AuthFormCard
|
<AuthFormCard
|
||||||
title="Sign In"
|
title="Sign In"
|
||||||
description="Use your administrator account to access Minikura."
|
description="Use your administrator account to access Minikura."
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { usePathname, useRouter } from "next/navigation";
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { BrandLockup } from "@/components/brand";
|
import { BrandLockup } from "@/components/brand";
|
||||||
import { FullScreenLoader } from "@/components/page-layout";
|
import { FullScreenLoader } from "@/components/page-layout";
|
||||||
|
import { ThemeToggle } from "@/components/theme-toggle";
|
||||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -161,6 +162,7 @@ export function DashboardLayout({ children }: { children: React.ReactNode }) {
|
|||||||
<span className="truncate font-mono text-[10px] font-bold uppercase tracking-[0.15em] text-muted-foreground">
|
<span className="truncate font-mono text-[10px] font-bold uppercase tracking-[0.15em] text-muted-foreground">
|
||||||
{currentPage ? `${currentPage.context} / ${currentPage.label}` : "Control plane"}
|
{currentPage ? `${currentPage.context} / ${currentPage.label}` : "Control plane"}
|
||||||
</span>
|
</span>
|
||||||
|
<ThemeToggle className="ml-auto" />
|
||||||
</header>
|
</header>
|
||||||
<main className="min-w-0 flex-1 overflow-auto p-4 sm:p-6 lg:p-8">{children}</main>
|
<main className="min-w-0 flex-1 overflow-auto p-4 sm:p-6 lg:p-8">{children}</main>
|
||||||
</SidebarInset>
|
</SidebarInset>
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
||||||
|
import type * as React from "react";
|
||||||
|
|
||||||
|
export function ThemeProvider({
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof NextThemesProvider>) {
|
||||||
|
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Monitor, Moon, Sun } from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuRadioGroup,
|
||||||
|
DropdownMenuRadioItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
import { cn } from "@/lib/cn";
|
||||||
|
|
||||||
|
type ThemeToggleProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ThemeToggle({ className }: ThemeToggleProps) {
|
||||||
|
const { theme, setTheme } = useTheme();
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon-sm"
|
||||||
|
className={cn("relative", className)}
|
||||||
|
aria-label="Toggle theme"
|
||||||
|
>
|
||||||
|
<Sun className="size-4 scale-100 rotate-0 transition-transform dark:scale-0 dark:-rotate-90" />
|
||||||
|
<Moon className="absolute size-4 scale-0 rotate-90 transition-transform dark:scale-100 dark:rotate-0" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end" className="min-w-36">
|
||||||
|
<DropdownMenuRadioGroup value={mounted ? theme : undefined} onValueChange={setTheme}>
|
||||||
|
<DropdownMenuRadioItem value="light">
|
||||||
|
<Sun />
|
||||||
|
Light
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="dark">
|
||||||
|
<Moon />
|
||||||
|
Dark
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="system">
|
||||||
|
<Monitor />
|
||||||
|
System
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
</DropdownMenuRadioGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Background, BackgroundVariant, Controls, MiniMap, Panel, ReactFlow } from "@xyflow/react";
|
import { Background, BackgroundVariant, Controls, MiniMap, Panel, ReactFlow } from "@xyflow/react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
import { useCallback, useMemo, useState } from "react";
|
import { useCallback, useMemo, useState } from "react";
|
||||||
import "@xyflow/react/dist/style.css";
|
import "@xyflow/react/dist/style.css";
|
||||||
import { useGraphLayout } from "@/hooks/use-graph-layout";
|
import { useGraphLayout } from "@/hooks/use-graph-layout";
|
||||||
@@ -15,6 +16,7 @@ interface TopologyCanvasProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function TopologyCanvas({ graph }: TopologyCanvasProps) {
|
export function TopologyCanvas({ graph }: TopologyCanvasProps) {
|
||||||
|
const { resolvedTheme } = useTheme();
|
||||||
const [selectedNode, setSelectedNode] = useState<TopologyNodeData | null>(null);
|
const [selectedNode, setSelectedNode] = useState<TopologyNodeData | null>(null);
|
||||||
const [filters, setFilters] = useState<TopologyFilters>({
|
const [filters, setFilters] = useState<TopologyFilters>({
|
||||||
showServers: true,
|
showServers: true,
|
||||||
@@ -68,24 +70,25 @@ export function TopologyCanvas({ graph }: TopologyCanvasProps) {
|
|||||||
}}
|
}}
|
||||||
minZoom={0.1}
|
minZoom={0.1}
|
||||||
maxZoom={1.5}
|
maxZoom={1.5}
|
||||||
|
colorMode={resolvedTheme === "dark" ? "dark" : "light"}
|
||||||
defaultEdgeOptions={{
|
defaultEdgeOptions={{
|
||||||
animated: false,
|
animated: false,
|
||||||
type: "smoothstep",
|
type: "smoothstep",
|
||||||
style: {
|
style: {
|
||||||
stroke: "#6f7565",
|
stroke: "var(--muted-foreground)",
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
strokeDasharray: "5 5",
|
strokeDasharray: "5 5",
|
||||||
},
|
},
|
||||||
markerEnd: {
|
markerEnd: {
|
||||||
type: "arrowclosed",
|
type: "arrowclosed",
|
||||||
color: "#6f7565",
|
color: "var(--muted-foreground)",
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
proOptions={{ hideAttribution: true }}
|
proOptions={{ hideAttribution: true }}
|
||||||
>
|
>
|
||||||
<Background variant={BackgroundVariant.Lines} color="#d2d0c5" gap={32} size={1} />
|
<Background variant={BackgroundVariant.Lines} color="var(--border)" gap={32} size={1} />
|
||||||
<Controls
|
<Controls
|
||||||
showZoom
|
showZoom
|
||||||
showFitView
|
showFitView
|
||||||
@@ -103,7 +106,7 @@ export function TopologyCanvas({ graph }: TopologyCanvasProps) {
|
|||||||
};
|
};
|
||||||
return colors[data.status] || "#94a3b8";
|
return colors[data.status] || "#94a3b8";
|
||||||
}}
|
}}
|
||||||
maskColor="rgba(29, 31, 26, 0.08)"
|
maskColor="color-mix(in oklch, var(--foreground) 8%, transparent)"
|
||||||
className="border bg-card/95 shadow-md backdrop-blur-sm"
|
className="border bg-card/95 shadow-md backdrop-blur-sm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function HealthBadge({
|
|||||||
healthy: "bg-green-500",
|
healthy: "bg-green-500",
|
||||||
degraded: "bg-yellow-500",
|
degraded: "bg-yellow-500",
|
||||||
unhealthy: "bg-red-500",
|
unhealthy: "bg-red-500",
|
||||||
unknown: "bg-gray-400",
|
unknown: "bg-muted-foreground",
|
||||||
}[status];
|
}[status];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -100,10 +100,10 @@ export function TopologyNodeCard({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-lg border bg-card p-3 shadow-md hover:shadow-lg transition-all w-[300px]",
|
"rounded-lg border bg-card p-3 shadow-md hover:shadow-lg transition-all w-[300px]",
|
||||||
selected && "ring-2 ring-primary ring-offset-2 shadow-xl"
|
selected && "ring-2 ring-primary ring-offset-2 ring-offset-background shadow-xl"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Handle type="target" position={Position.Top} className="w-3 h-3 !bg-gray-400" />
|
<Handle type="target" position={Position.Top} className="h-3 w-3 !bg-muted-foreground" />
|
||||||
<div className="space-y-2.5">
|
<div className="space-y-2.5">
|
||||||
<div className="flex items-start justify-between gap-2">
|
<div className="flex items-start justify-between gap-2">
|
||||||
<div className="flex items-center gap-2 flex-1 min-w-0">
|
<div className="flex items-center gap-2 flex-1 min-w-0">
|
||||||
@@ -119,7 +119,7 @@ export function TopologyNodeCard({
|
|||||||
</div>
|
</div>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
<Handle type="source" position={Position.Bottom} className="w-3 h-3 !bg-gray-400" />
|
<Handle type="source" position={Position.Bottom} className="h-3 w-3 !bg-muted-foreground" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
"elysia": "^1.4.29",
|
"elysia": "^1.4.29",
|
||||||
"lucide-react": "^1.31.0",
|
"lucide-react": "^1.31.0",
|
||||||
"next": "^16.3.0",
|
"next": "^16.3.0",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
"postcss": "^8.5.26",
|
"postcss": "^8.5.26",
|
||||||
"react": "^19.2.8",
|
"react": "^19.2.8",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
"elysia": "^1.4.29",
|
"elysia": "^1.4.29",
|
||||||
"lucide-react": "^1.31.0",
|
"lucide-react": "^1.31.0",
|
||||||
"next": "^16.3.0",
|
"next": "^16.3.0",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
"postcss": "^8.5.26",
|
"postcss": "^8.5.26",
|
||||||
"react": "^19.2.8",
|
"react": "^19.2.8",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
@@ -1103,6 +1104,8 @@
|
|||||||
|
|
||||||
"next": ["next@16.3.0", "", { "dependencies": { "@next/env": "16.3.0", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.5.23", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.3.0", "@next/swc-darwin-x64": "16.3.0", "@next/swc-linux-arm64-gnu": "16.3.0", "@next/swc-linux-arm64-musl": "16.3.0", "@next/swc-linux-x64-gnu": "16.3.0", "@next/swc-linux-x64-musl": "16.3.0", "@next/swc-win32-arm64-msvc": "16.3.0", "@next/swc-win32-x64-msvc": "16.3.0", "sharp": "^0.35.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-NEdGOzH+08eTXMUp9UYkA99Nhi5N6Thrhc1jgFOQgfgnGK/dA2hRwBpXep+exdFQrnwlRf/3Wixyp8lLBUpE2A=="],
|
"next": ["next@16.3.0", "", { "dependencies": { "@next/env": "16.3.0", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.5.23", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.3.0", "@next/swc-darwin-x64": "16.3.0", "@next/swc-linux-arm64-gnu": "16.3.0", "@next/swc-linux-arm64-musl": "16.3.0", "@next/swc-linux-x64-gnu": "16.3.0", "@next/swc-linux-x64-musl": "16.3.0", "@next/swc-win32-arm64-msvc": "16.3.0", "@next/swc-win32-x64-msvc": "16.3.0", "sharp": "^0.35.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-NEdGOzH+08eTXMUp9UYkA99Nhi5N6Thrhc1jgFOQgfgnGK/dA2hRwBpXep+exdFQrnwlRf/3Wixyp8lLBUpE2A=="],
|
||||||
|
|
||||||
|
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
|
||||||
|
|
||||||
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||||
|
|
||||||
"node-releases": ["node-releases@2.0.53", "", {}, "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ=="],
|
"node-releases": ["node-releases@2.0.53", "", {}, "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ=="],
|
||||||
|
|||||||
Reference in New Issue
Block a user