bump: 0.10

This commit is contained in:
dvelo 2024-08-17 14:15:30 -05:00
parent 2e23e9b43f
commit 8aeae0cda4
9 changed files with 687 additions and 368 deletions

@ -1,6 +1,6 @@
{
"name": "mh-stats",
"version": "0.1.0",
"version": "0.10.0",
"private": true,
"packageManager": "yarn@1.22.22",
"scripts": {
@ -16,6 +16,8 @@
"@babel/parser": "^7.24.7",
"@clerk/nextjs": "^5.1.3",
"@monaco-editor/react": "^4.6.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-menubar": "^1.1.1",
"@unocss/eslint-plugin": "^0.61.5",
"@unocss/postcss": "^0.61.5",
"@unocss/transformer-directives": "^0.61.5",
@ -43,41 +45,8 @@
"unplugin-tailwindcss-mangle": "^3.0.1"
},
"devDependencies": {
"geist": "^1.3.0",
"@hookform/resolvers": "^3.9.0",
"@types/canvas-confetti": "^1.6.4",
"@types/nprogress": "^0.2.3",
"@types/react-twemoji": "^0.4.3",
"@clerk/themes": "^2.1.19",
"@tailwindcss/typography": "^0.5.13",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@unocss/eslint-config": "^0.61.5",
"@unocss/preset-uno": "^0.61.5",
"@unocss/transformer-compile-class": "^0.61.5",
"eslint": "^8",
"eslint-config-next": "14.2.3",
"mangle-css-class-webpack-plugin": "^5.1.0",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5",
"vaul": "^0.9.1",
"zod": "^3.23.8",
"react-hook-form": "^7.52.2",
"react-hot-toast": "^2.4.1",
"react-hotkeys-hook": "^4.5.0",
"react-infinite-scroll-component": "^6.1.0",
"react-markdown": "^9.0.1",
"react-resizable-panels": "^2.0.23",
"recharts": "^2.12.7",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12",
"canvas-confetti": "^1.9.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"framer-motion": "^11.3.8",
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-context-menu": "^2.1.5",
"@radix-ui/react-dialog": "^1.1.1",
@ -90,6 +59,39 @@
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.0.7"
"@radix-ui/react-tooltip": "^1.0.7",
"@tailwindcss/typography": "^0.5.13",
"@types/canvas-confetti": "^1.6.4",
"@types/node": "^20",
"@types/nprogress": "^0.2.3",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react-twemoji": "^0.4.3",
"@unocss/eslint-config": "^0.61.5",
"@unocss/preset-uno": "^0.61.5",
"@unocss/transformer-compile-class": "^0.61.5",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12",
"canvas-confetti": "^1.9.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"eslint": "^8",
"eslint-config-next": "14.2.3",
"framer-motion": "^11.3.8",
"geist": "^1.3.0",
"mangle-css-class-webpack-plugin": "^5.1.0",
"postcss": "^8",
"react-hook-form": "^7.52.2",
"react-hot-toast": "^2.4.1",
"react-hotkeys-hook": "^4.5.0",
"react-infinite-scroll-component": "^6.1.0",
"react-markdown": "^9.0.1",
"react-resizable-panels": "^2.0.23",
"recharts": "^2.12.7",
"tailwindcss": "^3.4.1",
"typescript": "^5",
"vaul": "^0.9.1",
"zod": "^3.23.8"
}
}

@ -100,22 +100,19 @@
backdrop-filter: blur(8px) !important;
}
/* width */
/** Cool scrollbar */
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background: transparent;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #555;
}

