Users Page - Add User Modal, Edit User Modal (#45)

* feat(users): Add in Add User modal, add in Label component

* feat(users): Make adjustments to Add User modal and Edit user modal

* feat(users): Populate data from mock API

* feat(users): Permissions - do not show team info to users, redirect users
This commit is contained in:
Sophia Dao
2024-08-30 08:30:10 -05:00
committed by GitHub
parent aa44572be5
commit c281f85742
15 changed files with 647 additions and 25 deletions
+10
View File
@@ -3,8 +3,10 @@ import { redirect } from "next/navigation";
import { Suspense } from "react";
import { getUsers } from "@/actions/users";
import { auth } from "@/auth.config";
import { Header } from "@/components/ui";
import {
AddUserModal,
ColumnsUser,
DataTableUser,
SkeletonTableUser,
@@ -12,11 +14,19 @@ import {
import { searchParamsProps } from "@/types";
export default async function Users({ searchParams }: searchParamsProps) {
const session = await auth();
if (session?.user?.role !== "admin") {
redirect("/");
}
return (
<>
<Header title="User Management" icon="ci:users" />
<Spacer y={4} />
<div className="flex flex-col items-end w-full">
<div className="flex space-x-6">
<AddUserModal />
</div>
<Spacer y={6} />
<Suspense key={searchParams.page} fallback={<SkeletonTableUser />}>
<SSRDataTable searchParams={searchParams} />
+200
View File
@@ -0,0 +1,200 @@
"use client";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check, ChevronRight, Circle } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
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 = React.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 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className,
)}
{...props}
>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
));
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName;
const DropdownMenuSubContent = React.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 bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
));
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName;
const DropdownMenuContent = React.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 bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
const DropdownMenuItem = React.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 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className,
)}
{...props}
/>
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
const DropdownMenuCheckboxItem = React.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-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
));
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName;
const DropdownMenuRadioItem = React.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-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
));
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
const DropdownMenuLabel = React.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 = React.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-muted", 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,
};
+2
View File
@@ -2,7 +2,9 @@ export * from "./action-card/ActionCard";
export * from "./alert/Alert";
export * from "./chart/Chart";
export * from "./dialog/Dialog";
export * from "./dropdown/Dropdown";
export * from "./header/Header";
export * from "./label/Label";
export * from "./select/Select";
export * from "./sidebar";
export * from "./table/SeverityBadge";
+26
View File
@@ -0,0 +1,26 @@
"use client";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
const Label = React.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 };
+6 -2
View File
@@ -18,7 +18,7 @@ import {
} from "../../icons/prowler/ProwlerIcons";
import { ThemeSwitch } from "../../ThemeSwitch";
import Sidebar from "./Sidebar";
import { sectionItemsWithTeams } from "./SidebarItems";
import { sectionItems, sectionItemsWithTeams } from "./SidebarItems";
import { UserAvatar } from "./UserAvatar";
export const SidebarWrap = () => {
@@ -81,7 +81,11 @@ export const SidebarWrap = () => {
<Sidebar
defaultSelectedKey="overview"
isCompact={isCompact}
items={sectionItemsWithTeams}
items={
session?.user?.role === "admin"
? sectionItemsWithTeams
: sectionItems
}
selectedKeys={[currentPath]}
/>
</ScrollShadow>
+62
View File
@@ -0,0 +1,62 @@
"use client";
import { Button, Input } from "@nextui-org/react";
import { useRef, useState } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui";
import { ButtonAddUser } from "./ButtonAddUser";
import { CustomSelectUser } from "./CustomSelectUser";
export const AddUserModal = () => {
const [open, setOpen] = useState(false);
const ref = useRef<HTMLFormElement>(null);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button aria-label="Add User" variant="ghost">
Add User
</Button>
</DialogTrigger>
<DialogContent
aria-describedby={undefined}
className="flex flex-col sm:max-w-md md:max-w-lg"
>
<DialogHeader className="mb-6 space-y-3">
<DialogTitle className="text-2xl text-center">Add User</DialogTitle>
</DialogHeader>
<form ref={ref} onSubmit={() => setOpen(false)}>
<div className="col-span-1 flex flex-col gap-y-2 my-auto">
<Input
type="text"
name="email"
label="Email"
labelPlacement="outside"
placeholder="Email"
aria-label="Enter Email"
size="md"
radius="md"
isRequired
fullWidth
classNames={{
base: "h-12 mb-4",
inputWrapper: "h-full",
}}
/>
<CustomSelectUser />
</div>
<div className="col-span-2 flex justify-center mt-4">
<ButtonAddUser />
</div>
</form>
</DialogContent>
</Dialog>
);
};
+14
View File
@@ -0,0 +1,14 @@
"use client";
import { Button } from "@nextui-org/react";
import React from "react";
import { useFormStatus } from "react-dom";
export const ButtonAddUser = () => {
const { pending } = useFormStatus();
return (
<Button type="submit" area-disabled={pending}>
{pending ? "Adding..." : "Invite user"}
</Button>
);
};
+14
View File
@@ -0,0 +1,14 @@
"use client";
import { Button } from "@nextui-org/react";
import React from "react";
import { useFormStatus } from "react-dom";
export const ButtonEditUser = () => {
const { pending } = useFormStatus();
return (
<Button type="submit" area-disabled={pending}>
{pending ? "Saving..." : "Edit user"}
</Button>
);
};
+39
View File
@@ -0,0 +1,39 @@
import {
Label,
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui";
import { UserProps } from "@/types";
interface CustomSelectUserProps {
userData?: UserProps;
}
export const CustomSelectUser: React.FC<CustomSelectUserProps> = ({
userData,
}) => {
return (
<>
<Label htmlFor="role">
Select a role<span className="text-red-500">*</span>
</Label>
<Select>
<SelectTrigger className="shadow-none h-12 rounded-xl bg-zinc-100 border-transparent text-foreground-500 focus:ring-2 focus:ring-blue-600 ring-0 hover:bg-zinc-200 focus:border-2 focus:border-white">
<SelectValue
placeholder={(userData && userData?.role) || "Select a role"}
/>
</SelectTrigger>
<SelectContent className="rounded-xl">
<SelectGroup className="[&>[data-highlighted]]:bg-transparent">
<SelectItem value="user">User</SelectItem>
<SelectItem value="admin">Admin</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</>
);
};
+82
View File
@@ -0,0 +1,82 @@
"use client";
import { Input } from "@nextui-org/react";
import { useRef } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui";
import { UserProps } from "@/types";
import { ButtonEditUser } from "./ButtonEditUser";
import { CustomSelectUser } from "./CustomSelectUser";
interface EditUserModalProps {
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
userData: UserProps;
}
export const EditUserModal: React.FC<EditUserModalProps> = ({
isOpen,
setIsOpen,
userData,
}) => {
const ref = useRef<HTMLFormElement>(null);
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent
aria-describedby={undefined}
className="flex flex-col sm:max-w-md md:max-w-lg"
>
<DialogHeader className="mb-6 space-y-3">
<DialogTitle className="text-2xl text-center">Edit User</DialogTitle>
</DialogHeader>
<form ref={ref} onSubmit={() => setIsOpen(false)}>
<div className="col-span-1 flex flex-col gap-y-2 my-auto">
<Input
type="name"
name="name"
label="Name"
labelPlacement="outside"
placeholder={userData?.name}
aria-label="Enter Name"
size="md"
radius="md"
isRequired
fullWidth
classNames={{
base: "h-12 mb-4",
inputWrapper: "h-full",
}}
/>
<Input
type="text"
name="email"
label="Email"
labelPlacement="outside"
placeholder={userData?.email}
aria-label="Enter Email"
size="md"
radius="md"
isRequired
fullWidth
classNames={{
base: "h-12 mb-4",
inputWrapper: "h-full",
}}
/>
<CustomSelectUser userData={userData} />
</div>
<div className="col-span-2 flex justify-center mt-4">
<ButtonEditUser />
</div>
</form>
</DialogContent>
</Dialog>
);
};
+6
View File
@@ -1,5 +1,11 @@
export * from "./AddUserModal";
export * from "./ButtonAddUser";
export * from "./ButtonEditUser";
export * from "./CustomSelectUser";
export * from "./EditUserModal";
export * from "./table/ColumnsUser";
export * from "./table/DataTableColumnHeader";
export * from "./table/DataTablePagination";
export * from "./table/DataTableUser";
export * from "./table/SkeletonTableUser";
export * from "./table/UserActions";
+4 -23
View File
@@ -1,17 +1,10 @@
"use client";
import {
Button,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownTrigger,
} from "@nextui-org/react";
import { ColumnDef } from "@tanstack/react-table";
import { VerticalDotsIcon } from "@/components/icons";
import { DateWithTime } from "@/components/providers";
import { StatusBadge } from "@/components/ui";
import { UserActions } from "@/components/users";
import { UserProps } from "@/types";
const getUserData = (row: { original: UserProps }) => {
@@ -63,21 +56,9 @@ export const ColumnsUser: ColumnDef<UserProps>[] = [
accessorKey: "actions",
header: () => <div className="text-right">Actions</div>,
id: "actions",
cell: () => {
return (
<div className="relative flex justify-end items-center gap-2">
<Dropdown className="bg-background border-1 border-default-200">
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
<VerticalDotsIcon className="text-default-400" />
</Button>
</DropdownTrigger>
<DropdownMenu>
<DropdownItem>Edit</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
cell: ({ row }) => {
const userData = getUserData(row);
return <UserActions userData={userData} />;
},
},
];
+54
View File
@@ -0,0 +1,54 @@
"use client";
import { useState } from "react";
import { VerticalDotsIcon } from "@/components/icons";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui";
import { EditUserModal } from "@/components/users";
import { UserProps } from "@/types";
interface UserActionsProps {
userData: UserProps;
}
export const UserActions: React.FC<UserActionsProps> = ({ userData }) => {
const [isEditOpen, setIsEditOpen] = useState(false);
return (
<>
<div className="relative flex justify-end items-center gap-2">
<DropdownMenu modal={false}>
<DropdownMenuTrigger>
<VerticalDotsIcon
size={28}
className="text-default-400 p-0.5 hover:bg-gray-200 hover:rounded-full"
/>
</DropdownMenuTrigger>
<DropdownMenuContent className="bg-white">
<DropdownMenuItem
className="hover:bg-gray-200 hover:cursor-pointer"
onClick={() => setIsEditOpen(true)}
>
Edit
</DropdownMenuItem>
<DropdownMenuItem className="hover:bg-gray-200 hover:cursor-pointer">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
{isEditOpen && (
<EditUserModal
isOpen={isEditOpen}
setIsOpen={setIsEditOpen}
userData={userData}
/>
)}
</>
);
};
+127
View File
@@ -13,6 +13,7 @@
"@nextui-org/system": "2.2.1",
"@nextui-org/theme": "2.2.5",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.1",
@@ -2886,6 +2887,35 @@
}
}
},
"node_modules/@radix-ui/react-dropdown-menu": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz",
"integrity": "sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-menu": "2.1.1",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"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
}
}
},
"node_modules/@radix-ui/react-focus-guards": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz",
@@ -2953,6 +2983,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz",
"integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.0.0"
},
@@ -2971,6 +3002,71 @@
}
}
},
"node_modules/@radix-ui/react-menu": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.1.tgz",
"integrity": "sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-dismissable-layer": "1.1.0",
"@radix-ui/react-focus-guards": "1.1.0",
"@radix-ui/react-focus-scope": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-popper": "1.2.0",
"@radix-ui/react-portal": "1.1.1",
"@radix-ui/react-presence": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-roving-focus": "1.1.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"aria-hidden": "^1.1.1",
"react-remove-scroll": "2.5.7"
},
"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
}
}
},
"node_modules/@radix-ui/react-menu/node_modules/react-remove-scroll": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz",
"integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==",
"license": "MIT",
"dependencies": {
"react-remove-scroll-bar": "^2.3.4",
"react-style-singleton": "^2.2.1",
"tslib": "^2.1.0",
"use-callback-ref": "^1.3.0",
"use-sidecar": "^1.1.2"
},
"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
}
}
},
"node_modules/@radix-ui/react-popper": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
@@ -3070,6 +3166,37 @@
}
}
},
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
"integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"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
}
}
},
"node_modules/@radix-ui/react-select": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.1.tgz",
+1
View File
@@ -5,6 +5,7 @@
"@nextui-org/system": "2.2.1",
"@nextui-org/theme": "2.2.5",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.1",