Enhance API with OIDC support, including login and callback endpoints. Update environment variables for OIDC configuration in .env.example. Add new features to the catalog service for listing software families, Minecraft versions, and deployment regions. Implement server management actions such as kill, delete, and update in the servers module. Integrate feature flags for maintenance mode in server operations. Update pnpm-lock.yaml with new dependencies and versions.
This commit is contained in:
@@ -12,6 +12,10 @@
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-dialog": "^1.1.6",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
|
||||
112
packages/ui/src/components/Dialog.tsx
Normal file
112
packages/ui/src/components/Dialog.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef, type HTMLAttributes } from "react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const Dialog = DialogPrimitive.Root;
|
||||
export const DialogTrigger = DialogPrimitive.Trigger;
|
||||
export const DialogPortal = DialogPrimitive.Portal;
|
||||
export const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
export const DialogOverlay = forwardRef<
|
||||
ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-zinc-950/60 backdrop-blur-sm",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||
|
||||
export const DialogContent = forwardRef<
|
||||
ElementRef<typeof DialogPrimitive.Content>,
|
||||
ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-1/2 top-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2",
|
||||
"rounded-lg border border-zinc-200 bg-white p-6 shadow-lg",
|
||||
"dark:border-zinc-800 dark:bg-zinc-900",
|
||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500 focus-visible:ring-offset-2",
|
||||
"dark:focus-visible:ring-offset-zinc-950",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close
|
||||
className={cn(
|
||||
"absolute right-4 top-4 rounded-md p-1 text-zinc-500 transition-colors",
|
||||
"hover:bg-zinc-100 hover:text-zinc-900",
|
||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500 focus-visible:ring-offset-2",
|
||||
"dark:hover:bg-zinc-800 dark:hover:text-zinc-100 dark:focus-visible:ring-offset-zinc-950",
|
||||
)}
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true" className="text-lg leading-none">
|
||||
×
|
||||
</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
));
|
||||
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
export interface DialogHeaderProps extends HTMLAttributes<HTMLDivElement> {}
|
||||
|
||||
export const DialogHeader = forwardRef<HTMLDivElement, DialogHeaderProps>(
|
||||
({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("flex flex-col gap-1.5 pr-8 text-left", className)} {...props} />
|
||||
),
|
||||
);
|
||||
|
||||
DialogHeader.displayName = "DialogHeader";
|
||||
|
||||
export interface DialogFooterProps extends HTMLAttributes<HTMLDivElement> {}
|
||||
|
||||
export const DialogFooter = forwardRef<HTMLDivElement, DialogFooterProps>(
|
||||
({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
);
|
||||
|
||||
DialogFooter.displayName = "DialogFooter";
|
||||
|
||||
export const DialogTitle = forwardRef<
|
||||
ElementRef<typeof DialogPrimitive.Title>,
|
||||
ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-base font-semibold tracking-tight text-zinc-900 dark:text-zinc-50", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
export const DialogDescription = forwardRef<
|
||||
ElementRef<typeof DialogPrimitive.Description>,
|
||||
ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-zinc-600 dark:text-zinc-400", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
199
packages/ui/src/components/DropdownMenu.tsx
Normal file
199
packages/ui/src/components/DropdownMenu.tsx
Normal file
@@ -0,0 +1,199 @@
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef, type HTMLAttributes } from "react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||
export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
||||
export const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
||||
export const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
||||
export const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
||||
export const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||
|
||||
export const DropdownMenuSubTrigger = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, children, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
|
||||
"text-zinc-700 focus:bg-zinc-100 data-[state=open]:bg-zinc-100",
|
||||
"dark:text-zinc-300 dark:focus:bg-zinc-800 dark:data-[state=open]:bg-zinc-800",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<span className="ml-auto text-xs text-zinc-500 dark:text-zinc-400" aria-hidden="true">
|
||||
›
|
||||
</span>
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
));
|
||||
|
||||
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
||||
|
||||
export const DropdownMenuSubContent = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 shadow-md",
|
||||
"dark:border-zinc-800 dark:bg-zinc-900",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
||||
|
||||
export const DropdownMenuContent = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
||||
>(({ className, sideOffset = 4, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Portal>
|
||||
<DropdownMenuPrimitive.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 shadow-md",
|
||||
"dark:border-zinc-800 dark:bg-zinc-900",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
));
|
||||
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
||||
|
||||
export const DropdownMenuItem = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
|
||||
"text-zinc-700 focus:bg-zinc-100 focus:text-zinc-900",
|
||||
"dark:text-zinc-300 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
|
||||
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
||||
|
||||
export const DropdownMenuCheckboxItem = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
||||
>(({ className, children, checked, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.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",
|
||||
"text-zinc-700 focus:bg-zinc-100 focus:text-zinc-900",
|
||||
"dark:text-zinc-300 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
|
||||
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<span className="text-xs" aria-hidden="true">
|
||||
✓
|
||||
</span>
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
));
|
||||
|
||||
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
||||
|
||||
export const DropdownMenuRadioItem = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.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",
|
||||
"text-zinc-700 focus:bg-zinc-100 focus:text-zinc-900",
|
||||
"dark:text-zinc-300 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
|
||||
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<span className="size-1.5 rounded-full bg-current" aria-hidden="true" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
));
|
||||
|
||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
||||
|
||||
export interface DropdownMenuLabelProps
|
||||
extends ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> {
|
||||
inset?: boolean;
|
||||
}
|
||||
|
||||
export const DropdownMenuLabel = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||
DropdownMenuLabelProps
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
||||
|
||||
export const DropdownMenuSeparator = forwardRef<
|
||||
ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("-mx-1 my-1 h-px bg-zinc-200 dark:bg-zinc-800", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
||||
|
||||
export interface DropdownMenuShortcutProps extends HTMLAttributes<HTMLSpanElement> {}
|
||||
|
||||
export const DropdownMenuShortcut = forwardRef<HTMLSpanElement, DropdownMenuShortcutProps>(
|
||||
({ className, ...props }, ref) => (
|
||||
<span
|
||||
ref={ref}
|
||||
className={cn("ml-auto text-xs tracking-widest text-zinc-500 dark:text-zinc-400", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
);
|
||||
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
||||
@@ -13,4 +13,37 @@ export {
|
||||
type CardProps,
|
||||
type CardTitleProps,
|
||||
} from "./components/Card";
|
||||
export {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
type DialogFooterProps,
|
||||
type DialogHeaderProps,
|
||||
} from "./components/Dialog";
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
type DropdownMenuLabelProps,
|
||||
type DropdownMenuShortcutProps,
|
||||
} from "./components/DropdownMenu";
|
||||
export { cn } from "./lib/cn";
|
||||
|
||||
Reference in New Issue
Block a user