@ -19,6 +19,7 @@ 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 UnofficalDialog from "@/components/misc/UnofficalDialog";
const inter = interFont({ variable: "--font-inter", subsets: ["latin"] });
export default async function RootLayout({
@ -68,6 +69,7 @@ export default async function RootLayout({
<CommandBarer />
<SpeedInsights />
<Analytics />
<UnofficalDialog />
</TooltipProvider>
</ThemeProvider>
</ClerkThemeProvider>

@ -23,22 +23,29 @@ import toast from "react-hot-toast";
import { allTags, allCategories } from "@/allTags";
import IconDisplay from "./IconDisplay";
import InfiniteScroll from "react-infinite-scroll-component";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Checkbox } from "@/components/ui/checkbox";
import { Spinner } from "./ui/spinner";
import { CommandIcon } from "lucide-react";
import { OnlineServer } from "@/lib/types/mh-server";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { useEffectOnce } from "@/lib/useEffectOnce";
import ServerCard from "./ServerCard";
import events from "@/lib/commandEvent";
import { BorderBeam } from "@/components/effects/border-beam";
import { Label } from "./ui/label";
import { useRouter } from "@/lib/useRouter";
import {
Menubar,
MenubarCheckboxItem,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSeparator,
MenubarShortcut,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
MenubarTrigger,
} from "@/components/ui/menubar";
export default function ServerList() {
const [loading, setLoading]: any = useState(true);
@ -62,6 +69,7 @@ export default function ServerList() {
const [inErrState, setErrState] = useState(false);
const [servers, setServers] = useState<Array<OnlineServer>>([]);
const router = useRouter();
const [ipr, setIPR] = useState("4");
const [filters, setFilters] = useState<
Array<(server: OnlineServer) => Promise<boolean>>
>([]);
@ -200,27 +208,77 @@ export default function ServerList() {
</div>
<br />
<Separator />
<div className="mt-3 ml-3">
<Button
onClick={() => events.emit("search-request-event")}
variant="secondary"
className="max-lg:mb-3"
>
Search{" "}
<code className="ml-2 flex items-center">
<Menubar className="mt-3 ml-2 border rounded p-2">
<MenubarMenu>
<MenubarTrigger>Servers</MenubarTrigger>
<MenubarContent>
<MenubarItem onSelect={() => events.emit("search-request-event")}>
Search Servers
<MenubarShortcut className="flex items-center ml-3">
<CommandIcon size={14} />
+Shift+K
</code>
</Button>
<Popover>
<PopoverTrigger>
<Button className="ml-3" variant="secondary">
Filter
<code className="ml-2">{filters.length}</code>
</Button>
</PopoverTrigger>
<PopoverContent className="w-[390px] z-3">
<RadioGroup
</MenubarShortcut>
</MenubarItem>
<MenubarItem
onSelect={() => {
setRandomData(serverList.getRandomServer());
setRandom(true);
}}
>
Pick Random Server
</MenubarItem>
<MenubarSeparator />
<MenubarItem
onSelect={() => {
toast.promise(
new Promise((s, e) => {
setLoading(true);
serverList
.fetchDataAndFilter()
.then(() => {
serverList.moveListDown();
let stringList: Array<{
server: string;
motd: string;
}> = [];
let obj: any = {};
serverList.currentServers.forEach((b) => {
stringList.push({ motd: b.motd, server: b.name });
});
serverList.getMOTDs(stringList).then((c) => {
var updatedSL = motdList;
c.forEach((b: { server: string; motd: string }) => {
updatedSL[b.server] = b.motd;
});
setMotdList(updatedSL);
setServers(serverList.currentServers);
setLoading(false);
s(false);
});
})
.catch(() => {
e();
});
}),
{
success: "Succesfully refreshed servers",
loading: "Refreshing...",
error: "Error while refreshing",
}
);
}}
>
Refresh
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Filter</MenubarTrigger>
<MenubarContent className="max-h-[400px] overflow-auto">
<MenubarRadioGroup
onValueChange={(v) => {
toast.promise(
new Promise((g, b) => {
@ -344,7 +402,7 @@ export default function ServerList() {
}
);
}}
defaultValue={(() => {
value={(() => {
if (nameFilters["smaller-tf"]) {
return "smaller";
} else if (nameFilters["bigger-tf"]) {
@ -354,57 +412,38 @@ export default function ServerList() {
}
})()}
>
<div className="items-top flex space-x-2">
<RadioGroupItem id="smaller" value="smaller" />
<div className="grid gap-1.5 leading-none">
<label
htmlFor="smaller"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
<MenubarRadioItem value="smaller">
<div className="block">
Only allow smaller servers
</label>
<p className="text-sm text-muted-foreground">
Server have 15-7 players, cannot be{" "}
<Badge variant="secondary">Always Online</Badge>
</p>
<br />
<span className="text-sm text-muted-foreground">
Only allow servers that have the player range 7-15, and
cannot <br />
be Always Online.
</span>
</div>
</div>
<div className="items-top flex space-x-2">
<RadioGroupItem id="bigger" value="bigger" />
<div className="grid gap-1.5 leading-none">
<label
htmlFor="bigger"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
</MenubarRadioItem>
<MenubarRadioItem value="bigger">
<div className="block">
Only allow bigger servers
</label>
<p className="text-sm text-muted-foreground">
Server has 16 players or more
</p>
</div>
</div>
<div className="items-top flex space-x-2">
<RadioGroupItem id="none" value="none" />
<div className="grid gap-1.5 leading-none">
<label
htmlFor="none"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Custom/no requirements
</label>
</div>
</div>
</RadioGroup>
<br />
<br />
<strong className="pb-2">Tags</strong>
<br />
<span className="text-sm text-muted-foreground">
Only allow servers with more than 15 players.
</span>
</div>
</MenubarRadioItem>
<MenubarRadioItem value="none">
No/custom requirements
</MenubarRadioItem>
</MenubarRadioGroup>
<MenubarSeparator />
<MenubarSub>
<span className="text-sm text-muted-foreground ml-2">Tags</span>
</MenubarSub>
{allTags.map((tag) => (
<div key={tag.docsName}>
{tag.docsName && tag.__filter == undefined && (
<div className="items-top flex space-x-2 pb-1">
<Checkbox
<MenubarCheckboxItem
disabled={templateFilter && tag.__disab != undefined}
id={tag.docsName}
checked={(() => {
@ -447,30 +486,22 @@ export default function ServerList() {
});
});
}}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor={tag.docsName}
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
<Badge variant={tag.role} className="mr-1">
{tag.docsName}
</Badge>
</label>
</div>
</div>
</MenubarCheckboxItem>
)}
</div>
))}
<br />
<strong>Categories</strong>
<br />
<MenubarSeparator />
<MenubarSub>
<span className="text-sm text-muted-foreground ml-2">
Categories
</span>
</MenubarSub>
{allCategories.map((categorie) => (
<div
className="items-top flex space-x-2 pb-1"
key={categorie.name}
>
<Checkbox
<MenubarCheckboxItem
id={categorie.name}
onCheckedChange={async (b) => {
var filt = nameFilters;
@ -510,98 +541,49 @@ export default function ServerList() {
checked={(() => {
return nameFilters["c-" + categorie.name];
})()}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor={categorie.name}
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
<Badge variant={categorie.role} className="mr-1">
{categorie.name}
</Badge>
</label>
</div>
</div>
</MenubarCheckboxItem>
))}
</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger>
<Button className="ml-2" variant="secondary">
Sort
</Button>
</PopoverTrigger>
<PopoverContent>
<RadioGroup
defaultValue="option-one"
onValueChange={() => router.push("/sort/favorites")}
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="option-one" id="option-one" />
<Label htmlFor="option-one">Online Players</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="option-two" id="option-two" />
<Label htmlFor="option-two">Favorites</Label>
</div>
</RadioGroup>
</PopoverContent>
</Popover>
<Button
variant="secondary"
className="md:ml-3 "
onClick={() => {
setRandomData(serverList.getRandomServer());
setRandom(true);
}}
>
Pick Random Server
</Button>
<Button
variant="secondary"
className="ml-3"
onClick={() => {
toast.promise(
new Promise((s, e) => {
setLoading(true);
serverList
.fetchDataAndFilter()
.then(() => {
serverList.moveListDown();
let stringList: Array<{ server: string; motd: string }> =
[];
let obj: any = {};
serverList.currentServers.forEach((b) => {
stringList.push({ motd: b.motd, server: b.name });
});
serverList.getMOTDs(stringList).then((c) => {
var updatedSL = motdList;
c.forEach((b: { server: string; motd: string }) => {
updatedSL[b.server] = b.motd;
});
setMotdList(updatedSL);
setServers(serverList.currentServers);
setLoading(false);
s(false);
});
})
.catch(() => {
e();
});
}),
{
success: "Succesfully refreshed servers",
loading: "Refreshing...",
error: "Error while refreshing",
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>View</MenubarTrigger>
<MenubarContent>
<MenubarSub>
<MenubarSubTrigger>Grid</MenubarSubTrigger>
<MenubarSubContent>
<MenubarRadioGroup value={ipr} onValueChange={setIPR}>
<MenubarRadioItem value="4">4 items per row</MenubarRadioItem>
<MenubarRadioItem value="5">5 items per row</MenubarRadioItem>
<MenubarRadioItem value="6">6 items per row</MenubarRadioItem>
</MenubarRadioGroup>
</MenubarSubContent>
</MenubarSub>
<MenubarSub>
<MenubarSubTrigger>Sort</MenubarSubTrigger>
<MenubarSubContent>
<MenubarRadioGroup
value="joins"
onValueChange={(c) =>
c == "favorites" && router.push("/sort/favorites")
}
);
}}
>
Refresh
</Button>
<MenubarRadioItem value="joins">
Players Online
</MenubarRadioItem>
<MenubarRadioItem value="favorites">
Favorites
</MenubarRadioItem>
</MenubarRadioGroup>
</MenubarSubContent>
</MenubarSub>
</MenubarContent>
</MenubarMenu>
</Menubar>
<Dialog open={random} onOpenChange={setRandom}>
<DialogContent>
{randomData == undefined && <>No data to randomize</>}
@ -679,7 +661,7 @@ export default function ServerList() {
)}
</DialogContent>
</Dialog>
</div>
<br />
<InfiniteScroll
dataLength={serverList.currentServers.length}
@ -712,7 +694,7 @@ export default function ServerList() {
}
style={{ overflow: "hidden !important", paddingLeft: 6 }}
>
<div className=" grid sm:grid-cols-4 gap-4">
<div className={" grid " + "grid-cols-" + ipr + " gap-4"}>
{servers.map((b: any) => (
<>
<ServerCard b={b} motd={motdList[b.name]} />

@ -0,0 +1,47 @@
"use client";
import { useEffect, useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
export default function UnofficalDialog() {
const [isOpen, setOpen] = useState(false);
useEffect(() => {
const dialog = localStorage.getItem("unoffical-dialog-open");
if (dialog == null) {
setOpen(true);
}
}, []);
const onChangeVal = (state: boolean) => {
if (state == false) {
setOpen(false);
localStorage.setItem("unoffical-dialog-open", "true");
} else setOpen(state);
};
return (
<Dialog open={isOpen} onOpenChange={onChangeVal}>
<DialogContent>
<DialogHeader>
<DialogTitle>Welcome to the Minehut Server List (MHSF)</DialogTitle>
</DialogHeader>
<DialogDescription>
MHSF is a Minehut server-list using the Minehut API to serve you
servers with filters, sorts and other helpful information when picking
a server to play.{" "}
<span className="font-bold">
Keep in mind that MHSF is not endorsed by Minehut or GamerSafer in
any way, as MHSF is a open-source unofficial project.
</span>
</DialogDescription>
</DialogContent>
</Dialog>
);
}

@ -0,0 +1,240 @@
"use client"
import * as React from "react"
import {
CheckIcon,
ChevronRightIcon,
DotFilledIcon,
} from "@radix-ui/react-icons"
import * as MenubarPrimitive from "@radix-ui/react-menubar"
import { cn } from "@/lib/utils"
const MenubarMenu = MenubarPrimitive.Menu
const MenubarGroup = MenubarPrimitive.Group
const MenubarPortal = MenubarPrimitive.Portal
const MenubarSub = MenubarPrimitive.Sub
const MenubarRadioGroup = MenubarPrimitive.RadioGroup
const Menubar = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Root
ref={ref}
className={cn(
"flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm",
className
)}
{...props}
/>
))
Menubar.displayName = MenubarPrimitive.Root.displayName
const MenubarTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Trigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
className
)}
{...props}
/>
))
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
const MenubarSubTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean
}
>(({ className, inset, children, ...props }, ref) => (
<MenubarPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
inset && "pl-8",
className
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto h-4 w-4" />
</MenubarPrimitive.SubTrigger>
))
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
const MenubarSubContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.SubContent
ref={ref}
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",
className
)}
{...props}
/>
))
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
const MenubarContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
>(
(
{ className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
ref
) => (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
ref={ref}
align={align}
alignOffset={alignOffset}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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
)}
{...props}
/>
</MenubarPrimitive.Portal>
)
)
MenubarContent.displayName = MenubarPrimitive.Content.displayName
const MenubarItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
)}
{...props}
/>
))
MenubarItem.displayName = MenubarPrimitive.Item.displayName
const MenubarCheckboxItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
<MenubarPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator>
<CheckIcon className="h-4 w-4" />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.CheckboxItem>
))
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
const MenubarRadioItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<MenubarPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator>
<DotFilledIcon className="h-4 w-4 fill-current" />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.RadioItem>
))
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
const MenubarLabel = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Label
ref={ref}
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
)}
{...props}
/>
))
MenubarLabel.displayName = MenubarPrimitive.Label.displayName
const MenubarSeparator = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
))
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
const MenubarShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
)}
{...props}
/>
)
}
MenubarShortcut.displayname = "MenubarShortcut"
export {
Menubar,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarItem,
MenubarSeparator,
MenubarLabel,
MenubarCheckboxItem,
MenubarRadioGroup,
MenubarRadioItem,
MenubarPortal,
MenubarSubContent,
MenubarSubTrigger,
MenubarGroup,
MenubarSub,
MenubarShortcut,
}

