Compare commits

...

9 Commits

Author SHA1 Message Date
dependabot[bot]
a85f760ced
Merge dc0f7e1a63cce6136458a576dbb0dab6876c9ebf into 7cc8671448c2b83f722e248bbf3fee38c4ad0bf2 2024-12-22 02:11:45 +00:00
dvelo
7cc8671448
push changes to main
push changes to main
2024-12-21 20:11:38 -06:00
dvelo
cc4bf911cf fix: server pages aren't clickable 2024-12-21 18:30:42 -06:00
dvelo
b49b73af80 fix: new changes 2024-12-21 18:11:07 -06:00
dvelo
a019e1e5b1 fix: remove legacy notifications 2024-12-21 17:25:40 -06:00
dvelo
e0d96b47cd fix: errors 2024-12-21 17:22:11 -06:00
dvelo
c8fe0a6051 feat: new banner system 2024-12-21 17:14:29 -06:00
dvelo
b144bafd03 fix: remove legacy email-list 2024-12-21 10:21:19 -06:00
dependabot[bot]
dc0f7e1a63
build(deps-dev): bump @unocss/preset-uno from 0.61.5 to 0.65.1
Bumps [@unocss/preset-uno](https://github.com/unocss/unocss/tree/HEAD/packages/preset-uno) from 0.61.5 to 0.65.1.
- [Release notes](https://github.com/unocss/unocss/releases)
- [Commits](https://github.com/unocss/unocss/commits/v0.65.1/packages/preset-uno)

---
updated-dependencies:
- dependency-name: "@unocss/preset-uno"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 05:58:52 +00:00
28 changed files with 698 additions and 212 deletions

1
.tool-versions Normal file

@ -0,0 +1 @@
nodejs 23.3.0

@ -20,6 +20,7 @@
"@emotion/is-prop-valid": "^1.3.0", "@emotion/is-prop-valid": "^1.3.0",
"@linear/sdk": "^31.0.0", "@linear/sdk": "^31.0.0",
"@monaco-editor/react": "^4.6.0", "@monaco-editor/react": "^4.6.0",
"@radix-ui/react-aspect-ratio": "^1.1.1",
"@radix-ui/react-avatar": "^1.1.1", "@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-collapsible": "^1.1.1", "@radix-ui/react-collapsible": "^1.1.1",
"@radix-ui/react-hover-card": "^1.1.1", "@radix-ui/react-hover-card": "^1.1.1",
@ -92,7 +93,7 @@
"@types/react-dom": "^18", "@types/react-dom": "^18",
"@types/react-twemoji": "^0.4.3", "@types/react-twemoji": "^0.4.3",
"@unocss/eslint-config": "^0.61.5", "@unocss/eslint-config": "^0.61.5",
"@unocss/preset-uno": "^0.61.5", "@unocss/preset-uno": "^0.65.1",
"@unocss/transformer-compile-class": "^0.61.5", "@unocss/transformer-compile-class": "^0.61.5",
"@vercel/analytics": "^1.3.1", "@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12", "@vercel/speed-insights": "^1.0.12",

@ -32,27 +32,17 @@ import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next"; import { SpeedInsights } from "@vercel/speed-insights/next";
import { GeistSans } from "geist/font/sans"; import { GeistSans } from "geist/font/sans";
import "../globals.css"; import "../globals.css";
import ClientFadeIn from "@/components/ClientFadeIn";
import { CommandBarer } from "@/components/CommandBar"; import { CommandBarer } from "@/components/CommandBar";
import { BrandingGenericIcon } from "@/components/Icon";
import TextFromPathname from "@/components/TextFromPathname";
import { ThemeProvider } from "@/components/ThemeProvider"; import { ThemeProvider } from "@/components/ThemeProvider";
import { ClerkThemeProvider } from "@/components/clerk/ClerkThemeProvider"; import { ClerkThemeProvider } from "@/components/clerk/ClerkThemeProvider";
import TopBar from "@/components/clerk/Topbar";
import NewDomainDialog from "@/components/misc/NewDomainDialog"; import NewDomainDialog from "@/components/misc/NewDomainDialog";
import ThemedToaster from "@/components/misc/ThemedToaster"; import ThemedToaster from "@/components/misc/ThemedToaster";
import UnofficalDialog from "@/components/misc/UnofficalDialog"; import UnofficalDialog from "@/components/misc/UnofficalDialog";
import {
Breadcrumb,
BreadcrumbList,
BreadcrumbPage,
} from "@/components/ui/breadcrumb";
import { TooltipProvider } from "@/components/ui/tooltip"; import { TooltipProvider } from "@/components/ui/tooltip";
import { banner } from "@/config/banner";
import NextTopLoader from "@/lib/top-loader";
import type { Metadata, Viewport } from "next"; import type { Metadata, Viewport } from "next";
import { Inter as interFont } from "next/font/google"; import { Inter as interFont } from "next/font/google";
import Link from "next/link"; import LayoutPart from "@/components/feat/LayoutPart";
import AllBanners from "@/components/feat/AllBanners";
export const extraMetadata = { export const extraMetadata = {
twitter: { twitter: {
@ -86,35 +76,8 @@ export default async function RootLayout({
<ClerkThemeProvider className={GeistSans.className}> <ClerkThemeProvider className={GeistSans.className}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem> <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<TooltipProvider> <TooltipProvider>
{banner.isBanner && ( <AllBanners />
<div className="bg-orange-600 z-10 w-screen h-8 border-b fixed text-black flex items-center text-center font-medium pl-2"> <LayoutPart>{children}</LayoutPart>
{banner.bannerText}
</div>
)}
<div
className={
"w-screen h-[3rem] border-b fixed backdrop-blur flex z-10 " +
(banner.isBanner == true ? "mt-8" : "")
}
>
<div className="items-center me-auto mt-2 pl-7 max-sm:mt-3">
<Breadcrumb>
<BreadcrumbList>
<Link href="/">
<BreadcrumbPage className="max-sm:hidden">
<BrandingGenericIcon className="max-w-[32px] max-h-[32px] " />
</BreadcrumbPage>
</Link>
<TextFromPathname />
</BreadcrumbList>
</Breadcrumb>
</div>
<TopBar inter={inter.className} />
</div>
<div className={banner.isBanner ? "pt-8" : undefined}>
<NextTopLoader />
<ClientFadeIn>{children}</ClientFadeIn>
</div>{" "}
<ThemedToaster /> <ThemedToaster />
<CommandBarer /> <CommandBarer />
<SpeedInsights /> <SpeedInsights />

@ -34,7 +34,6 @@ import ColorProvider from "@/components/ColorProvider";
import ServerView from "@/components/ServerView"; import ServerView from "@/components/ServerView";
import StickyTopbar from "@/components/misc/StickyTopbar"; import StickyTopbar from "@/components/misc/StickyTopbar";
import TabServer from "@/components/misc/TabServer"; import TabServer from "@/components/misc/TabServer";
import { Separator } from "@/components/ui/separator";
import type { Metadata, ResolvingMetadata } from "next"; import type { Metadata, ResolvingMetadata } from "next";
type Props = { type Props = {
@ -129,17 +128,17 @@ export async function generateMetadata(
export default function ServerPage({ params }: { params: { server: string } }) { export default function ServerPage({ params }: { params: { server: string } }) {
return ( return (
<main> <main style={{ "color-scheme": "dark" } as React.CSSProperties}>
<ColorProvider server={params.server}> <ColorProvider server={params.server}>
<div className={"pt-16 xl:px-[100px]"}> <div className={"pt-[300px] xl:px-[100px]"}>
<Banner server={params.server} /> <Banner server={params.server} />
<div className="pt-8 z-10 relative">
<ServerView server={params.server} />
</div>
<StickyTopbar scrollElevation={100} className="pt-4"> <StickyTopbar scrollElevation={100} className="pt-4">
<TabServer server={params.server} tabDef="general" /> <TabServer server={params.server} tabDef="general" />
</StickyTopbar> </StickyTopbar>
<div className="pt-8">
<ServerView server={params.server} />
</div>
<Separator />
<br /> <br />
<AfterServerView server={params.server} /> <AfterServerView server={params.server} />
</div> </div>

@ -35,6 +35,7 @@ import ServerView from "@/components/ServerView";
import TabServer from "@/components/misc/TabServer"; import TabServer from "@/components/misc/TabServer";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import type { Metadata, ResolvingMetadata } from "next"; import type { Metadata, ResolvingMetadata } from "next";
import StickyTopbar from "@/components/misc/StickyTopbar";
type Props = { type Props = {
params: { server: string }; params: { server: string };
@ -96,20 +97,23 @@ export async function generateMetadata(
export default function ServerPage({ params }: { params: { server: string } }) { export default function ServerPage({ params }: { params: { server: string } }) {
return ( return (
<main> <main style={{ "color-scheme": "dark" } as React.CSSProperties}>
<ColorProvider server={params.server}> <ColorProvider server={params.server}>
<div className={"pt-16 xl:px-[100px]"}> <div className={"pt-[300px] xl:px-[100px]"}>
<Banner server={params.server} /> <Banner server={params.server} />
<TabServer server={params.server} tabDef="statistics" /> <div className="pt-8 z-10 relative">
<div className="pt-8">
<ServerView server={params.server} /> <ServerView server={params.server} />
</div>
<StickyTopbar scrollElevation={100} className="pt-4">
<TabServer server={params.server} tabDef="statistics" />
</StickyTopbar>
<Separator /> <Separator />
<br /> <br />
<div className="p-4 gap-4"> <div className="p-4 gap-4">
<NewChart server={params.server} /> <NewChart server={params.server} />
</div> </div>
</div> </div>
</div>
</ColorProvider> </ColorProvider>
</main> </main>
); );

@ -117,7 +117,7 @@ export default function AfterServerView({ server }: { server: string }) {
<QRCodeGenerator server={server} /> <QRCodeGenerator server={server} />
</DrawerContent> </DrawerContent>
</Drawer> </Drawer>
<FadeIn> <FadeIn className="relative z-10">
<div className="grid sm:grid-cols-6 h-full pl-4 pr-4 "> <div className="grid sm:grid-cols-6 h-full pl-4 pr-4 ">
<div className="ml-5 mb-2 flex items-center sm:hidden overflow-auto w-[calc(100vw-5rem)]"> <div className="ml-5 mb-2 flex items-center sm:hidden overflow-auto w-[calc(100vw-5rem)]">
{(description != "" || discord != "") && ( {(description != "" || discord != "") && (

@ -31,10 +31,12 @@
"use client"; "use client";
import { getCustomization } from "@/lib/api"; import { getCustomization } from "@/lib/api";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import useTotalBannerSize from "@/lib/hooks/use-total-banner-size";
export default function Banner({ server }: { server: string }) { export default function Banner({ server }: { server: string }) {
const [bannerURL, setBannerURL] = useState(""); const [bannerURL, setBannerURL] = useState("");
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const { bannerSize } = useTotalBannerSize();
useEffect(() => { useEffect(() => {
getCustomization(server).then((c) => { getCustomization(server).then((c) => {
@ -64,8 +66,16 @@ export default function Banner({ server }: { server: string }) {
? bannerURL ? bannerURL
: "wsrv.nl/?url=" + encodeURIComponent(bannerURL) + "?n=-1" : "wsrv.nl/?url=" + encodeURIComponent(bannerURL) + "?n=-1"
} }
className="rounded align-middle block ml-auto mr-auto w-[50%] max-h-[150px]" className="rounded align-middle block ml-auto mr-auto absolute left-0 z-0 w-full object-fill"
alt="User-provided banner for this server." alt="User-provided banner for this server."
style={
{
"-webkit-mask-image":
"linear-gradient(to top, transparent, black)",
maskImage: "linear-gradient(to top, transparent, black)",
top: `${bannerSize * 32 + 36}px`,
} as React.CSSProperties
}
/> />
)} )}
<br /> <br />

@ -30,7 +30,6 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import Banner from "./Banner";
import ServerCustomize from "./ServerCustomize"; import ServerCustomize from "./ServerCustomize";
import TabServer from "./misc/TabServer"; import TabServer from "./misc/TabServer";
@ -42,7 +41,6 @@ export default function CustomizeRoot({
const [color, setColor] = useState(""); const [color, setColor] = useState("");
return ( return (
<div className={"pt-16 xl:px-[100px] theme-" + color}> <div className={"pt-16 xl:px-[100px] theme-" + color}>
<Banner server={params.server} />
<TabServer server={params.server} tabDef="customize" /> <TabServer server={params.server} tabDef="customize" />
<br /> <br />
<div className="pl-[40px] pr-[40px]"> <div className="pl-[40px] pr-[40px]">

@ -33,6 +33,7 @@
import * as React from "react"; import * as React from "react";
import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes"; import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes";
import { type ThemeProviderProps } from "next-themes"; import { type ThemeProviderProps } from "next-themes";
import { usePathname } from "next/navigation";
declare global { declare global {
interface Document { interface Document {
@ -48,6 +49,7 @@ declare global {
export function ThemeProvider({ children, ...props }: ThemeProviderProps) { export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
const [mounted, setMounted] = React.useState(false); const [mounted, setMounted] = React.useState(false);
const pathname = usePathname();
React.useEffect(() => { React.useEffect(() => {
setMounted(true); setMounted(true);
@ -55,7 +57,14 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
if (!mounted) return null; if (!mounted) return null;
return <NextThemesProvider {...props}>{children}</NextThemesProvider>; return (
<NextThemesProvider
forcedTheme={pathname?.startsWith("/server") ? "dark" : undefined}
{...props}
>
{children}
</NextThemesProvider>
);
} }
interface UseThemeTransitionResult { interface UseThemeTransitionResult {

@ -39,9 +39,11 @@ import {
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { useThemeTransition } from "./ThemeProvider"; import { useThemeTransition } from "./ThemeProvider";
import { usePathname } from "next/navigation";
export function ModeToggle() { export function ModeToggle() {
const { changeTheme } = useThemeTransition(); const { changeTheme } = useThemeTransition();
const pathname = usePathname();
return ( return (
<DropdownMenu> <DropdownMenu>
@ -53,13 +55,28 @@ export function ModeToggle() {
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => changeTheme("light")}> {pathname?.startsWith("/server") && (
<div className="text-sm p-4">
For compatibility reasons, <br /> server pages are forced to dark
mode
</div>
)}
<DropdownMenuItem
onClick={() => changeTheme("light")}
disabled={pathname?.startsWith("/server")}
>
Light Light
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("dark")}> <DropdownMenuItem
onClick={() => changeTheme("dark")}
disabled={pathname?.startsWith("/server")}
>
Dark Dark
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => changeTheme("system")}> <DropdownMenuItem
onClick={() => changeTheme("system")}
disabled={pathname?.startsWith("/server")}
>
System System
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>

@ -0,0 +1,73 @@
/*
* 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) 2024 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.
*/
"use client";
import React, { useEffect, useState } from "react";
import { Gradient } from "stripe-gradient";
export default function GradientBanner({
children,
}: {
children?: React.ReactNode;
}) {
const [gradientId, setGradientId] = useState("gradient-banner");
useEffect(() => {
setGradientId("gradient-banner");
const gradient = new Gradient();
gradient.initGradient("#" + gradientId);
}, [gradientId]);
return (
<div className="fixed top-0 left-0 backdrop-blur">
<canvas
id={gradientId}
data-js-darken-top
className="w-screen blur-sm h-[4rem] border-b z-1"
style={
{
"--gradient-color-1": "#6ec3f4",
"--gradient-color-2": "#3a3aff",
"--gradient-color-3": "#ff61ab",
"--gradient-color-4": "#E63946",
webKitMaskImage: "linear-gradient(to top, transparent, black)",
maskImage: "linear-gradient(to top, transparent, black)",
} as React.CSSProperties
}
height="64"
width={window.screen.width}
/>{" "}
<div className="fixed top-0 left-0 z-2 p-2 text-left text-black dark:text-white">
{children}
</div>
</div>
);
}

@ -1,7 +1,7 @@
/* /*
* MHSF, Minehut Server List * MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement * All external content is rather licensed under the ECA Agreement
* located here: https://list.mlnehut.com/docs/legal/external-content-agreement * located here: https://mhsf.app/docs/legal/external-content-agreement
* *
* All code under MHSF is licensed under the MIT License * All code under MHSF is licensed under the MIT License
* by open source contributors * by open source contributors
@ -28,26 +28,16 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
import { Button } from "@/components/ui/button"; "use client";
import Link from "next/link";
/** used when there is a outage */ import { useBanners } from "@/lib/hooks/use-banners";
export const banner = {
isBanner: export default function AllBanners() {
process.env.NEXT_PUBLIC_VERCEL_ENV !== "production" const { banners } = useBanners();
? true
: /** Set this to true when outage --->*/ false, return (
bannerText: <div className="fixed grid grid-cols-1 z-10">
process.env.NEXT_PUBLIC_VERCEL_ENV !== "production" ? ( {banners.map((banner) => banner.bannerContent)}
<> </div>
Your not in production!{" "} );
<Link href="https://list.mlnehut.com"> }
<Button variant="link" className="dark:text-black">
Go to production
</Button>
</Link>
</>
) : (
<>{/** Set this to an explanation! */}</>
),
};

@ -0,0 +1,51 @@
/*
* 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) 2024 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.
*/
"use client";
import useTotalBannerSize from "@/lib/hooks/use-total-banner-size";
export default function BannerContainer({
children,
className,
style,
}: {
children: React.ReactNode;
className?: string;
style: (size: number) => React.CSSProperties;
}) {
const { bannerSize } = useTotalBannerSize();
return (
<div className={className} style={style(bannerSize)}>
{children}
</div>
);
}

@ -0,0 +1,55 @@
"use client";
import ClientFadeIn from "@/components/ClientFadeIn";
import { BrandingGenericIcon } from "@/components/Icon";
import TextFromPathname from "@/components/TextFromPathname";
import TopBar from "@/components/clerk/Topbar";
import {
Breadcrumb,
BreadcrumbList,
BreadcrumbPage,
} from "@/components/ui/breadcrumb";
import NextTopLoader from "@/lib/top-loader";
import Link from "next/link";
import BannerContainer from "@/components/feat/BannerContainer";
import { Inter } from "next/font/google";
const inter = Inter({ variable: "--font-inter", subsets: ["latin"] });
export default function LayoutPart({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<BannerContainer
className={"w-screen h-[3rem] border-b fixed backdrop-blur flex z-10"}
style={(size: number) => ({
marginTop: `${2 * size}rem`,
})}
>
<div className="items-center me-auto mt-2 pl-7 max-sm:mt-3">
<Breadcrumb>
<BreadcrumbList>
<Link href="/">
<BreadcrumbPage className="max-sm:hidden">
<BrandingGenericIcon className="max-w-[32px] max-h-[32px] " />
</BreadcrumbPage>
</Link>
<TextFromPathname />
</BreadcrumbList>
</Breadcrumb>
</div>
<TopBar inter={inter.className} />
</BannerContainer>
<BannerContainer
style={(size: number) => ({
paddingTop: `${2 * size}rem`,
})}
>
<NextTopLoader />
<ClientFadeIn>{children}</ClientFadeIn>
</BannerContainer>
</>
);
}

@ -0,0 +1,50 @@
/*
* 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) 2024 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.
*/
export default function MainBanner({
className,
size = 1,
children,
}: {
className?: string;
size?: number;
children?: React.ReactNode;
}) {
return (
<div
className={`w-screen border-b text-black flex items-center text-center font-medium pl-2 ${className}`}
style={{
height: `${size * 2}rem`,
}}
>
{children}
</div>
);
}

@ -0,0 +1,29 @@
/*
* 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) 2024 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.
*/

@ -29,8 +29,7 @@
*/ */
"use client"; "use client";
import useTotalBannerSize from "@/lib/hooks/use-total-banner-size";
import { banner } from "@/config/banner";
import { useEffect, useState, ReactNode } from "react"; import { useEffect, useState, ReactNode } from "react";
export default function StickyTopbar({ export default function StickyTopbar({
@ -43,6 +42,7 @@ export default function StickyTopbar({
className?: string; className?: string;
}) { }) {
const [isSticky, setIsSticky] = useState(false); const [isSticky, setIsSticky] = useState(false);
const { bannerSize } = useTotalBannerSize();
const handleScroll = () => { const handleScroll = () => {
if (window.scrollY > scrollElevation) { if (window.scrollY > scrollElevation) {
@ -61,7 +61,10 @@ export default function StickyTopbar({
return ( return (
<div <div
className={`transition-all duration-300 ${isSticky ? "fixed left-0 w-full backdrop-blur shadow-lg " + (banner.isBanner == true ? "top-[70px] " : "top-[38px] ") + className : "block w-full bg-transparent"}`} className={`transition-all duration-300 ${isSticky ? "fixed left-0 w-full backdrop-blur shadow-lg " + className : "block w-full bg-transparent"}`}
style={{
top: isSticky ? `${bannerSize * 32 + 38}px` : undefined,
}}
> >
{children} {children}
</div> </div>

@ -0,0 +1,7 @@
"use client"
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
const AspectRatio = AspectRatioPrimitive.Root
export { AspectRatio }

@ -0,0 +1,17 @@
import type { SVGProps } from "react";
const Discord = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 256 199"
width="1em"
height="1em"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid"
{...props}
>
<path
d="M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046-19.692-2.961-39.203-2.961-58.533 0-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632 108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237 136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848 21.142-6.58 42.646-16.637 64.815-33.213 5.316-56.288-9.08-105.09-38.056-148.36ZM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2.02 14.375-10.148 26.18-23.015 26.18Zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2 0 14.375-10.148 26.18-23.015 26.18Z"
fill="#5865F2"
/>
</svg>
);
export default Discord;

@ -0,0 +1,15 @@
import type { SVGProps } from "react";
const Github = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 256 250"
width="1em"
height="1em"
fill="#fff"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid"
{...props}
>
<path d="M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z" />
</svg>
);
export default Github;

41
src/config/banners.tsx Normal file

@ -0,0 +1,41 @@
export const defaultBanners: {
bannerSpace: number;
bannerContent: React.ReactNode;
}[] = [
// The sponsor banner ALWAYS has to be first.
// {
// bannerSpace: 2,
// bannerContent: (
// <MainBanner size={2} className="max-h-[4rem] border-0">
// {" "}
// <GradientBanner>
// <strong>???</strong> — <i>an official affiliate of MHSF</i>{" "}
// <br />
// Lorem ipsum odor amet, consectetuer adipiscing elit. — check it out
// </GradientBanner>
// </MainBanner>
// ),
// },
];
export const bannerHooks: (() =>
| { bannerSpace: number; bannerContent: React.ReactNode }
| undefined)[] = [
() => {
// if (process.env.NEXT_PUBLIC_VERCEL_ENV !== "production")
// return {
// bannerSpace: 1,
// bannerContent: (
// <MainBanner className="bg-orange-600">
// Your not in production!{" "}
// <Link href="https://mhsf.app">
// <Button variant="link" className="dark:text-black">
// Go to production
// </Button>
// </Link>
// </MainBanner>
// ),
// };
return undefined;
},
];

@ -73,7 +73,6 @@ export const allFolders: DocsFolder[] = [
name: "Legal", name: "Legal",
docs: [ docs: [
{ title: "ECA Agreement", url: "/docs/legal/external-content-agreement" }, { title: "ECA Agreement", url: "/docs/legal/external-content-agreement" },
{ title: "Email List", url: "/docs/legal/email-list" },
], ],
}, },
]; ];

@ -65,7 +65,7 @@ export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
features={[ features={[
"New MOTD engine that is over 3,000% faster, runs client-side, and doesn't need any requests to run.", "New MOTD engine that is over 3,000% faster, runs client-side, and doesn't need any requests to run.",
"Fixed issue where GitHub link was broken if you were signed-out", "Fixed issue where GitHub link was broken if you were signed-out",
"", "Adding snowfall finally (better late then ever)",
]} ]}
title={ title={
<strong className="flex items-center"> <strong className="flex items-center">

@ -62,13 +62,17 @@ async function apiConstructor<K>(
export async function getMOTDFromServer( export async function getMOTDFromServer(
list: Array<{ server: string; motd: string }>, list: Array<{ server: string; motd: string }>,
): Promise<Array<{ server: string; motd: string }>> { ): Promise<Array<{ server: string; motd: string }>> {
const result = await fetch(connector("/motd", { version: 1 }), { const result = await fetch(
process.env.NEXT_PUBLIC_ALTERNATE_MOTD_ENDPOINT ??
connector("/motd", { version: 1 }),
{
body: JSON.stringify({ motd: list }), body: JSON.stringify({ motd: list }),
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}); },
);
let json = await result.json(); let json = await result.json();
return json.result; return json.result;

@ -0,0 +1,57 @@
/*
* 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) 2024 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 { bannerHooks, defaultBanners } from "@/config/banners";
import { useEffect, useState } from "react";
import { useIsMobile } from "./use-mobile";
export function useBanners() {
const [banners, setBanners] = useState<
{
bannerSpace: number;
bannerContent: React.ReactNode;
}[]
>(defaultBanners);
const isOnMobile = useIsMobile();
useEffect(() => {
if (isOnMobile) {
setBanners([]);
return;
}
setBanners(defaultBanners);
bannerHooks.forEach((hook) => {
const run = hook();
if (run !== undefined) setBanners((oldBanners) => [...oldBanners, run]);
});
}, [isOnMobile]);
return { banners };
}

@ -0,0 +1,61 @@
/*
* 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) 2024 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 { bannerHooks, defaultBanners } from "@/config/banners";
import { useEffect, useState } from "react";
import { useIsMobile } from "./use-mobile";
export default function useTotalBannerSize() {
const [bannerSize, setBannerSize] = useState(0);
const isOnMobile = useIsMobile();
useEffect(() => {
setBannerSize(0);
if (isOnMobile) return;
const allBanners = [];
// First push the default banners
allBanners.push(...defaultBanners);
// Then push the banner hooks
bannerHooks.forEach((hook) => {
allBanners.push(hook());
});
setBannerSize(
allBanners.reduce(
(acc, banner) => acc + (banner ?? { bannerSpace: 0 }).bannerSpace,
0
) ?? 0
);
}, [isOnMobile]);
return { bannerSize };
}

5
src/lib/types/stripe-gradient.d.ts vendored Normal file

@ -0,0 +1,5 @@
declare module "stripe-gradient" {
declare class Gradient {
initGradient(id: string): void;
};
}

@ -748,7 +748,7 @@
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@jridgewell/sourcemap-codec@^1.4.15": "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
@ -1178,6 +1178,13 @@
dependencies: dependencies:
"@radix-ui/react-primitive" "2.0.0" "@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-aspect-ratio@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.1.tgz#95d7692e61bab5eb7fec91f241ea993899593313"
integrity sha512-kNU4FIpcFMBLkOUcgeIteH06/8JLBcYY6Le1iKenDGCYNYFX3TQqCZjzkOsz37h7r94/99GTb7YhEr98ZBJibw==
dependencies:
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-avatar@^1.1.1": "@radix-ui/react-avatar@^1.1.1":
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.1.1.tgz#5848d2ed5f34d18b36fc7e2d227c41fca8600ea1" resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.1.1.tgz#5848d2ed5f34d18b36fc7e2d227c41fca8600ea1"
@ -2487,6 +2494,11 @@
resolved "https://registry.yarnpkg.com/@unocss/core/-/core-0.61.5.tgz#09f4da600f6f50dbb68a173f23566e9171d5cd3d" resolved "https://registry.yarnpkg.com/@unocss/core/-/core-0.61.5.tgz#09f4da600f6f50dbb68a173f23566e9171d5cd3d"
integrity sha512-hB8zr2rnrCzz9x8ho2SAXQiYTEjwAPMiBzpaEe2C0+CFWeL1179h9508YVyZHHAzMyZILIG9YrVAWrrMdt2/Xg== integrity sha512-hB8zr2rnrCzz9x8ho2SAXQiYTEjwAPMiBzpaEe2C0+CFWeL1179h9508YVyZHHAzMyZILIG9YrVAWrrMdt2/Xg==
"@unocss/core@0.65.1", "@unocss/core@^0.65.1":
version "0.65.1"
resolved "https://registry.yarnpkg.com/@unocss/core/-/core-0.65.1.tgz#3fcab446794e895abadb33ed517e9ac472d8acb1"
integrity sha512-Ke0WNZjfSCE6pniJb8PjiwhO6/McxVb1EQYrkkz8aJuR83xu+AEcTog9D4N9EUkRfHS5tZYXQtTj4Uh90T6CEg==
"@unocss/eslint-config@^0.61.5": "@unocss/eslint-config@^0.61.5":
version "0.61.5" version "0.61.5"
resolved "https://registry.yarnpkg.com/@unocss/eslint-config/-/eslint-config-0.61.5.tgz#01a8ebb4a626d22d6e29d9800c31d2f87bed2b6b" resolved "https://registry.yarnpkg.com/@unocss/eslint-config/-/eslint-config-0.61.5.tgz#01a8ebb4a626d22d6e29d9800c31d2f87bed2b6b"
@ -2505,12 +2517,12 @@
magic-string "^0.30.10" magic-string "^0.30.10"
synckit "^0.9.1" synckit "^0.9.1"
"@unocss/extractor-arbitrary-variants@0.61.5": "@unocss/extractor-arbitrary-variants@0.65.1":
version "0.61.5" version "0.65.1"
resolved "https://registry.yarnpkg.com/@unocss/extractor-arbitrary-variants/-/extractor-arbitrary-variants-0.61.5.tgz#478b15f0ae298b0f05d9978ef528b08723c22cb5" resolved "https://registry.yarnpkg.com/@unocss/extractor-arbitrary-variants/-/extractor-arbitrary-variants-0.65.1.tgz#2104da17d8463d41393934af05408bd5d711dcde"
integrity sha512-UB1EweAaJrUxv+h3n5FqoizKHrnUgUzkdmOdJTfV6xvow90ITqbUoza+L6iVMNfcrcXTx8QpDnWh6rhLRyKY+g== integrity sha512-VpF7j29TlmVjNolkIjhQ/cwYkuPUoXLv+ko62YRMibE5632QepbNob69pNYGOZustrZt3LvgHD/GcriKwJO4BA==
dependencies: dependencies:
"@unocss/core" "0.61.5" "@unocss/core" "0.65.1"
"@unocss/postcss@^0.61.5": "@unocss/postcss@^0.61.5":
version "0.61.5" version "0.61.5"
@ -2525,33 +2537,33 @@
magic-string "^0.30.10" magic-string "^0.30.10"
postcss "^8.4.39" postcss "^8.4.39"
"@unocss/preset-mini@0.61.5": "@unocss/preset-mini@0.65.1":
version "0.61.5" version "0.65.1"
resolved "https://registry.yarnpkg.com/@unocss/preset-mini/-/preset-mini-0.61.5.tgz#60dc1aa2c05e415b6e9860493fb92a20acce62da" resolved "https://registry.yarnpkg.com/@unocss/preset-mini/-/preset-mini-0.65.1.tgz#4009cf5f0d4538cc9e1fcfba03176d00c5f59b9d"
integrity sha512-gVm7Z9X0krx8CK/+pKAqcVmpqzRk1+SH7bfgRxKtKhyFSxJlwpjNp1rKm3gCT0F1Tlp3d8aufYRksaXGZhs8Ow== integrity sha512-dKIxi+ChWSZvXG8I7yVBjw4FLHdAvKrrCN9bjKpR4/4epKD6jRtEcR6S1wL6XSBWabh7V7D/VbVk+XZ6WsGuXA==
dependencies: dependencies:
"@unocss/core" "0.61.5" "@unocss/core" "0.65.1"
"@unocss/extractor-arbitrary-variants" "0.61.5" "@unocss/extractor-arbitrary-variants" "0.65.1"
"@unocss/rule-utils" "0.61.5" "@unocss/rule-utils" "0.65.1"
"@unocss/preset-uno@^0.61.5": "@unocss/preset-uno@^0.65.1":
version "0.61.5" version "0.65.1"
resolved "https://registry.yarnpkg.com/@unocss/preset-uno/-/preset-uno-0.61.5.tgz#80c85edaf4ed364c91df3400dae5abfe3976f21e" resolved "https://registry.yarnpkg.com/@unocss/preset-uno/-/preset-uno-0.65.1.tgz#6a7d862d2e047950953baf8c2d780efb46835f2f"
integrity sha512-CflB0l9CeZx+b/Q8mA4Ow4d63Caf+vFJ+1EGA06jG9qYjPLy76Rkci//0m9cEtO+vPnYtgLc7HZAZv0X6wh4Tg== integrity sha512-OSEkphrlR9/RM5un9t9AqVQXOGBLJgjcEweZSm2ng9AK7BsxBXuVP1FelmRqeXVYT5uFtBoD4dfgCgBjGFIW9Q==
dependencies: dependencies:
"@unocss/core" "0.61.5" "@unocss/core" "0.65.1"
"@unocss/preset-mini" "0.61.5" "@unocss/preset-mini" "0.65.1"
"@unocss/preset-wind" "0.61.5" "@unocss/preset-wind" "0.65.1"
"@unocss/rule-utils" "0.61.5" "@unocss/rule-utils" "0.65.1"
"@unocss/preset-wind@0.61.5": "@unocss/preset-wind@0.65.1":
version "0.61.5" version "0.65.1"
resolved "https://registry.yarnpkg.com/@unocss/preset-wind/-/preset-wind-0.61.5.tgz#049f4cf3d15be5d5bf1bb3c2108cff22a69d0884" resolved "https://registry.yarnpkg.com/@unocss/preset-wind/-/preset-wind-0.65.1.tgz#d64b92a52247d9a8f5251ee999e3e5a9273f1bdc"
integrity sha512-n4uepxv3gVoVQb0tv7iV8M4W0CgwLw0QaMX+3ECYzFLMynjCkZmFDtdQAX720yTvLZxwCxEZfQCgydOSt0qjZA== integrity sha512-7rw3hAWOkWMSjoprWKcQidqJRFQm8qM0IdLjFLQa2ROSzPSnIlNisXGEwAphf4/VYdP7+URUnu5eySQsIRWRzg==
dependencies: dependencies:
"@unocss/core" "0.61.5" "@unocss/core" "0.65.1"
"@unocss/preset-mini" "0.61.5" "@unocss/preset-mini" "0.65.1"
"@unocss/rule-utils" "0.61.5" "@unocss/rule-utils" "0.65.1"
"@unocss/rule-utils@0.61.5": "@unocss/rule-utils@0.61.5":
version "0.61.5" version "0.61.5"
@ -2561,6 +2573,14 @@
"@unocss/core" "^0.61.5" "@unocss/core" "^0.61.5"
magic-string "^0.30.10" magic-string "^0.30.10"
"@unocss/rule-utils@0.65.1":
version "0.65.1"
resolved "https://registry.yarnpkg.com/@unocss/rule-utils/-/rule-utils-0.65.1.tgz#56abda142b506004670bc867cebcf2a35ee80914"
integrity sha512-XGXdXsRmIuMDQk/3Fd3g5JMhsyDGWsTfs6aN4vFQ1rfdSgY4UwbslqUNbIH9xxoTfmzUOJ2lhNrFw78RygCNSA==
dependencies:
"@unocss/core" "^0.65.1"
magic-string "^0.30.14"
"@unocss/transformer-compile-class@^0.61.5": "@unocss/transformer-compile-class@^0.61.5":
version "0.61.5" version "0.61.5"
resolved "https://registry.yarnpkg.com/@unocss/transformer-compile-class/-/transformer-compile-class-0.61.5.tgz#be992b1a9e2300314618b1866854f1f6ea95419c" resolved "https://registry.yarnpkg.com/@unocss/transformer-compile-class/-/transformer-compile-class-0.61.5.tgz#be992b1a9e2300314618b1866854f1f6ea95419c"
@ -5305,6 +5325,13 @@ magic-string@^0.30.10:
dependencies: dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15" "@jridgewell/sourcemap-codec" "^1.4.15"
magic-string@^0.30.14:
version "0.30.14"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.14.tgz#e9bb29870b81cfc1ec3cc656552f5a7fcbf19077"
integrity sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
mangle-css-class-webpack-plugin@^5.1.0: mangle-css-class-webpack-plugin@^5.1.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/mangle-css-class-webpack-plugin/-/mangle-css-class-webpack-plugin-5.1.0.tgz#42008a8fbe0257f491968796320eb94b17a36321" resolved "https://registry.yarnpkg.com/mangle-css-class-webpack-plugin/-/mangle-css-class-webpack-plugin-5.1.0.tgz#42008a8fbe0257f491968796320eb94b17a36321"