Redesign UI with shadcn
This commit is contained in:
@@ -18,6 +18,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elysiajs/eden": "catalog:",
|
"@elysiajs/eden": "catalog:",
|
||||||
|
"@radix-ui/react-dialog": "catalog:",
|
||||||
|
"@radix-ui/react-dropdown-menu": "catalog:",
|
||||||
|
"@radix-ui/react-label": "catalog:",
|
||||||
|
"@radix-ui/react-slot": "catalog:",
|
||||||
"clsx": "catalog:",
|
"clsx": "catalog:",
|
||||||
"common": "workspace:^",
|
"common": "workspace:^",
|
||||||
"lucide-react": "catalog:",
|
"lucide-react": "catalog:",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { mapProp, Update } from "@/hooks/useStore";
|
||||||
import { getMediaTypeForFile } from "common/MediaType";
|
import { getMediaTypeForFile } from "common/MediaType";
|
||||||
import { mapProp, Update } from "./store";
|
|
||||||
|
|
||||||
export function FileReducer(prev: FileReducer.State, action: FileReducer.Action): FileReducer.State {
|
export function FileReducer(prev: FileReducer.State, action: FileReducer.Action): FileReducer.State {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { StrictMode } from "react";
|
import { Home } from "@/routes/Home";
|
||||||
|
import { Login } from "@/routes/Login";
|
||||||
|
import { Piece } from "@/routes/Piece";
|
||||||
|
import { Root } from "@/routes/Root";
|
||||||
|
import { lazy, StrictMode } from "react";
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import { Attachment } from "./routes/Attachment";
|
|
||||||
import { Home } from "./routes/Home";
|
|
||||||
import { Login } from "./routes/Login";
|
|
||||||
import { Piece } from "./routes/Piece";
|
|
||||||
import { Root } from "./routes/Root";
|
|
||||||
import "./style.css";
|
import "./style.css";
|
||||||
|
|
||||||
|
const Attachment = lazy(() => import("@/routes/Attachment"));
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
|
|||||||
52
packages/frontend/src/components/ui/button.tsx
Normal file
52
packages/frontend/src/components/ui/button.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const buttonVariants = cva(
|
||||||
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stone-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:ring-offset-stone-950 dark:focus-visible:ring-stone-300",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: "bg-stone-900 text-stone-50 hover:bg-stone-900/90 dark:bg-stone-50 dark:text-stone-900 dark:hover:bg-stone-50/90",
|
||||||
|
destructive: "bg-red-500 text-stone-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-stone-50 dark:hover:bg-red-900/90",
|
||||||
|
outline: "border border-stone-200 bg-white hover:bg-stone-100 hover:text-stone-900 dark:border-stone-800 dark:bg-stone-950 dark:hover:bg-stone-800 dark:hover:text-stone-50",
|
||||||
|
secondary: "bg-stone-100 text-stone-900 hover:bg-stone-100/80 dark:bg-stone-800 dark:text-stone-50 dark:hover:bg-stone-800/80",
|
||||||
|
ghost: "hover:bg-stone-100 hover:text-stone-900 dark:hover:bg-stone-800 dark:hover:text-stone-50",
|
||||||
|
link: "text-stone-900 underline-offset-4 hover:underline dark:text-stone-50",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: "h-10 px-4 py-2",
|
||||||
|
sm: "h-9 rounded-md px-3",
|
||||||
|
lg: "h-11 rounded-md px-8",
|
||||||
|
icon: "h-10 w-10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
size: "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface ButtonProps
|
||||||
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||||
|
VariantProps<typeof buttonVariants> {
|
||||||
|
asChild?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||||
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "button";
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Button.displayName = "Button";
|
||||||
|
|
||||||
|
export { Button, buttonVariants };
|
||||||
79
packages/frontend/src/components/ui/card.tsx
Normal file
79
packages/frontend/src/components/ui/card.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const Card = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"rounded-lg border border-stone-200 bg-white text-stone-950 shadow-sm dark:border-stone-800 dark:bg-stone-950 dark:text-stone-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
Card.displayName = "Card";
|
||||||
|
|
||||||
|
const CardHeader = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
CardHeader.displayName = "CardHeader";
|
||||||
|
|
||||||
|
const CardTitle = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"text-2xl font-semibold leading-none tracking-tight",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
CardTitle.displayName = "CardTitle";
|
||||||
|
|
||||||
|
const CardDescription = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn("text-sm text-stone-500 dark:text-stone-400", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
CardDescription.displayName = "CardDescription";
|
||||||
|
|
||||||
|
const CardContent = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||||
|
));
|
||||||
|
CardContent.displayName = "CardContent";
|
||||||
|
|
||||||
|
const CardFooter = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn("flex items-center p-6 pt-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
CardFooter.displayName = "CardFooter";
|
||||||
|
|
||||||
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
|
||||||
|
|
||||||
107
packages/frontend/src/components/ui/dialog.tsx
Normal file
107
packages/frontend/src/components/ui/dialog.tsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||||
|
import { X } from "lucide-react";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const Dialog = DialogPrimitive.Root;
|
||||||
|
const DialogTrigger = DialogPrimitive.Trigger;
|
||||||
|
const DialogPortal = DialogPrimitive.Portal;
|
||||||
|
const DialogClose = DialogPrimitive.Close;
|
||||||
|
|
||||||
|
const DialogOverlay = forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DialogPrimitive.Overlay
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||||
|
|
||||||
|
const DialogContent = forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<DialogPortal>
|
||||||
|
<DialogOverlay />
|
||||||
|
<DialogPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-stone-200 bg-white p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg dark:border-stone-800 dark:bg-stone-950",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-stone-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-stone-100 data-[state=open]:text-stone-500 dark:ring-offset-stone-950 dark:focus:ring-stone-300 dark:data-[state=open]:bg-stone-800 dark:data-[state=open]:text-stone-400">
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</DialogPrimitive.Close>
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
|
));
|
||||||
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
const DialogHeader = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col space-y-1.5 text-center sm:text-left",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
DialogHeader.displayName = "DialogHeader";
|
||||||
|
|
||||||
|
const DialogFooter = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
DialogFooter.displayName = "DialogFooter";
|
||||||
|
|
||||||
|
const DialogTitle = forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DialogPrimitive.Title
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"text-lg font-semibold leading-none tracking-tight",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||||
|
|
||||||
|
const DialogDescription = forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DialogPrimitive.Description
|
||||||
|
ref={ref}
|
||||||
|
className={cn("text-sm text-stone-500 dark:text-stone-400", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||||
|
|
||||||
|
export {
|
||||||
|
Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger
|
||||||
|
};
|
||||||
179
packages/frontend/src/components/ui/dropdown-menu.tsx
Normal file
179
packages/frontend/src/components/ui/dropdown-menu.tsx
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||||
|
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||||
|
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
||||||
|
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
||||||
|
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
||||||
|
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
||||||
|
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||||
|
|
||||||
|
const DropdownMenuSubTrigger = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||||
|
inset?: boolean,
|
||||||
|
}
|
||||||
|
>(({ className, inset, children, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-stone-100 data-[state=open]:bg-stone-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus:bg-stone-800 dark:data-[state=open]:bg-stone-800",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ChevronRight className="ml-auto" />
|
||||||
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
|
));
|
||||||
|
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuSubContent = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.SubContent
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-stone-200 bg-white p-1 text-stone-950 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 dark:border-stone-800 dark:bg-stone-950 dark:text-stone-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuContent = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||||
|
React.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-stone-200 bg-white p-1 text-stone-950 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 dark:border-stone-800 dark:bg-stone-950 dark:text-stone-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</DropdownMenuPrimitive.Portal>
|
||||||
|
));
|
||||||
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuItem = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||||
|
inset?: boolean,
|
||||||
|
}
|
||||||
|
>(({ className, inset, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"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-stone-100 focus:text-stone-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus:bg-stone-800 dark:focus:text-stone-50",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuCheckboxItem = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||||
|
React.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 transition-colors focus:bg-stone-100 focus:text-stone-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-stone-800 dark:focus:text-stone-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
checked={checked}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
<Check className="h-4 w-4" />
|
||||||
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
{children}
|
||||||
|
</DropdownMenuPrimitive.CheckboxItem>
|
||||||
|
));
|
||||||
|
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuRadioItem = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||||
|
React.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 transition-colors focus:bg-stone-100 focus:text-stone-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-stone-800 dark:focus:text-stone-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
<Circle className="h-2 w-2 fill-current" />
|
||||||
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
{children}
|
||||||
|
</DropdownMenuPrimitive.RadioItem>
|
||||||
|
));
|
||||||
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuLabel = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
||||||
|
inset?: boolean
|
||||||
|
}
|
||||||
|
>(({ className, inset, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Label
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"px-2 py-1.5 text-sm font-semibold",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuSeparator = forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Separator
|
||||||
|
ref={ref}
|
||||||
|
className={cn("-mx-1 my-1 h-px bg-stone-100 dark:bg-stone-800", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
||||||
|
|
||||||
|
const DropdownMenuShortcut = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
||||||
|
|
||||||
|
export {
|
||||||
|
DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator,
|
||||||
|
DropdownMenuShortcut, DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger, DropdownMenuTrigger
|
||||||
|
};
|
||||||
|
|
||||||
21
packages/frontend/src/components/ui/input.tsx
Normal file
21
packages/frontend/src/components/ui/input.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const Input = forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||||
|
({ className, type, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
className={cn(
|
||||||
|
"flex h-10 w-full rounded-md border border-stone-200 bg-white px-3 py-2 text-base ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-stone-950 placeholder:text-stone-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stone-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:border-stone-800 dark:bg-stone-950 dark:ring-offset-stone-950 dark:file:text-stone-50 dark:placeholder:text-stone-400 dark:focus-visible:ring-stone-300",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Input.displayName = "Input";
|
||||||
|
|
||||||
|
export { Input };
|
||||||
24
packages/frontend/src/components/ui/label.tsx
Normal file
24
packages/frontend/src/components/ui/label.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const labelVariants = cva(
|
||||||
|
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
||||||
|
);
|
||||||
|
|
||||||
|
const Label = forwardRef<
|
||||||
|
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
||||||
|
VariantProps<typeof labelVariants>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<LabelPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn(labelVariants(), className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
Label.displayName = LabelPrimitive.Root.displayName;
|
||||||
|
|
||||||
|
export { Label };
|
||||||
|
|
||||||
109
packages/frontend/src/components/ui/table.tsx
Normal file
109
packages/frontend/src/components/ui/table.tsx
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { forwardRef } from "react";
|
||||||
|
|
||||||
|
const Table = forwardRef<
|
||||||
|
HTMLTableElement,
|
||||||
|
React.HTMLAttributes<HTMLTableElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div className="relative w-full overflow-auto">
|
||||||
|
<table
|
||||||
|
ref={ref}
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
Table.displayName = "Table";
|
||||||
|
|
||||||
|
const TableHeader = forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
||||||
|
));
|
||||||
|
TableHeader.displayName = "TableHeader";
|
||||||
|
|
||||||
|
const TableBody = forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tbody
|
||||||
|
ref={ref}
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableBody.displayName = "TableBody";
|
||||||
|
|
||||||
|
const TableFooter = forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tfoot
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-t bg-stone-100/50 font-medium [&>tr]:last:border-b-0 dark:bg-stone-800/50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableFooter.displayName = "TableFooter";
|
||||||
|
|
||||||
|
const TableRow = forwardRef<
|
||||||
|
HTMLTableRowElement,
|
||||||
|
React.HTMLAttributes<HTMLTableRowElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tr
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-b transition-colors hover:bg-stone-100/50 data-[state=selected]:bg-stone-100 dark:hover:bg-stone-800/50 dark:data-[state=selected]:bg-stone-800",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableRow.displayName = "TableRow";
|
||||||
|
|
||||||
|
const TableHead = forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<th
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"h-12 px-4 text-left align-middle font-medium text-stone-500 [&:has([role=checkbox])]:pr-0 dark:text-stone-400",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableHead.displayName = "TableHead";
|
||||||
|
|
||||||
|
const TableCell = forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<td
|
||||||
|
ref={ref}
|
||||||
|
className={cn("p-1 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableCell.displayName = "TableCell";
|
||||||
|
|
||||||
|
const TableCaption = forwardRef<
|
||||||
|
HTMLTableCaptionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableCaptionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<caption
|
||||||
|
ref={ref}
|
||||||
|
className={cn("mt-4 text-sm text-stone-500 dark:text-stone-400", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableCaption.displayName = "TableCaption";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow
|
||||||
|
};
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { useStore } from "@/hooks/useStore";
|
||||||
import { Treaty } from "@elysiajs/eden";
|
import { Treaty } from "@elysiajs/eden";
|
||||||
import { ELYSIA_FORM_DATA } from "elysia";
|
import { ELYSIA_FORM_DATA } from "elysia";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useStore } from "./store";
|
|
||||||
|
|
||||||
type FormDataFix<T> = T extends { [ELYSIA_FORM_DATA]: infer U } ? U : T;
|
type FormDataFix<T> = T extends { [ELYSIA_FORM_DATA]: infer U } ? U : T;
|
||||||
|
|
||||||
@@ -4,3 +4,7 @@ import { twMerge } from "tailwind-merge";
|
|||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function timeout(timeMs: number): Promise<void> {
|
||||||
|
return new Promise<void>((resolve) => setTimeout(resolve, timeMs));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
export { OpenSheetMusicDisplay as default } from "opensheetmusicdisplay";
|
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
|
import { client } from "@/client";
|
||||||
|
import { useLoading } from "@/hooks/useLoading.ts";
|
||||||
import { AttachmentId, PieceId } from "common";
|
import { AttachmentId, PieceId } from "common";
|
||||||
import { lazy, useEffect, useRef } from "react";
|
import { OpenSheetMusicDisplay } from "opensheetmusicdisplay";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { client } from "../client";
|
|
||||||
import { useLoading } from "../loading";
|
|
||||||
|
|
||||||
export const Attachment = lazy(async () => {
|
export default function Attachment() {
|
||||||
|
|
||||||
const { default: OpenSheetMusicDisplay } = await import("../opensheetmusicdisplay.ts");
|
|
||||||
|
|
||||||
return {
|
|
||||||
default: function Attachment() {
|
|
||||||
|
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const pieceId = PieceId(params.pieceId!);
|
const pieceId = PieceId(params.pieceId!);
|
||||||
@@ -61,6 +57,4 @@ export const Attachment = lazy(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <div ref={containerRef} className="w-full h-full overflow-scroll" />;
|
return <div ref={containerRef} className="w-full h-full overflow-scroll" />;
|
||||||
},
|
};
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import { FormEventHandler, ReactNode, useId, useRef, useState } from "react";
|
import { client } from "@/client";
|
||||||
import { Link } from "react-router-dom";
|
import { Button } from "@/components/ui/button";
|
||||||
import { client } from "../client";
|
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||||
import { useLoading } from "../loading";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "../styled/Button";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Input } from "../styled/Input";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||||
|
import { useLoading } from "@/hooks/useLoading";
|
||||||
|
import { Loader2, Plus } from "lucide-react";
|
||||||
|
import { FormEventHandler, ReactNode, useId, useState } from "react";
|
||||||
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
export function Home() {
|
export function Home() {
|
||||||
|
|
||||||
@@ -18,20 +22,28 @@ export function Home() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 overflow-y-auto flex flex-wrap items-start gap-4">
|
<div className="p-4 overflow-y-auto flex flex-col items-start gap-4">
|
||||||
{error !== null ? (
|
{error !== null ? (
|
||||||
`Wystąpił błąd: ${error.value}`
|
`Wystąpił błąd: ${error.value}`
|
||||||
) : (
|
) : (<>
|
||||||
<table className="grow">
|
<Dialog>
|
||||||
<thead>
|
<DialogTrigger asChild>
|
||||||
<tr>
|
<Button variant="outline">
|
||||||
<th className="p-1 border">Tytuł</th>
|
<Plus />Dodaj utwór
|
||||||
<th className="p-1 border">Twórcy</th>
|
</Button>
|
||||||
<th className="p-1 border">Dodano</th>
|
</DialogTrigger>
|
||||||
<th className="p-1 border">Zmodyfikowano</th>
|
<AddPieceDialogContent />
|
||||||
</tr>
|
</Dialog>
|
||||||
</thead>
|
<Table>
|
||||||
<tbody>
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Tytuł</TableHead>
|
||||||
|
<TableHead>Twórcy</TableHead>
|
||||||
|
<TableHead className="text-center">Dodano</TableHead>
|
||||||
|
<TableHead className="text-center">Zmodyfikowano</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
{data.map((piece) => {
|
{data.map((piece) => {
|
||||||
const composerParts: ReactNode[] = [];
|
const composerParts: ReactNode[] = [];
|
||||||
if (piece.composer !== null) composerParts.push(piece.composer);
|
if (piece.composer !== null) composerParts.push(piece.composer);
|
||||||
@@ -39,31 +51,32 @@ export function Home() {
|
|||||||
if (piece.lyricist !== null) composerParts.push(`słowa: ${piece.lyricist}`);
|
if (piece.lyricist !== null) composerParts.push(`słowa: ${piece.lyricist}`);
|
||||||
if (composerParts.length === 0) composerParts.push(<em>Nieznani</em>);
|
if (composerParts.length === 0) composerParts.push(<em>Nieznani</em>);
|
||||||
return (
|
return (
|
||||||
<tr key={piece.pieceId}>
|
<TableRow key={piece.pieceId}>
|
||||||
<td className="p-1 border"><Link className="underline" to={`piece/${piece.pieceId}`}>{piece.name}</Link></td>
|
<TableCell><Link className="underline" to={`piece/${piece.pieceId}`}>{piece.name}</Link></TableCell>
|
||||||
<td className="p-1 border">{...composerParts.flatMap((x, i, a) => i < a.length - 1 ? [x, <br />] : [x])}</td>
|
<TableCell>{...composerParts.flatMap((x, i, a) => i < a.length - 1 ? [x, <br />] : [x])}</TableCell>
|
||||||
<td className="p-1 border text-center font-mono text-sm">
|
<TableCell className="text-center font-mono text-xs">
|
||||||
{piece.createdAt}
|
{piece.createdAt}
|
||||||
{piece.createdBy !== null && <><br />przez {piece.createdBy}</>}
|
{piece.createdBy !== null && <><br />przez {piece.createdBy}</>}
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="p-1 border text-center font-mono text-sm">
|
<TableCell className="text-center font-mono text-xs">
|
||||||
{piece.modifiedAt === null && piece.modifiedBy === null ? "\u2014"
|
{piece.modifiedAt === null && piece.modifiedBy === null ? "\u2014"
|
||||||
: piece.modifiedAt !== null && piece.modifiedBy === null ? piece.modifiedAt
|
: piece.modifiedAt !== null && piece.modifiedBy === null ? piece.modifiedAt
|
||||||
: piece.modifiedAt === null ? `przez ${piece.createdBy}`
|
: piece.modifiedAt === null ? `przez ${piece.createdBy}`
|
||||||
: <>{piece.createdAt}<br />przez {piece.createdBy}</>}
|
: <>{piece.createdAt}<br />przez {piece.createdBy}</>}
|
||||||
</td>
|
</TableCell>
|
||||||
</tr>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</TableBody>
|
||||||
</table>
|
</Table>
|
||||||
)}
|
</>)}
|
||||||
<PieceForm />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PieceForm() {
|
function AddPieceDialogContent() {
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [composer, setComposer] = useState("");
|
const [composer, setComposer] = useState("");
|
||||||
@@ -75,66 +88,81 @@ function PieceForm() {
|
|||||||
const lyricistId = useId();
|
const lyricistId = useId();
|
||||||
const arrangerId = useId();
|
const arrangerId = useId();
|
||||||
|
|
||||||
const autoFocusRef = useRef<HTMLInputElement>(null);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { error } = await client.piece.post({
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const { data, error } = await client.piece.post({
|
||||||
name,
|
name,
|
||||||
composer: composer.length > 0 ? composer : null,
|
composer: composer.length > 0 ? composer : null,
|
||||||
lyricist: lyricist.length > 0 ? lyricist : null,
|
lyricist: lyricist.length > 0 ? lyricist : null,
|
||||||
arranger: arranger.length > 0 ? arranger : null,
|
arranger: arranger.length > 0 ? arranger : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error !== null) {
|
||||||
console.error(error.value);
|
console.error(error.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setName("");
|
navigate(`piece/${data.pieceId}`);
|
||||||
setComposer("");
|
} finally {
|
||||||
setLyricist("");
|
setIsLoading(false);
|
||||||
setArranger("");
|
}
|
||||||
|
|
||||||
autoFocusRef.current?.focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="p-2 flex flex-col gap-2 border rounded" onSubmit={onSubmit}>
|
<DialogContent>
|
||||||
<label htmlFor={nameId}>Tytuł</label>
|
<form onSubmit={onSubmit}>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Dodaj utwór</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid items-baseline grid-cols-4 gap-4 py-4">
|
||||||
|
<Label htmlFor={nameId} className="text-right">Tytuł</Label>
|
||||||
<Input
|
<Input
|
||||||
ref={autoFocusRef}
|
|
||||||
id={nameId}
|
id={nameId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={name}
|
value={name}
|
||||||
|
autoFocus
|
||||||
required
|
required
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={composerId}>Kompozytor</label>
|
<Label htmlFor={composerId} className="text-right">Kompozytor</Label>
|
||||||
<Input
|
<Input
|
||||||
id={composerId}
|
id={composerId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={composer}
|
value={composer}
|
||||||
onChange={(e) => setComposer(e.target.value)}
|
onChange={(e) => setComposer(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={lyricistId}>Słowa</label>
|
<Label htmlFor={lyricistId} className="text-right">Słowa</Label>
|
||||||
<Input
|
<Input
|
||||||
id={lyricistId}
|
id={lyricistId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={lyricist}
|
value={lyricist}
|
||||||
onChange={(e) => setLyricist(e.target.value)}
|
onChange={(e) => setLyricist(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={arrangerId}>Opracowanie</label>
|
<Label htmlFor={arrangerId} className="text-right">Opracowanie</Label>
|
||||||
<Input
|
<Input
|
||||||
id={arrangerId}
|
id={arrangerId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={arranger}
|
value={arranger}
|
||||||
onChange={(e) => setArranger(e.target.value)}
|
onChange={(e) => setArranger(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Button type="submit">
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button type="submit" disabled={isLoading}>
|
||||||
|
{isLoading && <Loader2 className="animate-spin" />}
|
||||||
Dodaj
|
Dodaj
|
||||||
</Button>
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
</form>
|
</form>
|
||||||
|
</DialogContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { FormEventHandler, useId } from "react";
|
import { client } from "@/client";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { useStore } from "@/hooks/useStore";
|
||||||
|
import { Loader2 } from "lucide-react";
|
||||||
|
import { FormEventHandler, useId, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { client } from "../client";
|
|
||||||
import { useStore } from "../store";
|
|
||||||
import { Button } from "../styled/Button";
|
|
||||||
import { Input } from "../styled/Input";
|
|
||||||
|
|
||||||
export function Login() {
|
export function Login() {
|
||||||
|
|
||||||
@@ -20,9 +23,14 @@ export function Login() {
|
|||||||
const usernameId = useId();
|
const usernameId = useId();
|
||||||
const passwordId = useId();
|
const passwordId = useId();
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
const { data, error } = await client.login.post({
|
const { data, error } = await client.login.post({
|
||||||
username: loginUsername,
|
username: loginUsername,
|
||||||
password: loginPassword,
|
password: loginPassword,
|
||||||
@@ -38,32 +46,47 @@ export function Login() {
|
|||||||
setUser(data);
|
setUser(data);
|
||||||
|
|
||||||
navigate("/");
|
navigate("/");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
<div className="w-full h-full flex items-center justify-center">
|
||||||
<form className="p-2 flex flex-col gap-2 border rounded" onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<header className="pb-2 border-b text-center font-bold">Repozytorium muzyczne</header>
|
<Card>
|
||||||
<label htmlFor={usernameId}>Nazwa użytkownika</label>
|
<CardHeader>
|
||||||
|
<CardTitle>Repozytorium muzyczne</CardTitle>
|
||||||
|
<CardDescription>Zaloguj się, aby kontynuować</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<Label htmlFor={usernameId}>Nazwa użytkownika</Label>
|
||||||
<Input
|
<Input
|
||||||
id={usernameId}
|
id={usernameId}
|
||||||
|
className="w-[32ch]"
|
||||||
type="text"
|
type="text"
|
||||||
value={loginUsername}
|
value={loginUsername}
|
||||||
autoFocus
|
autoFocus
|
||||||
required
|
required
|
||||||
onChange={(e) => setLoginUsername(e.target.value)}
|
onChange={(e) => setLoginUsername(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={passwordId}>Hasło</label>
|
<Label htmlFor={passwordId}>Hasło</Label>
|
||||||
<Input
|
<Input
|
||||||
id={passwordId}
|
id={passwordId}
|
||||||
|
className="w-[32ch]"
|
||||||
type="password"
|
type="password"
|
||||||
value={loginPassword}
|
value={loginPassword}
|
||||||
required
|
required
|
||||||
onChange={(e) => setLoginPassword(e.target.value)}
|
onChange={(e) => setLoginPassword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Button type="submit">
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button type="submit" className="w-full" disabled={isLoading}>
|
||||||
|
{isLoading && <Loader2 className="animate-spin" />}
|
||||||
Zaloguj się
|
Zaloguj się
|
||||||
</Button>
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
|
import { client } from "@/client";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||||
|
import { FileReducer } from "@/FileReducer";
|
||||||
|
import { useLoading } from "@/hooks/useLoading";
|
||||||
|
import { timeout } from "@/lib/utils";
|
||||||
|
import { Label } from "@radix-ui/react-label";
|
||||||
import type { Attachment, Piece } from "backend/database";
|
import type { Attachment, Piece } from "backend/database";
|
||||||
import { PieceId } from "common";
|
import { PieceId } from "common";
|
||||||
import { ACCEPTED_EXTENSIONS } from "common/MediaType";
|
import { ACCEPTED_EXTENSIONS } from "common/MediaType";
|
||||||
import { ELYSIA_FORM_DATA } from "elysia";
|
import { ELYSIA_FORM_DATA } from "elysia";
|
||||||
|
import { Download, Loader2, Trash } from "lucide-react";
|
||||||
import { FormEventHandler, MouseEvent, useCallback, useId, useReducer, useRef, useState } from "react";
|
import { FormEventHandler, MouseEvent, useCallback, useId, useReducer, useRef, useState } from "react";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useParams } from "react-router-dom";
|
||||||
import { client } from "../client";
|
|
||||||
import { FileReducer } from "../FileReducer";
|
|
||||||
import { useLoading } from "../loading";
|
|
||||||
import { Button } from "../styled/Button";
|
|
||||||
import { Input } from "../styled/Input";
|
|
||||||
|
|
||||||
export function Piece() {
|
export function Piece() {
|
||||||
|
|
||||||
@@ -32,9 +36,13 @@ export function Piece() {
|
|||||||
) : piece.data[0] === undefined ? (
|
) : piece.data[0] === undefined ? (
|
||||||
"Utwór nie istnieje"
|
"Utwór nie istnieje"
|
||||||
) : (<>
|
) : (<>
|
||||||
|
<div className="flex flex-col gap-4 p-4 border rounded">
|
||||||
|
<h3 className="font-bold text-lg">Utwór</h3>
|
||||||
<PieceForm piece={piece.data[0]} />
|
<PieceForm piece={piece.data[0]} />
|
||||||
<Attachments pieceId={piece.data[0].pieceId} attachments={attachments.data} />
|
<h3 className="font-bold text-lg">Załączniki</h3>
|
||||||
<AttachmentForm pieceId={piece.data[0].pieceId} />
|
<AttachmentForm pieceId={piece.data[0].pieceId} />
|
||||||
|
</div>
|
||||||
|
<Attachments pieceId={piece.data[0].pieceId} attachments={attachments.data} />
|
||||||
</>)}
|
</>)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -58,11 +66,15 @@ function PieceForm(props: PieceForm.Props) {
|
|||||||
const lyricistId = useId();
|
const lyricistId = useId();
|
||||||
const arrangerId = useId();
|
const arrangerId = useId();
|
||||||
|
|
||||||
const autoFocusRef = useRef<HTMLInputElement>(null);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
const delay = timeout(250);
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
const { error } = await client.piece({ pieceId: props.piece.pieceId }).put({
|
const { error } = await client.piece({ pieceId: props.piece.pieceId }).put({
|
||||||
name,
|
name,
|
||||||
composer: composer.length > 0 ? composer : null,
|
composer: composer.length > 0 ? composer : null,
|
||||||
@@ -74,45 +86,55 @@ function PieceForm(props: PieceForm.Props) {
|
|||||||
console.error(error.value);
|
console.error(error.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
autoFocusRef.current?.focus();
|
await delay;
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="p-2 flex flex-col gap-2 border rounded" onSubmit={onSubmit}>
|
<form className="flex flex-col gap-4" onSubmit={onSubmit}>
|
||||||
<label htmlFor={nameId}>Tytuł</label>
|
<div className="grid items-baseline grid-cols-4 gap-4">
|
||||||
|
<Label htmlFor={nameId} className="text-right">Tytuł</Label>
|
||||||
<Input
|
<Input
|
||||||
ref={autoFocusRef}
|
|
||||||
id={nameId}
|
id={nameId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={name}
|
value={name}
|
||||||
required
|
required
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={composerId}>Kompozytor</label>
|
<Label htmlFor={composerId} className="text-right">Kompozytor</Label>
|
||||||
<Input
|
<Input
|
||||||
id={composerId}
|
id={composerId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={composer}
|
value={composer}
|
||||||
onChange={(e) => setComposer(e.target.value)}
|
onChange={(e) => setComposer(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={lyricistId}>Słowa</label>
|
<Label htmlFor={lyricistId} className="text-right">Słowa</Label>
|
||||||
<Input
|
<Input
|
||||||
id={lyricistId}
|
id={lyricistId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={lyricist}
|
value={lyricist}
|
||||||
onChange={(e) => setLyricist(e.target.value)}
|
onChange={(e) => setLyricist(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={arrangerId}>Opracowanie</label>
|
<Label htmlFor={arrangerId} className="text-right">Opracowanie</Label>
|
||||||
<Input
|
<Input
|
||||||
id={arrangerId}
|
id={arrangerId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={arranger}
|
value={arranger}
|
||||||
onChange={(e) => setArranger(e.target.value)}
|
onChange={(e) => setArranger(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Button type="submit">
|
</div>
|
||||||
|
<div className="flex flex-col-reverse items-end">
|
||||||
|
<Button type="submit" disabled={isLoading}>
|
||||||
|
{isLoading && <Loader2 className="animate-spin" />}
|
||||||
Zapisz
|
Zapisz
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -126,20 +148,22 @@ namespace Attachments {
|
|||||||
|
|
||||||
function Attachments(props: Attachments.Props) {
|
function Attachments(props: Attachments.Props) {
|
||||||
return (
|
return (
|
||||||
<table className="grow">
|
<div className="grow">
|
||||||
<thead>
|
<Table>
|
||||||
<tr>
|
<TableHeader>
|
||||||
<th className="p-1 border">Nazwa pliku</th>
|
<TableRow>
|
||||||
<th className="p-1 border">Typ</th>
|
<TableHead>Nazwa pliku</TableHead>
|
||||||
<th className="p-1 border">Dodano</th>
|
<TableHead>Typ</TableHead>
|
||||||
<th className="p-1 border">Zmodyfikowano</th>
|
<TableHead className="text-center">Dodano</TableHead>
|
||||||
<th className="p-1 border">Pobierz</th>
|
<TableHead className="text-center">Zmodyfikowano</TableHead>
|
||||||
</tr>
|
<TableHead className="text-center">Akcje</TableHead>
|
||||||
</thead>
|
</TableRow>
|
||||||
<tbody>
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
{props.attachments.map((attachment) => <AttachmentRow key={attachment.attachmentId} attachment={attachment} />)}
|
{props.attachments.map((attachment) => <AttachmentRow key={attachment.attachmentId} attachment={attachment} />)}
|
||||||
</tbody>
|
</TableBody>
|
||||||
</table>
|
</Table>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +195,13 @@ function AttachmentRow(props: AttachmentRow.Props) {
|
|||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}, [props.attachment.attachmentId, props.attachment.pieceId]);
|
}, [props.attachment.attachmentId, props.attachment.pieceId]);
|
||||||
|
|
||||||
const open = useCallback(async () => {
|
const open = useCallback(async (event: MouseEvent<HTMLAnchorElement>) => {
|
||||||
|
if (props.attachment.mediaType !== "application/pdf") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
const { error, data: _data } = await client
|
const { error, data: _data } = await client
|
||||||
.piece({ pieceId: props.attachment.pieceId })
|
.piece({ pieceId: props.attachment.pieceId })
|
||||||
.attachment({ attachmentId: props.attachment.attachmentId })
|
.attachment({ attachmentId: props.attachment.attachmentId })
|
||||||
@@ -186,47 +216,41 @@ function AttachmentRow(props: AttachmentRow.Props) {
|
|||||||
const url = URL.createObjectURL(data.data);
|
const url = URL.createObjectURL(data.data);
|
||||||
window.open(url, "_target");
|
window.open(url, "_target");
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}, [props.attachment.attachmentId, props.attachment.pieceId, props.attachment.mediaType]);
|
}, [props.attachment.mediaType, props.attachment.attachmentId, props.attachment.pieceId]);
|
||||||
|
|
||||||
const onOpen = useCallback((event: MouseEvent<HTMLAnchorElement>) => {
|
|
||||||
if (props.attachment.mediaType !== "application/pdf") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
open();
|
|
||||||
}, [props.attachment.mediaType, open]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<TableRow>
|
||||||
<td className="p-1 border">
|
<TableCell>
|
||||||
{props.attachment.mediaType === "application/vnd.recordare.musicxml"
|
{props.attachment.mediaType === "application/vnd.recordare.musicxml"
|
||||||
|| props.attachment.mediaType === "application/vnd.recordare.musicxml+xml"
|
|| props.attachment.mediaType === "application/vnd.recordare.musicxml+xml"
|
||||||
|| props.attachment.mediaType === "application/pdf" ? (
|
|| props.attachment.mediaType === "application/pdf" ? (
|
||||||
<Link className="underline" to={`attachment/${props.attachment.attachmentId}`} onClick={onOpen}>
|
<Link className="underline" to={`attachment/${props.attachment.attachmentId}`} onClick={open}>
|
||||||
{props.attachment.filename}
|
{props.attachment.filename}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
props.attachment.filename
|
props.attachment.filename
|
||||||
)}
|
)}
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="p-1 border">{props.attachment.mediaType}</td>
|
<TableCell>{props.attachment.mediaType}</TableCell>
|
||||||
<td className="p-1 border text-center font-mono text-sm">
|
<TableCell className="text-center font-mono text-xs">
|
||||||
{props.attachment.createdAt}
|
{props.attachment.createdAt}
|
||||||
{props.attachment.createdBy !== null && <><br />przez {props.attachment.createdBy}</>}
|
{props.attachment.createdBy !== null && <><br />przez {props.attachment.createdBy}</>}
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="p-1 border text-center font-mono text-sm">
|
<TableCell className="text-center font-mono text-xs">
|
||||||
{props.attachment.modifiedAt === null && props.attachment.modifiedBy === null ? "\u2014"
|
{props.attachment.modifiedAt === null && props.attachment.modifiedBy === null ? "\u2014"
|
||||||
: props.attachment.modifiedAt !== null && props.attachment.modifiedBy === null ? props.attachment.modifiedAt
|
: props.attachment.modifiedAt !== null && props.attachment.modifiedBy === null ? props.attachment.modifiedAt
|
||||||
: props.attachment.modifiedAt === null ? `przez ${props.attachment.createdBy}`
|
: props.attachment.modifiedAt === null ? `przez ${props.attachment.createdBy}`
|
||||||
: <>{props.attachment.createdAt}<br />przez {props.attachment.createdBy}</>}
|
: <>{props.attachment.createdAt}<br />przez {props.attachment.createdBy}</>}
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="p-1 border text-center">
|
<TableCell className="text-center flex justify-center gap-4">
|
||||||
<Button type="button" onClick={download}>
|
<Button type="button" variant="ghost" size="icon" title="Pobierz" onClick={download}>
|
||||||
Pobierz
|
<Download />
|
||||||
</Button>
|
</Button>
|
||||||
</td>
|
<Button type="button" variant="ghost" size="icon" title="Usuń">
|
||||||
</tr>
|
<Trash />
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,9 +270,14 @@ function AttachmentForm(props: AttachmentForm.Props) {
|
|||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
const { error } = await client.piece({ pieceId: props.pieceId }).attachment.post({
|
const { error } = await client.piece({ pieceId: props.pieceId }).attachment.post({
|
||||||
filename,
|
filename,
|
||||||
mediaType,
|
mediaType,
|
||||||
@@ -264,29 +293,36 @@ function AttachmentForm(props: AttachmentForm.Props) {
|
|||||||
if (fileInputRef.current !== null) {
|
if (fileInputRef.current !== null) {
|
||||||
fileInputRef.current.files = null;
|
fileInputRef.current.files = null;
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="p-2 flex flex-col gap-2 border rounded" onSubmit={onSubmit}>
|
<form className="flex flex-col gap-4" onSubmit={onSubmit}>
|
||||||
<label htmlFor={filenameId}>Nazwa pliku</label>
|
<div className="grid items-baseline grid-cols-4 gap-4">
|
||||||
|
<Label htmlFor={filenameId} className="text-right">Nazwa pliku</Label>
|
||||||
<Input
|
<Input
|
||||||
id={filenameId}
|
id={filenameId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={filename}
|
value={filename}
|
||||||
required
|
required
|
||||||
onChange={(e) => reduce(FileReducer.setFilename(e.target.value))}
|
onChange={(e) => reduce(FileReducer.setFilename(e.target.value))}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={mediaTypeId}>Typ</label>
|
<Label htmlFor={mediaTypeId} className="text-right">Typ</Label>
|
||||||
<Input
|
<Input
|
||||||
id={mediaTypeId}
|
id={mediaTypeId}
|
||||||
|
className="col-span-3"
|
||||||
type="text"
|
type="text"
|
||||||
value={mediaType}
|
value={mediaType}
|
||||||
onChange={(e) => reduce(FileReducer.setMediaType(e.target.value))}
|
onChange={(e) => reduce(FileReducer.setMediaType(e.target.value))}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={fileId}>Plik</label>
|
<Label htmlFor={fileId} className="text-right">Plik</Label>
|
||||||
<Input
|
<Input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
id={fileId}
|
id={fileId}
|
||||||
|
className="col-span-3"
|
||||||
type="file"
|
type="file"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const file = e.target.files?.item(0) ?? null;
|
const file = e.target.files?.item(0) ?? null;
|
||||||
@@ -294,9 +330,13 @@ function AttachmentForm(props: AttachmentForm.Props) {
|
|||||||
}}
|
}}
|
||||||
accept={ACCEPTED_EXTENSIONS}
|
accept={ACCEPTED_EXTENSIONS}
|
||||||
/>
|
/>
|
||||||
<Button type="submit">
|
</div>
|
||||||
|
<div className="flex flex-col-reverse items-end">
|
||||||
|
<Button type="submit" disabled={isLoading}>
|
||||||
|
{isLoading && <Loader2 className="animate-spin" />}
|
||||||
Dodaj
|
Dodaj
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import { client } from "@/client";
|
||||||
|
import { Button, buttonVariants } from "@/components/ui/button";
|
||||||
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||||
|
import { useStore } from "@/hooks/useStore";
|
||||||
|
import { LogOut, Settings, User } from "lucide-react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Link, Outlet, useNavigate } from "react-router-dom";
|
import { Link, Outlet, useNavigate } from "react-router-dom";
|
||||||
import { client } from "../client";
|
|
||||||
import { useStore } from "../store";
|
|
||||||
import { Button } from "../styled/Button";
|
|
||||||
|
|
||||||
export function Root() {
|
export function Root() {
|
||||||
|
|
||||||
@@ -47,20 +49,25 @@ export function Root() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full overflow-hidden flex flex-col items-stretch">
|
<div className="w-full h-full overflow-hidden flex flex-col items-stretch">
|
||||||
<div className="flex p-4 justify-between items-baseline">
|
<div className="flex p-4 justify-between items-baseline border-b">
|
||||||
<div>
|
<Link className={buttonVariants({ variant: "outline" })} to="/">
|
||||||
<Link className="underline" to="/">
|
|
||||||
Repozytorium muzyczne
|
Repozytorium muzyczne
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
<DropdownMenu>
|
||||||
<div className="flex items-baseline gap-4">
|
<DropdownMenuTrigger asChild>
|
||||||
<div>
|
<Button type="button" variant="outline">
|
||||||
{user.username}
|
<User />{user.username}
|
||||||
</div>
|
|
||||||
<Button type="button" onClick={onLogoutClick}>
|
|
||||||
Wyloguj się
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<Settings />Ustawienia
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem onClick={onLogoutClick}>
|
||||||
|
<LogOut />Wyloguj się
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
<Outlet context={user} />
|
<Outlet context={user} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import { ButtonHTMLAttributes, DetailedHTMLProps, forwardRef } from "react";
|
|
||||||
|
|
||||||
export namespace Button {
|
|
||||||
export type Props = Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "className">;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Button = forwardRef<HTMLButtonElement, Button.Props>(function Button({ children, ...props }, ref) {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
className="p-2 bg-stone-300 border-2 border-t-stone-200 border-l-stone-200 border-r-stone-600 border-b-stone-600 active:border-t-stone-600 active:border-l-stone-600 active:border-r-stone-200 active:border-b-stone-200 rounded focus:outline focus:outline-2 focus:outline-red-500"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { DetailedHTMLProps, forwardRef, InputHTMLAttributes } from "react";
|
|
||||||
|
|
||||||
export namespace Input {
|
|
||||||
export type Props = Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "className">;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Input = forwardRef<HTMLInputElement, Input.Props>(function Input({ children, ...props }, ref) {
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
className="w-[32ch] p-2 bg-transparent border rounded focus:outline focus:outline-2 focus:outline-red-500"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</input>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export function timeout(timeMs: number): Promise<void> {
|
|
||||||
return new Promise<void>((resolve) => setTimeout(resolve, timeMs));
|
|
||||||
}
|
|
||||||
@@ -2,10 +2,13 @@
|
|||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": ["react", "react-dom"],
|
"types": ["react", "react-dom"],
|
||||||
|
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"],
|
"@/*": ["./src/*"],
|
||||||
|
"common": ["../common/src/index.ts"],
|
||||||
|
"common/*": ["../common/src/*.ts"],
|
||||||
|
"backend": ["../backend/src/index.ts"],
|
||||||
|
"backend/*": ["../backend/src/*.ts"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"references": [
|
"references": [
|
||||||
|
|||||||
741
pnpm-lock.yaml
generated
741
pnpm-lock.yaml
generated
@@ -12,6 +12,18 @@ catalogs:
|
|||||||
'@elysiajs/eden':
|
'@elysiajs/eden':
|
||||||
specifier: ^1.1.3
|
specifier: ^1.1.3
|
||||||
version: 1.1.3
|
version: 1.1.3
|
||||||
|
'@radix-ui/react-dialog':
|
||||||
|
specifier: ^1.1.2
|
||||||
|
version: 1.1.2
|
||||||
|
'@radix-ui/react-dropdown-menu':
|
||||||
|
specifier: ^2.1.2
|
||||||
|
version: 2.1.2
|
||||||
|
'@radix-ui/react-label':
|
||||||
|
specifier: ^2.1.0
|
||||||
|
version: 2.1.0
|
||||||
|
'@radix-ui/react-slot':
|
||||||
|
specifier: ^1.1.0
|
||||||
|
version: 1.1.0
|
||||||
'@types/bun':
|
'@types/bun':
|
||||||
specifier: ^1.1.13
|
specifier: ^1.1.13
|
||||||
version: 1.1.13
|
version: 1.1.13
|
||||||
@@ -120,6 +132,18 @@ importers:
|
|||||||
'@elysiajs/eden':
|
'@elysiajs/eden':
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 1.1.3(elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3))
|
version: 1.1.3(elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3))
|
||||||
|
'@radix-ui/react-dialog':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-dropdown-menu':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-label':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 2.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-slot':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
clsx:
|
clsx:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
@@ -419,6 +443,21 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@floating-ui/core@1.6.8':
|
||||||
|
resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.6.12':
|
||||||
|
resolution: {integrity: sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==}
|
||||||
|
|
||||||
|
'@floating-ui/react-dom@2.1.2':
|
||||||
|
resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
react-dom: '>=16.8.0'
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.8':
|
||||||
|
resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==}
|
||||||
|
|
||||||
'@gar/promisify@1.1.3':
|
'@gar/promisify@1.1.3':
|
||||||
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
|
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
|
||||||
|
|
||||||
@@ -469,6 +508,298 @@ packages:
|
|||||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
'@radix-ui/primitive@1.1.0':
|
||||||
|
resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==}
|
||||||
|
|
||||||
|
'@radix-ui/react-arrow@1.1.0':
|
||||||
|
resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-collection@1.1.0':
|
||||||
|
resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-compose-refs@1.1.0':
|
||||||
|
resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-context@1.1.0':
|
||||||
|
resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-context@1.1.1':
|
||||||
|
resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-dialog@1.1.2':
|
||||||
|
resolution: {integrity: sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-direction@1.1.0':
|
||||||
|
resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-dismissable-layer@1.1.1':
|
||||||
|
resolution: {integrity: sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-dropdown-menu@2.1.2':
|
||||||
|
resolution: {integrity: sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-focus-guards@1.1.1':
|
||||||
|
resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-focus-scope@1.1.0':
|
||||||
|
resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-id@1.1.0':
|
||||||
|
resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-label@2.1.0':
|
||||||
|
resolution: {integrity: sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-menu@2.1.2':
|
||||||
|
resolution: {integrity: sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-popper@1.2.0':
|
||||||
|
resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-portal@1.1.2':
|
||||||
|
resolution: {integrity: sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-presence@1.1.1':
|
||||||
|
resolution: {integrity: sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-primitive@2.0.0':
|
||||||
|
resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-roving-focus@1.1.0':
|
||||||
|
resolution: {integrity: sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-slot@1.1.0':
|
||||||
|
resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-callback-ref@1.1.0':
|
||||||
|
resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-controllable-state@1.1.0':
|
||||||
|
resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-escape-keydown@1.1.0':
|
||||||
|
resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-layout-effect@1.1.0':
|
||||||
|
resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-rect@1.1.0':
|
||||||
|
resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-size@1.1.0':
|
||||||
|
resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/rect@1.1.0':
|
||||||
|
resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==}
|
||||||
|
|
||||||
'@remix-run/router@1.21.0':
|
'@remix-run/router@1.21.0':
|
||||||
resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==}
|
resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -661,6 +992,10 @@ packages:
|
|||||||
arg@5.0.2:
|
arg@5.0.2:
|
||||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||||
|
|
||||||
|
aria-hidden@1.2.4:
|
||||||
|
resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
autoprefixer@10.4.20:
|
autoprefixer@10.4.20:
|
||||||
resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
|
resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
@@ -816,6 +1151,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
detect-node-es@1.1.0:
|
||||||
|
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
|
||||||
|
|
||||||
didyoumean@1.2.2:
|
didyoumean@1.2.2:
|
||||||
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
||||||
|
|
||||||
@@ -933,6 +1271,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
get-nonce@1.0.1:
|
||||||
|
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
github-from-package@0.0.0:
|
github-from-package@0.0.0:
|
||||||
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
|
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
|
||||||
|
|
||||||
@@ -1023,6 +1365,9 @@ packages:
|
|||||||
ini@1.3.8:
|
ini@1.3.8:
|
||||||
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
||||||
|
|
||||||
|
invariant@2.2.4:
|
||||||
|
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
|
||||||
|
|
||||||
ip-address@9.0.5:
|
ip-address@9.0.5:
|
||||||
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
|
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
|
||||||
engines: {node: '>= 12'}
|
engines: {node: '>= 12'}
|
||||||
@@ -1398,6 +1743,26 @@ packages:
|
|||||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
react-remove-scroll-bar@2.3.6:
|
||||||
|
resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
react-remove-scroll@2.6.0:
|
||||||
|
resolution: {integrity: sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
react-router-dom@6.28.0:
|
react-router-dom@6.28.0:
|
||||||
resolution: {integrity: sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==}
|
resolution: {integrity: sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -1411,6 +1776,16 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16.8'
|
react: '>=16.8'
|
||||||
|
|
||||||
|
react-style-singleton@2.2.1:
|
||||||
|
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
react@18.3.1:
|
react@18.3.1:
|
||||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -1607,6 +1982,9 @@ packages:
|
|||||||
ts-interface-checker@0.1.13:
|
ts-interface-checker@0.1.13:
|
||||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||||
|
|
||||||
|
tslib@2.8.1:
|
||||||
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
tunnel-agent@0.6.0:
|
tunnel-agent@0.6.0:
|
||||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||||
|
|
||||||
@@ -1641,6 +2019,26 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
browserslist: '>= 4.21.0'
|
browserslist: '>= 4.21.0'
|
||||||
|
|
||||||
|
use-callback-ref@1.3.2:
|
||||||
|
resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
use-sidecar@1.1.2:
|
||||||
|
resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
@@ -1908,6 +2306,23 @@ snapshots:
|
|||||||
'@esbuild/win32-x64@0.21.5':
|
'@esbuild/win32-x64@0.21.5':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@floating-ui/core@1.6.8':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/utils': 0.2.8
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.6.12':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/core': 1.6.8
|
||||||
|
'@floating-ui/utils': 0.2.8
|
||||||
|
|
||||||
|
'@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/dom': 1.6.12
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.8': {}
|
||||||
|
|
||||||
'@gar/promisify@1.1.3':
|
'@gar/promisify@1.1.3':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -1964,6 +2379,275 @@ snapshots:
|
|||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/primitive@1.1.0': {}
|
||||||
|
|
||||||
|
'@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-context@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-context@1.1.1(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-dialog@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.0
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-portal': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
aria-hidden: 1.2.4
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
react-remove-scroll: 2.6.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-direction@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.0
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-dropdown-menu@2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.0
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-menu': 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-focus-guards@1.1.1(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-id@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-label@2.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-menu@2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.0
|
||||||
|
'@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-portal': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
aria-hidden: 1.2.4
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
react-remove-scroll: 2.6.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-size': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/rect': 1.1.0
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-portal@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-presence@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.0
|
||||||
|
'@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
'@types/react-dom': 18.3.1
|
||||||
|
|
||||||
|
'@radix-ui/react-slot@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-use-rect@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/rect': 1.1.0
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/react-use-size@1.1.0(@types/react@18.3.12)(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react: 18.3.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
'@radix-ui/rect@1.1.0': {}
|
||||||
|
|
||||||
'@remix-run/router@1.21.0': {}
|
'@remix-run/router@1.21.0': {}
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.27.2':
|
'@rollup/rollup-android-arm-eabi@4.27.2':
|
||||||
@@ -2133,6 +2817,10 @@ snapshots:
|
|||||||
|
|
||||||
arg@5.0.2: {}
|
arg@5.0.2: {}
|
||||||
|
|
||||||
|
aria-hidden@1.2.4:
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
autoprefixer@10.4.20(postcss@8.4.49):
|
autoprefixer@10.4.20(postcss@8.4.49):
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.23.3
|
browserslist: 4.23.3
|
||||||
@@ -2312,6 +3000,8 @@ snapshots:
|
|||||||
detect-libc@2.0.3:
|
detect-libc@2.0.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
detect-node-es@1.1.0: {}
|
||||||
|
|
||||||
didyoumean@1.2.2: {}
|
didyoumean@1.2.2: {}
|
||||||
|
|
||||||
dlv@1.1.3: {}
|
dlv@1.1.3: {}
|
||||||
@@ -2444,6 +3134,8 @@ snapshots:
|
|||||||
|
|
||||||
gensync@1.0.0-beta.2: {}
|
gensync@1.0.0-beta.2: {}
|
||||||
|
|
||||||
|
get-nonce@1.0.1: {}
|
||||||
|
|
||||||
github-from-package@0.0.0:
|
github-from-package@0.0.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -2569,6 +3261,10 @@ snapshots:
|
|||||||
ini@1.3.8:
|
ini@1.3.8:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
invariant@2.2.4:
|
||||||
|
dependencies:
|
||||||
|
loose-envify: 1.4.0
|
||||||
|
|
||||||
ip-address@9.0.5:
|
ip-address@9.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
jsbn: 1.1.0
|
jsbn: 1.1.0
|
||||||
@@ -2966,6 +3662,25 @@ snapshots:
|
|||||||
|
|
||||||
react-refresh@0.14.2: {}
|
react-refresh@0.14.2: {}
|
||||||
|
|
||||||
|
react-remove-scroll-bar@2.3.6(@types/react@18.3.12)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
react-remove-scroll@2.6.0(@types/react@18.3.12)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
react-remove-scroll-bar: 2.3.6(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
tslib: 2.8.1
|
||||||
|
use-callback-ref: 1.3.2(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
use-sidecar: 1.1.2(@types/react@18.3.12)(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@remix-run/router': 1.21.0
|
'@remix-run/router': 1.21.0
|
||||||
@@ -2978,6 +3693,15 @@ snapshots:
|
|||||||
'@remix-run/router': 1.21.0
|
'@remix-run/router': 1.21.0
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
|
react-style-singleton@2.2.1(@types/react@18.3.12)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
get-nonce: 1.0.1
|
||||||
|
invariant: 2.2.4
|
||||||
|
react: 18.3.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
react@18.3.1:
|
react@18.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
@@ -3257,6 +3981,8 @@ snapshots:
|
|||||||
|
|
||||||
ts-interface-checker@0.1.13: {}
|
ts-interface-checker@0.1.13: {}
|
||||||
|
|
||||||
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
tunnel-agent@0.6.0:
|
tunnel-agent@0.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
@@ -3290,6 +4016,21 @@ snapshots:
|
|||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
|
|
||||||
|
use-callback-ref@1.3.2(@types/react@18.3.12)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
|
use-sidecar@1.1.2(@types/react@18.3.12)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
detect-node-es: 1.1.0
|
||||||
|
react: 18.3.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
vexflow@1.2.93: {}
|
vexflow@1.2.93: {}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ packages:
|
|||||||
catalog:
|
catalog:
|
||||||
'@elysiajs/cors': '^1.1.1'
|
'@elysiajs/cors': '^1.1.1'
|
||||||
'@elysiajs/eden': '^1.1.3'
|
'@elysiajs/eden': '^1.1.3'
|
||||||
|
'@radix-ui/react-dialog': '^1.1.2'
|
||||||
|
'@radix-ui/react-dropdown-menu': '^2.1.2'
|
||||||
|
'@radix-ui/react-label': '^2.1.0'
|
||||||
|
'@radix-ui/react-slot': '^1.1.0'
|
||||||
'@types/bun': '^1.1.13'
|
'@types/bun': '^1.1.13'
|
||||||
'@types/react': '^18.3.12'
|
'@types/react': '^18.3.12'
|
||||||
'@types/react-dom': '^18.3.1'
|
'@types/react-dom': '^18.3.1'
|
||||||
|
|||||||
Reference in New Issue
Block a user