mirror of
https://github.com/DeveloLongScript/MHSF.git
synced 2026-05-09 05:34:59 -05:00
feat: revamped documentation
This commit is contained in:
parent
dd9104f2f3
commit
3c1fd6cfc4
@ -11,12 +11,12 @@ The command-bar has many mods and is a great tool for power-users to use as its
|
|||||||
|
|
||||||
## Triggering the command-bar
|
## Triggering the command-bar
|
||||||
|
|
||||||
There are two ways to trigger the command bar, using `Ctrl+K` and `Ctrl+Shift+K`. Both put you in a command-bar, however when using `Ctrl+K`, you go into a general page with other settings.
|
There are two ways to trigger the command bar, using `Ctrl+K` and <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd>. Both put you in a command-bar, however when using `Ctrl+K`, you go into a general page with other settings.
|
||||||
Using `Ctrl+Shift+K` opens a server viewer, and this may be faster then going through the general page.
|
Using <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd> opens a server viewer, and this may be faster then going through the general page.
|
||||||
|
|
||||||
## Functions using `Ctrl+K`
|
## Functions using Ctrl+K
|
||||||
|
|
||||||
- **Servers** opens a server list, same as `Ctrl+Shift+K`
|
- **Servers** opens a server list, same as <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd>
|
||||||
- **Sort Servers** allows you to go into a sorted server list quickly
|
- **Sort Servers** allows you to go into a sorted server list quickly
|
||||||
- **Links** shows links useful for MHSF
|
- **Links** shows links useful for MHSF
|
||||||
- **Pick Random Server** picks a random server and shows the user what that server is, is similar to the one on [the server list](/)
|
- **Pick Random Server** picks a random server and shows the user what that server is, is similar to the one on [the server list](/)
|
||||||
|
|||||||
@ -5,11 +5,11 @@ folder: "Guides"
|
|||||||
|
|
||||||
# Owning a server
|
# Owning a server
|
||||||
|
|
||||||
Owning a server is quite simple and allows you to [customize your server](/docs/guides/customization) your server and make it stand out from other servers. Before owning your server, make sure you agree to the [ECA](Docs:legal/external-content-agreement).
|
Owning a server is quite simple and allows you to [customize your server](/docs/guides/customization) and make it stand out from other servers. Before owning your server, make sure you agree to the [ECA](Docs:legal/external-content-agreement).
|
||||||
|
|
||||||
## Linking
|
## Linking
|
||||||
|
|
||||||
Find the server you would like to own (either by looking for it, or using the keyboard shortcut `Ctrl`+`Shift`+`K` and searching for it), and make sure your account has [already been linked with your Minecraft account](Docs:guides/linking). Go to the server, and hit the Customization tab. If the owner of the server, and the user your linked to match, you will gain access to the server.
|
Find the server you would like to own (either by looking for it, or using the keyboard shortcut <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>K</kbd> and searching for it), and make sure your account has [already been linked with your Minecraft account](Docs:guides/linking). Go to the server, and hit the Customization tab. If the owner of the server, and the user your linked to match, you will gain access to the server.
|
||||||
If they match, you should see a button named Click to own. Press that button, and you should automagically own the server. Congratulations!
|
If they match, you should see a button named Click to own. Press that button, and you should automagically own the server. Congratulations!
|
||||||
|
|
||||||
## I can't link my server, because my server doesn't have a author
|
## I can't link my server, because my server doesn't have a author
|
||||||
|
|||||||
12
package.json
12
package.json
@ -19,6 +19,8 @@
|
|||||||
"@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-avatar": "^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",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-menubar": "^1.1.1",
|
"@radix-ui/react-menubar": "^1.1.1",
|
||||||
@ -35,7 +37,7 @@
|
|||||||
"inngest": "^3.21.2",
|
"inngest": "^3.21.2",
|
||||||
"input-otp": "^1.2.4",
|
"input-otp": "^1.2.4",
|
||||||
"json-beautify": "^1.1.1",
|
"json-beautify": "^1.1.1",
|
||||||
"lucide-react": "^0.416.0",
|
"lucide-react": "^0.454.0",
|
||||||
"minimessage-2-html": "1.6.0",
|
"minimessage-2-html": "1.6.0",
|
||||||
"mongodb": "^6.8.0",
|
"mongodb": "^6.8.0",
|
||||||
"next": "14.2.10",
|
"next": "14.2.10",
|
||||||
@ -63,17 +65,17 @@
|
|||||||
"@hookform/resolvers": "^3.9.0",
|
"@hookform/resolvers": "^3.9.0",
|
||||||
"@radix-ui/react-checkbox": "^1.1.1",
|
"@radix-ui/react-checkbox": "^1.1.1",
|
||||||
"@radix-ui/react-context-menu": "^2.1.5",
|
"@radix-ui/react-context-menu": "^2.1.5",
|
||||||
"@radix-ui/react-dialog": "^1.1.1",
|
"@radix-ui/react-dialog": "^1.1.2",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||||
"@radix-ui/react-popover": "^1.0.7",
|
"@radix-ui/react-popover": "^1.0.7",
|
||||||
"@radix-ui/react-radio-group": "^1.2.0",
|
"@radix-ui/react-radio-group": "^1.2.0",
|
||||||
"@radix-ui/react-scroll-area": "^1.1.0",
|
"@radix-ui/react-scroll-area": "^1.1.0",
|
||||||
"@radix-ui/react-separator": "^1.0.3",
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
"@radix-ui/react-tabs": "^1.1.0",
|
"@radix-ui/react-tabs": "^1.1.0",
|
||||||
"@radix-ui/react-tooltip": "^1.0.7",
|
"@radix-ui/react-tooltip": "^1.1.3",
|
||||||
"@tailwindcss/typography": "^0.5.13",
|
"@tailwindcss/typography": "^0.5.13",
|
||||||
"@types/canvas-confetti": "^1.6.4",
|
"@types/canvas-confetti": "^1.6.4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
|
|||||||
129
src/app/(docs)/docs/[[...slug]]/page.tsx
Normal file
129
src/app/(docs)/docs/[[...slug]]/page.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* MHSF, Minehut Server List
|
||||||
|
* All external content is rather licensed under the ECA Agreement
|
||||||
|
* located here: https://list.mlnehut.com/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 TableOfContent from "@/components/docs/TOC";
|
||||||
|
import { ALegacy } from "@/components/misc/Link";
|
||||||
|
import { MDXElements } from "@/components/misc/MDXElements";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { allDocs } from "contentlayer/generated";
|
||||||
|
import { useMDXComponent } from "next-contentlayer/hooks";
|
||||||
|
import NextLink from "next/link";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
|
||||||
|
export const generateStaticParams = async () =>
|
||||||
|
allDocs.map((post) => ({ slug: [post._raw.flattenedPath] }));
|
||||||
|
|
||||||
|
export const generateMetadata = ({
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
params: { slug: string[] };
|
||||||
|
}) => {
|
||||||
|
const post = allDocs.find(
|
||||||
|
(post) => post._raw.flattenedPath === params.slug.join("/"),
|
||||||
|
);
|
||||||
|
if (!post) notFound();
|
||||||
|
return { title: post.title + " | MHSF Docs", themeColor: "#000000" };
|
||||||
|
};
|
||||||
|
|
||||||
|
const PostLayout = ({ params }: { params: { slug: string[] } }) => {
|
||||||
|
const doc = allDocs.find(
|
||||||
|
(post) => post._raw.flattenedPath === params.slug.join("/"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!doc) notFound();
|
||||||
|
console.log(doc);
|
||||||
|
const MDXContent = useMDXComponent(doc.body.code);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="relative py-6 lg:gap-10 lg:py-8 xl:grid xl:grid-cols-[1fr_300px]">
|
||||||
|
<div className="mx-auto w-full min-w-0">
|
||||||
|
<div className="pb-12 pt-8 prose dark:prose-invert">
|
||||||
|
{doc.folder && <span>{doc.folder}</span>}{" "}
|
||||||
|
{doc.lastUpdated && <span> - last updated {doc.lastUpdated}</span>}{" "}
|
||||||
|
<MDXContent
|
||||||
|
components={{
|
||||||
|
Separator,
|
||||||
|
a: (props) => <ALegacy {...props} />,
|
||||||
|
...MDXElements,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{doc.toc && (
|
||||||
|
<div className="hidden text-sm xl:block">
|
||||||
|
<div className="sticky top-16 -mt-10 pt-4">
|
||||||
|
<ScrollArea className="pb-10">
|
||||||
|
<div className="sticky top-16 -mt-10 h-[calc(100vh-3.5rem)] py-12 space-y-2">
|
||||||
|
<p className="font-medium">On This Page</p>
|
||||||
|
{doc.toc.map(
|
||||||
|
(c: { level: number; text: string; slug: string }) => (
|
||||||
|
<TableOfContent toc={c} doc={doc} key={c.slug} />
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
<div className="space-y-2">
|
||||||
|
<p className="font-medium">Contribute</p>
|
||||||
|
<ul className="m-0 list-none">
|
||||||
|
<li className="mt-0 pt-2">
|
||||||
|
<NextLink
|
||||||
|
href={
|
||||||
|
"https://github.com/DeveloLongScript/MHSF/edit/main/docs/" +
|
||||||
|
doc._raw.flattenedPath +
|
||||||
|
".mdx"
|
||||||
|
}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors no-underline"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 438.549 438.549"
|
||||||
|
fontSize={16}
|
||||||
|
className="mr-2 size-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Edit page on GitHub
|
||||||
|
</NextLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default PostLayout;
|
||||||
@ -28,47 +28,75 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
"use client";
|
||||||
|
|
||||||
import { Sidebar } from "@/components/docs/Sidebar";
|
import { Sidebar } from "@/components/docs/Sidebar";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
|
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import {
|
||||||
|
SidebarInset,
|
||||||
|
SidebarProvider,
|
||||||
|
SidebarTrigger,
|
||||||
|
} from "@/components/ui/sidebar";
|
||||||
import { version } from "@/config/version";
|
import { version } from "@/config/version";
|
||||||
import { HamburgerMenuIcon } from "@radix-ui/react-icons";
|
import { HamburgerMenuIcon } from "@radix-ui/react-icons";
|
||||||
|
import { GeistMono } from "geist/font/mono";
|
||||||
|
import { GeistSans } from "geist/font/sans";
|
||||||
|
import "../globals.css";
|
||||||
|
import "../../themes.css";
|
||||||
|
import { ThemeProvider } from "@/components/ThemeProvider";
|
||||||
|
import { ClerkThemeProvider } from "@/components/clerk/ClerkThemeProvider";
|
||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbLink,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbPage,
|
||||||
|
BreadcrumbSeparator,
|
||||||
|
} from "@/components/ui/breadcrumb";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import NextTopLoader from "@/lib/top-loader";
|
||||||
|
import { useRouter } from "@/lib/useRouter";
|
||||||
|
import { allDocs } from "contentlayer/generated";
|
||||||
|
import { GetServerSideProps } from "next";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
pathname: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
const pathname = usePathname();
|
||||||
<div className="border-b pt-[40px]">
|
return (
|
||||||
<div className="container flex-1 items-start md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10">
|
<ClerkThemeProvider className="">
|
||||||
<aside className="fixed top-14 z-30 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block">
|
<div className="theme-zinc">
|
||||||
<ScrollArea className="h-full py-6 pr-6 lg:py-8">
|
<NextTopLoader />
|
||||||
<div className="bg-muted w-full rounded justify-center p-4 flex items-center">
|
<SidebarProvider>
|
||||||
MHSF Docs <small className="ml-2">Version {version}</small>
|
<Sidebar />
|
||||||
</div>
|
<SidebarInset>
|
||||||
<br />
|
<div className="fixed backdrop-blur w-full flex h-16 z-10 items-center gap-2 px-4 ">
|
||||||
<Sidebar />
|
<SidebarTrigger />
|
||||||
</ScrollArea>
|
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||||
</aside>
|
{
|
||||||
<br className="md:hidden" />
|
allDocs.find(
|
||||||
|
(c) =>
|
||||||
<div className="bg-muted w-full rounded justify-center p-4 flex items-center md:hidden">
|
c._raw.flattenedPath ===
|
||||||
MHSF Docs <small className="ml-2">Version {version}</small>
|
pathname
|
||||||
<Drawer>
|
?.split("/")
|
||||||
<DrawerTrigger>
|
.splice(2, pathname?.split("/").length)
|
||||||
<Button className="ml-2">
|
.join("/"),
|
||||||
<HamburgerMenuIcon />
|
)?.title
|
||||||
</Button>
|
}
|
||||||
</DrawerTrigger>
|
</div>
|
||||||
<DrawerContent className="p-4">
|
<div className="px-[100px] pt-[50px]">{children}</div>
|
||||||
<Sidebar />
|
</SidebarInset>
|
||||||
</DrawerContent>
|
</SidebarProvider>
|
||||||
</Drawer>
|
</div>
|
||||||
</div>
|
</ClerkThemeProvider>
|
||||||
{children}
|
);
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@ -28,104 +28,104 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { GeistSans } from "geist/font/sans";
|
|
||||||
import { SpeedInsights } from "@vercel/speed-insights/next";
|
|
||||||
import { Analytics } from "@vercel/analytics/react";
|
import { Analytics } from "@vercel/analytics/react";
|
||||||
import "./globals.css";
|
import { SpeedInsights } from "@vercel/speed-insights/next";
|
||||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
import { GeistSans } from "geist/font/sans";
|
||||||
|
import "../globals.css";
|
||||||
|
import ClientFadeIn from "@/components/ClientFadeIn";
|
||||||
|
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 NextTopLoader from "@/lib/top-loader";
|
|
||||||
import { banner } from "@/config/banner";
|
|
||||||
import {
|
|
||||||
Breadcrumb,
|
|
||||||
BreadcrumbList,
|
|
||||||
BreadcrumbPage,
|
|
||||||
} from "@/components/ui/breadcrumb";
|
|
||||||
import Link from "next/link";
|
|
||||||
import TopBar from "@/components/clerk/Topbar";
|
import TopBar from "@/components/clerk/Topbar";
|
||||||
import TextFromPathname from "@/components/TextFromPathname";
|
|
||||||
import { Inter as interFont } from "next/font/google";
|
|
||||||
import { CommandBarer } from "@/components/CommandBar";
|
|
||||||
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 ClientFadeIn from "@/components/ClientFadeIn";
|
import {
|
||||||
import { BrandingGenericIcon } from "@/components/Icon";
|
Breadcrumb,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbPage,
|
||||||
|
} from "@/components/ui/breadcrumb";
|
||||||
|
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 Link from "next/link";
|
||||||
|
|
||||||
export const extraMetadata = {
|
export const extraMetadata = {
|
||||||
twitter: {
|
twitter: {
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: "/public/imgs/icon-cf.png",
|
url: "/imgs/icon-cf.png",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
themeColor: "#000000",
|
themeColor: "#000000",
|
||||||
openGraph: {
|
openGraph: {
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: "/public/imgs/icon-cf.png",
|
url: "/imgs/icon-cf.png",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
} satisfies Metadata;
|
} satisfies Metadata;
|
||||||
export const viewport: Viewport = {
|
export const viewport: Viewport = {
|
||||||
themeColor: "black",
|
themeColor: "black",
|
||||||
colorScheme: "dark",
|
colorScheme: "dark",
|
||||||
};
|
};
|
||||||
|
|
||||||
const inter = interFont({ variable: "--font-inter", subsets: ["latin"] });
|
const inter = interFont({ variable: "--font-inter", subsets: ["latin"] });
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<ClerkThemeProvider className={GeistSans.className}>
|
<ClerkThemeProvider className={GeistSans.className}>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
attribute="class"
|
attribute="class"
|
||||||
defaultTheme="system"
|
defaultTheme="system"
|
||||||
enableSystem
|
enableSystem
|
||||||
disableTransitionOnChange
|
disableTransitionOnChange
|
||||||
>
|
>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
{banner.isBanner && (
|
{banner.isBanner && (
|
||||||
<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">
|
<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">
|
||||||
{banner.bannerText}
|
{banner.bannerText}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"w-screen h-[3rem] border-b fixed backdrop-blur flex z-10 " +
|
"w-screen h-[3rem] border-b fixed backdrop-blur flex z-10 " +
|
||||||
(banner.isBanner == true ? "mt-8" : "")
|
(banner.isBanner == true ? "mt-8" : "")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="items-center me-auto mt-2 pl-7 max-sm:mt-3">
|
<div className="items-center me-auto mt-2 pl-7 max-sm:mt-3">
|
||||||
<Breadcrumb>
|
<Breadcrumb>
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
<BreadcrumbPage className="max-sm:hidden">
|
<BreadcrumbPage className="max-sm:hidden">
|
||||||
<BrandingGenericIcon className="max-w-[32px] max-h-[32px] " />
|
<BrandingGenericIcon className="max-w-[32px] max-h-[32px] " />
|
||||||
</BreadcrumbPage>
|
</BreadcrumbPage>
|
||||||
</Link>
|
</Link>
|
||||||
<TextFromPathname />
|
<TextFromPathname />
|
||||||
</BreadcrumbList>
|
</BreadcrumbList>
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
<TopBar inter={inter.className} />
|
<TopBar inter={inter.className} />
|
||||||
</div>
|
</div>
|
||||||
<div className={banner.isBanner ? "pt-8" : undefined}>
|
<div className={banner.isBanner ? "pt-8" : undefined}>
|
||||||
<NextTopLoader />
|
<NextTopLoader />
|
||||||
<ClientFadeIn>{children}</ClientFadeIn>
|
<ClientFadeIn>{children}</ClientFadeIn>
|
||||||
</div>{" "}
|
</div>{" "}
|
||||||
<ThemedToaster />
|
<ThemedToaster />
|
||||||
<CommandBarer />
|
<CommandBarer />
|
||||||
<SpeedInsights />
|
<SpeedInsights />
|
||||||
<Analytics />
|
<Analytics />
|
||||||
<UnofficalDialog />
|
<UnofficalDialog />
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ClerkThemeProvider>
|
</ClerkThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -31,16 +31,16 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
export default function NotFound() {
|
export default function NotFound() {
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<div className="pt-[60px] p-4">
|
<div className="pt-[60px] p-4">
|
||||||
<strong>404 - Page not found</strong>
|
<strong>404 - Page not found</strong>
|
||||||
<br />
|
<br />
|
||||||
<p>
|
<p>
|
||||||
We couldn't find the page you were looking for.{" "}
|
We couldn't find the page you were looking for.{" "}
|
||||||
<Link href="/">Go home</Link>
|
<Link href="/public">Go home</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -32,34 +32,34 @@ import ServerList from "@/components/ServerList";
|
|||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "the MHSF project by dvelo",
|
title: "the MHSF project by dvelo",
|
||||||
description:
|
description:
|
||||||
process.env.NEXT_PUBLIC_VERCEL_ENV != undefined
|
process.env.NEXT_PUBLIC_VERCEL_ENV != undefined
|
||||||
? `currently running in ${process.env.NEXT_PUBLIC_VERCEL_ENV} | commit (${(process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA as string).substring(0, 7)}}) "${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE}" by ${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME}`
|
? `currently running in ${process.env.NEXT_PUBLIC_VERCEL_ENV} | commit (${(process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA as string).substring(0, 7)}}) "${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE}" by ${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME}`
|
||||||
: "currently running in dev",
|
: "currently running in dev",
|
||||||
twitter: {
|
twitter: {
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: "/public/imgs/icon-cf.png",
|
url: "/imgs/icon-cf.png",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
themeColor: "#000000",
|
themeColor: "#000000",
|
||||||
openGraph: {
|
openGraph: {
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: "/public/imgs/icon-cf.png",
|
url: "/imgs/icon-cf.png",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<div className="pt-[60px]">
|
<div className="pt-[60px]">
|
||||||
<ServerList />
|
<ServerList />
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
155
src/app/(main)/server/[server]/page.tsx
Normal file
155
src/app/(main)/server/[server]/page.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* MHSF, Minehut Server List
|
||||||
|
* All external content is rather licensed under the ECA Agreement
|
||||||
|
* located here: https://list.mlnehut.com/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 AfterServerView from "@/components/AfterServerView";
|
||||||
|
import Banner from "@/components/Banner";
|
||||||
|
import ColorProvider from "@/components/ColorProvider";
|
||||||
|
import ServerView from "@/components/ServerView";
|
||||||
|
import TabServer from "@/components/misc/TabServer";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { CornerDownLeft } from "lucide-react";
|
||||||
|
import type { Metadata, ResolvingMetadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: { server: string };
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function generateMetadata(
|
||||||
|
{ params }: Props,
|
||||||
|
parent: ResolvingMetadata,
|
||||||
|
): Promise<Metadata> {
|
||||||
|
// read route params
|
||||||
|
const { server } = params;
|
||||||
|
const json = await (
|
||||||
|
await fetch("https://api.minehut.com/server/" + server + "?byName=true")
|
||||||
|
).json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
themeColor: "#000000",
|
||||||
|
title:
|
||||||
|
json.server == null
|
||||||
|
? "Server doesn't exist | MHSF"
|
||||||
|
: json.server.name +
|
||||||
|
", " +
|
||||||
|
(json.server.online
|
||||||
|
? json.server.playerCount +
|
||||||
|
(json.server.maxPlayers != 10
|
||||||
|
? "/" + json.server.maxPlayers
|
||||||
|
: "") +
|
||||||
|
" online"
|
||||||
|
: "Offline") +
|
||||||
|
" | MHSF",
|
||||||
|
description:
|
||||||
|
json.server == null
|
||||||
|
? `The server ${server} doesn't exist.`
|
||||||
|
: `View ${server} on Minehut Server Finder!`,
|
||||||
|
authors: json.server == null ? undefined : { name: json.server.owner },
|
||||||
|
applicationName: "MHSF (Minehut Server Finder)",
|
||||||
|
icons:
|
||||||
|
json.server == null
|
||||||
|
? undefined
|
||||||
|
: "https://minehut-server-icons-live.s3.us-west-2.amazonaws.com/" +
|
||||||
|
(json.server.icon == undefined ? "OAK_SIGN" : json.server.icon) +
|
||||||
|
".png",
|
||||||
|
twitter: {
|
||||||
|
title:
|
||||||
|
json.server == null
|
||||||
|
? "Server doesn't exist | MHSF"
|
||||||
|
: json.server.name +
|
||||||
|
", " +
|
||||||
|
(json.server.online
|
||||||
|
? json.server.playerCount +
|
||||||
|
(json.server.maxPlayers != 10
|
||||||
|
? "/" + json.server.maxPlayers
|
||||||
|
: "") +
|
||||||
|
" online"
|
||||||
|
: "Offline") +
|
||||||
|
" | MHSF",
|
||||||
|
description:
|
||||||
|
json.server == null
|
||||||
|
? `The server ${server} doesn't exist.`
|
||||||
|
: `View ${server} on Minehut Server Finder!`,
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url:
|
||||||
|
"https://minehut-server-icons-live.s3.us-west-2.amazonaws.com/" +
|
||||||
|
json.server.icon +
|
||||||
|
".png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/public/imgs/icon-cf.png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
openGraph: {
|
||||||
|
type: "profile",
|
||||||
|
siteName: "MHSF (Minehut Server Finder)",
|
||||||
|
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url:
|
||||||
|
"https://minehut-server-icons-live.s3.us-west-2.amazonaws.com/" +
|
||||||
|
json.server.icon +
|
||||||
|
".png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/public/imgs/icon-cf.png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ServerPage({ params }: { params: { server: string } }) {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<ColorProvider server={params.server}>
|
||||||
|
<div className={"pt-16"}>
|
||||||
|
<Banner server={params.server} />
|
||||||
|
<Link href="/">
|
||||||
|
<Button variant="link" className="text-muted-foreground text-sm">
|
||||||
|
<CornerDownLeft size={16} className="mr-2" /> Go back to the
|
||||||
|
server list
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
<TabServer server={params.server} tabDef="general" />
|
||||||
|
<div className="pt-8">
|
||||||
|
<ServerView server={params.server} />
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<br />
|
||||||
|
<AfterServerView server={params.server} />
|
||||||
|
</div>
|
||||||
|
</ColorProvider>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
116
src/app/(main)/server/[server]/statistics/page.tsx
Normal file
116
src/app/(main)/server/[server]/statistics/page.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* MHSF, Minehut Server List
|
||||||
|
* All external content is rather licensed under the ECA Agreement
|
||||||
|
* located here: https://list.mlnehut.com/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 Banner from "@/components/Banner";
|
||||||
|
import ColorProvider from "@/components/ColorProvider";
|
||||||
|
import { NewChart } from "@/components/NewChart";
|
||||||
|
import ServerView from "@/components/ServerView";
|
||||||
|
import TabServer from "@/components/misc/TabServer";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import type { Metadata, ResolvingMetadata } from "next";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: { server: string };
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function generateMetadata(
|
||||||
|
{ params }: Props,
|
||||||
|
parent: ResolvingMetadata,
|
||||||
|
): Promise<Metadata> {
|
||||||
|
// read route params
|
||||||
|
const { server } = params;
|
||||||
|
const json = await (
|
||||||
|
await fetch("https://api.minehut.com/server/" + server + "?byName=true")
|
||||||
|
).json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
title:
|
||||||
|
json.server == null
|
||||||
|
? "Server doesn't exist | MHSF"
|
||||||
|
: json.server.name +
|
||||||
|
", " +
|
||||||
|
(json.server.online
|
||||||
|
? json.server.playerCount +
|
||||||
|
(json.server.maxPlayers != 10
|
||||||
|
? "/" + json.server.maxPlayers
|
||||||
|
: "") +
|
||||||
|
" online"
|
||||||
|
: "Offline") +
|
||||||
|
" | MHSF",
|
||||||
|
description:
|
||||||
|
json.server == null
|
||||||
|
? `The server ${server} doesn't exist.`
|
||||||
|
: `View ${server} on Minehut Server Finder!`,
|
||||||
|
authors: json.server == null ? undefined : { name: json.server.owner },
|
||||||
|
applicationName: "MHSF (Minehut Server Finder)",
|
||||||
|
icons:
|
||||||
|
json.server == null
|
||||||
|
? undefined
|
||||||
|
: "https://mcapi.marveldc.me/item/" +
|
||||||
|
(json.server.icon == undefined ? "OAK_SIGN" : json.server.icon) +
|
||||||
|
"?width=64&height=64",
|
||||||
|
openGraph: {
|
||||||
|
type: "profile",
|
||||||
|
siteName: "MHSF (Minehut Server Finder)",
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url:
|
||||||
|
"https://mcapi.marveldc.me/item/" +
|
||||||
|
json.server.icon +
|
||||||
|
"?width=64&height=64",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/favicon.ico",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ServerPage({ params }: { params: { server: string } }) {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<ColorProvider server={params.server}>
|
||||||
|
<div className={"pt-16"}>
|
||||||
|
<Banner server={params.server} />
|
||||||
|
<TabServer server={params.server} tabDef="statistics" />
|
||||||
|
<div className="pt-8">
|
||||||
|
<ServerView server={params.server} />
|
||||||
|
<Separator />
|
||||||
|
<br />
|
||||||
|
<div className="p-4 gap-4">
|
||||||
|
<NewChart server={params.server} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ColorProvider>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* MHSF, Minehut Server List
|
|
||||||
* All external content is rather licensed under the ECA Agreement
|
|
||||||
* located here: https://list.mlnehut.com/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 TableOfContent from "@/components/docs/TOC";
|
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
||||||
import { allDocs } from "contentlayer/generated";
|
|
||||||
import { useMDXComponent } from "next-contentlayer/hooks";
|
|
||||||
import NextLink from "next/link";
|
|
||||||
import { notFound } from "next/navigation";
|
|
||||||
import { Separator } from "@/components/ui/separator";
|
|
||||||
import { ALegacy } from "@/components/misc/Link";
|
|
||||||
import { MDXElements } from "@/components/misc/MDXElements";
|
|
||||||
|
|
||||||
export const generateStaticParams = async () =>
|
|
||||||
allDocs.map((post) => ({ slug: [post._raw.flattenedPath] }));
|
|
||||||
|
|
||||||
export const generateMetadata = ({
|
|
||||||
params,
|
|
||||||
}: {
|
|
||||||
params: { slug: string[] };
|
|
||||||
}) => {
|
|
||||||
const post = allDocs.find(
|
|
||||||
(post) => post._raw.flattenedPath === params.slug.join("/")
|
|
||||||
);
|
|
||||||
if (!post) notFound();
|
|
||||||
return { title: post.title + " | MHSF Docs", themeColor: "#000000" };
|
|
||||||
};
|
|
||||||
|
|
||||||
const PostLayout = ({ params }: { params: { slug: string[] } }) => {
|
|
||||||
const doc = allDocs.find(
|
|
||||||
(post) => post._raw.flattenedPath === params.slug.join("/")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!doc) notFound();
|
|
||||||
console.log(doc);
|
|
||||||
const MDXContent = useMDXComponent(doc.body.code);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<main className="relative py-6 lg:gap-10 lg:py-8 xl:grid xl:grid-cols-[1fr_300px]">
|
|
||||||
<div className="mx-auto w-full min-w-0">
|
|
||||||
<div className="pb-12 pt-8 prose dark:prose-invert">
|
|
||||||
{doc.folder && <span>{doc.folder}</span>}{" "}
|
|
||||||
{doc.lastUpdated && <span> - last updated {doc.lastUpdated}</span>}{" "}
|
|
||||||
<MDXContent
|
|
||||||
components={{
|
|
||||||
Separator,
|
|
||||||
a: (props) => <ALegacy {...props} />,
|
|
||||||
...MDXElements,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{doc.toc && (
|
|
||||||
<div className="hidden text-sm xl:block">
|
|
||||||
<div className="sticky top-16 -mt-10 pt-4">
|
|
||||||
<ScrollArea className="pb-10">
|
|
||||||
<div className="sticky top-16 -mt-10 h-[calc(100vh-3.5rem)] py-12 space-y-2">
|
|
||||||
<p className="font-medium">On This Page</p>
|
|
||||||
{doc.toc.map(
|
|
||||||
(c: { level: number; text: string; slug: string }) => (
|
|
||||||
<TableOfContent toc={c} doc={doc} key={c.slug} />
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
<br />
|
|
||||||
<div className="space-y-2">
|
|
||||||
<p className="font-medium">Contribute</p>
|
|
||||||
<ul className="m-0 list-none">
|
|
||||||
<li className="mt-0 pt-2">
|
|
||||||
<NextLink
|
|
||||||
href={
|
|
||||||
"https://github.com/DeveloLongScript/MHSF/edit/main/docs/" +
|
|
||||||
doc._raw.flattenedPath +
|
|
||||||
".mdx"
|
|
||||||
}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors no-underline"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 438.549 438.549"
|
|
||||||
fontSize={16}
|
|
||||||
className="mr-2 size-4"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Edit page on GitHub
|
|
||||||
</NextLink>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default PostLayout;
|
|
||||||
@ -73,6 +73,15 @@
|
|||||||
--color-one: #37ecba;
|
--color-one: #37ecba;
|
||||||
--color-two: #72afd3;
|
--color-two: #72afd3;
|
||||||
--color-three: #ff2e63;
|
--color-three: #ff2e63;
|
||||||
|
--sidebar-background: 0 0% 98%;
|
||||||
|
--sidebar-foreground: 240 5.3% 26.1%;
|
||||||
|
--sidebar-primary: 240 5.9% 10%;
|
||||||
|
--sidebar-primary-foreground: 0 0% 98%;
|
||||||
|
--sidebar-mhsf: 240 1% 92%;
|
||||||
|
--sidebar-accent: 240 4.8% 95.9%;
|
||||||
|
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||||
|
--sidebar-border: 220 13% 91%;
|
||||||
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
@ -112,6 +121,15 @@
|
|||||||
--chart-3: 216 92% 60%;
|
--chart-3: 216 92% 60%;
|
||||||
--chart-4: 210 98% 78%;
|
--chart-4: 210 98% 78%;
|
||||||
--chart-5: 212 97% 87%;
|
--chart-5: 212 97% 87%;
|
||||||
|
--sidebar-background: 240 5.9% 10%;
|
||||||
|
--sidebar-foreground: 240 4.8% 95.9%;
|
||||||
|
--sidebar-primary: 224.3 76.3% 48%;
|
||||||
|
--sidebar-primary-foreground: 0 0% 100%;
|
||||||
|
--sidebar-mhsf: 240 0% 13%;
|
||||||
|
--sidebar-accent: 240 3.7% 15.9%;
|
||||||
|
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||||
|
--sidebar-border: 240 3.7% 15.9%;
|
||||||
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,11 +141,11 @@
|
|||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@layer base {
|
/*@layer base {*/
|
||||||
a {
|
/* a {*/
|
||||||
@apply underline text-blue-400;
|
/* @apply underline text-blue-400;*/
|
||||||
}
|
/* }*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
.backdrop-blur {
|
.backdrop-blur {
|
||||||
-webkit-backdrop-filter: blur(8px) !important;
|
-webkit-backdrop-filter: blur(8px) !important;
|
||||||
|
|||||||
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* MHSF, Minehut Server List
|
|
||||||
* All external content is rather licensed under the ECA Agreement
|
|
||||||
* located here: https://list.mlnehut.com/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 ServerView from "@/components/ServerView";
|
|
||||||
import type { Metadata, ResolvingMetadata } from "next";
|
|
||||||
import TabServer from "@/components/misc/TabServer";
|
|
||||||
import ColorProvider from "@/components/ColorProvider";
|
|
||||||
import AfterServerView from "@/components/AfterServerView";
|
|
||||||
import Banner from "@/components/Banner";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { CornerDownLeft } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
params: { server: string };
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function generateMetadata(
|
|
||||||
{ params }: Props,
|
|
||||||
parent: ResolvingMetadata
|
|
||||||
): Promise<Metadata> {
|
|
||||||
// read route params
|
|
||||||
const { server } = params;
|
|
||||||
const json = await (
|
|
||||||
await fetch("https://api.minehut.com/server/" + server + "?byName=true")
|
|
||||||
).json();
|
|
||||||
|
|
||||||
return {
|
|
||||||
themeColor: "#000000",
|
|
||||||
title:
|
|
||||||
json.server == null
|
|
||||||
? "Server doesn't exist | MHSF"
|
|
||||||
: json.server.name +
|
|
||||||
", " +
|
|
||||||
(json.server.online
|
|
||||||
? json.server.playerCount +
|
|
||||||
(json.server.maxPlayers != 10
|
|
||||||
? "/" + json.server.maxPlayers
|
|
||||||
: "") +
|
|
||||||
" online"
|
|
||||||
: "Offline") +
|
|
||||||
" | MHSF",
|
|
||||||
description:
|
|
||||||
json.server == null
|
|
||||||
? `The server ${server} doesn't exist.`
|
|
||||||
: `View ${server} on Minehut Server Finder!`,
|
|
||||||
authors: json.server == null ? undefined : { name: json.server.owner },
|
|
||||||
applicationName: "MHSF (Minehut Server Finder)",
|
|
||||||
icons:
|
|
||||||
json.server == null
|
|
||||||
? undefined
|
|
||||||
: "https://minehut-server-icons-live.s3.us-west-2.amazonaws.com/" +
|
|
||||||
(json.server.icon == undefined ? "OAK_SIGN" : json.server.icon) +
|
|
||||||
".png",
|
|
||||||
twitter: {
|
|
||||||
title:
|
|
||||||
json.server == null
|
|
||||||
? "Server doesn't exist | MHSF"
|
|
||||||
: json.server.name +
|
|
||||||
", " +
|
|
||||||
(json.server.online
|
|
||||||
? json.server.playerCount +
|
|
||||||
(json.server.maxPlayers != 10
|
|
||||||
? "/" + json.server.maxPlayers
|
|
||||||
: "") +
|
|
||||||
" online"
|
|
||||||
: "Offline") +
|
|
||||||
" | MHSF",
|
|
||||||
description:
|
|
||||||
json.server == null
|
|
||||||
? `The server ${server} doesn't exist.`
|
|
||||||
: `View ${server} on Minehut Server Finder!`,
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url:
|
|
||||||
"https://minehut-server-icons-live.s3.us-west-2.amazonaws.com/" +
|
|
||||||
json.server.icon +
|
|
||||||
".png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "/public/imgs/icon-cf.png",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
openGraph: {
|
|
||||||
type: "profile",
|
|
||||||
siteName: "MHSF (Minehut Server Finder)",
|
|
||||||
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url:
|
|
||||||
"https://minehut-server-icons-live.s3.us-west-2.amazonaws.com/" +
|
|
||||||
json.server.icon +
|
|
||||||
".png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "/public/imgs/icon-cf.png",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ServerPage({ params }: { params: { server: string } }) {
|
|
||||||
return (
|
|
||||||
<main>
|
|
||||||
<ColorProvider server={params.server}>
|
|
||||||
<div className={"pt-16"}>
|
|
||||||
<Banner server={params.server} />
|
|
||||||
<Link href="/">
|
|
||||||
<Button variant="link" className="text-muted-foreground text-sm">
|
|
||||||
<CornerDownLeft size={16} className="mr-2" /> Go back to the
|
|
||||||
server list
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<TabServer server={params.server} tabDef="general" />
|
|
||||||
<div className="pt-8">
|
|
||||||
<ServerView server={params.server} />
|
|
||||||
</div>
|
|
||||||
<AfterServerView server={params.server} />
|
|
||||||
</div>
|
|
||||||
</ColorProvider>
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* MHSF, Minehut Server List
|
|
||||||
* All external content is rather licensed under the ECA Agreement
|
|
||||||
* located here: https://list.mlnehut.com/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 ServerView from "@/components/ServerView";
|
|
||||||
import type { Metadata, ResolvingMetadata } from "next";
|
|
||||||
import TabServer from "@/components/misc/TabServer";
|
|
||||||
import { NewChart } from "@/components/NewChart";
|
|
||||||
import ColorProvider from "@/components/ColorProvider";
|
|
||||||
import Banner from "@/components/Banner";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
params: { server: string };
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function generateMetadata(
|
|
||||||
{ params }: Props,
|
|
||||||
parent: ResolvingMetadata
|
|
||||||
): Promise<Metadata> {
|
|
||||||
// read route params
|
|
||||||
const { server } = params;
|
|
||||||
const json = await (
|
|
||||||
await fetch("https://api.minehut.com/server/" + server + "?byName=true")
|
|
||||||
).json();
|
|
||||||
|
|
||||||
return {
|
|
||||||
title:
|
|
||||||
json.server == null
|
|
||||||
? "Server doesn't exist | MHSF"
|
|
||||||
: json.server.name +
|
|
||||||
", " +
|
|
||||||
(json.server.online
|
|
||||||
? json.server.playerCount +
|
|
||||||
(json.server.maxPlayers != 10
|
|
||||||
? "/" + json.server.maxPlayers
|
|
||||||
: "") +
|
|
||||||
" online"
|
|
||||||
: "Offline") +
|
|
||||||
" | MHSF",
|
|
||||||
description:
|
|
||||||
json.server == null
|
|
||||||
? `The server ${server} doesn't exist.`
|
|
||||||
: `View ${server} on Minehut Server Finder!`,
|
|
||||||
authors: json.server == null ? undefined : { name: json.server.owner },
|
|
||||||
applicationName: "MHSF (Minehut Server Finder)",
|
|
||||||
icons:
|
|
||||||
json.server == null
|
|
||||||
? undefined
|
|
||||||
: "https://mcapi.marveldc.me/item/" +
|
|
||||||
(json.server.icon == undefined ? "OAK_SIGN" : json.server.icon) +
|
|
||||||
"?width=64&height=64",
|
|
||||||
openGraph: {
|
|
||||||
type: "profile",
|
|
||||||
siteName: "MHSF (Minehut Server Finder)",
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url:
|
|
||||||
"https://mcapi.marveldc.me/item/" +
|
|
||||||
json.server.icon +
|
|
||||||
"?width=64&height=64",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "/favicon.ico",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ServerPage({ params }: { params: { server: string } }) {
|
|
||||||
return (
|
|
||||||
<main>
|
|
||||||
<ColorProvider server={params.server}>
|
|
||||||
<div className={"pt-16"}>
|
|
||||||
<Banner server={params.server} />
|
|
||||||
<TabServer server={params.server} tabDef="statistics" />
|
|
||||||
<div className="pt-8">
|
|
||||||
<ServerView server={params.server} />
|
|
||||||
<div className="p-4 gap-4">
|
|
||||||
<NewChart server={params.server} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ColorProvider>
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -30,382 +30,413 @@
|
|||||||
|
|
||||||
"use client";
|
"use client";
|
||||||
import { getCommunityServerFavorites, getCustomization } from "@/lib/api";
|
import { getCommunityServerFavorites, getCustomization } from "@/lib/api";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "./ui/card";
|
|
||||||
import Markdown from "react-markdown";
|
|
||||||
import { useTheme } from "next-themes";
|
|
||||||
import FadeIn from "react-fade-in/lib/FadeIn";
|
|
||||||
import { Button } from "./ui/button";
|
|
||||||
import { ServerResponse } from "@/lib/types/mh-server";
|
|
||||||
import { Copy, Info } from "lucide-react";
|
|
||||||
import toast, { CheckmarkIcon } from "react-hot-toast";
|
|
||||||
import { MHSF } from "@/lib/mhsf";
|
import { MHSF } from "@/lib/mhsf";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
|
import { ServerResponse } from "@/lib/types/mh-server";
|
||||||
|
import { MinehutIcon, getMinehutIcons } from "@/lib/types/server-icon";
|
||||||
|
import { Copy, Info } from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import FadeIn from "react-fade-in/lib/FadeIn";
|
||||||
|
import toast, { CheckmarkIcon } from "react-hot-toast";
|
||||||
|
import Markdown from "react-markdown";
|
||||||
import AchievementList from "./feat/AchievementList";
|
import AchievementList from "./feat/AchievementList";
|
||||||
|
import { Button } from "./ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "./ui/card";
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
|
||||||
|
|
||||||
export default function AfterServerView({ server }: { server: string }) {
|
export default function AfterServerView({ server }: { server: string }) {
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [discord, setDiscord] = useState("");
|
const [discord, setDiscord] = useState("");
|
||||||
const [mhsf, setMHSF] = useState(new MHSF());
|
const [mhsf, setMHSF] = useState(new MHSF());
|
||||||
const { resolvedTheme } = useTheme();
|
const [icons, setIcons] = useState<MinehutIcon[]>();
|
||||||
const [loading, setLoading] = useState(true);
|
const { resolvedTheme } = useTheme();
|
||||||
const [view, setView] = useState(
|
const [loading, setLoading] = useState(true);
|
||||||
description !== "" || discord !== "" ? "desc" : "extra"
|
const [view, setView] = useState(
|
||||||
);
|
description !== "" || discord !== "" ? "desc" : "extra",
|
||||||
const [serverObject, setServerObject] = useState<ServerResponse | undefined>(
|
);
|
||||||
undefined
|
const [serverObject, setServerObject] = useState<ServerResponse | undefined>(
|
||||||
);
|
undefined,
|
||||||
const [copied, setCopied] = useState(false);
|
);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCustomization(server).then((b) => {
|
getCustomization(server).then((b) => {
|
||||||
if (b != null) {
|
if (b != null) {
|
||||||
setDescription(b.description == null ? "" : b.description);
|
setDescription(b.description == null ? "" : b.description);
|
||||||
setDiscord(b.discord == null ? "" : b.discord);
|
setDiscord(b.discord == null ? "" : b.discord);
|
||||||
mhsf.setCustomizations(b);
|
mhsf.setCustomizations(b);
|
||||||
getCommunityServerFavorites(server).then((c) => {
|
getCommunityServerFavorites(server).then((c) => {
|
||||||
mhsf.setFavorites(c);
|
mhsf.setFavorites(c);
|
||||||
});
|
});
|
||||||
}
|
getMinehutIcons().then((i) => {
|
||||||
fetch("https://api.minehut.com/server/" + server + "?byName=true").then(
|
setIcons(i);
|
||||||
(c) => c.json().then((n) => setServerObject(n.server))
|
});
|
||||||
);
|
}
|
||||||
setLoading(false);
|
fetch("https://api.minehut.com/server/" + server + "?byName=true").then(
|
||||||
});
|
(c) => c.json().then((n) => setServerObject(n.server)),
|
||||||
}, []);
|
);
|
||||||
if (loading) return <></>;
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
if (loading) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<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">
|
<div className="ml-5 mb-2 flex items-center sm:hidden">
|
||||||
{(description != "" || discord != "") && (
|
{(description != "" || discord != "") && (
|
||||||
<Button
|
<Button
|
||||||
variant={view == "desc" ? undefined : "ghost"}
|
variant={view == "desc" ? undefined : "ghost"}
|
||||||
onClick={() => setView("desc")}
|
onClick={() => setView("desc")}
|
||||||
>
|
>
|
||||||
Description
|
Description
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant={view == "extra" ? undefined : "ghost"}
|
variant={view == "extra" ? undefined : "ghost"}
|
||||||
onClick={() => setView("extra")}
|
onClick={() => setView("extra")}
|
||||||
className="ml-2"
|
className="ml-2"
|
||||||
>
|
>
|
||||||
Server Information
|
Server Information
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={view == "achievements" ? undefined : "ghost"}
|
variant={view == "achievements" ? undefined : "ghost"}
|
||||||
onClick={() => setView("achievements")}
|
onClick={() => setView("achievements")}
|
||||||
className="ml-2"
|
className="ml-2"
|
||||||
>
|
>
|
||||||
Achievements
|
Achievements
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
<Button
|
||||||
<div className="max-sm:hidden">
|
variant={view == "icons" ? undefined : "ghost"}
|
||||||
<div className="grid">
|
onClick={() => setView("icons")}
|
||||||
{(description != "" || discord != "") && (
|
>
|
||||||
<Button
|
Purchased Icons
|
||||||
variant={view == "desc" ? undefined : "ghost"}
|
</Button>
|
||||||
onClick={() => setView("desc")}
|
</div>
|
||||||
>
|
<div className="max-sm:hidden">
|
||||||
Description
|
<div className="grid">
|
||||||
</Button>
|
{(description != "" || discord != "") && (
|
||||||
)}
|
<Button
|
||||||
<Button
|
variant={view == "desc" ? undefined : "ghost"}
|
||||||
variant={view == "extra" ? undefined : "ghost"}
|
onClick={() => setView("desc")}
|
||||||
onClick={() => setView("extra")}
|
>
|
||||||
>
|
Description
|
||||||
Server Information
|
</Button>
|
||||||
</Button>
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant={view == "achievements" ? undefined : "ghost"}
|
variant={view == "extra" ? undefined : "ghost"}
|
||||||
onClick={() => setView("achievements")}
|
onClick={() => setView("extra")}
|
||||||
>
|
>
|
||||||
Achievements
|
Server Information
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
<Button
|
||||||
</div>
|
variant={view == "achievements" ? undefined : "ghost"}
|
||||||
|
onClick={() => setView("achievements")}
|
||||||
|
>
|
||||||
|
Achievements
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={view == "icons" ? undefined : "ghost"}
|
||||||
|
onClick={() => setView("icons")}
|
||||||
|
>
|
||||||
|
Purchased Icons
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-4 pl-4 pr-4 gap-3.5 col-span-5">
|
<div className="grid lg:grid-cols-4 pl-4 pr-4 gap-3.5 col-span-5">
|
||||||
{description != "" && view == "desc" && (
|
{description != "" && view == "desc" && (
|
||||||
<Card className="sm:col-span-3">
|
<Card className="sm:col-span-3">
|
||||||
<CardDescription className="p-4 prose dark:prose-invert">
|
<CardDescription className="p-4 prose dark:prose-invert">
|
||||||
<Markdown disallowedElements={["img"]}>
|
<Markdown disallowedElements={["img"]}>
|
||||||
{description}
|
{description}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
{discord != "" && view == "desc" && (
|
{discord != "" && view == "desc" && (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Discord Server</CardTitle>
|
<CardTitle>Discord Server</CardTitle>
|
||||||
<CardDescription className="p-4 prose dark:prose-invert">
|
<CardDescription className="p-4 prose dark:prose-invert">
|
||||||
<iframe
|
<iframe
|
||||||
src={`https://discord.com/widget?id=${discord}&theme=${resolvedTheme}`}
|
src={`https://discord.com/widget?id=${discord}&theme=${resolvedTheme}`}
|
||||||
height="500"
|
height="500"
|
||||||
allowTransparency={true}
|
allowTransparency={true}
|
||||||
className="rounded-lg max-sm:w-[100px] max-md:w-[250px]"
|
className="rounded-lg max-sm:w-[100px] max-md:w-[250px]"
|
||||||
sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
|
sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
|
||||||
/>
|
/>
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
)}{" "}
|
)}{" "}
|
||||||
{view == "achievements" && (
|
{view == "achievements" && (
|
||||||
<div className="col-span-4">
|
<div className="col-span-4">
|
||||||
<AchievementList server={server} />
|
<AchievementList server={server} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{view == "extra" && (
|
{view == "extra" && (
|
||||||
<div className="sm:grid sm:grid-cols-3 col-span-4 gap-4">
|
<div className="sm:grid sm:grid-cols-3 col-span-4 gap-4">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Plan Details</CardTitle>
|
<CardTitle>Plan Details</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Information about the plan being used by the server
|
Information about the plan being used by the server
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
{(() => {
|
{(() => {
|
||||||
console.log(serverObject);
|
console.log(serverObject);
|
||||||
return true;
|
return true;
|
||||||
})()}
|
})()}
|
||||||
<CardContent>
|
<CardContent>
|
||||||
{" "}
|
{" "}
|
||||||
<table className="table-auto w-full">
|
<table className="table-auto w-full">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server plan</th>
|
<th className="border p-2">Server plan</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.expired == undefined ? (
|
{serverObject?.expired == undefined ? (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
Free{" "}
|
Free{" "}
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<div>
|
<div>
|
||||||
<Info size={16} className="ml-2" />
|
<Info size={16} className="ml-2" />
|
||||||
</div>
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
The plan is really unknown, but in most
|
The plan is really unknown, but in most
|
||||||
scenarios, the Minehut API returns{" "}
|
scenarios, the Minehut API returns{" "}
|
||||||
<code>undefined</code> if the server is free.
|
<code>undefined</code> if the server is free.
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>{serverObject?.activeServerPlan}</>
|
<>{serverObject?.activeServerPlan}</>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Raw plan</th>
|
<th className="border p-2">Raw plan</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.expired == undefined ? (
|
{serverObject?.expired == undefined ? (
|
||||||
"? (unknown)"
|
"? (unknown)"
|
||||||
) : (
|
) : (
|
||||||
<code>{serverObject?.rawPlan}</code>
|
<code>{serverObject?.rawPlan}</code>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Credits per day</th>
|
<th className="border p-2">Credits per day</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.credits_per_day == undefined
|
{serverObject?.credits_per_day == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: Math.floor(serverObject?.credits_per_day)}
|
: Math.floor(serverObject?.credits_per_day)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server expired</th>
|
<th className="border p-2">Server expired</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.expired == undefined
|
{serverObject?.expired == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: toJSX(serverObject?.expired)}
|
: toJSX(serverObject?.expired)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server external</th>
|
<th className="border p-2">Server external</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.rawPlan == undefined
|
{serverObject?.rawPlan == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: toJSX(serverObject?.rawPlan == "EXTERNAL")}
|
: toJSX(serverObject?.rawPlan == "EXTERNAL")}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>{" "}
|
</table>{" "}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<br className="sm:hidden" />
|
<br className="sm:hidden" />
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Additional Info</CardTitle>
|
<CardTitle>Additional Info</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Additional info that could be useful{" "}
|
Additional info that could be useful{" "}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<table className="table-auto w-full">
|
<table className="table-auto w-full">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Icon</th>
|
<th className="border p-2">Icon</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.icon == undefined ? (
|
{serverObject?.icon == undefined ? (
|
||||||
<>
|
<>
|
||||||
Default (<code>OAK_SIGN</code>)
|
Default (<code>OAK_SIGN</code>)
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<code>{serverObject?.icon}</code>
|
<code>{serverObject?.icon}</code>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">All-time joins</th>
|
<th className="border p-2">All-time joins</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.joins == undefined
|
{serverObject?.joins == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: serverObject?.joins}
|
: serverObject?.joins}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server Type</th>
|
<th className="border p-2">Server Type</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.server_version_type == undefined ? (
|
{serverObject?.server_version_type == undefined ? (
|
||||||
"? (unknown)"
|
"? (unknown)"
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{serverObject?.server_version_type.toLowerCase()}
|
{serverObject?.server_version_type.toLowerCase()}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server Platform</th>
|
<th className="border p-2">Server Platform</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.platform == undefined
|
{serverObject?.platform == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: serverObject?.platform}
|
: serverObject?.platform}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<br className="sm:hidden" />
|
<br className="sm:hidden" />
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>
|
<CardTitle>
|
||||||
<div>
|
<div>
|
||||||
<span>Technical Info</span>
|
<span>Technical Info</span>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipContent className="font-normal tracking-normal">
|
<TooltipContent className="font-normal tracking-normal">
|
||||||
Copy JSON data about the server
|
Copy JSON data about the server
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<Button
|
<Button
|
||||||
className="justify-right ml-2"
|
className="justify-right ml-2"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
try {
|
try {
|
||||||
navigator.clipboard.writeText(
|
navigator.clipboard.writeText(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
minehut: serverObject,
|
minehut: serverObject,
|
||||||
mhsf: mhsf.getMHSF(),
|
mhsf: mhsf.getMHSF(),
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
toast.error(
|
toast.error(
|
||||||
"Clipboard is inaccessible. Cannot copy"
|
"Clipboard is inaccessible. Cannot copy",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
toast.success(
|
toast.success(
|
||||||
<div className="block w-[300px]">
|
<div className="block w-[300px]">
|
||||||
Copied the following: <br />{" "}
|
Copied the following: <br />{" "}
|
||||||
<code className="flex items-center">
|
<code className="flex items-center">
|
||||||
{JSON.stringify({
|
{JSON.stringify({
|
||||||
minehut: serverObject,
|
minehut: serverObject,
|
||||||
mhsf,
|
mhsf,
|
||||||
}).substring(0, 36)}
|
}).substring(0, 36)}
|
||||||
...
|
...
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
setTimeout(() => setCopied(false), 1000);
|
setTimeout(() => setCopied(false), 1000);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!copied && <Copy size={16} />}
|
{!copied && <Copy size={16} />}
|
||||||
{copied && <CheckmarkIcon />}
|
{copied && <CheckmarkIcon />}
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Technical information about the server{" "}
|
Technical information about the server{" "}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<table className="table-auto w-full">
|
<table className="table-auto w-full">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Visible</th>
|
<th className="border p-2">Visible</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.visibility == undefined
|
{serverObject?.visibility == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: toJSX(serverObject?.visibility)}
|
: toJSX(serverObject?.visibility)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server Port</th>
|
<th className="border p-2">Server Port</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.port == undefined ? (
|
{serverObject?.port == undefined ? (
|
||||||
"? (unknown)"
|
"? (unknown)"
|
||||||
) : (
|
) : (
|
||||||
<code>{serverObject?.port}</code>
|
<code>{serverObject?.port}</code>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Storage Node</th>
|
<th className="border p-2">Storage Node</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?.storage_node == undefined
|
{serverObject?.storage_node == undefined
|
||||||
? "? (unknown)"
|
? "? (unknown)"
|
||||||
: serverObject?.storage_node.toUpperCase()}
|
: serverObject?.storage_node.toUpperCase()}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="border p-2">Server ID</th>
|
<th className="border p-2">Server ID</th>
|
||||||
<td className="border p-2">
|
<td className="border p-2">
|
||||||
{serverObject?._id == undefined ? (
|
{serverObject?._id == undefined ? (
|
||||||
"? (unknown)"
|
"? (unknown)"
|
||||||
) : (
|
) : (
|
||||||
<code>{serverObject?._id}</code>
|
<code>{serverObject?._id}</code>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
{view == "icons" && (
|
||||||
</div>
|
<div>
|
||||||
<br />
|
<p>
|
||||||
<br />
|
Purchased Icons are icons that are under the server's
|
||||||
</FadeIn>
|
ownership, they may or may not available at that certain
|
||||||
</>
|
moment either.
|
||||||
);
|
</p>
|
||||||
|
{serverObject?.purchased_icons.map((icon) => (
|
||||||
|
<div key={icon}>
|
||||||
|
{icons?.find((c) => c._id === icon)?.icon_name}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
</FadeIn>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toJSX(boolean: boolean) {
|
function toJSX(boolean: boolean) {
|
||||||
if (boolean) {
|
if (boolean) {
|
||||||
return <div className="text-green-400">True</div>;
|
return <div className="text-green-400">True</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className="text-red-400">False</div>;
|
return <div className="text-red-400">False</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,25 +29,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
"use client";
|
"use client";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import TabServer from "./misc/TabServer";
|
|
||||||
import ServerCustomize from "./ServerCustomize";
|
|
||||||
import Banner from "./Banner";
|
import Banner from "./Banner";
|
||||||
|
import ServerCustomize from "./ServerCustomize";
|
||||||
|
import TabServer from "./misc/TabServer";
|
||||||
|
|
||||||
export default function CustomizeRoot({
|
export default function CustomizeRoot({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: { server: string };
|
params: { server: string };
|
||||||
}) {
|
}) {
|
||||||
const [color, setColor] = useState("");
|
const [color, setColor] = useState("");
|
||||||
return (
|
return (
|
||||||
<div className={"pt-16 theme-" + color}>
|
<div className={"pt-16 theme-" + color}>
|
||||||
<Banner server={params.server} />
|
<Banner server={params.server} />
|
||||||
<TabServer server={params.server} tabDef="customize" />
|
<TabServer server={params.server} tabDef="customize" />
|
||||||
<br />
|
<Separator />
|
||||||
<div className="pl-[40px] pr-[40px]">
|
<br />
|
||||||
<ServerCustomize server={params.server} cs={color} setCS={setColor} />
|
<div className="pl-[40px] pr-[40px]">
|
||||||
</div>
|
<ServerCustomize server={params.server} cs={color} setCS={setColor} />
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,108 +28,120 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useClerk } from "@clerk/nextjs";
|
||||||
import { Cog, ExternalLink, KeyRound, Link, UserPen } from "lucide-react";
|
import { Cog, ExternalLink, KeyRound, Link, UserPen } from "lucide-react";
|
||||||
|
import NextLink from "next/link";
|
||||||
import { Button } from "./ui/button";
|
import { Button } from "./ui/button";
|
||||||
import {
|
import {
|
||||||
ResizableHandle,
|
ResizableHandle,
|
||||||
ResizablePanel,
|
ResizablePanel,
|
||||||
ResizablePanelGroup,
|
ResizablePanelGroup,
|
||||||
} from "./ui/resizable";
|
} from "./ui/resizable";
|
||||||
import NextLink from "next/link";
|
|
||||||
import { useClerk } from "@clerk/nextjs";
|
|
||||||
|
|
||||||
export function Sidebar({
|
export function Sidebar({
|
||||||
children,
|
children,
|
||||||
curPage,
|
curPage,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
curPage: string;
|
curPage: string;
|
||||||
}) {
|
}) {
|
||||||
const clerk = useClerk();
|
const clerk = useClerk();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResizablePanelGroup
|
<ResizablePanelGroup
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
className="min-h-[calc(100vh-70px)] pt-[70px]"
|
className="min-h-[calc(100vh-70px)] pt-[70px]"
|
||||||
>
|
>
|
||||||
<ResizablePanel className="max-md:hidden min-w-[285px] max-w-[285px] w-[285px]">
|
<ResizablePanel className="max-md:hidden min-w-[285px] max-w-[285px] w-[285px]">
|
||||||
<div className="w-[300px] ml-[10px]">
|
<div className="w-[300px] ml-[10px]">
|
||||||
<NextLink href="/account/settings" className="text-inherit">
|
<NextLink
|
||||||
<Button
|
href="/src/app/(main)/account/settings"
|
||||||
className="mb-[2px] w-[250px]"
|
className="text-inherit"
|
||||||
variant={curPage !== "/account/settings" ? "ghost" : "default"}
|
>
|
||||||
>
|
<Button
|
||||||
<Link size={16} className="mr-2" /> Linking
|
className="mb-[2px] w-[250px]"
|
||||||
</Button>
|
variant={curPage !== "/account/settings" ? "ghost" : "default"}
|
||||||
</NextLink>
|
>
|
||||||
<NextLink href="/account/settings/options" className="text-inherit">
|
<Link size={16} className="mr-2" /> Linking
|
||||||
<Button
|
</Button>
|
||||||
className="mb-[2px] w-[250px] "
|
</NextLink>
|
||||||
variant={
|
<NextLink
|
||||||
curPage !== "/account/settings/options" ? "ghost" : "default"
|
href="/src/app/(main)/account/settings/options"
|
||||||
}
|
className="text-inherit"
|
||||||
>
|
>
|
||||||
<Cog size={16} className="mr-2" /> Options
|
<Button
|
||||||
</Button>
|
className="mb-[2px] w-[250px] "
|
||||||
</NextLink>
|
variant={
|
||||||
<Button
|
curPage !== "/account/settings/options" ? "ghost" : "default"
|
||||||
className="mb-[2px] w-[250px]"
|
}
|
||||||
variant="ghost"
|
>
|
||||||
onClick={() => clerk.openUserProfile({})}
|
<Cog size={16} className="mr-2" /> Options
|
||||||
>
|
</Button>
|
||||||
<UserPen size={16} className="mr-2" /> Profile{" "}
|
</NextLink>
|
||||||
<ExternalLink size={16} className="ml-2" />
|
<Button
|
||||||
</Button>
|
className="mb-[2px] w-[250px]"
|
||||||
<Button
|
variant="ghost"
|
||||||
className="mb-[2px] w-[250px]"
|
onClick={() => clerk.openUserProfile({})}
|
||||||
variant="ghost"
|
>
|
||||||
onClick={() => clerk.openUserProfile({})}
|
<UserPen size={16} className="mr-2" /> Profile{" "}
|
||||||
>
|
<ExternalLink size={16} className="ml-2" />
|
||||||
<KeyRound size={16} className="mr-2" /> Security{" "}
|
</Button>
|
||||||
<ExternalLink size={16} className="ml-2" />
|
<Button
|
||||||
</Button>
|
className="mb-[2px] w-[250px]"
|
||||||
</div>
|
variant="ghost"
|
||||||
</ResizablePanel>
|
onClick={() => clerk.openUserProfile({})}
|
||||||
<ResizableHandle className="max-md:hidden" />
|
>
|
||||||
<ResizablePanel>
|
<KeyRound size={16} className="mr-2" /> Security{" "}
|
||||||
<div className="md:hidden ml-2">
|
<ExternalLink size={16} className="ml-2" />
|
||||||
<NextLink href="/account/settings" className="text-inherit">
|
</Button>
|
||||||
<Button
|
</div>
|
||||||
className="mr-[2px]"
|
</ResizablePanel>
|
||||||
variant={curPage !== "/account/settings" ? "ghost" : "default"}
|
<ResizableHandle className="max-md:hidden" />
|
||||||
>
|
<ResizablePanel>
|
||||||
<Link size={16} className="mr-2" /> Linking
|
<div className="md:hidden ml-2">
|
||||||
</Button>
|
<NextLink
|
||||||
</NextLink>
|
href="/src/app/(main)/account/settings"
|
||||||
<NextLink href="/account/settings/options" className="text-inherit">
|
className="text-inherit"
|
||||||
<Button
|
>
|
||||||
className="mr-[2px]"
|
<Button
|
||||||
variant={
|
className="mr-[2px]"
|
||||||
curPage !== "/account/settings/options" ? "ghost" : "default"
|
variant={curPage !== "/account/settings" ? "ghost" : "default"}
|
||||||
}
|
>
|
||||||
>
|
<Link size={16} className="mr-2" /> Linking
|
||||||
<Cog size={16} className="mr-2" /> Options
|
</Button>
|
||||||
</Button>
|
</NextLink>
|
||||||
</NextLink>
|
<NextLink
|
||||||
<Button
|
href="/src/app/(main)/account/settings/options"
|
||||||
className="mr-[2px]"
|
className="text-inherit"
|
||||||
variant="ghost"
|
>
|
||||||
onClick={() => clerk.openUserProfile({})}
|
<Button
|
||||||
>
|
className="mr-[2px]"
|
||||||
<UserPen size={16} className="mr-2" /> Profile{" "}
|
variant={
|
||||||
<ExternalLink size={16} className="ml-2" />
|
curPage !== "/account/settings/options" ? "ghost" : "default"
|
||||||
</Button>
|
}
|
||||||
<Button
|
>
|
||||||
className="mr-[2px] mb-[30px]"
|
<Cog size={16} className="mr-2" /> Options
|
||||||
variant="ghost"
|
</Button>
|
||||||
onClick={() => clerk.openUserProfile({})}
|
</NextLink>
|
||||||
>
|
<Button
|
||||||
<KeyRound size={16} className="mr-2" /> Security{" "}
|
className="mr-[2px]"
|
||||||
<ExternalLink size={16} className="ml-2" />
|
variant="ghost"
|
||||||
</Button>
|
onClick={() => clerk.openUserProfile({})}
|
||||||
</div>
|
>
|
||||||
{children}{" "}
|
<UserPen size={16} className="mr-2" /> Profile{" "}
|
||||||
</ResizablePanel>
|
<ExternalLink size={16} className="ml-2" />
|
||||||
</ResizablePanelGroup>
|
</Button>
|
||||||
);
|
<Button
|
||||||
|
className="mr-[2px] mb-[30px]"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => clerk.openUserProfile({})}
|
||||||
|
>
|
||||||
|
<KeyRound size={16} className="mr-2" /> Security{" "}
|
||||||
|
<ExternalLink size={16} className="ml-2" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{children}{" "}
|
||||||
|
</ResizablePanel>
|
||||||
|
</ResizablePanelGroup>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,32 +28,15 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { NewChart } from "@/components/NewChart";
|
||||||
|
import { MiniJoinsChart } from "@/components/misc/MiniJoinsChart";
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
ContextMenuTrigger,
|
|
||||||
ContextMenuItem,
|
|
||||||
ContextMenuContent,
|
ContextMenuContent,
|
||||||
|
ContextMenuItem,
|
||||||
ContextMenuSeparator,
|
ContextMenuSeparator,
|
||||||
|
ContextMenuTrigger,
|
||||||
} from "@/components/ui/context-menu";
|
} from "@/components/ui/context-menu";
|
||||||
import toast, { LoaderIcon } from "react-hot-toast";
|
|
||||||
import {
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
CardDescription,
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
} from "./ui/card";
|
|
||||||
import IconDisplay from "./IconDisplay";
|
|
||||||
import { TagShower } from "./ServerList";
|
|
||||||
import {
|
|
||||||
ArrowRight,
|
|
||||||
ChartArea,
|
|
||||||
Copy,
|
|
||||||
EllipsisVertical,
|
|
||||||
Layers,
|
|
||||||
Star,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { Button } from "./ui/button";
|
|
||||||
import {
|
import {
|
||||||
Drawer,
|
Drawer,
|
||||||
DrawerContent,
|
DrawerContent,
|
||||||
@ -62,20 +45,39 @@ import {
|
|||||||
DrawerTitle,
|
DrawerTitle,
|
||||||
DrawerTrigger,
|
DrawerTrigger,
|
||||||
} from "@/components/ui/drawer";
|
} from "@/components/ui/drawer";
|
||||||
import { Tooltip } from "@radix-ui/react-tooltip";
|
|
||||||
import { TooltipContent, TooltipTrigger } from "./ui/tooltip";
|
|
||||||
import { useRouter } from "@/lib/useRouter";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { favoriteServer, isFavorited } from "@/lib/api";
|
|
||||||
import { useUser } from "@clerk/nextjs";
|
|
||||||
import { useTheme } from "next-themes";
|
|
||||||
import {
|
import {
|
||||||
HoverCard,
|
HoverCard,
|
||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger,
|
HoverCardTrigger,
|
||||||
} from "@/components/ui/hover-card";
|
} from "@/components/ui/hover-card";
|
||||||
|
import { favoriteServer, isFavorited } from "@/lib/api";
|
||||||
import useClipboard from "@/lib/useClipboard";
|
import useClipboard from "@/lib/useClipboard";
|
||||||
|
import { useRouter } from "@/lib/useRouter";
|
||||||
|
import { useUser } from "@clerk/nextjs";
|
||||||
|
import { Tooltip } from "@radix-ui/react-tooltip";
|
||||||
|
import {
|
||||||
|
ArrowRight,
|
||||||
|
ChartArea,
|
||||||
|
Copy,
|
||||||
|
EllipsisVertical,
|
||||||
|
Layers,
|
||||||
|
Star,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useState } from "react";
|
||||||
|
import toast, { LoaderIcon } from "react-hot-toast";
|
||||||
|
import IconDisplay from "./IconDisplay";
|
||||||
|
import { TagShower } from "./ServerList";
|
||||||
|
import { Button } from "./ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "./ui/card";
|
||||||
|
import { TooltipContent, TooltipTrigger } from "./ui/tooltip";
|
||||||
|
|
||||||
export default function ServerCard({ b, motd, mini, favs }: any) {
|
export default function ServerCard({ b, motd, mini, favs }: any) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -130,6 +132,13 @@ export default function ServerCard({ b, motd, mini, favs }: any) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<strong className="text-sm font-semibold text-center">
|
||||||
|
Joins Chart
|
||||||
|
</strong>
|
||||||
|
<MiniJoinsChart server={b.name} />
|
||||||
|
|
||||||
<div className="flex items-center pt-2">
|
<div className="flex items-center pt-2">
|
||||||
<span className="text-xs text-muted-foreground flex items-center">
|
<span className="text-xs text-muted-foreground flex items-center">
|
||||||
<ArrowRight size={16} className="mr-2" />
|
<ArrowRight size={16} className="mr-2" />
|
||||||
@ -272,7 +281,7 @@ export default function ServerCard({ b, motd, mini, favs }: any) {
|
|||||||
</div>
|
</div>
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuSeparator />
|
<ContextMenuSeparator />
|
||||||
<Link href={"/server/" + b.name}>
|
<Link href={"/src/app/(main)/server/" + b.name}>
|
||||||
<ContextMenuItem>Open server page</ContextMenuItem>
|
<ContextMenuItem>Open server page</ContextMenuItem>
|
||||||
</Link>
|
</Link>
|
||||||
</ContextMenuContent>
|
</ContextMenuContent>
|
||||||
|
|||||||
@ -181,7 +181,7 @@ export default function ServerCustomize({
|
|||||||
Is this server in violation of the ECA?
|
Is this server in violation of the ECA?
|
||||||
</div>
|
</div>
|
||||||
Is this server in violation of the{" "}
|
Is this server in violation of the{" "}
|
||||||
<Link href="/docs/legal/external-content-agreement">
|
<Link href="/src/app/(main)/docs/legal/external-content-agreement">
|
||||||
External Content Agreement (aka ECA)
|
External Content Agreement (aka ECA)
|
||||||
</Link>
|
</Link>
|
||||||
? You can report the server to remove the customizations from the
|
? You can report the server to remove the customizations from the
|
||||||
@ -196,7 +196,7 @@ export default function ServerCustomize({
|
|||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
This will send a notification to MHSF maintainers. This
|
This will send a notification to MHSF maintainers. This
|
||||||
server must be in violation of the{" "}
|
server must be in violation of the{" "}
|
||||||
<Link href="/docs/legal/external-content-agreement">
|
<Link href="/src/app/(main)/docs/legal/external-content-agreement">
|
||||||
ECA
|
ECA
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
to be a valid report. Typical response times include 1 hour
|
to be a valid report. Typical response times include 1 hour
|
||||||
@ -329,7 +329,7 @@ export default function ServerCustomize({
|
|||||||
Minehuts Terms of Service
|
Minehuts Terms of Service
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
& the{" "}
|
& the{" "}
|
||||||
<Link href="/docs/legal/external-content-agreement">
|
<Link href="/src/app/(main)/docs/legal/external-content-agreement">
|
||||||
External Content Agreement
|
External Content Agreement
|
||||||
</Link>
|
</Link>
|
||||||
.
|
.
|
||||||
@ -436,7 +436,7 @@ export default function ServerCustomize({
|
|||||||
Imgurs Terms of Service
|
Imgurs Terms of Service
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
& the{" "}
|
& the{" "}
|
||||||
<Link href="/docs/legal/external-content-agreement">
|
<Link href="/src/app/(main)/docs/legal/external-content-agreement">
|
||||||
External Content Agreement
|
External Content Agreement
|
||||||
</Link>
|
</Link>
|
||||||
.
|
.
|
||||||
@ -468,7 +468,7 @@ export default function ServerCustomize({
|
|||||||
Discords Terms of Service
|
Discords Terms of Service
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
& the{" "}
|
& the{" "}
|
||||||
<Link href="/docs/legal/external-content-agreement">
|
<Link href="/src/app/(main)/docs/legal/external-content-agreement">
|
||||||
External Content Agreement
|
External Content Agreement
|
||||||
</Link>
|
</Link>
|
||||||
.
|
.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -30,50 +30,50 @@
|
|||||||
|
|
||||||
"use client";
|
"use client";
|
||||||
import { ClerkProvider } from "@clerk/nextjs";
|
import { ClerkProvider } from "@clerk/nextjs";
|
||||||
import { useTheme } from "next-themes";
|
|
||||||
import { dark } from "@clerk/themes";
|
import { dark } from "@clerk/themes";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import { type ReactNode, useEffect, useState } from "react";
|
||||||
import { ThemeProvider } from "../ThemeProvider";
|
import { ThemeProvider } from "../ThemeProvider";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
export function ClerkThemeProvider({
|
export function ClerkThemeProvider({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
children: JSX.Element;
|
children: ReactNode | ReactNode[];
|
||||||
className: string;
|
className: string | undefined;
|
||||||
}) {
|
}) {
|
||||||
const [theme, setTheme] = useState<string | undefined>("");
|
const [theme, setTheme] = useState<string | undefined>("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClerkProvider
|
<ClerkProvider
|
||||||
appearance={{ baseTheme: theme == "dark" ? dark : undefined }}
|
appearance={{ baseTheme: theme == "dark" ? dark : undefined }}
|
||||||
>
|
>
|
||||||
<html lang="en" className={className}>
|
<html lang="en" className={className}>
|
||||||
<body>
|
<body>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
attribute="class"
|
attribute="class"
|
||||||
defaultTheme="system"
|
defaultTheme="system"
|
||||||
enableSystem
|
enableSystem
|
||||||
disableTransitionOnChange
|
disableTransitionOnChange
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
{/** This *has* to be implemented in component form for the `useTheme` to load at the appropriate time. */}
|
{/** This *has* to be implemented in component form for the `useTheme` to load at the appropriate time. */}
|
||||||
<ThemeElement setTheme={setTheme} />
|
<ThemeElement setTheme={setTheme} />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
</ClerkProvider>
|
</ClerkProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ThemeElement({
|
function ThemeElement({
|
||||||
setTheme,
|
setTheme,
|
||||||
}: {
|
}: {
|
||||||
setTheme: (update: string | undefined) => void;
|
setTheme: (update: string | undefined) => void;
|
||||||
}) {
|
}) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTheme(theme.resolvedTheme);
|
setTheme(theme.resolvedTheme);
|
||||||
}, [theme.resolvedTheme, setTheme]);
|
}, [theme.resolvedTheme, setTheme]);
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|||||||
199
src/components/docs/NavUser.tsx
Normal file
199
src/components/docs/NavUser.tsx
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* MHSF, Minehut Server List
|
||||||
|
* All external content is rather licensed under the ECA Agreement
|
||||||
|
* located here: https://list.mlnehut.com/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 {
|
||||||
|
BadgeCheck,
|
||||||
|
Bell,
|
||||||
|
ChevronsUpDown,
|
||||||
|
Computer,
|
||||||
|
CreditCard,
|
||||||
|
LogIn,
|
||||||
|
LogOut,
|
||||||
|
Moon,
|
||||||
|
SettingsIcon,
|
||||||
|
Sparkles,
|
||||||
|
Sun,
|
||||||
|
} from "lucide-react";
|
||||||
|
|
||||||
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuCheckboxItem,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuPortal,
|
||||||
|
DropdownMenuRadioGroup,
|
||||||
|
DropdownMenuRadioItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
import {
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
useSidebar,
|
||||||
|
} from "@/components/ui/sidebar";
|
||||||
|
import { useClerk, useUser } from "@clerk/nextjs";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
|
||||||
|
export function NavUser() {
|
||||||
|
const { isMobile } = useSidebar();
|
||||||
|
const { user, isSignedIn } = useUser();
|
||||||
|
const clerk = useClerk();
|
||||||
|
const { setTheme, theme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidebarMenu>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<SidebarMenuButton
|
||||||
|
size="lg"
|
||||||
|
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||||
|
>
|
||||||
|
{isSignedIn && (
|
||||||
|
<Avatar className="h-8 w-8 rounded-lg">
|
||||||
|
<AvatarImage
|
||||||
|
src={
|
||||||
|
user?.imageUrl == undefined
|
||||||
|
? "https://img.clerk.com/preview.png?size=144&seed=seed&initials=AD&isSquare=true&bgType=marble&bgColor=6c47ff&fgType=silhouette&fgColor=FFFFFF&type=user&w=48&q=75"
|
||||||
|
: user?.imageUrl
|
||||||
|
}
|
||||||
|
alt={user?.username || "?"}
|
||||||
|
/>
|
||||||
|
<AvatarFallback className="rounded-lg">?</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||||
|
<span className="truncate font-semibold">
|
||||||
|
{isSignedIn ? user?.username : "Not logged in"}
|
||||||
|
</span>
|
||||||
|
<span className="truncate text-xs">
|
||||||
|
{user?.primaryEmailAddress?.emailAddress}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ChevronsUpDown className="ml-auto size-4" />
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent
|
||||||
|
className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
|
||||||
|
side={isMobile ? "bottom" : "right"}
|
||||||
|
align="end"
|
||||||
|
sideOffset={4}
|
||||||
|
>
|
||||||
|
{isSignedIn && (
|
||||||
|
<>
|
||||||
|
<DropdownMenuLabel className="p-0 font-normal">
|
||||||
|
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||||
|
<Avatar className="h-8 w-8 rounded-lg">
|
||||||
|
<AvatarImage
|
||||||
|
src={
|
||||||
|
user?.imageUrl == undefined
|
||||||
|
? "https://img.clerk.com/preview.png?size=144&seed=seed&initials=AD&isSquare=true&bgType=marble&bgColor=6c47ff&fgType=silhouette&fgColor=FFFFFF&type=user&w=48&q=75"
|
||||||
|
: user?.imageUrl
|
||||||
|
}
|
||||||
|
alt={user?.username || "?"}
|
||||||
|
/>
|
||||||
|
<AvatarFallback className="rounded-lg">?</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||||
|
<span className="truncate font-semibold">
|
||||||
|
{user?.username}
|
||||||
|
</span>
|
||||||
|
<span className="truncate text-xs">
|
||||||
|
{user?.primaryEmailAddress?.emailAddress}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DropdownMenuLabel>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuRadioGroup
|
||||||
|
onValueChange={(c) => setTheme(c)}
|
||||||
|
value={theme}
|
||||||
|
>
|
||||||
|
<DropdownMenuRadioItem value="dark">
|
||||||
|
<Moon /> Dark
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="light">
|
||||||
|
<Sun /> Light
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="system">
|
||||||
|
<Computer /> System
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
</DropdownMenuRadioGroup>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
|
||||||
|
{isSignedIn && (
|
||||||
|
<>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem onSelect={() => clerk.openUserProfile()}>
|
||||||
|
<SettingsIcon />
|
||||||
|
Account Settings
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="text-red-500"
|
||||||
|
onSelect={() => clerk.signOut()}
|
||||||
|
>
|
||||||
|
<LogOut />
|
||||||
|
Log out
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!isSignedIn && (
|
||||||
|
<>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem onSelect={() => clerk.openSignIn()}>
|
||||||
|
<LogIn />
|
||||||
|
Sign in
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarMenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,134 +1,51 @@
|
|||||||
/*
|
import * as React from "react";
|
||||||
* MHSF, Minehut Server List
|
|
||||||
* All external content is rather licensed under the ECA Agreement
|
|
||||||
* located here: https://list.mlnehut.com/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 { NavUser } from "@/components/docs/NavUser";
|
||||||
import { allFolders, Docs, DocsFolder } from "@/config/docs";
|
import { VersionSwitcher } from "@/components/docs/VersionSwitcher";
|
||||||
import { usePathname } from "next/navigation";
|
import {
|
||||||
import { Button } from "../ui/button";
|
Sidebar as ShadSidebar,
|
||||||
import { useState } from "react";
|
SidebarContent,
|
||||||
import { ChevronRight } from "lucide-react";
|
SidebarFooter,
|
||||||
import { useRouter } from "@/lib/useRouter";
|
SidebarGroup,
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
SidebarGroupContent,
|
||||||
|
SidebarGroupLabel,
|
||||||
|
SidebarHeader,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarRail,
|
||||||
|
} from "@/components/ui/sidebar";
|
||||||
|
import { allFolders } from "@/config/docs";
|
||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<>
|
<ShadSidebar>
|
||||||
{allFolders.map((docs) => (
|
<SidebarHeader>
|
||||||
<Folder docs={docs} key={"url" in docs ? docs.title : docs.name} />
|
<VersionSwitcher />
|
||||||
))}
|
</SidebarHeader>
|
||||||
</>
|
<SidebarContent>
|
||||||
);
|
{/* We create a SidebarGroup for each parent. */}
|
||||||
}
|
{allFolders.map((item) => (
|
||||||
|
<SidebarGroup key={item.name}>
|
||||||
function Folder({ docs }: { docs: any }) {
|
<SidebarGroupLabel>{item.name}</SidebarGroupLabel>
|
||||||
const [folderOpen, setOpen] = useState(false);
|
<SidebarGroupContent>
|
||||||
const router = useRouter();
|
<SidebarMenu>
|
||||||
const pathname = usePathname();
|
{item.docs.map((item) => (
|
||||||
|
<SidebarMenuItem key={item.title}>
|
||||||
return (
|
<SidebarMenuButton asChild>
|
||||||
<div key={"url" in docs ? docs.title : docs.name}>
|
<a href={item.url}>{item.title}</a>
|
||||||
<Button
|
</SidebarMenuButton>
|
||||||
size="sm"
|
</SidebarMenuItem>
|
||||||
className="w-full font-normal tracking-normal mt-1"
|
))}
|
||||||
noJustify
|
</SidebarMenu>
|
||||||
variant={
|
</SidebarGroupContent>
|
||||||
"url" in docs
|
</SidebarGroup>
|
||||||
? pathname === docs.url
|
))}
|
||||||
? "default"
|
</SidebarContent>
|
||||||
: "ghost"
|
<SidebarFooter>
|
||||||
: "ghost"
|
<NavUser />
|
||||||
}
|
</SidebarFooter>
|
||||||
onClick={() => {
|
<SidebarRail />
|
||||||
if ("docs" in docs) {
|
</ShadSidebar>
|
||||||
setOpen(!folderOpen);
|
);
|
||||||
} else {
|
|
||||||
router.push(docs.url);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{"url" in docs ? docs.title : docs.name}
|
|
||||||
<div className="flex items-center ml-auto text-muted-foreground">
|
|
||||||
<AnimatePresence>
|
|
||||||
{"docs" in docs && folderOpen && (
|
|
||||||
<motion.div initial={{ rotate: 90 }} animate={{ rotate: 0 }}>
|
|
||||||
<ChevronRight size={18} />
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
{"docs" in docs && !folderOpen && (
|
|
||||||
<motion.div initial={{ rotate: 0 }} animate={{ rotate: 90 }}>
|
|
||||||
<ChevronRight size={18} />
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
<div className="ml-2">
|
|
||||||
{folderOpen && <Subdocs docs={"docs" in docs ? docs.docs : []} />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Subdocs({ docs }: { docs: (Docs | DocsFolder)[] }) {
|
|
||||||
const pathname = usePathname();
|
|
||||||
const router = useRouter();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{docs.map((doc) => {
|
|
||||||
if ("docs" in doc) {
|
|
||||||
return <Subdocs docs={doc.docs} key={doc.name} />;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
className="w-full font-normal tracking-normal mt-1"
|
|
||||||
noJustify
|
|
||||||
onClick={() => {
|
|
||||||
router.push(doc.url);
|
|
||||||
}}
|
|
||||||
key={doc.title}
|
|
||||||
variant={
|
|
||||||
"url" in doc
|
|
||||||
? pathname == doc.url
|
|
||||||
? "default"
|
|
||||||
: "ghost"
|
|
||||||
: "ghost"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{doc.title}
|
|
||||||
</Button>
|
|
||||||
<br key={doc.url} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,59 +28,51 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button } from "../ui/button";
|
import { Changelog } from "@/components/changelog";
|
||||||
import { Book, Calendar, Star, TerminalIcon } from "lucide-react";
|
import { changelog, version } from "@/config/version";
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { Changelog, version } from "@/config/version";
|
|
||||||
import events from "@/lib/commandEvent";
|
import events from "@/lib/commandEvent";
|
||||||
import { ScrollArea } from "../ui/scroll-area";
|
|
||||||
import { useRouter } from "@/lib/useRouter";
|
import { useRouter } from "@/lib/useRouter";
|
||||||
|
import { Book, Calendar, Star, TerminalIcon } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
|
||||||
|
import { ScrollArea } from "../ui/scroll-area";
|
||||||
|
|
||||||
export default function InfoPopover() {
|
export default function InfoPopover() {
|
||||||
const [changeLog, setChangelog] = useState(false);
|
const router = useRouter();
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid w-full">
|
<div className="grid w-full">
|
||||||
<strong className="text-center">The future of Minehut lists</strong>
|
<strong className="text-center">The future of Minehut lists</strong>
|
||||||
<small className="text-center mb-3">
|
<small className="text-center mb-3">
|
||||||
Use filters, intuitive keyboard shortcuts and other features for
|
Use filters, intuitive keyboard shortcuts and other features for
|
||||||
completely free, and *open-source. <br /> Currently on version{" "}
|
completely free, and *open-source. <br /> Currently on version{" "}
|
||||||
<code>{version}</code>.<br />{" "}
|
<code>{version}</code>.<br />{" "}
|
||||||
<small>* Licensed under the MIT License</small>
|
<small>* Licensed under the MIT License</small>
|
||||||
</small>
|
</small>
|
||||||
|
|
||||||
<Button variant={"ghost"} onClick={() => setChangelog(true)}>
|
<Changelog items={changelog}>
|
||||||
<Calendar size={18} className="mr-2" /> Changelog
|
<Button variant={"ghost"}>
|
||||||
</Button>
|
<Calendar size={18} className="mr-2" /> Changelog
|
||||||
<Dialog open={changeLog} onOpenChange={setChangelog}>
|
</Button>
|
||||||
<DialogContent>
|
</Changelog>
|
||||||
<ScrollArea className="max-h-[500px]">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Changelog</DialogTitle>
|
|
||||||
<Changelog />
|
|
||||||
</DialogHeader>
|
|
||||||
</ScrollArea>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant={"ghost"}
|
variant={"ghost"}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
window
|
window
|
||||||
.open("https://github.com/DeveloLongScript/MHSF", "_blank")
|
.open("https://github.com/DeveloLongScript/MHSF", "_blank")
|
||||||
?.focus()
|
?.focus()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Star size={18} className="mr-2" /> Star on GitHub
|
<Star size={18} className="mr-2" /> Star on GitHub
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant={"ghost"} onClick={() => router.push("/docs")}>
|
<Button variant={"ghost"} onClick={() => router.push("/docs")}>
|
||||||
<Book size={18} className="mr-2" /> See the docs
|
<Book size={18} className="mr-2" /> See the docs
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" onClick={() => events.emit("cmd-event")}>
|
<Button variant="ghost" onClick={() => events.emit("cmd-event")}>
|
||||||
<TerminalIcon size={18} className="mr-2" /> Open commands
|
<TerminalIcon size={18} className="mr-2" /> Open commands
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
111
src/components/misc/MiniJoinsChart.tsx
Normal file
111
src/components/misc/MiniJoinsChart.tsx
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* MHSF, Minehut Server List
|
||||||
|
* All external content is rather licensed under the ECA Agreement
|
||||||
|
* located here: https://list.mlnehut.com/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 {
|
||||||
|
type ChartConfig,
|
||||||
|
ChartContainer,
|
||||||
|
ChartTooltip,
|
||||||
|
ChartTooltipContent,
|
||||||
|
} from "@/components/ui/chart";
|
||||||
|
import { getShortTermData } from "@/lib/api";
|
||||||
|
import { useEffectOnce } from "@/lib/useEffectOnce";
|
||||||
|
import * as React from "react";
|
||||||
|
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
|
||||||
|
|
||||||
|
const chartConfig = {
|
||||||
|
player_count: {
|
||||||
|
label: "Joins",
|
||||||
|
color: "hsl(var(--chart-1))",
|
||||||
|
},
|
||||||
|
} satisfies ChartConfig;
|
||||||
|
|
||||||
|
export function MiniJoinsChart({ server }: { server: string }) {
|
||||||
|
const [chartData, setChartData] = React.useState<any>([]);
|
||||||
|
const [loading, setLoading] = React.useState(true);
|
||||||
|
|
||||||
|
useEffectOnce(() => {
|
||||||
|
getShortTermData(server, ["player_count", "date"]).then((result) => {
|
||||||
|
setChartData(result.slice(-20));
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="max-h-[160px] w-full">
|
||||||
|
<ChartContainer config={chartConfig}>
|
||||||
|
<LineChart accessibilityLayer data={chartData}>
|
||||||
|
<CartesianGrid vertical={false} />
|
||||||
|
<YAxis
|
||||||
|
dataKey={"player_count"}
|
||||||
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
tickFormatter={(value) => {
|
||||||
|
return value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<XAxis
|
||||||
|
dataKey="date"
|
||||||
|
className="hidden"
|
||||||
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
tickMargin={8}
|
||||||
|
minTickGap={32}
|
||||||
|
tickFormatter={(value) => {
|
||||||
|
return new Date(value).toLocaleTimeString("en-US", {
|
||||||
|
timeStyle: "short",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ChartTooltip
|
||||||
|
content={
|
||||||
|
<ChartTooltipContent
|
||||||
|
className="w-[150px]"
|
||||||
|
nameKey={"player_count"}
|
||||||
|
indicator="line"
|
||||||
|
labelFormatter={(value) => {
|
||||||
|
return new Date(value).toLocaleTimeString("en-US", {
|
||||||
|
timeStyle: "short",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
dataKey={"player_count"}
|
||||||
|
type="monotone"
|
||||||
|
stroke={"var(--color-player_count)"}
|
||||||
|
strokeWidth={2}
|
||||||
|
dot={false}
|
||||||
|
/>
|
||||||
|
</LineChart>
|
||||||
|
</ChartContainer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -28,203 +28,203 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||||
import { Check, ChevronRight, Circle } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const DropdownMenu = DropdownMenuPrimitive.Root
|
const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||||
|
|
||||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
||||||
|
|
||||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
||||||
|
|
||||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
||||||
|
|
||||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
||||||
|
|
||||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||||
|
|
||||||
const DropdownMenuSubTrigger = React.forwardRef<
|
const DropdownMenuSubTrigger = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}
|
}
|
||||||
>(({ className, inset, children, ...props }, ref) => (
|
>(({ className, inset, children, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.SubTrigger
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
||||||
inset && "pl-8",
|
inset && "pl-8",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronRight className="ml-auto h-4 w-4" />
|
<ChevronRight className="ml-auto h-4 w-4" />
|
||||||
</DropdownMenuPrimitive.SubTrigger>
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
))
|
));
|
||||||
DropdownMenuSubTrigger.displayName =
|
DropdownMenuSubTrigger.displayName =
|
||||||
DropdownMenuPrimitive.SubTrigger.displayName
|
DropdownMenuPrimitive.SubTrigger.displayName;
|
||||||
|
|
||||||
const DropdownMenuSubContent = React.forwardRef<
|
const DropdownMenuSubContent = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DropdownMenuSubContent.displayName =
|
DropdownMenuSubContent.displayName =
|
||||||
DropdownMenuPrimitive.SubContent.displayName
|
DropdownMenuPrimitive.SubContent.displayName;
|
||||||
|
|
||||||
const DropdownMenuContent = React.forwardRef<
|
const DropdownMenuContent = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
||||||
>(({ className, sideOffset = 4, ...props }, ref) => (
|
>(({ className, sideOffset = 4, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.Portal>
|
<DropdownMenuPrimitive.Portal>
|
||||||
<DropdownMenuPrimitive.Content
|
<DropdownMenuPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</DropdownMenuPrimitive.Portal>
|
</DropdownMenuPrimitive.Portal>
|
||||||
))
|
));
|
||||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
||||||
|
|
||||||
const DropdownMenuItem = React.forwardRef<
|
const DropdownMenuItem = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}
|
}
|
||||||
>(({ className, inset, ...props }, ref) => (
|
>(({ className, inset, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
inset && "pl-8",
|
inset && "pl-8",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
||||||
|
|
||||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
||||||
>(({ className, children, checked, ...props }, ref) => (
|
>(({ className, children, checked, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.CheckboxItem
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
<DropdownMenuPrimitive.ItemIndicator>
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
<Check className="h-4 w-4" />
|
<Check className="h-4 w-4" />
|
||||||
</DropdownMenuPrimitive.ItemIndicator>
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</DropdownMenuPrimitive.CheckboxItem>
|
</DropdownMenuPrimitive.CheckboxItem>
|
||||||
))
|
));
|
||||||
DropdownMenuCheckboxItem.displayName =
|
DropdownMenuCheckboxItem.displayName =
|
||||||
DropdownMenuPrimitive.CheckboxItem.displayName
|
DropdownMenuPrimitive.CheckboxItem.displayName;
|
||||||
|
|
||||||
const DropdownMenuRadioItem = React.forwardRef<
|
const DropdownMenuRadioItem = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
||||||
>(({ className, children, ...props }, ref) => (
|
>(({ className, children, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.RadioItem
|
<DropdownMenuPrimitive.RadioItem
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0 gap-3",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
<DropdownMenuPrimitive.ItemIndicator>
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
<Circle className="h-2 w-2 fill-current" />
|
<Circle className="h-2 w-2 fill-current" />
|
||||||
</DropdownMenuPrimitive.ItemIndicator>
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</DropdownMenuPrimitive.RadioItem>
|
</DropdownMenuPrimitive.RadioItem>
|
||||||
))
|
));
|
||||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
||||||
|
|
||||||
const DropdownMenuLabel = React.forwardRef<
|
const DropdownMenuLabel = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}
|
}
|
||||||
>(({ className, inset, ...props }, ref) => (
|
>(({ className, inset, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.Label
|
<DropdownMenuPrimitive.Label
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-2 py-1.5 text-sm font-semibold",
|
"px-2 py-1.5 text-sm font-semibold",
|
||||||
inset && "pl-8",
|
inset && "pl-8",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
||||||
|
|
||||||
const DropdownMenuSeparator = React.forwardRef<
|
const DropdownMenuSeparator = React.forwardRef<
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.Separator
|
<DropdownMenuPrimitive.Separator
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
||||||
|
|
||||||
const DropdownMenuShortcut = ({
|
const DropdownMenuShortcut = ({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuCheckboxItem,
|
DropdownMenuCheckboxItem,
|
||||||
DropdownMenuRadioItem,
|
DropdownMenuRadioItem,
|
||||||
DropdownMenuLabel,
|
DropdownMenuLabel,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuShortcut,
|
DropdownMenuShortcut,
|
||||||
DropdownMenuGroup,
|
DropdownMenuGroup,
|
||||||
DropdownMenuPortal,
|
DropdownMenuPortal,
|
||||||
DropdownMenuSub,
|
DropdownMenuSub,
|
||||||
DropdownMenuSubContent,
|
DropdownMenuSubContent,
|
||||||
DropdownMenuSubTrigger,
|
DropdownMenuSubTrigger,
|
||||||
DropdownMenuRadioGroup,
|
DropdownMenuRadioGroup,
|
||||||
}
|
};
|
||||||
|
|||||||
@ -28,60 +28,61 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const allFolders: (DocsFolder | Docs)[] = [
|
export const allFolders: DocsFolder[] = [
|
||||||
{
|
{
|
||||||
title: "Getting Started",
|
name: "General",
|
||||||
url: "/docs/getting-started",
|
docs: [
|
||||||
},
|
{
|
||||||
{
|
title: "Getting Started",
|
||||||
title: "Server List",
|
url: "/docs/getting-started",
|
||||||
url: "/",
|
},
|
||||||
},
|
{
|
||||||
{
|
title: "Reading",
|
||||||
title: "Reading",
|
url: "/docs/reading",
|
||||||
url: "/docs/reading",
|
},
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
name: "Guides",
|
{
|
||||||
docs: [
|
name: "Guides",
|
||||||
{
|
docs: [
|
||||||
title: "Linking",
|
{
|
||||||
url: "/docs/guides/linking",
|
title: "Linking",
|
||||||
},
|
url: "/docs/guides/linking",
|
||||||
{
|
},
|
||||||
title: "Owning a Server",
|
{
|
||||||
url: "/docs/guides/owning-a-server",
|
title: "Owning a Server",
|
||||||
},
|
url: "/docs/guides/owning-a-server",
|
||||||
{
|
},
|
||||||
title: "Server Customization",
|
{
|
||||||
url: "/docs/guides/customization",
|
title: "Server Customization",
|
||||||
},
|
url: "/docs/guides/customization",
|
||||||
{ title: "Reporting a server", url: "/docs/guides/reporting-server" },
|
},
|
||||||
],
|
{ title: "Reporting a server", url: "/docs/guides/reporting-server" },
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
name: "Advanced",
|
{
|
||||||
docs: [
|
name: "Advanced",
|
||||||
{ title: "Tech Stack", url: "/docs/advanced/tech-stack" },
|
docs: [
|
||||||
{ title: "Using the Command-bar", url: "/docs/advanced/command-bar" },
|
{ title: "Tech Stack", url: "/docs/advanced/tech-stack" },
|
||||||
{ title: "Tips with external servers", url: "/docs/advanced/external" },
|
{ title: "Using the Command-bar", url: "/docs/advanced/command-bar" },
|
||||||
{ title: "Achievements", url: "/docs/advanced/achievements" },
|
{ title: "Tips with external servers", url: "/docs/advanced/external" },
|
||||||
],
|
{ title: "Achievements", url: "/docs/advanced/achievements" },
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
name: "Legal",
|
{
|
||||||
docs: [
|
name: "Legal",
|
||||||
{ title: "ECA Agreement", url: "/docs/legal/external-content-agreement" },
|
docs: [
|
||||||
],
|
{ title: "ECA Agreement", url: "/docs/legal/external-content-agreement" },
|
||||||
},
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export type Docs = {
|
export type Docs = {
|
||||||
title: string;
|
title: string;
|
||||||
url: string;
|
url: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DocsFolder = {
|
export type DocsFolder = {
|
||||||
name: string;
|
name: string;
|
||||||
docs: Array<Docs>;
|
docs: Array<Docs>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -278,7 +278,7 @@ export const allCategories: Array<{
|
|||||||
];
|
];
|
||||||
|
|
||||||
async function requestServer(s: OnlineServer): Promise<ServerResponse> {
|
async function requestServer(s: OnlineServer): Promise<ServerResponse> {
|
||||||
if (serverCache[s.name] == undefined) {
|
if (serverCache[s.name] === undefined) {
|
||||||
const re = await fetch(
|
const re = await fetch(
|
||||||
"https://api.minehut.com/server/" + s.name + "?byName=true",
|
"https://api.minehut.com/server/" + s.name + "?byName=true",
|
||||||
);
|
);
|
||||||
|
|||||||
@ -29,407 +29,346 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
"use client";
|
"use client";
|
||||||
import Image from "next/image";
|
import A from "@/components/misc/Link";
|
||||||
import Link from "next/link";
|
import type { ReactNode } from "react";
|
||||||
import { Separator } from "../components/ui/separator";
|
|
||||||
import { Button } from "../components/ui/button";
|
|
||||||
import confetti from "canvas-confetti";
|
|
||||||
|
|
||||||
export const version = "1.3.2";
|
|
||||||
|
|
||||||
const User = ({ user }: { user: string }) => (
|
const User = ({ user }: { user: string }) => (
|
||||||
<span className="cursor-pointer bg-[rgba(255,165,0,0.25);] rounded p-[2.5px]">
|
<span className="cursor-pointer bg-[rgba(255,165,0,0.25);] rounded p-[2.5px]">
|
||||||
{user}
|
{user}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
const handleClick = () => {
|
|
||||||
const duration = 5 * 1000;
|
|
||||||
const animationEnd = Date.now() + duration;
|
|
||||||
const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
|
|
||||||
|
|
||||||
const randomInRange = (min: number, max: number) =>
|
const FeatureList = ({
|
||||||
Math.random() * (max - min) + min;
|
features,
|
||||||
|
title,
|
||||||
const interval = window.setInterval(() => {
|
}: { features: (string | ReactNode)[]; title: ReactNode }) => {
|
||||||
const timeLeft = animationEnd - Date.now();
|
return (
|
||||||
|
<ul>
|
||||||
if (timeLeft <= 0) {
|
{title}
|
||||||
return clearInterval(interval);
|
{features.map((feature, i) => (
|
||||||
}
|
<li key={i}>• {feature}</li>
|
||||||
|
))}
|
||||||
const particleCount = 50 * (timeLeft / duration);
|
</ul>
|
||||||
confetti({
|
);
|
||||||
...defaults,
|
|
||||||
particleCount,
|
|
||||||
zIndex: 60,
|
|
||||||
origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 },
|
|
||||||
});
|
|
||||||
confetti({
|
|
||||||
...defaults,
|
|
||||||
particleCount,
|
|
||||||
zIndex: 60,
|
|
||||||
origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 },
|
|
||||||
});
|
|
||||||
}, 250);
|
|
||||||
};
|
|
||||||
export const Changelog = () => {
|
|
||||||
const router = useRouter();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
Running on commit{" "}
|
|
||||||
<code>
|
|
||||||
<a
|
|
||||||
href={`https://github.com/DeveloLongScript/mhsf/commit/${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA}`}
|
|
||||||
>
|
|
||||||
{(
|
|
||||||
process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA || "unknown"
|
|
||||||
).substring(0, 7)}
|
|
||||||
</a>{" "}
|
|
||||||
{process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID != undefined &&
|
|
||||||
process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID != "" && (
|
|
||||||
<>
|
|
||||||
{" "}
|
|
||||||
| on PR{" "}
|
|
||||||
<a
|
|
||||||
href={`https://github.com/DeveloLongScript/MHSF/pull/${process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID}`}
|
|
||||||
>
|
|
||||||
{process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID}
|
|
||||||
</a>{" "}
|
|
||||||
by{" "}
|
|
||||||
<a
|
|
||||||
href={`https://github.com/${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME}`}
|
|
||||||
>
|
|
||||||
{process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME}
|
|
||||||
</a>
|
|
||||||
</>
|
|
||||||
)}{" "}
|
|
||||||
{process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE != undefined &&
|
|
||||||
`| ${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE.substring(0, 24)}`}
|
|
||||||
</code>
|
|
||||||
</div>
|
|
||||||
<div className="md:grid md:grid-cols-3 gap-1.5">
|
|
||||||
<Button
|
|
||||||
className="text-sm hover:h-[60px] animate-all group block max-md:w-full max-md:mt-2"
|
|
||||||
onClick={() =>
|
|
||||||
window.open("https://discord.com/invite/cCyEeUs", "_blank")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span className="group-hover:underline flex items-center">
|
|
||||||
<Discord className="mr-2"/> Discord
|
|
||||||
</span>
|
|
||||||
<Marquee
|
|
||||||
className="hidden group-hover:flex font-normal"
|
|
||||||
style={{"--duration": "15s"}}
|
|
||||||
>
|
|
||||||
Join the offical Minehut Discord server! Talk to people that like
|
|
||||||
MHSF too!
|
|
||||||
</Marquee>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
className="text-sm max-md:w-full max-md:mt-2 hover:h-[60px] animate-all group block "
|
|
||||||
onClick={() =>
|
|
||||||
window.open("https://github.com/DeveloLongScript/MHSF", "_blank")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span className="group-hover:underline flex items-center">
|
|
||||||
<Github className="mr-2" fill={useDepTheme()}/> Star on GitHub
|
|
||||||
</span>
|
|
||||||
<Marquee
|
|
||||||
className="hidden group-hover:flex font-normal"
|
|
||||||
style={{"--duration": "10s"}}
|
|
||||||
>
|
|
||||||
Support the development of MHSF by starring it on GitHub!
|
|
||||||
</Marquee>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
className="text-sm max-md:w-full max-md:mt-2 hover:h-[60px] animate-all group block "
|
|
||||||
onClick={() => window.open("/docs", "_blank")}
|
|
||||||
>
|
|
||||||
<span className="group-hover:underline flex items-center">
|
|
||||||
<BookIcon className="mr-2" size={16}/> See the docs
|
|
||||||
</span>
|
|
||||||
<Marquee
|
|
||||||
className="hidden group-hover:flex font-normal"
|
|
||||||
style={{"--duration": "10s"}}
|
|
||||||
>
|
|
||||||
See more information about MHSF and how to use it
|
|
||||||
</Marquee>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version 1.3.2 (October 4th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
• Minor backend changes
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
• <A alt="Please check on GitHub for statuses about this project.">Special:GitHub/releases/tag/1.3.2</A>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version 1.3.0 (September 9th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
• <A alt="New documentation linking">Docs:Reading</A>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
• Achievements are here! See more at{" "}
|
|
||||||
<A alt="here">Docs:Advanced/Achievements</A>
|
|
||||||
</li>
|
|
||||||
<li>• Finally fixed Cron actions for the final time™</li>
|
|
||||||
<li>• Overhauled account preferences</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version 1.2.0 (September 3rd 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Added documentation</li>
|
|
||||||
<li>• Brand new linking of padding and server options</li>
|
|
||||||
<li>• New system to ensure automatic Cron actions!</li>
|
|
||||||
<li>• and alot more!</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version 1.1.0 (August 24rd 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Brand new hero page</li>
|
|
||||||
<li>• New padding option on server list</li>
|
|
||||||
<li>• New help guide</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version 1.0.0 (August 22nd 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
• 1.0!{" "}
|
|
||||||
<Button className="h-[25px] w-[50px] ml-2" onClick={handleClick}>
|
|
||||||
woah!
|
|
||||||
</Button>
|
|
||||||
</li>
|
|
||||||
<li>• New hover card on server title hover</li>
|
|
||||||
<li>• Moving to self-hosted cron jobs</li>
|
|
||||||
<li>• Fixing some mobile issues</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<Separator/>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.10.7 (August 18th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• New server information tab on server pages</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.10.2 (August 18th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Content fades-in on load</li>
|
|
||||||
<li>• Instead of using spinners, now we are using Skeletons</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.10.0 (August 17th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Revamped server list button list</li>
|
|
||||||
<li>• Added welcome dialog when first launching</li>
|
|
||||||
<li>
|
|
||||||
• Fixed an issue where servers were still able to be favorited
|
|
||||||
client-side when logged out
|
|
||||||
</li>
|
|
||||||
<li>• Improved MOTD engine</li>
|
|
||||||
</ul>
|
|
||||||
<br/>
|
|
||||||
<i>👀</i>
|
|
||||||
{/** Ensure Tailwind pre-renders all grid column types */}
|
|
||||||
<span className="grid-cols-6"/>
|
|
||||||
<span className="grid-cols-5"/>
|
|
||||||
<span className="grid-cols-4"/>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.9.0 (August 15th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Adding favorites sorting option</li>
|
|
||||||
<li>• Fixed right-click context menu on the server list</li>
|
|
||||||
<li>• Fixed metadata bugs</li>
|
|
||||||
</ul>
|
|
||||||
<br/>
|
|
||||||
<i>
|
|
||||||
Hey! Update on statistics. Recently, we have figured out the Minehut
|
|
||||||
API is blocked to Vercel servers (atleast the <code>/servers</code>{" "}
|
|
||||||
endpoint). I'm actively trying to find a loop-hole so that statistics
|
|
||||||
works correctly. Thank you {":)"}
|
|
||||||
</i>
|
|
||||||
<br/>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.8.0 (August 11th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Fixing up command bar</li>
|
|
||||||
<li>• Renaming "Short Term" to "Statistics"</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.7.2 (August 7th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Adding new spinners to pages that needed it</li>
|
|
||||||
<li>• Fixed lots of bugs</li>
|
|
||||||
<li>• Moved from Inngest to Vercel Cron</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.7.0 (August 7th 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Added customization to servers</li>
|
|
||||||
<li>• New button focus effect</li>
|
|
||||||
<li>• Lots of bugfixes</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.6.0 (August 3rd 2024)
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Enhanced shortcuts</li>
|
|
||||||
<li>• Added gradient beam to player count</li>
|
|
||||||
<li>• Updated loading animations</li>
|
|
||||||
<li>• Lots of bugfixes</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.4.5 (July 26th 2024):
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Made charts better</li>
|
|
||||||
<li>• Sorted API endpoints</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.4 (July 25th 2024):
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Added Info button</li>
|
|
||||||
<li>• Fixed Clerk in production</li>
|
|
||||||
<li>• Added Turbo for faster builds</li>
|
|
||||||
<li>
|
|
||||||
• <strong>Added historical data</strong>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.3 (July 23th 2024):
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
• Fixed minor bugs described by <User user="@Tarna"/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong className="flex items-center">
|
|
||||||
Version b-0.2 (July 23th 2024):
|
|
||||||
</strong>
|
|
||||||
<ul>
|
|
||||||
<li>• Inital release!</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<strong>All developers that helped out:</strong>
|
|
||||||
<Link href="https://dvelo.vercel.app">
|
|
||||||
<Image
|
|
||||||
src="/imgs/badge1.gif"
|
|
||||||
alt="cool badge"
|
|
||||||
width={88}
|
|
||||||
height={31}
|
|
||||||
className="w-[88px] h-[31px]"
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const version = "1.4.0";
|
||||||
const Github = (props: SVGProps<SVGSVGElement>) => (
|
export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
|
||||||
<svg
|
{
|
||||||
viewBox="0 0 256 250"
|
id: "amq4suhgcfwrb7y5j6",
|
||||||
width="1em"
|
name: "v1.4.0",
|
||||||
height="1em"
|
changelog: (
|
||||||
fill="#24292f"
|
<FeatureList
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
features={[
|
||||||
preserveAspectRatio="xMidYMid"
|
"Revamped documentation",
|
||||||
{...props}
|
"Revamped changelog UI",
|
||||||
>
|
"New hover joins chart",
|
||||||
<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" />
|
title={
|
||||||
</svg>
|
<strong className="flex items-center">
|
||||||
);
|
Version 1.4.0 (November 3rd 2024)
|
||||||
|
</strong>
|
||||||
import type { SVGProps } from "react";
|
}
|
||||||
import Marquee from "@/components/effects/marquee";
|
/>
|
||||||
import { useRouter } from "@/lib/useRouter";
|
),
|
||||||
import { BookIcon } from "lucide-react";
|
},
|
||||||
import A from "@/components/misc/Link";
|
{
|
||||||
import { useDepTheme } from "@/lib/getDependentTheming";
|
id: "jeh48p7w9bx2k3ad6f",
|
||||||
const Discord = (props: SVGProps<SVGSVGElement>) => (
|
name: "v1.3.2",
|
||||||
<svg
|
changelog: (
|
||||||
viewBox="0 0 256 199"
|
<div>
|
||||||
width="1em"
|
<strong className="flex items-center">
|
||||||
height="1em"
|
Version 1.3.2 (October 4th 2024)
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
</strong>
|
||||||
preserveAspectRatio="xMidYMid"
|
<ul>
|
||||||
{...props}
|
<li>• Minor backend changes</li>
|
||||||
>
|
<li>
|
||||||
<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"
|
<A alt="Please check on GitHub for statuses about this project.">
|
||||||
fill="#5865F2"
|
Special:GitHub/releases/tag/1.3.2
|
||||||
/>
|
</A>
|
||||||
</svg>
|
</li>
|
||||||
);
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "wvg9x5dbpj76sn4yrz",
|
||||||
|
name: "v1.3.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version 1.3.0 (September 9th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
• <A alt="New documentation linking">Docs:Reading</A>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
• Achievements are here! See more at{" "}
|
||||||
|
<A alt="here">Docs:Advanced/Achievements</A>
|
||||||
|
</li>
|
||||||
|
<li>• Finally fixed Cron actions for the final time™</li>
|
||||||
|
<li>• Overhauled account preferences</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v1.2.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version 1.2.0 (September 3rd 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Added documentation</li>
|
||||||
|
<li>• Brand new linking of padding and server options</li>
|
||||||
|
<li>• New system to ensure automatic Cron actions!</li>
|
||||||
|
<li>• and alot more!</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "e482y9k5hvjt73urfx",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v1.1.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version 1.1.0 (August 24rd 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Brand new hero page</li>
|
||||||
|
<li>• New padding option on server list</li>
|
||||||
|
<li>• New help guide</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "hfn9p243765x8bwurj",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v1.0.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version 1.0.0 (August 22nd 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• 1.0!</li>
|
||||||
|
<li>• New hover card on server title hover</li>
|
||||||
|
<li>• Moving to self-hosted cron jobs</li>
|
||||||
|
<li>• Fixing some mobile issues</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "a8w4xvjbg3s7ynehu6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.10.7",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.10.7 (August 18th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• New server information tab on server pages</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "asbt64h9fdyu8neqmp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.10.2",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.10.2 (August 18th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Content fades-in on load</li>
|
||||||
|
<li>• Instead of using spinners, now we are using Skeletons</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "kct29adbp6zug5r3q8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.10.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.10.0 (August 17th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Revamped server list button list</li>
|
||||||
|
<li>• Added welcome dialog when first launching</li>
|
||||||
|
<li>
|
||||||
|
• Fixed an issue where servers were still able to be favorited
|
||||||
|
client-side when logged out
|
||||||
|
</li>
|
||||||
|
<li>• Improved MOTD engine</li>
|
||||||
|
</ul>
|
||||||
|
<br />
|
||||||
|
<i>👀</i>
|
||||||
|
{/** Ensure Tailwind pre-renders all grid column types */}
|
||||||
|
<span className="grid-cols-6" />
|
||||||
|
<span className="grid-cols-5" />
|
||||||
|
<span className="grid-cols-4" />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "ah6t7c8sfzyrkp3u52",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.9.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.9.0 (August 15th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Adding favorites sorting option</li>
|
||||||
|
<li>• Fixed right-click context menu on the server list</li>
|
||||||
|
<li>• Fixed metadata bugs</li>
|
||||||
|
</ul>
|
||||||
|
<br />
|
||||||
|
<i>
|
||||||
|
Hey! Update on statistics. Recently, we have figured out the Minehut
|
||||||
|
API is blocked to Vercel servers (atleast the <code>/servers</code>{" "}
|
||||||
|
endpoint). I'm actively trying to find a loop-hole so that statistics
|
||||||
|
works correctly. Thank you {":)"}
|
||||||
|
</i>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "kjxnrfazc7hp9q4e82",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.8.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.8.0 (August 11th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Fixing up command bar</li>
|
||||||
|
<li>• Renaming "Short Term" to "Statistics"</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "f8rmhwzuxk3qyds542",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.7.2",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.7.2 (August 7th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Adding new spinners to pages that needed it</li>
|
||||||
|
<li>• Fixed lots of bugs</li>
|
||||||
|
<li>• Moved from Inngest to Vercel Cron</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "g2rhxfj6bu8wqk43n7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.7.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.7.0 (August 7th 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Added customization to servers</li>
|
||||||
|
<li>• New button focus effect</li>
|
||||||
|
<li>• Lots of bugfixes</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "a5xb97jv3surwmqn62",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.6.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.6.0 (August 3rd 2024)
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Enhanced shortcuts</li>
|
||||||
|
<li>• Added gradient beam to player count</li>
|
||||||
|
<li>• Updated loading animations</li>
|
||||||
|
<li>• Lots of bugfixes</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "u83r5mkea9x4p2fjnb",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.4.5",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.4.5 (July 26th 2024):
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Made charts better</li>
|
||||||
|
<li>• Sorted API endpoints</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "vu3k2daqj4y68bnwsp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.4.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.4 (July 25th 2024):
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Added Info button</li>
|
||||||
|
<li>• Fixed Clerk in production</li>
|
||||||
|
<li>• Added Turbo for faster builds</li>
|
||||||
|
<li>
|
||||||
|
• <strong>Added historical data</strong>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "psr9tx5jah74d32vq6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.3.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.3 (July 23th 2024):
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
• Fixed minor bugs described by <User user="@Tarna" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "m2ngpd6fwtv7xh5zrk",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "v0.2.0",
|
||||||
|
changelog: (
|
||||||
|
<div>
|
||||||
|
<strong className="flex items-center">
|
||||||
|
Version b-0.2 (July 23th 2024):
|
||||||
|
</strong>
|
||||||
|
<ul>
|
||||||
|
<li>• Inital release!</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
id: "xsfw2rcnv7m3kuhpbq",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
@ -30,19 +30,28 @@
|
|||||||
|
|
||||||
import { LinearClient, LinearFetch, User } from "@linear/sdk";
|
import { LinearClient, LinearFetch, User } from "@linear/sdk";
|
||||||
|
|
||||||
export async function createReportIssue(server: string, reportDescription: string, userId: string) {
|
export async function createReportIssue(
|
||||||
const linearClient = new LinearClient({
|
server: string,
|
||||||
apiKey: process.env.LINEAR
|
reportDescription: string,
|
||||||
})
|
userId: string,
|
||||||
|
) {
|
||||||
|
const linearClient = new LinearClient({
|
||||||
|
apiKey: process.env.LINEAR,
|
||||||
|
});
|
||||||
|
|
||||||
const allTeams = await linearClient.teams();
|
const allTeams = await linearClient.teams();
|
||||||
// Always grabs the first issue category.
|
// Always grabs the first issue category.
|
||||||
const team = allTeams.nodes[0];
|
const team = allTeams.nodes[0];
|
||||||
|
|
||||||
// Ensure there *actually* is a team there
|
// Ensure there *actually* is a team there
|
||||||
if (team.id) {
|
if (team.id) {
|
||||||
await linearClient.createIssue({teamId: team.id, title: `Issue against server \`${server}\``, description: desc(userId, server, reportDescription), assigneeId: (await team.members()).nodes[0].id })
|
await linearClient.createIssue({
|
||||||
}
|
teamId: team.id,
|
||||||
|
title: `Issue against server \`${server}\``,
|
||||||
|
description: desc(userId, server, reportDescription),
|
||||||
|
assigneeId: (await team.members()).nodes[0].id,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const desc = (user: string, server: string, reason: string) => `There was a report against the server, submitted by a user.
|
const desc = (user: string, server: string, reason: string) => `There was a report against the server, submitted by a user.
|
||||||
@ -56,4 +65,4 @@ ${reason}
|
|||||||
|
|
||||||
|
|
||||||
*This was an automatically added issue by the report bot. Add the canceled status to remove the issue from the active issues, along with the labels Not Controllable & Spam for their respective values.*
|
*This was an automatically added issue by the report bot. Add the canceled status to remove the issue from the active issues, along with the labels Not Controllable & Spam for their respective values.*
|
||||||
`
|
`;
|
||||||
|
|||||||
58
src/lib/types/server-icon.ts
Normal file
58
src/lib/types/server-icon.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* MHSF, Minehut Server List
|
||||||
|
* All external content is rather licensed under the ECA Agreement
|
||||||
|
* located here: https://list.mlnehut.com/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 async function getMinehutIcons(): Promise<MinehutIcon[] | undefined> {
|
||||||
|
const icons = await fetch("https://api.minehut.com/servers/icons");
|
||||||
|
console.log(icons);
|
||||||
|
if (!icons.ok) return undefined;
|
||||||
|
return await icons.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MinehutIcon = {
|
||||||
|
_id: string;
|
||||||
|
display_name: string;
|
||||||
|
icon_name: string;
|
||||||
|
price: number;
|
||||||
|
rank: string;
|
||||||
|
available: boolean;
|
||||||
|
disabled: boolean;
|
||||||
|
created: number;
|
||||||
|
last_updated: number;
|
||||||
|
__v: number;
|
||||||
|
salePrice: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rarityIndex = {
|
||||||
|
common: { bg: "#40464d", text: "#b7bfc5" },
|
||||||
|
uncommon: { bg: "#184f02", text: "#61bf01" },
|
||||||
|
rare: { bg: "#15448a", text: "#41afff" },
|
||||||
|
epic: { bg: "#4c1a7b", text: "#ce59ff" },
|
||||||
|
legendary: { bg: "#de6e0d", text: "#fce8cf" },
|
||||||
|
};
|
||||||
@ -31,138 +31,177 @@
|
|||||||
import type { Config } from "tailwindcss";
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
content: [
|
content: [
|
||||||
"./pages/**/*.{ts,tsx}",
|
"./pages/**/*.{ts,tsx}",
|
||||||
"./components/**/*.{ts,tsx}",
|
"./components/**/*.{ts,tsx}",
|
||||||
"./app/**/*.{ts,tsx}",
|
"./app/**/*.{ts,tsx}",
|
||||||
"./src/**/*.{ts,tsx,json}",
|
"./src/**/*.{ts,tsx,json}",
|
||||||
],
|
],
|
||||||
prefix: "",
|
prefix: "",
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: 'true',
|
||||||
padding: "2rem",
|
padding: '2rem',
|
||||||
screens: {
|
screens: {
|
||||||
"2xl": "1400px",
|
'2xl': '1400px'
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
border: 'hsl(var(--border))',
|
||||||
|
input: 'hsl(var(--input))',
|
||||||
|
ring: 'hsl(var(--ring))',
|
||||||
|
background: 'hsl(var(--background))',
|
||||||
|
foreground: 'hsl(var(--foreground))',
|
||||||
|
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))'
|
||||||
|
},
|
||||||
|
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))',
|
||||||
|
mhsf: 'hsl(var(--sidebar-mhsf))'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: 'var(--radius)',
|
||||||
|
md: 'calc(var(--radius) - 2px)',
|
||||||
|
sm: 'calc(var(--radius) - 4px)'
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
'image-glow': {
|
||||||
|
'0%': {
|
||||||
|
opacity: '0',
|
||||||
|
'animation-timing-function': 'cubic-bezier(0.74, 0.25, 0.76, 1)'
|
||||||
|
},
|
||||||
|
'10%': {
|
||||||
|
opacity: '0.7',
|
||||||
|
'animation-timing-function': 'cubic-bezier(0.12, 0.01, 0.08, 0.99)'
|
||||||
|
},
|
||||||
|
'100%': {
|
||||||
|
opacity: '0.4'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'border-beam': {
|
||||||
|
'100%': {
|
||||||
|
'offset-distance': '100%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'caret-blink': {
|
||||||
|
'0%,70%,100%': {
|
||||||
|
opacity: '1'
|
||||||
|
},
|
||||||
|
'20%,50%': {
|
||||||
|
opacity: '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'accordion-down': {
|
||||||
|
from: {
|
||||||
|
height: '0'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
height: 'var(--radix-accordion-content-height)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'accordion-up': {
|
||||||
|
from: {
|
||||||
|
height: 'var(--radix-accordion-content-height)'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
height: '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'fade-in': {
|
||||||
|
from: {
|
||||||
|
opacity: '0',
|
||||||
|
transform: 'translateY(-10px)'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
opacity: '1',
|
||||||
|
transform: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
marquee: {
|
||||||
|
from: {
|
||||||
|
transform: 'translateX(0)'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
transform: 'translateX(calc(-100% - var(--gap)))'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'marquee-vertical': {
|
||||||
|
from: {
|
||||||
|
transform: 'translateY(0)'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
transform: 'translateY(calc(-100% - var(--gap)))'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'fade-up': {
|
||||||
|
from: {
|
||||||
|
opacity: '0',
|
||||||
|
transform: 'translateY(20px)'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
opacity: '1',
|
||||||
|
transform: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shimmer: {
|
||||||
|
'0%, 90%, 100%': {
|
||||||
|
'background-position': 'calc(-100% - var(--shimmer-width)) 0'
|
||||||
|
},
|
||||||
|
'30%, 60%': {
|
||||||
|
'background-position': 'calc(100% + var(--shimmer-width)) 0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
marquee: 'marquee var(--duration) linear infinite',
|
||||||
|
'marquee-vertical': 'marquee-vertical var(--duration) linear infinite',
|
||||||
|
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||||
|
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||||
|
'image-glow': 'image-glow 4100ms 600ms ease-out forwards',
|
||||||
|
shimmer: 'shimmer 8s infinite',
|
||||||
|
'fade-in': 'fade-in 1000ms var(--animation-delay, 0ms) ease forwards',
|
||||||
|
'caret-blink': 'caret-blink 1.25s ease-out infinite',
|
||||||
|
'border-beam': 'border-beam calc(var(--duration)*1s) infinite linear',
|
||||||
|
'fade-up': 'fade-up 1000ms var(--animation-delay, 0ms) ease forwards'
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
extend: {
|
plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
|
||||||
colors: {
|
|
||||||
border: "hsl(var(--border))",
|
|
||||||
input: "hsl(var(--input))",
|
|
||||||
ring: "hsl(var(--ring))",
|
|
||||||
background: "hsl(var(--background))",
|
|
||||||
foreground: "hsl(var(--foreground))",
|
|
||||||
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))",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
borderRadius: {
|
|
||||||
lg: "var(--radius)",
|
|
||||||
md: "calc(var(--radius) - 2px)",
|
|
||||||
sm: "calc(var(--radius) - 4px)",
|
|
||||||
},
|
|
||||||
keyframes: {
|
|
||||||
'image-glow': {
|
|
||||||
'0%': {
|
|
||||||
'opacity': '0',
|
|
||||||
'animation-timing-function': 'cubic-bezier(0.74, 0.25, 0.76, 1)',
|
|
||||||
},
|
|
||||||
'10%': {
|
|
||||||
'opacity': '0.7',
|
|
||||||
'animation-timing-function': 'cubic-bezier(0.12, 0.01, 0.08, 0.99)',
|
|
||||||
},
|
|
||||||
'100%': {
|
|
||||||
opacity: '0.4',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"border-beam": {
|
|
||||||
"100%": {
|
|
||||||
"offset-distance": "100%",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"caret-blink": {
|
|
||||||
"0%,70%,100%": { opacity: "1" },
|
|
||||||
"20%,50%": { opacity: "0" },
|
|
||||||
},
|
|
||||||
|
|
||||||
"accordion-down": {
|
|
||||||
from: { height: "0" },
|
|
||||||
to: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
},
|
|
||||||
"accordion-up": {
|
|
||||||
from: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
to: { height: "0" },
|
|
||||||
},
|
|
||||||
|
|
||||||
"fade-in": {
|
|
||||||
from: { opacity: "0", transform: "translateY(-10px)" },
|
|
||||||
to: { opacity: "1", transform: "none" },
|
|
||||||
},
|
|
||||||
marquee: {
|
|
||||||
from: { transform: "translateX(0)" },
|
|
||||||
to: { transform: "translateX(calc(-100% - var(--gap)))" },
|
|
||||||
},
|
|
||||||
"marquee-vertical": {
|
|
||||||
from: { transform: "translateY(0)" },
|
|
||||||
to: { transform: "translateY(calc(-100% - var(--gap)))" },
|
|
||||||
},
|
|
||||||
"fade-up": {
|
|
||||||
from: { opacity: "0", transform: "translateY(20px)" },
|
|
||||||
to: { opacity: "1", transform: "none" },
|
|
||||||
},
|
|
||||||
|
|
||||||
'shimmer': {
|
|
||||||
'0%, 90%, 100%': {
|
|
||||||
'background-position': 'calc(-100% - var(--shimmer-width)) 0',
|
|
||||||
},
|
|
||||||
'30%, 60%': {
|
|
||||||
'background-position': 'calc(100% + var(--shimmer-width)) 0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
marquee: "marquee var(--duration) linear infinite",
|
|
||||||
"marquee-vertical": "marquee-vertical var(--duration) linear infinite",
|
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
|
||||||
'image-glow': 'image-glow 4100ms 600ms ease-out forwards',
|
|
||||||
'shimmer': 'shimmer 8s infinite',
|
|
||||||
"fade-in": "fade-in 1000ms var(--animation-delay, 0ms) ease forwards",
|
|
||||||
"caret-blink": "caret-blink 1.25s ease-out infinite",
|
|
||||||
"border-beam": "border-beam calc(var(--duration)*1s) infinite linear",
|
|
||||||
|
|
||||||
"fade-up": "fade-up 1000ms var(--animation-delay, 0ms) ease forwards",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
|
|
||||||
} satisfies Config;
|
} satisfies Config;
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
193
yarn.lock
193
yarn.lock
@ -1157,6 +1157,16 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@radix-ui/react-primitive" "2.0.0"
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-avatar@^1.1.1":
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.1.1.tgz#5848d2ed5f34d18b36fc7e2d227c41fca8600ea1"
|
||||||
|
integrity sha512-eoOtThOmxeoizxpX6RiEsQZ2wj5r4+zoeqAwO0cBaFQGjJwIH3dIX0OCxNrCyrrdxG+vBweMETh3VziQG7c1kw==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/react-context" "1.1.1"
|
||||||
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||||
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-checkbox@^1.1.1":
|
"@radix-ui/react-checkbox@^1.1.1":
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz#a559c4303957d797acee99914480b755aa1f27d6"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz#a559c4303957d797acee99914480b755aa1f27d6"
|
||||||
@ -1171,6 +1181,20 @@
|
|||||||
"@radix-ui/react-use-previous" "1.1.0"
|
"@radix-ui/react-use-previous" "1.1.0"
|
||||||
"@radix-ui/react-use-size" "1.1.0"
|
"@radix-ui/react-use-size" "1.1.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-collapsible@^1.1.1":
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.1.tgz#1382cc9ec48f8b473c14f3779d317f0cdf6da5e9"
|
||||||
|
integrity sha512-1///SnrfQHJEofLokyczERxQbWfCGQlQ2XsCZMucVs6it+lq9iw4vXy+uDn1edlb58cOZOWSldnfPAYcT4O/Yg==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/primitive" "1.1.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
|
"@radix-ui/react-context" "1.1.1"
|
||||||
|
"@radix-ui/react-id" "1.1.0"
|
||||||
|
"@radix-ui/react-presence" "1.1.1"
|
||||||
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||||
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-collection@1.0.3":
|
"@radix-ui/react-collection@1.0.3":
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz"
|
||||||
@ -1229,6 +1253,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8"
|
||||||
integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==
|
integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==
|
||||||
|
|
||||||
|
"@radix-ui/react-context@1.1.1":
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a"
|
||||||
|
integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
|
||||||
|
|
||||||
"@radix-ui/react-dialog@1.0.5":
|
"@radix-ui/react-dialog@1.0.5":
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300"
|
||||||
@ -1250,7 +1279,7 @@
|
|||||||
aria-hidden "^1.1.1"
|
aria-hidden "^1.1.1"
|
||||||
react-remove-scroll "2.5.5"
|
react-remove-scroll "2.5.5"
|
||||||
|
|
||||||
"@radix-ui/react-dialog@^1.0.4", "@radix-ui/react-dialog@^1.1.1":
|
"@radix-ui/react-dialog@^1.0.4":
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz#4906507f7b4ad31e22d7dad69d9330c87c431d44"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz#4906507f7b4ad31e22d7dad69d9330c87c431d44"
|
||||||
integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
|
integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
|
||||||
@ -1270,6 +1299,26 @@
|
|||||||
aria-hidden "^1.1.1"
|
aria-hidden "^1.1.1"
|
||||||
react-remove-scroll "2.5.7"
|
react-remove-scroll "2.5.7"
|
||||||
|
|
||||||
|
"@radix-ui/react-dialog@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz#d9345575211d6f2d13e209e84aec9a8584b54d6c"
|
||||||
|
integrity sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/primitive" "1.1.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
|
"@radix-ui/react-context" "1.1.1"
|
||||||
|
"@radix-ui/react-dismissable-layer" "1.1.1"
|
||||||
|
"@radix-ui/react-focus-guards" "1.1.1"
|
||||||
|
"@radix-ui/react-focus-scope" "1.1.0"
|
||||||
|
"@radix-ui/react-id" "1.1.0"
|
||||||
|
"@radix-ui/react-portal" "1.1.2"
|
||||||
|
"@radix-ui/react-presence" "1.1.1"
|
||||||
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
"@radix-ui/react-slot" "1.1.0"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||||
|
aria-hidden "^1.1.1"
|
||||||
|
react-remove-scroll "2.6.0"
|
||||||
|
|
||||||
"@radix-ui/react-direction@1.0.1":
|
"@radix-ui/react-direction@1.0.1":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz"
|
||||||
@ -1305,16 +1354,27 @@
|
|||||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||||
"@radix-ui/react-use-escape-keydown" "1.1.0"
|
"@radix-ui/react-use-escape-keydown" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-dropdown-menu@^2.1.1":
|
"@radix-ui/react-dismissable-layer@1.1.1":
|
||||||
version "2.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz#3dc578488688250dbbe109d9ff2ca28a9bca27ec"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz#cbdcb739c5403382bdde5f9243042ba643883396"
|
||||||
integrity sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==
|
integrity sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@radix-ui/primitive" "1.1.0"
|
"@radix-ui/primitive" "1.1.0"
|
||||||
"@radix-ui/react-compose-refs" "1.1.0"
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
"@radix-ui/react-context" "1.1.0"
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||||
|
"@radix-ui/react-use-escape-keydown" "1.1.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-dropdown-menu@^2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz#acc49577130e3c875ef0133bd1e271ea3392d924"
|
||||||
|
integrity sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/primitive" "1.1.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
|
"@radix-ui/react-context" "1.1.1"
|
||||||
"@radix-ui/react-id" "1.1.0"
|
"@radix-ui/react-id" "1.1.0"
|
||||||
"@radix-ui/react-menu" "2.1.1"
|
"@radix-ui/react-menu" "2.1.2"
|
||||||
"@radix-ui/react-primitive" "2.0.0"
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||||
|
|
||||||
@ -1330,6 +1390,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13"
|
||||||
integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==
|
integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==
|
||||||
|
|
||||||
|
"@radix-ui/react-focus-guards@1.1.1":
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe"
|
||||||
|
integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==
|
||||||
|
|
||||||
"@radix-ui/react-focus-scope@1.0.4":
|
"@radix-ui/react-focus-scope@1.0.4":
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz"
|
resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz"
|
||||||
@ -1440,6 +1505,30 @@
|
|||||||
aria-hidden "^1.1.1"
|
aria-hidden "^1.1.1"
|
||||||
react-remove-scroll "2.5.7"
|
react-remove-scroll "2.5.7"
|
||||||
|
|
||||||
|
"@radix-ui/react-menu@2.1.2":
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.2.tgz#91f6815845a4298dde775563ed2d80b7ad667899"
|
||||||
|
integrity sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/primitive" "1.1.0"
|
||||||
|
"@radix-ui/react-collection" "1.1.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
|
"@radix-ui/react-context" "1.1.1"
|
||||||
|
"@radix-ui/react-direction" "1.1.0"
|
||||||
|
"@radix-ui/react-dismissable-layer" "1.1.1"
|
||||||
|
"@radix-ui/react-focus-guards" "1.1.1"
|
||||||
|
"@radix-ui/react-focus-scope" "1.1.0"
|
||||||
|
"@radix-ui/react-id" "1.1.0"
|
||||||
|
"@radix-ui/react-popper" "1.2.0"
|
||||||
|
"@radix-ui/react-portal" "1.1.2"
|
||||||
|
"@radix-ui/react-presence" "1.1.1"
|
||||||
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
"@radix-ui/react-roving-focus" "1.1.0"
|
||||||
|
"@radix-ui/react-slot" "1.1.0"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||||
|
aria-hidden "^1.1.1"
|
||||||
|
react-remove-scroll "2.6.0"
|
||||||
|
|
||||||
"@radix-ui/react-menubar@^1.1.1":
|
"@radix-ui/react-menubar@^1.1.1":
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-menubar/-/react-menubar-1.1.1.tgz#e126514cb1c46e0a4f9fba7d016e578cc4e41f22"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-menubar/-/react-menubar-1.1.1.tgz#e126514cb1c46e0a4f9fba7d016e578cc4e41f22"
|
||||||
@ -1548,6 +1637,14 @@
|
|||||||
"@radix-ui/react-primitive" "2.0.0"
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-portal@1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.2.tgz#51eb46dae7505074b306ebcb985bf65cc547d74e"
|
||||||
|
integrity sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-presence@1.0.1":
|
"@radix-ui/react-presence@1.0.1":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz"
|
||||||
@ -1565,6 +1662,14 @@
|
|||||||
"@radix-ui/react-compose-refs" "1.1.0"
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-presence@1.1.1":
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.1.tgz#98aba423dba5e0c687a782c0669dcd99de17f9b1"
|
||||||
|
integrity sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-primitive@1.0.3":
|
"@radix-ui/react-primitive@1.0.3":
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz"
|
||||||
@ -1642,13 +1747,12 @@
|
|||||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-separator@^1.0.3":
|
"@radix-ui/react-separator@^1.1.0":
|
||||||
version "1.0.3"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.0.tgz#ee0f4d86003b0e3ea7bc6ccab01ea0adee32663e"
|
||||||
integrity sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==
|
integrity sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.13.10"
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
"@radix-ui/react-primitive" "1.0.3"
|
|
||||||
|
|
||||||
"@radix-ui/react-slot@1.0.2":
|
"@radix-ui/react-slot@1.0.2":
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@ -1692,24 +1796,23 @@
|
|||||||
"@radix-ui/react-roving-focus" "1.1.0"
|
"@radix-ui/react-roving-focus" "1.1.0"
|
||||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||||
|
|
||||||
"@radix-ui/react-tooltip@^1.0.7":
|
"@radix-ui/react-tooltip@^1.1.3":
|
||||||
version "1.0.7"
|
version "1.1.3"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.3.tgz#4250b14723f2d8477e7a3d0526c169f91d1f2f74"
|
||||||
integrity sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==
|
integrity sha512-Z4w1FIS0BqVFI2c1jZvb/uDVJijJjJ2ZMuPV81oVgTZ7g3BZxobplnMVvXtFWgtozdvYJ+MFWtwkM5S2HnAong==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.13.10"
|
"@radix-ui/primitive" "1.1.0"
|
||||||
"@radix-ui/primitive" "1.0.1"
|
"@radix-ui/react-compose-refs" "1.1.0"
|
||||||
"@radix-ui/react-compose-refs" "1.0.1"
|
"@radix-ui/react-context" "1.1.1"
|
||||||
"@radix-ui/react-context" "1.0.1"
|
"@radix-ui/react-dismissable-layer" "1.1.1"
|
||||||
"@radix-ui/react-dismissable-layer" "1.0.5"
|
"@radix-ui/react-id" "1.1.0"
|
||||||
"@radix-ui/react-id" "1.0.1"
|
"@radix-ui/react-popper" "1.2.0"
|
||||||
"@radix-ui/react-popper" "1.1.3"
|
"@radix-ui/react-portal" "1.1.2"
|
||||||
"@radix-ui/react-portal" "1.0.4"
|
"@radix-ui/react-presence" "1.1.1"
|
||||||
"@radix-ui/react-presence" "1.0.1"
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
"@radix-ui/react-primitive" "1.0.3"
|
"@radix-ui/react-slot" "1.1.0"
|
||||||
"@radix-ui/react-slot" "1.0.2"
|
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||||
"@radix-ui/react-use-controllable-state" "1.0.1"
|
"@radix-ui/react-visually-hidden" "1.1.0"
|
||||||
"@radix-ui/react-visually-hidden" "1.0.3"
|
|
||||||
|
|
||||||
"@radix-ui/react-use-callback-ref@1.0.1":
|
"@radix-ui/react-use-callback-ref@1.0.1":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
@ -1815,6 +1918,13 @@
|
|||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-primitive" "1.0.3"
|
"@radix-ui/react-primitive" "1.0.3"
|
||||||
|
|
||||||
|
"@radix-ui/react-visually-hidden@1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2"
|
||||||
|
integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/react-primitive" "2.0.0"
|
||||||
|
|
||||||
"@radix-ui/rect@1.0.1":
|
"@radix-ui/rect@1.0.1":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz"
|
||||||
@ -2809,7 +2919,7 @@ citty@^0.1.6:
|
|||||||
|
|
||||||
class-variance-authority@^0.7.0:
|
class-variance-authority@^0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz"
|
resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522"
|
||||||
integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==
|
integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==
|
||||||
dependencies:
|
dependencies:
|
||||||
clsx "2.0.0"
|
clsx "2.0.0"
|
||||||
@ -5010,10 +5120,10 @@ lru-cache@^10.2.0:
|
|||||||
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz"
|
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz"
|
||||||
integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
|
integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
|
||||||
|
|
||||||
lucide-react@^0.416.0:
|
lucide-react@^0.454.0:
|
||||||
version "0.416.0"
|
version "0.454.0"
|
||||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.416.0.tgz#657da248f9b862703d7d80aafb912e79ad886313"
|
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.454.0.tgz#a81b9c482018720f07ead0503ae502d94d528444"
|
||||||
integrity sha512-wPWxTzdss1CTz2aqcNWNlbh4YSnH9neJWP3RaeXepxpLCTW+pmu7WcT/wxJe+Q7Y7DqGOxAqakJv0pIK3431Ag==
|
integrity sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==
|
||||||
|
|
||||||
luxon@~3.4.0:
|
luxon@~3.4.0:
|
||||||
version "3.4.4"
|
version "3.4.4"
|
||||||
@ -6708,7 +6818,7 @@ react-markdown@^9.0.1:
|
|||||||
unist-util-visit "^5.0.0"
|
unist-util-visit "^5.0.0"
|
||||||
vfile "^6.0.0"
|
vfile "^6.0.0"
|
||||||
|
|
||||||
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4:
|
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4, react-remove-scroll-bar@^2.3.6:
|
||||||
version "2.3.6"
|
version "2.3.6"
|
||||||
resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz"
|
resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz"
|
||||||
integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==
|
integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==
|
||||||
@ -6738,6 +6848,17 @@ react-remove-scroll@2.5.7:
|
|||||||
use-callback-ref "^1.3.0"
|
use-callback-ref "^1.3.0"
|
||||||
use-sidecar "^1.1.2"
|
use-sidecar "^1.1.2"
|
||||||
|
|
||||||
|
react-remove-scroll@2.6.0:
|
||||||
|
version "2.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz#fb03a0845d7768a4f1519a99fdb84983b793dc07"
|
||||||
|
integrity sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==
|
||||||
|
dependencies:
|
||||||
|
react-remove-scroll-bar "^2.3.6"
|
||||||
|
react-style-singleton "^2.2.1"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
use-callback-ref "^1.3.0"
|
||||||
|
use-sidecar "^1.1.2"
|
||||||
|
|
||||||
react-resizable-panels@^2.0.23:
|
react-resizable-panels@^2.0.23:
|
||||||
version "2.0.23"
|
version "2.0.23"
|
||||||
resolved "https://registry.yarnpkg.com/react-resizable-panels/-/react-resizable-panels-2.0.23.tgz#7a4296f23028c32ffcbe8086aa918cd934e7e87f"
|
resolved "https://registry.yarnpkg.com/react-resizable-panels/-/react-resizable-panels-2.0.23.tgz#7a4296f23028c32ffcbe8086aa918cd934e7e87f"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user