mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
feat: big refactor for filters and tons of components
This commit is contained in:
@@ -2,7 +2,7 @@ import { Spacer } from "@nextui-org/react";
|
||||
import { Suspense } from "react";
|
||||
|
||||
import { getProviders } from "@/actions";
|
||||
import { FilterControls } from "@/components/filters";
|
||||
import { FilterControls, filtersProviders } from "@/components/filters";
|
||||
import { AddProvider } from "@/components/providers";
|
||||
import {
|
||||
ColumnsProvider,
|
||||
@@ -24,7 +24,7 @@ export default async function Providers({
|
||||
<Header title="Providers" icon="fluent:cloud-sync-24-regular" />
|
||||
|
||||
<Spacer y={4} />
|
||||
<FilterControls search providers />
|
||||
<FilterControls search providers date customFilters={filtersProviders} />
|
||||
<Spacer y={4} />
|
||||
|
||||
<AddProvider />
|
||||
@@ -33,7 +33,6 @@ export default async function Providers({
|
||||
<Suspense key={searchParamsKey} fallback={<SkeletonTableProvider />}>
|
||||
<SSRDataTable searchParams={searchParams} />
|
||||
</Suspense>
|
||||
{/* <NewTable /> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ export const CustomDatePicker = () => {
|
||||
return (
|
||||
<div className="flex flex-col md:gap-2 w-full">
|
||||
<DatePicker
|
||||
CalendarBottomContent={<div className="min-w-[380px]"></div>}
|
||||
CalendarTopContent={
|
||||
<ButtonGroup
|
||||
fullWidth
|
||||
@@ -89,7 +88,6 @@ export const CustomDatePicker = () => {
|
||||
}}
|
||||
value={value}
|
||||
onChange={handleDateChange}
|
||||
label="Scan date"
|
||||
size="sm"
|
||||
variant="flat"
|
||||
/>
|
||||
+3
-3
@@ -37,7 +37,7 @@ export const CustomSearchInput: React.FC = () => {
|
||||
|
||||
return (
|
||||
<Input
|
||||
variant="bordered"
|
||||
variant="flat"
|
||||
placeholder="Search..."
|
||||
labelPlacement="outside"
|
||||
value={searchQuery}
|
||||
@@ -54,8 +54,8 @@ export const CustomSearchInput: React.FC = () => {
|
||||
</button>
|
||||
)
|
||||
}
|
||||
radius="full"
|
||||
size="lg"
|
||||
radius="sm"
|
||||
size="sm"
|
||||
/>
|
||||
);
|
||||
};
|
||||
+7
-10
@@ -9,7 +9,7 @@ import {
|
||||
CustomProviderInputAzure,
|
||||
CustomProviderInputGCP,
|
||||
CustomProviderInputKubernetes,
|
||||
} from "./CustomProviderInputs";
|
||||
} from "./custom-provider-inputs";
|
||||
|
||||
const dataInputsProvider = [
|
||||
{
|
||||
@@ -43,9 +43,9 @@ export const CustomSelectProvider = () => {
|
||||
(value: string) => {
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
if (value) {
|
||||
params.set("filter[provider]", value);
|
||||
params.set("filter[provider__in]", value);
|
||||
} else {
|
||||
params.delete("filter[provider]");
|
||||
params.delete("filter[provider__in]");
|
||||
}
|
||||
router.push(`?${params.toString()}`, { scroll: false });
|
||||
},
|
||||
@@ -53,21 +53,18 @@ export const CustomSelectProvider = () => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const providerFromUrl = searchParams.get("filter[provider]") || "";
|
||||
const providerFromUrl = searchParams.get("filter[provider__in]") || "";
|
||||
setSelectedProvider(providerFromUrl);
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
<Select
|
||||
items={dataInputsProvider}
|
||||
label="Select a Provider"
|
||||
// selectionMode="multiple"
|
||||
// label="Select a Provider"
|
||||
placeholder="Select a provider"
|
||||
labelPlacement="inside"
|
||||
labelPlacement="outside"
|
||||
size="sm"
|
||||
classNames={{
|
||||
base: "w-full",
|
||||
trigger: "h-12",
|
||||
}}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
setSelectedProvider(value);
|
||||
@@ -1,8 +1,8 @@
|
||||
export const filtersProviders = [
|
||||
{
|
||||
key: "provider",
|
||||
labelCheckboxGroup: "Provider",
|
||||
values: ["aws", "gcp", "azure"],
|
||||
key: "provider__in",
|
||||
labelCheckboxGroup: "Select a Provider",
|
||||
values: ["aws", "gcp", "azure", "kubernetes"],
|
||||
},
|
||||
{
|
||||
key: "connected",
|
||||
@@ -3,25 +3,17 @@
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { FilterControlsProps } from "@/types";
|
||||
|
||||
import { CrossIcon } from "../icons";
|
||||
import { DataTableFilterCustom } from "../providers/table";
|
||||
import { CustomButton } from "../ui/custom";
|
||||
import { CustomAccountSelection } from "./CustomAccountSelection";
|
||||
import { CustomCheckboxMutedFindings } from "./CustomCheckboxMutedFindings";
|
||||
import { CustomDatePicker } from "./CustomDatePicker";
|
||||
import { CustomRegionSelection } from "./CustomRegionSelection";
|
||||
import { CustomSearchInput } from "./CustomSearchInput";
|
||||
import { CustomSelectProvider } from "./CustomSelectProvider";
|
||||
|
||||
interface FilterControlsProps {
|
||||
search?: boolean;
|
||||
providers?: boolean;
|
||||
date?: boolean;
|
||||
regions?: boolean;
|
||||
accounts?: boolean;
|
||||
mutedFindings?: boolean;
|
||||
customFilters?: { key: string; values: string[] }[];
|
||||
}
|
||||
import { CustomCheckboxMutedFindings } from "./custo-checkbox-muted-findings";
|
||||
import { CustomAccountSelection } from "./custom-account-selection";
|
||||
import { CustomDatePicker } from "./custom-date-picker";
|
||||
import { CustomRegionSelection } from "./custom-region-selection";
|
||||
import { CustomSearchInput } from "./custom-search-input";
|
||||
import { CustomSelectProvider } from "./custom-select-provider";
|
||||
|
||||
export const FilterControls: React.FC<FilterControlsProps> = ({
|
||||
search = false,
|
||||
@@ -1,8 +1,8 @@
|
||||
export * from "../filters/CustomAccountSelection";
|
||||
export * from "../filters/CustomCheckboxMutedFindings";
|
||||
export * from "../filters/CustomDatePicker";
|
||||
export * from "../filters/CustomProviderInputs";
|
||||
export * from "../filters/CustomRegionSelection";
|
||||
export * from "../filters/CustomSelectProvider";
|
||||
export * from "../filters/FilterControls";
|
||||
export * from "../filters/filters";
|
||||
export * from "./custo-checkbox-muted-findings";
|
||||
export * from "./custom-account-selection";
|
||||
export * from "./custom-date-picker";
|
||||
export * from "./custom-provider-inputs";
|
||||
export * from "./custom-region-selection";
|
||||
export * from "./custom-select-provider";
|
||||
export * from "./data-filters";
|
||||
export * from "./filter-controls";
|
||||
|
||||
@@ -717,19 +717,16 @@ export const CustomFilterIcon: React.FC<IconSvgProps> = ({
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
height={size || height || 15}
|
||||
viewBox="0 0 15 15"
|
||||
width={size || width || 15}
|
||||
aria-hidden="true"
|
||||
height={size || height || 16}
|
||||
width={size || width || 16}
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M2.15 4a1.85 1.85 0 1 1 3.7 0 1.85 1.85 0 0 1-3.7 0ZM4 1.25a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5ZM5.82 11 2.5 12.837V9.163L5.82 11ZM2.64 8.212a.7.7 0 0 0-1.039.612v4.352a.7.7 0 0 0 1.039.613l3.933-2.176a.7.7 0 0 0 0-1.225L2.64 8.212ZM8.3 9a.7.7 0 0 1 .7-.7h4a.7.7 0 0 1 .7.7v4a.7.7 0 0 1-.7.7H9a.7.7 0 0 1-.7-.7V9Zm.9.2v3.6h3.6V9.2H9.2Zm4.243-7.007a.45.45 0 0 0-.636-.636L11 3.364 9.193 1.557a.45.45 0 1 0-.636.636L10.364 4 8.557 5.807a.45.45 0 1 0 .636.636L11 4.636l1.807 1.807a.45.45 0 0 0 .636-.636L11.636 4l1.807-1.807Z"
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
<g fill="none" stroke="currentColor" strokeWidth="1.5">
|
||||
<path d="M9.5 14a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm5-10a3 3 0 1 0 0 6 3 3 0 0 0 0-6Z" />
|
||||
<path strokeLinecap="round" d="M15 16.959h7m-13-10H2m0 10h2m18-10h-2" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Chip } from "@nextui-org/react";
|
||||
import { useState } from "react";
|
||||
|
||||
import { AddIcon } from "../icons";
|
||||
@@ -23,17 +22,7 @@ export const AddProvider = () => {
|
||||
<AddForm setIsOpen={setIsAddOpen} />
|
||||
</CustomAlertModal>
|
||||
|
||||
<div className="w-full flex items-center justify-between">
|
||||
<div className="flex w-fit items-center gap-2">
|
||||
<h1 className="text-2xl font-[700] leading-[32px]">TBD</h1>
|
||||
<Chip
|
||||
className="hidden items-center text-default-500 sm:flex"
|
||||
size="sm"
|
||||
variant="flat"
|
||||
>
|
||||
3
|
||||
</Chip>
|
||||
</div>
|
||||
<div className="w-full flex items-center justify-end">
|
||||
<CustomButton
|
||||
variant="solid"
|
||||
color="action"
|
||||
|
||||
@@ -1,52 +1,34 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
Input,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@nextui-org/react";
|
||||
import { SearchIcon } from "lucide-react";
|
||||
import { Divider } from "@nextui-org/react";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { useCallback } from "react";
|
||||
|
||||
import { CustomFilterIcon, PlusCircleIcon } from "@/components/icons";
|
||||
import { CustomButton } from "@/components/ui/custom";
|
||||
import { CustomFilterIcon } from "@/components/icons";
|
||||
import { CustomButton, CustomDropdownFilter } from "@/components/ui/custom";
|
||||
import { FilterOption } from "@/types";
|
||||
|
||||
interface DataTableFilterCustomProps {
|
||||
filters: { key: string; values: string[] }[];
|
||||
export interface DataTableFilterCustomProps {
|
||||
filters: FilterOption[];
|
||||
}
|
||||
|
||||
export function DataTableFilterCustom({ filters }: DataTableFilterCustomProps) {
|
||||
export const DataTableFilterCustom = ({
|
||||
filters,
|
||||
}: DataTableFilterCustomProps) => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const [showFilters, setShowFilters] = useState(false);
|
||||
|
||||
const activeFilters = useMemo(() => {
|
||||
const currentFilters: Record<string, string> = {};
|
||||
Array.from(searchParams.entries()).forEach(([key, value]) => {
|
||||
if (key.startsWith("filter[") && key.endsWith("]")) {
|
||||
const filterKey = key.slice(7, -1);
|
||||
if (filters.some((filter) => filter.key === filterKey)) {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
currentFilters[filterKey] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
return currentFilters;
|
||||
}, [searchParams, filters]);
|
||||
|
||||
const applyFilter = useCallback(
|
||||
(key: string, value: string) => {
|
||||
const pushDropdownFilter = useCallback(
|
||||
(key: string, values: string[]) => {
|
||||
const params = new URLSearchParams(searchParams);
|
||||
const filterKey = `filter[${key}]`;
|
||||
|
||||
if (params.get(filterKey) === value) {
|
||||
if (values.length === 0) {
|
||||
params.delete(filterKey);
|
||||
} else {
|
||||
params.set(filterKey, value);
|
||||
params.set(filterKey, values.join(","));
|
||||
}
|
||||
|
||||
router.push(`?${params.toString()}`);
|
||||
@@ -55,74 +37,41 @@ export function DataTableFilterCustom({ filters }: DataTableFilterCustomProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center gap-4 overflow-auto px-[6px] py-[4px]">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-4">
|
||||
<Input
|
||||
className="min-w-[200px]"
|
||||
endContent={
|
||||
<SearchIcon className="text-default-400" width={16} />
|
||||
}
|
||||
placeholder="Search"
|
||||
size="sm"
|
||||
// value={filterValue}
|
||||
// onValueChange={onSearchChange}
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<CustomButton
|
||||
variant="flat"
|
||||
color={showFilters ? "action" : "primary"}
|
||||
size="sm"
|
||||
startContent={<CustomFilterIcon size={16} />}
|
||||
onPress={() => setShowFilters(!showFilters)}
|
||||
>
|
||||
{showFilters ? "Hide Filters" : "Show Filters"}
|
||||
</CustomButton>
|
||||
|
||||
<div
|
||||
className={`transition-all duration-500 ease-in-out ${
|
||||
showFilters
|
||||
? "opacity-100 max-h-96 overflow-visible"
|
||||
: "opacity-0 max-h-0 overflow-hidden"
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-row gap-4">
|
||||
{filters.map((filter) => (
|
||||
<CustomDropdownFilter
|
||||
key={filter.key}
|
||||
filter={{
|
||||
...filter,
|
||||
labelCheckboxGroup: filter.labelCheckboxGroup,
|
||||
}}
|
||||
onFilterChange={pushDropdownFilter}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Popover placement="bottom">
|
||||
<PopoverTrigger>
|
||||
<Button
|
||||
className="bg-default-100 text-default-800"
|
||||
startContent={
|
||||
<PlusCircleIcon className="text-default-400" width={16} />
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80">
|
||||
<div className="flex w-full flex-col gap-6 px-2 py-4">
|
||||
<CheckboxGroup
|
||||
label="Select cities"
|
||||
defaultValue={["buenos-aires", "london"]}
|
||||
>
|
||||
<Checkbox value="buenos-aires">Buenos Aires</Checkbox>
|
||||
<Checkbox value="sydney">Sydney</Checkbox>
|
||||
<Checkbox value="san-francisco">San Francisco</Checkbox>
|
||||
<Checkbox value="london">London</Checkbox>
|
||||
<Checkbox value="tokyo">Tokyo</Checkbox>
|
||||
</CheckboxGroup>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
))}
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Divider className="text-default-800 h-5" orientation="vertical" />
|
||||
<span className="text-sm text-default-800">Selected</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center space-x-2">
|
||||
<CustomButton
|
||||
variant="dashed"
|
||||
size="sm"
|
||||
startContent={<CustomFilterIcon size={16} />}
|
||||
>
|
||||
Show Filters
|
||||
</CustomButton>
|
||||
{filters.flatMap(({ key, values }) =>
|
||||
values.map((value) => (
|
||||
<Button
|
||||
key={`${key}-${value}`}
|
||||
onPress={() => applyFilter(key, value)}
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
variant={activeFilters[key] === value ? "faded" : "light"}
|
||||
>
|
||||
{value || "All"}
|
||||
</Button>
|
||||
)),
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,40 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
Divider,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@nextui-org/react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { PlusCircleIcon } from "@/components/icons";
|
||||
|
||||
interface FilterOption {
|
||||
key: string;
|
||||
labelCheckboxGroup: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
interface CustomDropdownFilterProps {
|
||||
filter?: FilterOption;
|
||||
onFilterChange?: (key: string, values: string[]) => void;
|
||||
}
|
||||
import { CustomDropdownFilterProps } from "@/types";
|
||||
|
||||
export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
|
||||
filter,
|
||||
onFilterChange,
|
||||
}) => {
|
||||
// Early return if filter is undefined
|
||||
if (!filter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const [groupSelected, setGroupSelected] = useState(new Set<string>());
|
||||
|
||||
const allFilterKeys = filter.values || [];
|
||||
const allFilterKeys = filter?.values || [];
|
||||
|
||||
const getActiveFilter = useMemo(() => {
|
||||
const currentFilters: Record<string, string> = {};
|
||||
Array.from(searchParams.entries()).forEach(([key, value]) => {
|
||||
if (key.startsWith("filter[") && key.endsWith("]")) {
|
||||
const filterKey = key.slice(7, -1);
|
||||
if (filter && filter.key === filterKey) {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
currentFilters[filterKey] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
return currentFilters;
|
||||
}, [searchParams, filter]);
|
||||
|
||||
useEffect(() => {
|
||||
if (filter && getActiveFilter[filter.key]) {
|
||||
const activeValues = getActiveFilter[filter.key].split(",");
|
||||
const newSelection = new Set(activeValues);
|
||||
if (newSelection.size === allFilterKeys.length) {
|
||||
newSelection.add("all");
|
||||
}
|
||||
setGroupSelected(newSelection);
|
||||
} else {
|
||||
setGroupSelected(new Set());
|
||||
}
|
||||
}, [getActiveFilter, filter, allFilterKeys]);
|
||||
|
||||
const onSelectionChange = useCallback(
|
||||
(keys: string[]) => {
|
||||
@@ -72,7 +88,6 @@ export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
|
||||
setGroupSelected(new Set(["all", ...allFilterKeys]));
|
||||
}
|
||||
}, [groupSelected, allFilterKeys]);
|
||||
|
||||
return (
|
||||
<div className="flex w-full max-w-xs flex-col gap-2">
|
||||
<Popover placement="bottom">
|
||||
@@ -84,13 +99,46 @@ export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
{filter.key}
|
||||
{filter?.labelCheckboxGroup}
|
||||
{groupSelected.size > 0 && (
|
||||
<>
|
||||
<Divider orientation="vertical" className="mx-2 h-4" />
|
||||
<Badge
|
||||
variant="flat"
|
||||
className="rounded-sm px-1 font-normal lg:hidden"
|
||||
>
|
||||
{groupSelected.size}
|
||||
</Badge>
|
||||
<div className="hidden space-x-1 lg:flex">
|
||||
{groupSelected.size > 2 ? (
|
||||
<Badge
|
||||
variant="flat"
|
||||
className="rounded-sm px-1 font-normal"
|
||||
>
|
||||
{groupSelected.size} selected
|
||||
</Badge>
|
||||
) : (
|
||||
Array.from(groupSelected)
|
||||
.filter((value) => value !== "all")
|
||||
.map((value) => (
|
||||
<Badge
|
||||
variant="flat"
|
||||
key={value}
|
||||
className="rounded-sm px-1 font-normal"
|
||||
>
|
||||
{value}
|
||||
</Badge>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80">
|
||||
<div className="flex w-full flex-col gap-6 px-2 py-4">
|
||||
<CheckboxGroup
|
||||
label={filter.labelCheckboxGroup}
|
||||
label={filter?.labelCheckboxGroup}
|
||||
value={Array.from(groupSelected)}
|
||||
onValueChange={onSelectionChange}
|
||||
>
|
||||
@@ -106,12 +154,14 @@ export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<p className="text-small text-default-500">
|
||||
Selected:{" "}
|
||||
{Array.from(groupSelected)
|
||||
.filter((item) => item !== "all")
|
||||
.join(", ")}
|
||||
</p>
|
||||
{groupSelected?.size > 0 && (
|
||||
<p className="text-small text-default-500">
|
||||
Selected:{" "}
|
||||
{Array.from(groupSelected)
|
||||
.filter((item) => item !== "all")
|
||||
.join(", ")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { X } from "lucide-react";
|
||||
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
@@ -38,14 +38,14 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-slate-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-slate-800 dark:bg-slate-950",
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background 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",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100 data-[state=open]:text-slate-500 dark:ring-offset-slate-950 dark:focus:ring-slate-300 dark:data-[state=open]:bg-slate-800 dark:data-[state=open]:text-slate-400">
|
||||
<X className="h-4 w-4" />
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<Cross2Icon className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
@@ -102,7 +102,7 @@ const DialogDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-slate-500 dark:text-slate-400", className)}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -2,7 +2,7 @@ export * from "./action-card/ActionCard";
|
||||
export * from "./alert/Alert";
|
||||
export * from "./alert-dialog/AlertDialog";
|
||||
export * from "./chart/Chart";
|
||||
export * from "./dialog/Dialog";
|
||||
export * from "./dialog/dialogg";
|
||||
export * from "./dropdown/Dropdown";
|
||||
export * from "./header/Header";
|
||||
export * from "./label/Label";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// export * from "./data-table-toolbar";
|
||||
export * from "./severity-badge";
|
||||
export * from "./status-badge";
|
||||
export * from "./table";
|
||||
|
||||
Generated
+379
@@ -28,6 +28,7 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"framer-motion": "~11.1.1",
|
||||
"intl-messageformat": "^10.5.0",
|
||||
@@ -6308,6 +6309,384 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz",
|
||||
"integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-dialog": "1.0.5",
|
||||
"@radix-ui/react-primitive": "1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/primitive": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz",
|
||||
"integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
||||
"integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-context": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz",
|
||||
"integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-dialog": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz",
|
||||
"integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "1.0.1",
|
||||
"@radix-ui/react-compose-refs": "1.0.1",
|
||||
"@radix-ui/react-context": "1.0.1",
|
||||
"@radix-ui/react-dismissable-layer": "1.0.5",
|
||||
"@radix-ui/react-focus-guards": "1.0.1",
|
||||
"@radix-ui/react-focus-scope": "1.0.4",
|
||||
"@radix-ui/react-id": "1.0.1",
|
||||
"@radix-ui/react-portal": "1.0.4",
|
||||
"@radix-ui/react-presence": "1.0.1",
|
||||
"@radix-ui/react-primitive": "1.0.3",
|
||||
"@radix-ui/react-slot": "1.0.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.0.1",
|
||||
"aria-hidden": "^1.1.1",
|
||||
"react-remove-scroll": "2.5.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-dismissable-layer": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz",
|
||||
"integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "1.0.1",
|
||||
"@radix-ui/react-compose-refs": "1.0.1",
|
||||
"@radix-ui/react-primitive": "1.0.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.0.1",
|
||||
"@radix-ui/react-use-escape-keydown": "1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-focus-guards": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz",
|
||||
"integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-focus-scope": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz",
|
||||
"integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1",
|
||||
"@radix-ui/react-primitive": "1.0.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-id": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
|
||||
"integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-use-layout-effect": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-portal": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz",
|
||||
"integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-primitive": "1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-presence": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz",
|
||||
"integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1",
|
||||
"@radix-ui/react-use-layout-effect": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
|
||||
"integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-slot": "1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
|
||||
"integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-use-controllable-state": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz",
|
||||
"integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-use-callback-ref": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-use-escape-keydown": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz",
|
||||
"integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-use-callback-ref": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz",
|
||||
"integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cmdk/node_modules/react-remove-scroll": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
|
||||
"integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-remove-scroll-bar": "^2.3.3",
|
||||
"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/code-block-writer": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"framer-motion": "~11.1.1",
|
||||
"intl-messageformat": "^10.5.0",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
export interface FilterOption {
|
||||
key: string;
|
||||
labelCheckboxGroup: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
export interface CustomDropdownFilterProps {
|
||||
filter: FilterOption;
|
||||
onFilterChange: (key: string, values: string[]) => void;
|
||||
}
|
||||
|
||||
export interface FilterControlsProps {
|
||||
search?: boolean;
|
||||
providers?: boolean;
|
||||
date?: boolean;
|
||||
regions?: boolean;
|
||||
accounts?: boolean;
|
||||
mutedFindings?: boolean;
|
||||
customFilters?: FilterOption[];
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./authFormSchema";
|
||||
export * from "./components";
|
||||
export * from "./filters";
|
||||
export * from "./formSchemas";
|
||||
|
||||
Reference in New Issue
Block a user