@ -115,7 +115,10 @@ export default function parseToHTML(m: string, tw?: boolean): Promise<string> {
});
}
function objToHTML(i: Element): string {
function objToHTML(i: Element | string): string {
if (typeof i == "string") {
return i;
}
var curClass = "";
var contents = "";
if (i.extra != undefined) {
@ -152,7 +155,7 @@ function createHTML(
) {
if (className == undefined) className = "";
if (contents == undefined) contents = "";
if (contents == "undefined") contents = "<br/>";
if (contents == "\n") contents = "<br>";
if (tw == false || tw == undefined) {
return (
@ -189,6 +192,9 @@ function colorConvert(className: string) {
if (classUnique.startsWith("text-[")) {
result +=
"color: " + classUnique.substring(6, classUnique.length - 1) + "; ";
} else {
result +=
"color: " + classUnique.substring(5, classUnique.length) + "; ";
}
}
if (classUnique.startsWith("font-bold")) {

@ -1,7 +1,7 @@
import Image from "next/image";
import Link from "next/link";
export const version = "b-0.9.0";
export const version = "b-0.10.0";
const User = ({ user }: { user: string }) => (
<span className="cursor-pointer bg-[rgba(255,165,0,0.25);] rounded p-[2.5px]">
@ -44,6 +44,28 @@ export const Changelog = () => (
</code>
</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)

@ -675,6 +675,11 @@
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-icons@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.0.tgz#c61af8f323d87682c5ca76b856d60c2312dbcb69"
integrity sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==
"@radix-ui/react-id@1.0.1":
version "1.0.1"
resolved "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz"
@ -746,6 +751,22 @@
aria-hidden "^1.1.1"
react-remove-scroll "2.5.7"
"@radix-ui/react-menubar@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-menubar/-/react-menubar-1.1.1.tgz#e126514cb1c46e0a4f9fba7d016e578cc4e41f22"
integrity sha512-V05Hryq/BE2m+rs8d5eLfrS0jmSWSDHEbG7jEyLA5D5J9jTvWj/o3v3xDN9YsOlH6QIkJgiaNDaP+S4T1rdykw==
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.0"
"@radix-ui/react-direction" "1.1.0"
"@radix-ui/react-id" "1.1.0"
"@radix-ui/react-menu" "2.1.1"
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-roving-focus" "1.1.0"
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-navigation-menu@^1.1.4":
version "1.1.4"
resolved "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.1.4.tgz"