From 27581d005703148e06cec53a624d88210e9f57ff Mon Sep 17 00:00:00 2001 From: Szymon Nowakowski Date: Sun, 1 Dec 2024 13:46:34 +0100 Subject: [PATCH] Redesign UI with shadcn --- packages/frontend/package.json | 4 + packages/frontend/src/FileReducer.ts | 2 +- packages/frontend/src/app.tsx | 13 +- .../frontend/src/components/ui/button.tsx | 52 ++ packages/frontend/src/components/ui/card.tsx | 79 ++ .../frontend/src/components/ui/dialog.tsx | 107 +++ .../src/components/ui/dropdown-menu.tsx | 179 +++++ packages/frontend/src/components/ui/input.tsx | 21 + packages/frontend/src/components/ui/label.tsx | 24 + packages/frontend/src/components/ui/table.tsx | 109 +++ .../src/{loading.ts => hooks/useLoading.ts} | 2 +- .../src/{store.ts => hooks/useStore.ts} | 0 packages/frontend/src/lib/utils.ts | 4 + .../frontend/src/opensheetmusicdisplay.ts | 1 - packages/frontend/src/routes/Attachment.tsx | 94 ++- packages/frontend/src/routes/Home.tsx | 200 +++-- packages/frontend/src/routes/Login.tsx | 103 ++- packages/frontend/src/routes/Piece.tsx | 312 ++++---- packages/frontend/src/routes/Root.tsx | 41 +- packages/frontend/src/styled/Button.tsx | 17 - packages/frontend/src/styled/Input.tsx | 17 - packages/frontend/src/utils.ts | 3 - packages/frontend/tsconfig.json | 5 +- pnpm-lock.yaml | 741 ++++++++++++++++++ pnpm-workspace.yaml | 4 + 25 files changed, 1758 insertions(+), 376 deletions(-) create mode 100644 packages/frontend/src/components/ui/button.tsx create mode 100644 packages/frontend/src/components/ui/card.tsx create mode 100644 packages/frontend/src/components/ui/dialog.tsx create mode 100644 packages/frontend/src/components/ui/dropdown-menu.tsx create mode 100644 packages/frontend/src/components/ui/input.tsx create mode 100644 packages/frontend/src/components/ui/label.tsx create mode 100644 packages/frontend/src/components/ui/table.tsx rename packages/frontend/src/{loading.ts => hooks/useLoading.ts} (96%) rename packages/frontend/src/{store.ts => hooks/useStore.ts} (100%) delete mode 100644 packages/frontend/src/opensheetmusicdisplay.ts delete mode 100644 packages/frontend/src/styled/Button.tsx delete mode 100644 packages/frontend/src/styled/Input.tsx delete mode 100644 packages/frontend/src/utils.ts diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 5936bca..1c28999 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -18,6 +18,10 @@ }, "dependencies": { "@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:", "common": "workspace:^", "lucide-react": "catalog:", diff --git a/packages/frontend/src/FileReducer.ts b/packages/frontend/src/FileReducer.ts index ed3ad13..6811cfe 100644 --- a/packages/frontend/src/FileReducer.ts +++ b/packages/frontend/src/FileReducer.ts @@ -1,5 +1,5 @@ +import { mapProp, Update } from "@/hooks/useStore"; import { getMediaTypeForFile } from "common/MediaType"; -import { mapProp, Update } from "./store"; export function FileReducer(prev: FileReducer.State, action: FileReducer.Action): FileReducer.State { switch (action.type) { diff --git a/packages/frontend/src/app.tsx b/packages/frontend/src/app.tsx index d5513f1..3dcc97f 100644 --- a/packages/frontend/src/app.tsx +++ b/packages/frontend/src/app.tsx @@ -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 { 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"; +const Attachment = lazy(() => import("@/routes/Attachment")); + const router = createBrowserRouter([ { path: "/", diff --git a/packages/frontend/src/components/ui/button.tsx b/packages/frontend/src/components/ui/button.tsx new file mode 100644 index 0000000..93bfb7b --- /dev/null +++ b/packages/frontend/src/components/ui/button.tsx @@ -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, + VariantProps { + asChild?: boolean; +} + +const Button = forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/packages/frontend/src/components/ui/card.tsx b/packages/frontend/src/components/ui/card.tsx new file mode 100644 index 0000000..c7862b2 --- /dev/null +++ b/packages/frontend/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import { cn } from "@/lib/utils"; +import { forwardRef } from "react"; + +const Card = forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +Card.displayName = "Card"; + +const CardHeader = forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardHeader.displayName = "CardHeader"; + +const CardTitle = forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardTitle.displayName = "CardTitle"; + +const CardDescription = forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardDescription.displayName = "CardDescription"; + +const CardContent = forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardContent.displayName = "CardContent"; + +const CardFooter = forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardFooter.displayName = "CardFooter"; + +export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }; + diff --git a/packages/frontend/src/components/ui/dialog.tsx b/packages/frontend/src/components/ui/dialog.tsx new file mode 100644 index 0000000..3a2070c --- /dev/null +++ b/packages/frontend/src/components/ui/dialog.tsx @@ -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, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = "DialogHeader"; + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = "DialogFooter"; + +const DialogTitle = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger +}; diff --git a/packages/frontend/src/components/ui/dropdown-menu.tsx b/packages/frontend/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..9b93847 --- /dev/null +++ b/packages/frontend/src/components/ui/dropdown-menu.tsx @@ -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, + React.ComponentPropsWithoutRef & { + inset?: boolean, + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)); +DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; + +const DropdownMenuSubContent = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; + +const DropdownMenuContent = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; + +const DropdownMenuItem = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean, + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; + +const DropdownMenuCheckboxItem = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; + +const DropdownMenuRadioItem = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; + +const DropdownMenuLabel = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; + +const DropdownMenuSeparator = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +}; +DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; + +export { + DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, + DropdownMenuShortcut, DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, DropdownMenuTrigger +}; + diff --git a/packages/frontend/src/components/ui/input.tsx b/packages/frontend/src/components/ui/input.tsx new file mode 100644 index 0000000..7d19eb2 --- /dev/null +++ b/packages/frontend/src/components/ui/input.tsx @@ -0,0 +1,21 @@ +import { cn } from "@/lib/utils"; +import { forwardRef } from "react"; + +const Input = forwardRef>( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/packages/frontend/src/components/ui/label.tsx b/packages/frontend/src/components/ui/label.tsx new file mode 100644 index 0000000..3bcd9ba --- /dev/null +++ b/packages/frontend/src/components/ui/label.tsx @@ -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, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; + diff --git a/packages/frontend/src/components/ui/table.tsx b/packages/frontend/src/components/ui/table.tsx new file mode 100644 index 0000000..8fff976 --- /dev/null +++ b/packages/frontend/src/components/ui/table.tsx @@ -0,0 +1,109 @@ +import { cn } from "@/lib/utils"; +import { forwardRef } from "react"; + +const Table = forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)); +Table.displayName = "Table"; + +const TableHeader = forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableHeader.displayName = "TableHeader"; + +const TableBody = forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableBody.displayName = "TableBody"; + +const TableFooter = forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0 dark:bg-stone-800/50", + className + )} + {...props} + /> +)); +TableFooter.displayName = "TableFooter"; + +const TableRow = forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableRow.displayName = "TableRow"; + +const TableHead = forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableHead.displayName = "TableHead"; + +const TableCell = forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableCell.displayName = "TableCell"; + +const TableCaption = forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableCaption.displayName = "TableCaption"; + +export { + Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow +}; diff --git a/packages/frontend/src/loading.ts b/packages/frontend/src/hooks/useLoading.ts similarity index 96% rename from packages/frontend/src/loading.ts rename to packages/frontend/src/hooks/useLoading.ts index 5abcefa..795518f 100644 --- a/packages/frontend/src/loading.ts +++ b/packages/frontend/src/hooks/useLoading.ts @@ -1,8 +1,8 @@ +import { useStore } from "@/hooks/useStore"; import { Treaty } from "@elysiajs/eden"; import { ELYSIA_FORM_DATA } from "elysia"; import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; -import { useStore } from "./store"; type FormDataFix = T extends { [ELYSIA_FORM_DATA]: infer U } ? U : T; diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/hooks/useStore.ts similarity index 100% rename from packages/frontend/src/store.ts rename to packages/frontend/src/hooks/useStore.ts diff --git a/packages/frontend/src/lib/utils.ts b/packages/frontend/src/lib/utils.ts index 3200be2..449fb08 100644 --- a/packages/frontend/src/lib/utils.ts +++ b/packages/frontend/src/lib/utils.ts @@ -4,3 +4,7 @@ import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +export function timeout(timeMs: number): Promise { + return new Promise((resolve) => setTimeout(resolve, timeMs)); +} diff --git a/packages/frontend/src/opensheetmusicdisplay.ts b/packages/frontend/src/opensheetmusicdisplay.ts deleted file mode 100644 index 257fbe9..0000000 --- a/packages/frontend/src/opensheetmusicdisplay.ts +++ /dev/null @@ -1 +0,0 @@ -export { OpenSheetMusicDisplay as default } from "opensheetmusicdisplay"; diff --git a/packages/frontend/src/routes/Attachment.tsx b/packages/frontend/src/routes/Attachment.tsx index b3f87fa..628b036 100644 --- a/packages/frontend/src/routes/Attachment.tsx +++ b/packages/frontend/src/routes/Attachment.tsx @@ -1,66 +1,60 @@ +import { client } from "@/client"; +import { useLoading } from "@/hooks/useLoading.ts"; 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 { client } from "../client"; -import { useLoading } from "../loading"; -export const Attachment = lazy(async () => { +export default function Attachment() { - const { default: OpenSheetMusicDisplay } = await import("../opensheetmusicdisplay.ts"); + const params = useParams(); + const pieceId = PieceId(params.pieceId!); + const attachmentId = AttachmentId(params.attachmentId!); - return { - default: function Attachment() { + const { isLoading, error, data } = useLoading(() => client.piece({ pieceId }).attachment({ attachmentId }).get()); - const params = useParams(); - const pieceId = PieceId(params.pieceId!); - const attachmentId = AttachmentId(params.attachmentId!); + const containerRef = useRef(null); - const { isLoading, error, data } = useLoading(() => client.piece({ pieceId }).attachment({ attachmentId }).get()); + useEffect(() => { + if (isLoading || error !== null) return; - const containerRef = useRef(null); + const url = URL.createObjectURL(data?.data); - useEffect(() => { - if (isLoading || error !== null) return; + const render = () => osmd.render(); - const url = URL.createObjectURL(data?.data); + const osmd = new OpenSheetMusicDisplay(containerRef.current!, { + autoResize: false, + drawTitle: false, + drawComposer: false, + drawMeasureNumbers: true, + drawMeasureNumbersOnlyAtSystemStart: true, + //measureNumberInterval: 5, + //renderSingleHorizontalStaffline: true, + }); - const render = () => osmd.render(); + osmd.load(url).then(render); - const osmd = new OpenSheetMusicDisplay(containerRef.current!, { - autoResize: false, - drawTitle: false, - drawComposer: false, - drawMeasureNumbers: true, - drawMeasureNumbersOnlyAtSystemStart: true, - //measureNumberInterval: 5, - //renderSingleHorizontalStaffline: true, - }); + window.addEventListener("resize", render); - osmd.load(url).then(render); + return () => { + URL.revokeObjectURL(url); + window.removeEventListener("resize", render); + }; + }, [isLoading, data]); - window.addEventListener("resize", render); + if (isLoading) { + return ( +
+
Ładowanie…
+
+ ); + } - return () => { - URL.revokeObjectURL(url); - window.removeEventListener("resize", render); - }; - }, [isLoading, data]); + if (error !== null) { +
+
Wystąpił błąd: {error.value}
+
+ } - if (isLoading) { - return ( -
-
Ładowanie…
-
- ); - } - - if (error !== null) { -
-
Wystąpił błąd: {error.value}
-
- } - - return
; - }, - }; -}); + return
; +}; diff --git a/packages/frontend/src/routes/Home.tsx b/packages/frontend/src/routes/Home.tsx index 97369c5..3451739 100644 --- a/packages/frontend/src/routes/Home.tsx +++ b/packages/frontend/src/routes/Home.tsx @@ -1,9 +1,13 @@ -import { FormEventHandler, ReactNode, useId, useRef, useState } from "react"; -import { Link } from "react-router-dom"; -import { client } from "../client"; -import { useLoading } from "../loading"; -import { Button } from "../styled/Button"; -import { Input } from "../styled/Input"; +import { client } from "@/client"; +import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +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() { @@ -18,20 +22,28 @@ export function Home() { } return ( -
+
{error !== null ? ( `Wystąpił błąd: ${error.value}` - ) : ( - - - - - - - - - - + ) : (<> + + + + + + +
TytułTwórcyDodanoZmodyfikowano
+ + + Tytuł + Twórcy + Dodano + Zmodyfikowano + + + {data.map((piece) => { const composerParts: ReactNode[] = []; 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 (composerParts.length === 0) composerParts.push(Nieznani); return ( - - - - - - + : piece.modifiedAt !== null && piece.modifiedBy === null ? piece.modifiedAt + : piece.modifiedAt === null ? `przez ${piece.createdBy}` + : <>{piece.createdAt}
przez {piece.createdBy}} + + ); })} - -
{piece.name}{...composerParts.flatMap((x, i, a) => i < a.length - 1 ? [x,
] : [x])}
+ + {piece.name} + {...composerParts.flatMap((x, i, a) => i < a.length - 1 ? [x,
] : [x])}
+ {piece.createdAt} {piece.createdBy !== null && <>
przez {piece.createdBy}} -
+ + {piece.modifiedAt === null && piece.modifiedBy === null ? "\u2014" - : piece.modifiedAt !== null && piece.modifiedBy === null ? piece.modifiedAt - : piece.modifiedAt === null ? `przez ${piece.createdBy}` - : <>{piece.createdAt}
przez {piece.createdBy}} -
- )} - + +
+ )}
); } -function PieceForm() { +function AddPieceDialogContent() { + + const navigate = useNavigate(); const [name, setName] = useState(""); const [composer, setComposer] = useState(""); @@ -75,66 +88,81 @@ function PieceForm() { const lyricistId = useId(); const arrangerId = useId(); - const autoFocusRef = useRef(null); + const [isLoading, setIsLoading] = useState(false); const onSubmit: FormEventHandler = async (e) => { e.preventDefault(); - const { error } = await client.piece.post({ - name, - composer: composer.length > 0 ? composer : null, - lyricist: lyricist.length > 0 ? lyricist : null, - arranger: arranger.length > 0 ? arranger : null, - }); + try { + setIsLoading(true); - if (error) { - console.error(error.value); - return; + const { data, error } = await client.piece.post({ + name, + composer: composer.length > 0 ? composer : null, + lyricist: lyricist.length > 0 ? lyricist : null, + arranger: arranger.length > 0 ? arranger : null, + }); + + if (error !== null) { + console.error(error.value); + return; + } + + navigate(`piece/${data.pieceId}`); + } finally { + setIsLoading(false); } - - setName(""); - setComposer(""); - setLyricist(""); - setArranger(""); - - autoFocusRef.current?.focus(); } return ( -
- - setName(e.target.value)} - /> - - setComposer(e.target.value)} - /> - - setLyricist(e.target.value)} - /> - - setArranger(e.target.value)} - /> - -
+ +
+ + Dodaj utwór + +
+ + setName(e.target.value)} + /> + + setComposer(e.target.value)} + /> + + setLyricist(e.target.value)} + /> + + setArranger(e.target.value)} + /> +
+ + + +
+
); } diff --git a/packages/frontend/src/routes/Login.tsx b/packages/frontend/src/routes/Login.tsx index 8e3149f..287bf59 100644 --- a/packages/frontend/src/routes/Login.tsx +++ b/packages/frontend/src/routes/Login.tsx @@ -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 { client } from "../client"; -import { useStore } from "../store"; -import { Button } from "../styled/Button"; -import { Input } from "../styled/Input"; export function Login() { @@ -20,50 +23,70 @@ export function Login() { const usernameId = useId(); const passwordId = useId(); + const [isLoading, setIsLoading] = useState(false); + const onSubmit: FormEventHandler = async (e) => { e.preventDefault(); - const { data, error } = await client.login.post({ - username: loginUsername, - password: loginPassword, - }); + try { + setIsLoading(true); - if (error) { - console.error(error.value); - return; + const { data, error } = await client.login.post({ + username: loginUsername, + password: loginPassword, + }); + + if (error) { + console.error(error.value); + return; + } + + setLoginUsername(""); + setLoginPassword(""); + setUser(data); + + navigate("/"); + } finally { + setIsLoading(false); } - - setLoginUsername(""); - setLoginPassword(""); - setUser(data); - - navigate("/"); }; return (
-
-
Repozytorium muzyczne
- - setLoginUsername(e.target.value)} - /> - - setLoginPassword(e.target.value)} - /> - + + + + Repozytorium muzyczne + Zaloguj się, aby kontynuować + + + + setLoginUsername(e.target.value)} + /> + + setLoginPassword(e.target.value)} + /> + + + + +
); diff --git a/packages/frontend/src/routes/Piece.tsx b/packages/frontend/src/routes/Piece.tsx index 2a6baf8..1774102 100644 --- a/packages/frontend/src/routes/Piece.tsx +++ b/packages/frontend/src/routes/Piece.tsx @@ -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 { PieceId } from "common"; import { ACCEPTED_EXTENSIONS } from "common/MediaType"; import { ELYSIA_FORM_DATA } from "elysia"; +import { Download, Loader2, Trash } from "lucide-react"; import { FormEventHandler, MouseEvent, useCallback, useId, useReducer, useRef, useState } from "react"; 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() { @@ -32,9 +36,13 @@ export function Piece() { ) : piece.data[0] === undefined ? ( "Utwór nie istnieje" ) : (<> - +
+

Utwór

+ +

Załączniki

+ +
- )}
); @@ -58,61 +66,75 @@ function PieceForm(props: PieceForm.Props) { const lyricistId = useId(); const arrangerId = useId(); - const autoFocusRef = useRef(null); + const [isLoading, setIsLoading] = useState(false); const onSubmit: FormEventHandler = async (e) => { e.preventDefault(); - const { error } = await client.piece({ pieceId: props.piece.pieceId }).put({ - name, - composer: composer.length > 0 ? composer : null, - lyricist: lyricist.length > 0 ? lyricist : null, - arranger: arranger.length > 0 ? arranger : null, - }); + const delay = timeout(250); + try { + setIsLoading(true); - if (error) { - console.error(error.value); - return; + const { error } = await client.piece({ pieceId: props.piece.pieceId }).put({ + name, + composer: composer.length > 0 ? composer : null, + lyricist: lyricist.length > 0 ? lyricist : null, + arranger: arranger.length > 0 ? arranger : null, + }); + + if (error) { + console.error(error.value); + return; + } + } finally { + await delay; + setIsLoading(false); } - - autoFocusRef.current?.focus(); } return ( -
- - setName(e.target.value)} - /> - - setComposer(e.target.value)} - /> - - setLyricist(e.target.value)} - /> - - setArranger(e.target.value)} - /> - + +
+ + setName(e.target.value)} + /> + + setComposer(e.target.value)} + /> + + setLyricist(e.target.value)} + /> + + setArranger(e.target.value)} + /> +
+
+ +
); } @@ -126,20 +148,22 @@ namespace Attachments { function Attachments(props: Attachments.Props) { return ( - - - - - - - - - - - - {props.attachments.map((attachment) => )} - -
Nazwa plikuTypDodanoZmodyfikowanoPobierz
+
+ + + + Nazwa pliku + Typ + Dodano + Zmodyfikowano + Akcje + + + + {props.attachments.map((attachment) => )} + +
+
); } @@ -171,7 +195,13 @@ function AttachmentRow(props: AttachmentRow.Props) { URL.revokeObjectURL(url); }, [props.attachment.attachmentId, props.attachment.pieceId]); - const open = useCallback(async () => { + const open = useCallback(async (event: MouseEvent) => { + if (props.attachment.mediaType !== "application/pdf") { + return; + } + + event.preventDefault(); + const { error, data: _data } = await client .piece({ pieceId: props.attachment.pieceId }) .attachment({ attachmentId: props.attachment.attachmentId }) @@ -186,47 +216,41 @@ function AttachmentRow(props: AttachmentRow.Props) { const url = URL.createObjectURL(data.data); window.open(url, "_target"); URL.revokeObjectURL(url); - }, [props.attachment.attachmentId, props.attachment.pieceId, props.attachment.mediaType]); - - const onOpen = useCallback((event: MouseEvent) => { - if (props.attachment.mediaType !== "application/pdf") { - return; - } - - event.preventDefault(); - open(); - }, [props.attachment.mediaType, open]); + }, [props.attachment.mediaType, props.attachment.attachmentId, props.attachment.pieceId]); return ( - - + + {props.attachment.mediaType === "application/vnd.recordare.musicxml" || props.attachment.mediaType === "application/vnd.recordare.musicxml+xml" || props.attachment.mediaType === "application/pdf" ? ( - + {props.attachment.filename} ) : ( props.attachment.filename )} - - {props.attachment.mediaType} - + + {props.attachment.mediaType} + {props.attachment.createdAt} {props.attachment.createdBy !== null && <>
przez {props.attachment.createdBy}} - - +
+ {props.attachment.modifiedAt === null && props.attachment.modifiedBy === null ? "\u2014" : props.attachment.modifiedAt !== null && props.attachment.modifiedBy === null ? props.attachment.modifiedAt - : props.attachment.modifiedAt === null ? `przez ${props.attachment.createdBy}` - : <>{props.attachment.createdAt}
przez {props.attachment.createdBy}} - - - - - + +
+
); } @@ -246,57 +270,73 @@ function AttachmentForm(props: AttachmentForm.Props) { const fileInputRef = useRef(null); + const [isLoading, setIsLoading] = useState(false); + const onSubmit: FormEventHandler = async (e) => { e.preventDefault(); - const { error } = await client.piece({ pieceId: props.pieceId }).attachment.post({ - filename, - mediaType, - data: file!, - }); + try { + setIsLoading(true); - if (error) { - console.error(error.value); - return; - } + const { error } = await client.piece({ pieceId: props.pieceId }).attachment.post({ + filename, + mediaType, + data: file!, + }); - reduce(FileReducer.reset); - if (fileInputRef.current !== null) { - fileInputRef.current.files = null; + if (error) { + console.error(error.value); + return; + } + + reduce(FileReducer.reset); + if (fileInputRef.current !== null) { + fileInputRef.current.files = null; + } + } finally { + setIsLoading(false); } } return ( -
- - reduce(FileReducer.setFilename(e.target.value))} - /> - - reduce(FileReducer.setMediaType(e.target.value))} - /> - - { - const file = e.target.files?.item(0) ?? null; - reduce(FileReducer.setFile(file)); - }} - accept={ACCEPTED_EXTENSIONS} - /> - + +
+ + reduce(FileReducer.setFilename(e.target.value))} + /> + + reduce(FileReducer.setMediaType(e.target.value))} + /> + + { + const file = e.target.files?.item(0) ?? null; + reduce(FileReducer.setFile(file)); + }} + accept={ACCEPTED_EXTENSIONS} + /> +
+
+ +
); } diff --git a/packages/frontend/src/routes/Root.tsx b/packages/frontend/src/routes/Root.tsx index 1cad5fc..85c1a4a 100644 --- a/packages/frontend/src/routes/Root.tsx +++ b/packages/frontend/src/routes/Root.tsx @@ -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 { Link, Outlet, useNavigate } from "react-router-dom"; -import { client } from "../client"; -import { useStore } from "../store"; -import { Button } from "../styled/Button"; export function Root() { @@ -47,20 +49,25 @@ export function Root() { return (
-
-
- - Repozytorium muzyczne - -
-
-
- {user.username} -
- -
+
+ + Repozytorium muzyczne + + + + + + + + Ustawienia + + + Wyloguj się + + +
diff --git a/packages/frontend/src/styled/Button.tsx b/packages/frontend/src/styled/Button.tsx deleted file mode 100644 index b83fbe6..0000000 --- a/packages/frontend/src/styled/Button.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ButtonHTMLAttributes, DetailedHTMLProps, forwardRef } from "react"; - -export namespace Button { - export type Props = Omit, HTMLButtonElement>, "className">; -} - -export const Button = forwardRef(function Button({ children, ...props }, ref) { - return ( - - ); -}); diff --git a/packages/frontend/src/styled/Input.tsx b/packages/frontend/src/styled/Input.tsx deleted file mode 100644 index 7d6980f..0000000 --- a/packages/frontend/src/styled/Input.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { DetailedHTMLProps, forwardRef, InputHTMLAttributes } from "react"; - -export namespace Input { - export type Props = Omit, HTMLInputElement>, "className">; -} - -export const Input = forwardRef(function Input({ children, ...props }, ref) { - return ( - - {children} - - ); -}); diff --git a/packages/frontend/src/utils.ts b/packages/frontend/src/utils.ts deleted file mode 100644 index ddfee26..0000000 --- a/packages/frontend/src/utils.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function timeout(timeMs: number): Promise { - return new Promise((resolve) => setTimeout(resolve, timeMs)); -} diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index 386772e..a15ce7e 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -2,10 +2,13 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "types": ["react", "react-dom"], - "baseUrl": ".", "paths": { "@/*": ["./src/*"], + "common": ["../common/src/index.ts"], + "common/*": ["../common/src/*.ts"], + "backend": ["../backend/src/index.ts"], + "backend/*": ["../backend/src/*.ts"], }, }, "references": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75893ef..13eaef8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,18 @@ catalogs: '@elysiajs/eden': specifier: ^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': specifier: ^1.1.13 version: 1.1.13 @@ -120,6 +132,18 @@ importers: '@elysiajs/eden': specifier: 'catalog:' 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: specifier: 'catalog:' version: 2.1.1 @@ -419,6 +443,21 @@ packages: cpu: [x64] 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': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} @@ -469,6 +508,298 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 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': resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==} engines: {node: '>=14.0.0'} @@ -661,6 +992,10 @@ packages: arg@5.0.2: 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: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -816,6 +1151,9 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -933,6 +1271,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 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: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -1023,6 +1365,9 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + ip-address@9.0.5: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} @@ -1398,6 +1743,26 @@ packages: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} 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: resolution: {integrity: sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==} engines: {node: '>=14.0.0'} @@ -1411,6 +1776,16 @@ packages: peerDependencies: 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: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -1607,6 +1982,9 @@ packages: ts-interface-checker@0.1.13: 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: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -1641,6 +2019,26 @@ packages: peerDependencies: 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: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1908,6 +2306,23 @@ snapshots: '@esbuild/win32-x64@0.21.5': 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': optional: true @@ -1964,6 +2379,275 @@ snapshots: '@pkgjs/parseargs@0.11.0': 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': {} '@rollup/rollup-android-arm-eabi@4.27.2': @@ -2133,6 +2817,10 @@ snapshots: arg@5.0.2: {} + aria-hidden@1.2.4: + dependencies: + tslib: 2.8.1 + autoprefixer@10.4.20(postcss@8.4.49): dependencies: browserslist: 4.23.3 @@ -2312,6 +3000,8 @@ snapshots: detect-libc@2.0.3: optional: true + detect-node-es@1.1.0: {} + didyoumean@1.2.2: {} dlv@1.1.3: {} @@ -2444,6 +3134,8 @@ snapshots: gensync@1.0.0-beta.2: {} + get-nonce@1.0.1: {} + github-from-package@0.0.0: optional: true @@ -2569,6 +3261,10 @@ snapshots: ini@1.3.8: optional: true + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + ip-address@9.0.5: dependencies: jsbn: 1.1.0 @@ -2966,6 +3662,25 @@ snapshots: 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): dependencies: '@remix-run/router': 1.21.0 @@ -2978,6 +3693,15 @@ snapshots: '@remix-run/router': 1.21.0 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: dependencies: loose-envify: 1.4.0 @@ -3257,6 +3981,8 @@ snapshots: ts-interface-checker@0.1.13: {} + tslib@2.8.1: {} + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 @@ -3290,6 +4016,21 @@ snapshots: escalade: 3.2.0 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: {} vexflow@1.2.93: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ead3a55..bb4aa48 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,6 +4,10 @@ packages: catalog: '@elysiajs/cors': '^1.1.1' '@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/react': '^18.3.12' '@types/react-dom': '^18.3.1'