mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
Compare commits
10 Commits
f4a400522a
...
e7f947a692
Author | SHA1 | Date | |
---|---|---|---|
|
e7f947a692 | ||
|
6f36d49e00 | ||
|
56ddf847a0 | ||
|
4da2eca1c1 | ||
|
d775cde3ca | ||
|
c59b381a35 | ||
|
5cd8d1d92e | ||
|
b74e7827d3 | ||
|
43fb66552e | ||
|
25bd7c41b4 |
@ -3,12 +3,13 @@
|
|||||||
import { LanguageSwitcher } from "@/components/LanguageSwitcher"
|
import { LanguageSwitcher } from "@/components/LanguageSwitcher"
|
||||||
import { ModeToggle } from "@/components/ThemeSwitcher"
|
import { ModeToggle } from "@/components/ThemeSwitcher"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
import { Skeleton } from "@/components/ui/skeleton"
|
|
||||||
import getEnv from "@/lib/env-entry"
|
import getEnv from "@/lib/env-entry"
|
||||||
|
import NumberFlow, { NumberFlowGroup } from "@number-flow/react"
|
||||||
import { DateTime } from "luxon"
|
import { DateTime } from "luxon"
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import { useEffect, useState } from "react"
|
import React from "react"
|
||||||
|
|
||||||
function Header() {
|
function Header() {
|
||||||
const t = useTranslations("Header")
|
const t = useTranslations("Header")
|
||||||
@ -99,33 +100,51 @@ function Links() {
|
|||||||
|
|
||||||
function Overview() {
|
function Overview() {
|
||||||
const t = useTranslations("Overview")
|
const t = useTranslations("Overview")
|
||||||
const [mouted, setMounted] = useState(false)
|
const [time, setTime] = React.useState({
|
||||||
useEffect(() => {
|
hh: DateTime.now().setLocale("en-US").hour,
|
||||||
setMounted(true)
|
mm: DateTime.now().setLocale("en-US").minute,
|
||||||
}, [])
|
ss: DateTime.now().setLocale("en-US").second,
|
||||||
const timeOption = DateTime.TIME_WITH_SECONDS
|
})
|
||||||
timeOption.hour12 = true
|
|
||||||
const [timeString, setTimeString] = useState(
|
React.useEffect(() => {
|
||||||
DateTime.now().setLocale("en-US").toLocaleString(timeOption),
|
const timer = setInterval(() => {
|
||||||
)
|
setTime({
|
||||||
useEffect(() => {
|
hh: DateTime.now().setLocale("en-US").hour,
|
||||||
const updateTime = () => {
|
mm: DateTime.now().setLocale("en-US").minute,
|
||||||
const now = DateTime.now().setLocale("en-US").toLocaleString(timeOption)
|
ss: DateTime.now().setLocale("en-US").second,
|
||||||
setTimeString(now)
|
})
|
||||||
requestAnimationFrame(updateTime)
|
}, 1000)
|
||||||
}
|
|
||||||
requestAnimationFrame(updateTime)
|
return () => clearInterval(timer)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={"mt-10 flex flex-col md:mt-16"}>
|
<section className={"mt-10 flex flex-col md:mt-16"}>
|
||||||
<p className="text-base font-semibold">{t("p_2277-2331_Overview")}</p>
|
<p className="text-base font-semibold">{t("p_2277-2331_Overview")}</p>
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<p className="text-sm font-medium opacity-50">{t("p_2390-2457_wherethetimeis")}</p>
|
<p className="text-sm font-medium opacity-50">{t("p_2390-2457_wherethetimeis")}</p>
|
||||||
{mouted ? (
|
<NumberFlowGroup>
|
||||||
<p className="text-sm font-medium">{timeString}</p>
|
<div
|
||||||
) : (
|
style={{ fontVariantNumeric: "tabular-nums" }}
|
||||||
<Skeleton className="h-[20px] w-[50px] rounded-[5px] bg-muted-foreground/10 animate-none" />
|
className="flex text-sm font-medium mt-0.5"
|
||||||
)}
|
>
|
||||||
|
<NumberFlow trend={1} value={time.hh} format={{ minimumIntegerDigits: 2 }} />
|
||||||
|
<NumberFlow
|
||||||
|
prefix=":"
|
||||||
|
trend={1}
|
||||||
|
value={time.mm}
|
||||||
|
digits={{ 1: { max: 5 } }}
|
||||||
|
format={{ minimumIntegerDigits: 2 }}
|
||||||
|
/>
|
||||||
|
<NumberFlow
|
||||||
|
prefix=":"
|
||||||
|
trend={1}
|
||||||
|
value={time.ss}
|
||||||
|
digits={{ 1: { max: 5 } }}
|
||||||
|
format={{ minimumIntegerDigits: 2 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</NumberFlowGroup>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,7 @@ export default function ServerCard({
|
|||||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||||
<Card
|
<Card
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 cursor-pointer hover:bg-accent/50 transition-colors",
|
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 cursor-pointer hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md",
|
||||||
{
|
{
|
||||||
"flex-col": fixedTopServerName,
|
"flex-col": fixedTopServerName,
|
||||||
"lg:flex-row": !fixedTopServerName,
|
"lg:flex-row": !fixedTopServerName,
|
||||||
@ -137,7 +137,7 @@ export default function ServerCard({
|
|||||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||||
<Card
|
<Card
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 cursor-pointer hover:bg-accent/50 transition-colors",
|
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 cursor-pointer hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md",
|
||||||
showNetTransfer ? "lg:min-h-[91px] min-h-[123px]" : "lg:min-h-[61px] min-h-[93px]",
|
showNetTransfer ? "lg:min-h-[91px] min-h-[123px]" : "lg:min-h-[61px] min-h-[93px]",
|
||||||
{
|
{
|
||||||
"flex-col": fixedTopServerName,
|
"flex-col": fixedTopServerName,
|
||||||
|
@ -29,7 +29,7 @@ export default function ServerCardInline({
|
|||||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||||
<Card
|
<Card
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center lg:flex-row justify-start gap-3 p-3 md:px-5 cursor-pointer hover:bg-accent/50 transition-colors min-w-[900px] w-full",
|
"flex items-center lg:flex-row justify-start gap-3 p-3 md:px-5 cursor-pointer hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md min-w-[900px] w-full",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<section
|
<section
|
||||||
@ -124,9 +124,10 @@ export default function ServerCardInline({
|
|||||||
</Card>
|
</Card>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
|
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||||
<Card
|
<Card
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center justify-start gap-3 p-3 md:px-5 min-h-[61px] min-w-[900px] flex-row",
|
"flex items-center justify-start gap-3 p-3 md:px-5 hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md min-h-[61px] min-w-[900px] flex-row",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<section
|
<section
|
||||||
@ -135,16 +136,22 @@ export default function ServerCardInline({
|
|||||||
>
|
>
|
||||||
<span className="h-2 w-2 shrink-0 rounded-full bg-red-500 self-center" />
|
<span className="h-2 w-2 shrink-0 rounded-full bg-red-500 self-center" />
|
||||||
<div
|
<div
|
||||||
className={cn("flex items-center justify-center", showFlag ? "min-w-[17px]" : "min-w-0")}
|
className={cn(
|
||||||
|
"flex items-center justify-center",
|
||||||
|
showFlag ? "min-w-[17px]" : "min-w-0",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{showFlag ? <ServerFlag country_code={country_code} /> : null}
|
{showFlag ? <ServerFlag country_code={country_code} /> : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="relative w-28">
|
<div className="relative w-28">
|
||||||
<p className={cn("break-all font-bold tracking-tight", showFlag ? "text-xs" : "text-sm")}>
|
<p
|
||||||
|
className={cn("break-all font-bold tracking-tight", showFlag ? "text-xs" : "text-sm")}
|
||||||
|
>
|
||||||
{name}
|
{name}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</Card>
|
</Card>
|
||||||
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { env } from "next-runtime-env"
|
import { getClientEnv, getServerEnv } from "./env"
|
||||||
|
import type { EnvKey } from "./env"
|
||||||
|
|
||||||
export default function getEnv(key: string) {
|
export default function getEnv(key: EnvKey): string | undefined {
|
||||||
if (key.startsWith("NEXT_PUBLIC_")) {
|
if (key.startsWith("NEXT_PUBLIC_")) {
|
||||||
return env(key)
|
const clientKey = key.replace("NEXT_PUBLIC_", "") as any
|
||||||
|
return getClientEnv(clientKey)
|
||||||
}
|
}
|
||||||
return process.env[key]
|
return getServerEnv(key as any)
|
||||||
}
|
}
|
||||||
|
147
lib/env.ts
Normal file
147
lib/env.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import { env } from "next-runtime-env"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server-side environment variables
|
||||||
|
*/
|
||||||
|
export interface ServerEnvConfig {
|
||||||
|
/** Nezha API base URL */
|
||||||
|
NezhaBaseUrl: string
|
||||||
|
/** Nezha API authentication token */
|
||||||
|
NezhaAuth: string
|
||||||
|
/** Default locale for the application */
|
||||||
|
DefaultLocale: string
|
||||||
|
/** Force show all servers */
|
||||||
|
ForceShowAllServers: boolean
|
||||||
|
/** Site password */
|
||||||
|
SitePassword: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client-side environment variables (NEXT_PUBLIC_*)
|
||||||
|
*/
|
||||||
|
export interface ClientEnvConfig {
|
||||||
|
/** Nezha data fetch interval in milliseconds */
|
||||||
|
NezhaFetchInterval: number
|
||||||
|
/** Show country flags */
|
||||||
|
ShowFlag: boolean
|
||||||
|
/** Disable cartoon effects */
|
||||||
|
DisableCartoon: boolean
|
||||||
|
/** Show server tags */
|
||||||
|
ShowTag: boolean
|
||||||
|
/** Show network transfer information */
|
||||||
|
ShowNetTransfer: boolean
|
||||||
|
/** Force use SVG flags */
|
||||||
|
ForceUseSvgFlag: boolean
|
||||||
|
/** Fix server names at the top */
|
||||||
|
FixedTopServerName: boolean
|
||||||
|
/** Custom logo URL */
|
||||||
|
CustomLogo: string
|
||||||
|
/** Custom site title */
|
||||||
|
CustomTitle: string
|
||||||
|
/** Custom site description */
|
||||||
|
CustomDescription: string
|
||||||
|
/** Custom navigation links */
|
||||||
|
Links: string
|
||||||
|
/** Disable search engine indexing */
|
||||||
|
DisableIndex: boolean
|
||||||
|
/** Show tag count */
|
||||||
|
ShowTagCount: boolean
|
||||||
|
/** Show IP information */
|
||||||
|
ShowIpInfo: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 环境变量键的类型定义
|
||||||
|
*/
|
||||||
|
export type EnvKey = ServerEnvKey | ClientEnvKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器端环境变量键
|
||||||
|
*/
|
||||||
|
export type ServerEnvKey = keyof ServerEnvConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端环境变量键
|
||||||
|
*/
|
||||||
|
export type ClientEnvKey = `NEXT_PUBLIC_${keyof ClientEnvConfig}`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a server-side environment variable
|
||||||
|
* @param key - Environment variable key
|
||||||
|
* @returns Environment variable value
|
||||||
|
*/
|
||||||
|
export function getServerEnv<K extends keyof ServerEnvConfig>(key: K): string | undefined {
|
||||||
|
const value = process.env[key]
|
||||||
|
if (!value) {
|
||||||
|
console.warn(`Environment variable ${key} is not set`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a client-side environment variable
|
||||||
|
* @param key - Environment variable key
|
||||||
|
* @returns Environment variable value
|
||||||
|
*/
|
||||||
|
export function getClientEnv<K extends keyof ClientEnvConfig>(key: K): string | undefined {
|
||||||
|
const envKey = `NEXT_PUBLIC_${key}`
|
||||||
|
const value = env(envKey)
|
||||||
|
if (!value) {
|
||||||
|
console.warn(`Environment variable ${envKey} is not set`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse boolean environment variable
|
||||||
|
* @param value - Environment variable value
|
||||||
|
* @returns Parsed boolean value
|
||||||
|
*/
|
||||||
|
export function parseBoolean(value: string | undefined): boolean {
|
||||||
|
return value?.toLowerCase() === "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse number environment variable
|
||||||
|
* @param value - Environment variable value
|
||||||
|
* @param defaultValue - Default value if parsing fails
|
||||||
|
* @returns Parsed number value
|
||||||
|
*/
|
||||||
|
export function parseNumber(value: string | undefined, defaultValue: number): number {
|
||||||
|
if (!value) return defaultValue
|
||||||
|
const parsed = Number.parseInt(value, 10)
|
||||||
|
return Number.isNaN(parsed) ? defaultValue : parsed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all environment variables with their current values
|
||||||
|
*/
|
||||||
|
export function getAllEnvConfig(): { server: ServerEnvConfig; client: ClientEnvConfig } {
|
||||||
|
return {
|
||||||
|
server: {
|
||||||
|
NezhaBaseUrl: getServerEnv("NezhaBaseUrl") || "",
|
||||||
|
NezhaAuth: getServerEnv("NezhaAuth") || "",
|
||||||
|
DefaultLocale: getServerEnv("DefaultLocale") || "",
|
||||||
|
ForceShowAllServers: parseBoolean(getServerEnv("ForceShowAllServers")),
|
||||||
|
SitePassword: getServerEnv("SitePassword") || "",
|
||||||
|
},
|
||||||
|
client: {
|
||||||
|
NezhaFetchInterval: parseNumber(getClientEnv("NezhaFetchInterval"), 5000),
|
||||||
|
ShowFlag: parseBoolean(getClientEnv("ShowFlag")),
|
||||||
|
DisableCartoon: parseBoolean(getClientEnv("DisableCartoon")),
|
||||||
|
ShowTag: parseBoolean(getClientEnv("ShowTag")),
|
||||||
|
ShowNetTransfer: parseBoolean(getClientEnv("ShowNetTransfer")),
|
||||||
|
ForceUseSvgFlag: parseBoolean(getClientEnv("ForceUseSvgFlag")),
|
||||||
|
FixedTopServerName: parseBoolean(getClientEnv("FixedTopServerName")),
|
||||||
|
CustomLogo: getClientEnv("CustomLogo") || "",
|
||||||
|
CustomTitle: getClientEnv("CustomTitle") || "",
|
||||||
|
CustomDescription: getClientEnv("CustomDescription") || "",
|
||||||
|
Links: getClientEnv("Links") || "",
|
||||||
|
DisableIndex: parseBoolean(getClientEnv("DisableIndex")),
|
||||||
|
ShowTagCount: parseBoolean(getClientEnv("ShowTagCount")),
|
||||||
|
ShowIpInfo: parseBoolean(getClientEnv("ShowIpInfo")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -112,7 +112,7 @@
|
|||||||
"p_1079-1199_Simpleandbeautifuldashbo": "Simple and beautiful dashboard"
|
"p_1079-1199_Simpleandbeautifuldashbo": "Simple and beautiful dashboard"
|
||||||
},
|
},
|
||||||
"Overview": {
|
"Overview": {
|
||||||
"p_2277-2331_Overview": "👋 Overview",
|
"p_2277-2331_Overview": "Overview",
|
||||||
"p_2390-2457_wherethetimeis": "where the time is"
|
"p_2390-2457_wherethetimeis": "where the time is"
|
||||||
},
|
},
|
||||||
"Global": {
|
"Global": {
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
"p_1079-1199_Simpleandbeautifuldashbo": "シンプルで美しいダッシュボード"
|
"p_1079-1199_Simpleandbeautifuldashbo": "シンプルで美しいダッシュボード"
|
||||||
},
|
},
|
||||||
"Overview": {
|
"Overview": {
|
||||||
"p_2277-2331_Overview": "👋 概要",
|
"p_2277-2331_Overview": "概要",
|
||||||
"p_2390-2457_wherethetimeis": "現在の時間"
|
"p_2390-2457_wherethetimeis": "現在の時間"
|
||||||
},
|
},
|
||||||
"Global": {
|
"Global": {
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
"p_1079-1199_Simpleandbeautifuldashbo": "簡單美觀的儀錶板"
|
"p_1079-1199_Simpleandbeautifuldashbo": "簡單美觀的儀錶板"
|
||||||
},
|
},
|
||||||
"Overview": {
|
"Overview": {
|
||||||
"p_2277-2331_Overview": "👋 概覽",
|
"p_2277-2331_Overview": "概覽",
|
||||||
"p_2390-2457_wherethetimeis": "當前時間"
|
"p_2390-2457_wherethetimeis": "當前時間"
|
||||||
},
|
},
|
||||||
"Global": {
|
"Global": {
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
"p_1079-1199_Simpleandbeautifuldashbo": "简单美观的仪表板"
|
"p_1079-1199_Simpleandbeautifuldashbo": "简单美观的仪表板"
|
||||||
},
|
},
|
||||||
"Overview": {
|
"Overview": {
|
||||||
"p_2277-2331_Overview": "👋 概览",
|
"p_2277-2331_Overview": "概览",
|
||||||
"p_2390-2457_wherethetimeis": "当前时间"
|
"p_2390-2457_wherethetimeis": "当前时间"
|
||||||
},
|
},
|
||||||
"Global": {
|
"Global": {
|
||||||
|
13
package.json
13
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nezha-dash",
|
"name": "nezha-dash",
|
||||||
"version": "2.5.1",
|
"version": "2.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3040",
|
"dev": "next dev -p 3040",
|
||||||
@ -15,6 +15,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ducanh2912/next-pwa": "^10.2.9",
|
"@ducanh2912/next-pwa": "^10.2.9",
|
||||||
"@heroicons/react": "^2.2.0",
|
"@heroicons/react": "^2.2.0",
|
||||||
|
"@number-flow/react": "^0.5.5",
|
||||||
"@radix-ui/react-dialog": "^1.1.5",
|
"@radix-ui/react-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.5",
|
"@radix-ui/react-dropdown-menu": "^2.1.5",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.1.1",
|
||||||
@ -25,19 +26,19 @@
|
|||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.1.1",
|
||||||
"@radix-ui/react-switch": "^1.1.2",
|
"@radix-ui/react-switch": "^1.1.2",
|
||||||
"@radix-ui/react-tooltip": "^1.1.7",
|
"@radix-ui/react-tooltip": "^1.1.7",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.1",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"@types/d3-geo": "^3.1.0",
|
"@types/d3-geo": "^3.1.0",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"caniuse-lite": "^1.0.30001695",
|
"caniuse-lite": "^1.0.30001696",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "1.0.0",
|
"cmdk": "^1.0.4",
|
||||||
"country-flag-icons": "^1.5.14",
|
"country-flag-icons": "^1.5.14",
|
||||||
"d3-geo": "^3.1.1",
|
"d3-geo": "^3.1.1",
|
||||||
"d3-selection": "^3.0.0",
|
"d3-selection": "^3.0.0",
|
||||||
"flag-icons": "^7.3.2",
|
"flag-icons": "^7.3.2",
|
||||||
"i18n-iso-countries": "^7.13.0",
|
"i18n-iso-countries": "^7.13.0",
|
||||||
"lucide-react": "^0.454.0",
|
"lucide-react": "^0.474.0",
|
||||||
"luxon": "^3.5.0",
|
"luxon": "^3.5.0",
|
||||||
"maxmind": "^4.3.24",
|
"maxmind": "^4.3.24",
|
||||||
"next": "^15.1.6",
|
"next": "^15.1.6",
|
||||||
@ -66,7 +67,7 @@
|
|||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
"tailwindcss": "^4.0.0",
|
"tailwindcss": "^4.0.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
"vercel": "^39.3.0"
|
"vercel": "^39.4.2"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"react-is": "^19.0.0-rc-69d4b800-20241021"
|
"react-is": "^19.0.0-rc-69d4b800-20241021"
|
||||||
|
Loading…
Reference in New Issue
Block a user