Merge pull request #61 from prowler-cloud/PRWLR-4763-Confirmation-screen

Confirmation modal component
This commit is contained in:
Pablo Lara
2024-09-23 08:25:39 +02:00
committed by GitHub
20 changed files with 432 additions and 140 deletions
+2 -2
View File
@@ -3,12 +3,12 @@ import { Suspense } from "react";
import { getProvider } from "@/actions";
import { FilterControls } from "@/components/filters";
import { AddProviderModal } from "@/components/providers";
import {
AddProviderModal,
ColumnsProvider,
DataTableProvider,
SkeletonTableProvider,
} from "@/components/providers";
} from "@/components/providers/table";
import { Header } from "@/components/ui";
import { SearchParamsProps } from "@/types";
-41
View File
@@ -1,41 +0,0 @@
"use client";
import { useRef } from "react";
import { deleteProvider } from "@/actions";
import { CustomButtonClientAction } from "../ui/custom";
import { useToast } from "../ui/toast";
export const DeleteProvider = ({ id }: { id: string }) => {
const ref = useRef<HTMLFormElement>(null);
const { toast } = useToast();
async function clientAction(formData: FormData) {
// reset the form
ref.current?.reset();
// client-side validation
const data = await deleteProvider(formData);
if (data?.errors && data.errors.length > 0) {
const error = data.errors[0];
const errorMessage = `${error.detail}`;
// show error
toast({
variant: "destructive",
title: "Oops! Something went wrong",
description: errorMessage,
});
} else {
toast({
title: "Success!",
description: "The provider was removed successfully.",
});
}
}
return (
<form ref={ref} action={clientAction} className="flex gap-x-2">
<input type="hidden" name="id" value={id} />
<CustomButtonClientAction buttonLabel="Delete" danger />
</form>
);
};
+85
View File
@@ -0,0 +1,85 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button, CircularProgress } from "@nextui-org/react";
import React, { Dispatch, SetStateAction } from "react";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { deleteProvider } from "@/actions";
import { useToast } from "@/components/ui";
import { Form } from "@/components/ui/form";
const formSchema = z.object({
providerId: z.string(),
});
export const DeleteForm = ({
providerId,
setIsOpen,
}: {
providerId: string;
setIsOpen: Dispatch<SetStateAction<boolean>>;
}) => {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
});
const { toast } = useToast();
const isLoading = form.formState.isSubmitting;
async function onSubmitClient(formData: FormData) {
// client-side validation
const data = await deleteProvider(formData);
if (data?.errors && data.errors.length > 0) {
const error = data.errors[0];
const errorMessage = `${error.detail}`;
// show error
toast({
variant: "destructive",
title: "Oops! Something went wrong",
description: errorMessage,
});
} else {
toast({
title: "Success!",
description: "The provider was removed successfully.",
});
}
}
return (
<Form {...form}>
<form action={onSubmitClient}>
<input type="hidden" name="id" value={providerId} />
<div className="w-full flex justify-center sm:space-x-6">
<Button
size="lg"
variant="bordered"
disabled={isLoading}
className="w-full hidden sm:block"
type="button"
onClick={() => setIsOpen(false)}
>
Cancel
</Button>
<Button
size="lg"
type="submit"
disabled={isLoading}
className="w-full bg-system-error hover:bg-system-error/90 text-white"
>
{isLoading ? (
<>
<CircularProgress aria-label="Loading..." size="sm" />
Deleting
</>
) : (
<span>Delete</span>
)}
</Button>
</div>
</form>
</Form>
);
};
+1
View File
@@ -0,0 +1 @@
export * from "./DeleteForm";
+1 -6
View File
@@ -4,12 +4,7 @@ export * from "./ButtonAddProvider";
export * from "./CheckConnectionProvider";
export * from "./CustomRadioProvider";
export * from "./DateWithTime";
export * from "./DeleteProvider";
export * from "./forms/DeleteForm";
export * from "./ProviderInfo";
export * from "./ScanStatus";
export * from "./SnippetIdProvider";
export * from "./table/ColumnsProvider";
export * from "./table/DataTableColumnHeader";
export * from "./table/DataTablePagination";
export * from "./table/DataTableProvider";
export * from "./table/SkeletonTableProvider";
@@ -1,41 +1,21 @@
"use client";
import {
Button,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownSection,
DropdownTrigger,
} from "@nextui-org/react";
import { ColumnDef } from "@tanstack/react-table";
import clsx from "clsx";
import { add } from "date-fns";
import { VerticalDotsIcon } from "@/components/icons";
import { StatusBadge } from "@/components/ui";
import { ProviderProps } from "@/types";
import { CheckConnectionProvider } from "../CheckConnectionProvider";
import { DateWithTime } from "../DateWithTime";
import { DeleteProvider } from "../DeleteProvider";
import { ProviderInfo } from "../ProviderInfo";
import { DataTableColumnHeader } from "./DataTableColumnHeader";
import { SnippetIdProvider } from "../SnippetIdProvider";
import { DataTableColumnHeader } from "./data-table-column-header";
import { DataTableRowActions } from "./data-table-row-actions";
const getProviderData = (row: { original: ProviderProps }) => {
return row.original;
};
import {
AddNoteBulkIcon,
DeleteDocumentBulkIcon,
EditDocumentBulkIcon,
} from "@nextui-org/shared-icons";
import { SnippetIdProvider } from "../SnippetIdProvider";
const iconClasses =
"text-2xl text-default-500 pointer-events-none flex-shrink-0";
export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
{
header: "n",
@@ -133,68 +113,9 @@ export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
},
},
{
accessorKey: "actions",
header: () => <div className="text-right">Actions</div>,
id: "actions",
cell: ({ row }) => {
const { id } = getProviderData(row);
return (
<div className="relative flex justify-end items-center gap-2">
<Dropdown className="shadow-xl" placement="bottom">
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
<VerticalDotsIcon className="text-default-400" />
</Button>
</DropdownTrigger>
<DropdownMenu
closeOnSelect
aria-label="Actions"
color="default"
variant="flat"
>
<DropdownSection title="Actions">
<DropdownItem
key="new"
description="Check the connection to the provider"
shortcut="⌘N"
textValue="Check Connection"
startContent={<AddNoteBulkIcon className={iconClasses} />}
>
<CheckConnectionProvider id={id} />
</DropdownItem>
<DropdownItem
key="edit"
description="Allows you to edit the provider"
shortcut="⌘⇧E"
textValue="Edit Provider"
startContent={
<EditDocumentBulkIcon className={iconClasses} />
}
>
Edit provider
</DropdownItem>
</DropdownSection>
<DropdownSection title="Danger zone">
<DropdownItem
key="delete"
className="text-danger"
color="danger"
description="Delete the provider permanently"
textValue="Delete Provider"
shortcut="⌘⇧D"
startContent={
<DeleteDocumentBulkIcon
className={clsx(iconClasses, "!text-danger")}
/>
}
>
<DeleteProvider id={id} />
</DropdownItem>
</DropdownSection>
</DropdownMenu>
</Dropdown>
</div>
);
return <DataTableRowActions row={row} />;
},
},
];
@@ -1,12 +1,14 @@
"use client";
import { Button } from "@nextui-org/react";
import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useMemo } from "react";
interface FilterColumnTableProps {
interface DataTableFilterCustomProps {
filters: { key: string; values: string[] }[];
}
export function FilterColumnTable({ filters }: FilterColumnTableProps) {
export function DataTableFilterCustom({ filters }: DataTableFilterCustomProps) {
const router = useRouter();
const searchParams = useSearchParams();
@@ -23,8 +23,8 @@ import {
} from "@/components/ui";
import { MetaDataProps } from "@/types";
import { DataTablePagination } from "./DataTablePagination";
import { FilterColumnTable } from "./FilterColumnTable";
import { DataTableFilterCustom } from "./data-table-filter-custom";
import { DataTablePagination } from "./data-table-pagination";
interface DataTableProviderProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
@@ -56,7 +56,7 @@ export function DataTableProvider<TData, TValue>({
});
// This will be used to have "custom" filters in the table and will be
// passed to the FilterColumnTable component. This needs to be dynamic
// passed to the DataTableFilterCustom component. This needs to be dynamic
// based on the columns that are available in the table.
const filters = [
@@ -67,7 +67,7 @@ export function DataTableProvider<TData, TValue>({
return (
<>
<FilterColumnTable filters={filters} />
<DataTableFilterCustom filters={filters} />
<div className="rounded-md border w-full">
<Table>
<TableHeader>
@@ -0,0 +1,112 @@
"use client";
import {
Button,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownSection,
DropdownTrigger,
} from "@nextui-org/react";
import {
AddNoteBulkIcon,
DeleteDocumentBulkIcon,
EditDocumentBulkIcon,
} from "@nextui-org/shared-icons";
import { Row } from "@tanstack/react-table";
import clsx from "clsx";
import { useState } from "react";
import { VerticalDotsIcon } from "@/components/icons";
import { CustomAlertModal } from "@/components/ui/custom";
import { CheckConnectionProvider } from "../CheckConnectionProvider";
import { DeleteForm } from "../forms/DeleteForm";
interface DataTableRowActionsProps<ProviderProps> {
row: Row<ProviderProps>;
}
const iconClasses =
"text-2xl text-default-500 pointer-events-none flex-shrink-0";
export function DataTableRowActions<ProviderProps>({
row,
}: DataTableRowActionsProps<ProviderProps>) {
// const [isEditOpen, setIsEditOpen] = useState(false);
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
const providerId = (row.original as { id: string }).id;
return (
<>
{/* <ResponsiveDialog
isOpen={isEditOpen}
setIsOpen={setIsEditOpen}
title="Edit Person"
>
<EditForm providerId={providerId} setIsOpen={setIsEditOpen} />
</ResponsiveDialog> */}
<CustomAlertModal
isOpen={isDeleteOpen}
onOpenChange={setIsDeleteOpen}
title="Are you absolutely sure?"
description="This action cannot be undone. This will permanently delete your provider account and remove your data from the server."
>
<DeleteForm providerId={providerId} setIsOpen={setIsDeleteOpen} />
</CustomAlertModal>
<div className="relative flex justify-end items-center gap-2">
<Dropdown className="shadow-xl" placement="bottom">
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
<VerticalDotsIcon className="text-default-400" />
</Button>
</DropdownTrigger>
<DropdownMenu
closeOnSelect
aria-label="Actions"
color="default"
variant="flat"
>
<DropdownSection title="Actions">
<DropdownItem
key="new"
description="Check the connection to the provider"
shortcut="⌘N"
textValue="Check Connection"
startContent={<AddNoteBulkIcon className={iconClasses} />}
>
<CheckConnectionProvider id={providerId} />
</DropdownItem>
<DropdownItem
key="edit"
description="Allows you to edit the provider"
shortcut="⌘⇧E"
textValue="Edit Provider"
startContent={<EditDocumentBulkIcon className={iconClasses} />}
>
Edit Provider
</DropdownItem>
</DropdownSection>
<DropdownSection title="Danger zone">
<DropdownItem
key="delete"
className="text-danger"
color="danger"
description="Delete the provider permanently"
textValue="Delete Provider"
shortcut="⌘⇧D"
startContent={
<DeleteDocumentBulkIcon
className={clsx(iconClasses, "!text-danger")}
/>
}
onClick={() => setIsDeleteOpen(true)}
>
Delete Provider
</DropdownItem>
</DropdownSection>
</DropdownMenu>
</Dropdown>
</div>
</>
);
}
+7
View File
@@ -0,0 +1,7 @@
export { ColumnsProvider } from "./columns-provider";
export { DataTableColumnHeader } from "./data-table-column-header";
export { DataTableFilterCustom } from "./data-table-filter-custom";
export { DataTablePagination } from "./data-table-pagination";
export { DataTableProvider } from "./data-table-provider";
export { DataTableRowActions } from "./data-table-row-actions";
export { SkeletonTableProvider } from "./skeleton-table-provider";
+131
View File
@@ -0,0 +1,131 @@
"use client";
import { cn } from "@nextui-org/react";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import * as React from "react";
const AlertDialog = AlertDialogPrimitive.Root;
const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
const AlertDialogPortal = AlertDialogPrimitive.Portal;
const AlertDialogOverlay = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
ref={ref}
/>
));
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
const AlertDialogContent = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
>(({ className, ...props }, ref) => (
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-neutral-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg dark:border-neutral-800 dark:bg-neutral-950",
className,
)}
{...props}
/>
</AlertDialogPortal>
));
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
const AlertDialogHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className,
)}
{...props}
/>
);
AlertDialogHeader.displayName = "AlertDialogHeader";
const AlertDialogFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
);
AlertDialogFooter.displayName = "AlertDialogFooter";
const AlertDialogTitle = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold", className)}
{...props}
/>
));
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
const AlertDialogDescription = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Description
ref={ref}
className={cn("text-sm text-neutral-500 dark:text-neutral-400", className)}
{...props}
/>
));
AlertDialogDescription.displayName =
AlertDialogPrimitive.Description.displayName;
const AlertDialogAction = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Action>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Action ref={ref} className={cn(className)} {...props} />
));
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
const AlertDialogCancel = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Cancel
ref={ref}
className={cn("mt-2 sm:mt-0", className)}
{...props}
/>
));
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
export {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
AlertDialogPortal,
AlertDialogTitle,
AlertDialogTrigger,
};
+39
View File
@@ -0,0 +1,39 @@
import { Modal, ModalBody, ModalContent, ModalHeader } from "@nextui-org/react";
import React, { ReactNode } from "react";
interface CustomAlertModalProps {
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
title: string;
description: string;
children: ReactNode;
}
export const CustomAlertModal: React.FC<CustomAlertModalProps> = ({
isOpen,
onOpenChange,
title,
description,
children,
}) => {
return (
<Modal
isOpen={isOpen}
onOpenChange={onOpenChange}
size="xl"
backdrop="blur"
>
<ModalContent className="py-4">
{(_onClose) => (
<>
<ModalHeader className="flex flex-col py-0">{title}</ModalHeader>
<ModalBody className="space-y-2">
<p>{description}</p>
{children}
</ModalBody>
</>
)}
</ModalContent>
</Modal>
);
};
+1
View File
@@ -1,3 +1,4 @@
export * from "./CustomAlertModal";
export * from "./CustomBox";
export * from "./CustomButtonClientAction";
export * from "./CustomInput";
+1
View File
@@ -1,5 +1,6 @@
export * from "./action-card/ActionCard";
export * from "./alert/Alert";
export * from "./alert-dialog/AlertDialog";
export * from "./chart/Chart";
export * from "./dialog/Dialog";
export * from "./dropdown/Dropdown";
+2 -1
View File
@@ -11,7 +11,6 @@ import {
} from "@tanstack/react-table";
import { useState } from "react";
import { DataTablePagination } from "@/components/providers";
import {
Table,
TableBody,
@@ -22,6 +21,8 @@ import {
} from "@/components/ui";
import { MetaDataProps } from "@/types";
import { DataTablePagination } from "./DataTablePagination";
interface DataTableUserProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
+36
View File
@@ -12,6 +12,7 @@
"@nextui-org/react": "^2.4.6",
"@nextui-org/system": "2.2.1",
"@nextui-org/theme": "2.2.5",
"@radix-ui/react-alert-dialog": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
@@ -2714,6 +2715,34 @@
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
"integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA=="
},
"node_modules/@radix-ui/react-alert-dialog": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.1.tgz",
"integrity": "sha512-wmCoJwj7byuVuiLKqDLlX7ClSUU0vd9sdCeM+2Ls+uf13+cpSJoMgwysHq1SGVVkJj5Xn0XWi1NoRCdkMpr6Mw==",
"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-dialog": "1.1.1",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-slot": "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-arrow": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
@@ -2959,6 +2988,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
"license": "MIT",
"peerDependencies": {
"react": "^16.x || ^17.x || ^18.x"
}
@@ -3268,6 +3298,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0"
},
@@ -6148,6 +6179,7 @@
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz",
"integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==",
"license": "Apache-2.0",
"dependencies": {
"clsx": "2.0.0"
},
@@ -6271,6 +6303,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
@@ -9543,6 +9576,7 @@
"version": "0.417.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.417.0.tgz",
"integrity": "sha512-F/MDUHDter8YMZ7JKQpW/5/+v38tdaoShKX3e+opYsqfCnaHwn+5zz3+lBrMDFMNtSsvxtNpchLIaMpEfsi/4w==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
@@ -11707,6 +11741,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz",
"integrity": "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
@@ -11776,6 +11811,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
"license": "MIT",
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
+1
View File
@@ -4,6 +4,7 @@
"@nextui-org/react": "^2.4.6",
"@nextui-org/system": "2.2.1",
"@nextui-org/theme": "2.2.5",
"@radix-ui/react-alert-dialog": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",