Merge pull request #64 from prowler-cloud/PRWLR-4917-Improving-Filtering-Impacts-the-whole-app-followUp

Codebase improvements: Tailwind formatting, accessibility fixes, and search optimization
This commit is contained in:
Pablo Lara
2024-10-01 08:16:54 +02:00
committed by GitHub
75 changed files with 347 additions and 248 deletions
+1
View File
@@ -10,6 +10,7 @@ module.exports = {
"plugin:@typescript-eslint/recommended",
"plugin:security/recommended-legacy",
"plugin:jsx-a11y/recommended",
"eslint-config-prettier",
"prettier",
],
parserOptions: {
+2 -1
View File
@@ -5,5 +5,6 @@
"tabWidth": 2,
"useTabs": false,
"semi": true,
"printWidth": 80
"printWidth": 80,
"plugins": ["prettier-plugin-tailwindcss"]
}
+1 -1
View File
@@ -20,7 +20,7 @@ export default function Error({
}, [error]);
return (
<Alert className="w-fit mx-auto mt-[35%]">
<Alert className="mx-auto mt-[35%] w-fit">
<RocketIcon className="h-5 w-5" />
<AlertTitle className="text-lg">An unexpected error occurred</AlertTitle>
<AlertDescription className="mb-5">
+1 -1
View File
@@ -13,7 +13,7 @@ export default async function Findings() {
<>
<Header title="Findings" icon="ph:list-checks-duotone" />
<Spacer />
<div className="flex flex-col items-start w-full overflow-hidden">
<div className="flex w-full flex-col items-start overflow-hidden">
<Spacer y={6} />
<Suspense fallback={<SkeletonTableFindings />}>
<SSRDataTable />
+2 -2
View File
@@ -44,9 +44,9 @@ export default function RootLayout({
)}
>
<Providers themeProps={{ attribute: "class", defaultTheme: "dark" }}>
<div className="flex items-center h-dvh justify-center overflow-hidden">
<div className="flex h-dvh items-center justify-center overflow-hidden">
<SidebarWrap />
<main className="container h-full flex-1 flex-col p-4 mb-auto overflow-y-auto no-scrollbar">
<main className="no-scrollbar container mb-auto h-full flex-1 flex-col overflow-y-auto p-4">
{children}
<Toaster />
</main>
+1 -1
View File
@@ -29,7 +29,7 @@ export default async function Users({
<>
<Header title="User Management" icon="ci:users" />
<Spacer y={4} />
<div className="flex flex-col items-end w-full">
<div className="flex w-full flex-col items-end">
<div className="flex space-x-6">
<AddUserModal />
</div>
+1 -1
View File
@@ -57,7 +57,7 @@ export const ThemeSwitch: FC<ThemeSwitchProps> = ({
className={slots.wrapper({
class: clsx(
[
"w-auto h-auto",
"h-auto w-auto",
"bg-transparent",
"rounded-lg",
"flex items-center justify-center",
+2 -2
View File
@@ -74,7 +74,7 @@ export const AuthForm = ({ type }: { type: string }) => {
>
{/* Brand Logo and ThemeSwitch */}
<div className="absolute right-10 top-10">
<div className="flex items-center self-center gap-4">
<div className="flex items-center gap-4 self-center">
<ThemeSwitch aria-label="Toggle theme" />
<ProwlerExtended />
</div>
@@ -82,7 +82,7 @@ export const AuthForm = ({ type }: { type: string }) => {
{/* Testimonial */}
<div className="absolute bottom-10 right-10 hidden md:block">
<p className="max-w-xl text-right text-white/60 text-md">
<p className="text-md max-w-xl text-right text-white/60">
<span className="font-medium"></span>
Open Cloud Security
<span className="font-medium"></span>
+4 -4
View File
@@ -55,7 +55,7 @@ export function StatusChart() {
}, []);
return (
<div className="flex items-center justify-center self-center my-auto">
<div className="my-auto flex items-center justify-center self-center">
<ChartContainer
config={chartConfig}
className="mx-auto aspect-square min-w-[200px] md:min-h-[250px]"
@@ -102,7 +102,7 @@ export function StatusChart() {
</Pie>
</PieChart>
</ChartContainer>
<div className="flex flex-col justify-center gap-2 mx-6 text-small">
<div className="mx-6 flex flex-col justify-center gap-2 text-small">
<div className="flex space-x-4">
<Chip
className="h-5"
@@ -122,7 +122,7 @@ export function StatusChart() {
No change from last scan
</div>
<Spacer y={4} />
<div className="flex flex-col gap-2 leading-none text-muted-foreground">
<div className="text-muted-foreground flex flex-col gap-2 leading-none">
<div className="flex space-x-4">
<Chip
className="h-5"
@@ -138,7 +138,7 @@ export function StatusChart() {
<span>{updatedChartData[1].percent}</span>
<Divider orientation="vertical" />
</div>
<div className="flex items-center font-medium leading-none gap-1">
<div className="flex items-center gap-1 font-medium leading-none">
+2 findings from last scan <TrendingUp className="h-4 w-4" />
</div>
</div>
+7 -7
View File
@@ -50,15 +50,15 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
return (
<Card fullWidth isPressable isHoverable shadow="sm">
<CardBody className="flex flex-row items-center space-x-4 justify-between">
<div className="flex space-x-4 items-center w-full">
<CardBody className="flex flex-row items-center justify-between space-x-4">
<div className="flex w-full items-center space-x-4">
<Image
src={getComplianceIcon(title)}
alt={`${title} logo`}
className="rounded-md p-1 border-gray-300 border-1 bg-white object-contain h-10 w-10 min-w-10"
className="h-10 w-10 min-w-10 rounded-md border-1 border-gray-300 bg-white object-contain p-1"
/>
<div className="flex flex-col w-full">
<h4 className="font-bold text-md 3xl:text-lg leading-5">{title}</h4>
<div className="flex w-full flex-col">
<h4 className="text-md font-bold leading-5 3xl:text-lg">{title}</h4>
<Progress
label="Your Rating:"
size="sm"
@@ -68,9 +68,9 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
className="mt-2 font-semibold"
color={getRatingColor(ratingPercentage)}
/>
<div className="flex justify-between mt-2">
<div className="mt-2 flex justify-between">
<small>
<span className="font-semibold mr-1">
<span className="mr-1 font-semibold">
{passingRequirements} / {totalRequirements}
</span>
Passing Requirements
@@ -3,8 +3,8 @@ import React from "react";
export const ComplianceSkeletonGrid = () => {
return (
<Card className="w-full h-fit p-4">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 3xl:grid-cols-4 gap-4">
<Card className="h-fit w-full p-4">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 3xl:grid-cols-4">
{[...Array(28)].map((_, index) => (
<div key={index} className="flex flex-col space-y-4">
<Skeleton className="h-28 rounded-lg">
@@ -3,7 +3,12 @@ import React from "react";
export const CustomCheckboxMutedFindings = () => {
return (
<Checkbox className="xl:-mt-8" size="md" color="danger">
<Checkbox
className="xl:-mt-8"
size="md"
color="danger"
aria-label="Include Muted Findings"
>
Include Muted Findings
</Checkbox>
);
@@ -18,6 +18,7 @@ export const CustomAccountSelection = () => {
return (
<Select
label="Account"
aria-label="Select an Account"
placeholder="Select an account"
selectionMode="multiple"
className="w-full"
+3 -2
View File
@@ -57,12 +57,13 @@ export const CustomDatePicker = () => {
};
return (
<div className="flex flex-col md:gap-2 w-full">
<div className="flex w-full flex-col md:gap-2">
<DatePicker
aria-label="Select a Date"
CalendarTopContent={
<ButtonGroup
fullWidth
className="px-3 pb-2 pt-3 bg-content1 [&>button]:text-default-500 [&>button]:border-default-200/60"
className="bg-content1 px-3 pb-2 pt-3 [&>button]:border-default-200/60 [&>button]:text-default-500"
radius="full"
size="sm"
variant="bordered"
@@ -9,7 +9,7 @@ import {
export const CustomProviderInputAWS = () => {
return (
<div className="flex gap-x-2 items-center">
<div className="flex items-center gap-x-2">
<AWSProviderBadge width={25} height={25} />
<p className="text-sm">Amazon Web Services</p>
</div>
@@ -18,7 +18,7 @@ export const CustomProviderInputAWS = () => {
export const CustomProviderInputAzure = () => {
return (
<div className="flex gap-x-2 items-center">
<div className="flex items-center gap-x-2">
<AzureProviderBadge width={25} height={25} />
<p className="text-sm">Azure</p>
</div>
@@ -27,7 +27,7 @@ export const CustomProviderInputAzure = () => {
export const CustomProviderInputGCP = () => {
return (
<div className="flex gap-x-2 items-center">
<div className="flex items-center gap-x-2">
<GCPProviderBadge width={25} height={25} />
<p className="text-sm">Google Cloud Platform</p>
</div>
@@ -36,7 +36,7 @@ export const CustomProviderInputGCP = () => {
export const CustomProviderInputKubernetes = () => {
return (
<div className="flex gap-x-2 items-center">
<div className="flex items-center gap-x-2">
<KS8ProviderBadge width={25} height={25} />
<p className="text-sm">Kubernetes</p>
</div>
@@ -37,6 +37,7 @@ export const CustomRegionSelection = () => {
return (
<Select
label="Region"
aria-label="Select a Region"
placeholder="Select a region"
selectionMode="multiple"
className="w-full"
@@ -38,6 +38,7 @@ export const CustomSearchInput: React.FC = () => {
return (
<Input
variant="flat"
aria-label="Search"
placeholder="Search..."
labelPlacement="outside"
value={searchQuery}
+19 -19
View File
@@ -2,7 +2,7 @@
import { Select, SelectItem } from "@nextui-org/react";
import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import React, { useCallback, useMemo } from "react";
import {
CustomProviderInputAWS,
@@ -34,10 +34,9 @@ const dataInputsProvider = [
},
];
export const CustomSelectProvider = () => {
export const CustomSelectProvider: React.FC = () => {
const router = useRouter();
const searchParams = useSearchParams();
const [selectedProvider, setSelectedProvider] = useState("");
const applyProviderFilter = useCallback(
(value: string) => {
@@ -52,38 +51,39 @@ export const CustomSelectProvider = () => {
[router, searchParams],
);
useEffect(() => {
const providerFromUrl = searchParams.get("filter[provider__in]") || "";
setSelectedProvider(providerFromUrl);
}, [searchParams]);
const currentProvider = searchParams.get("filter[provider__in]") || "";
const selectedKeys = useMemo(() => {
return dataInputsProvider.some(
(provider) => provider.key === currentProvider,
)
? [currentProvider]
: [];
}, [currentProvider]);
return (
<Select
items={dataInputsProvider}
// selectionMode="multiple"
// label="Select a Provider"
aria-label="Select a Provider"
placeholder="Select a provider"
labelPlacement="outside"
size="sm"
onChange={(e) => {
const value = e.target.value;
setSelectedProvider(value);
applyProviderFilter(value);
}}
selectedKeys={selectedProvider ? [selectedProvider] : []}
selectedKeys={selectedKeys}
renderValue={(items) => {
return items.map((item) => {
return (
<div key={item.key} className="flex items-center gap-2">
{item.data?.value}
</div>
);
});
return items.map((item) => (
<div key={item.key} className="flex items-center gap-2">
{item.data?.value}
</div>
));
}}
>
{(item) => (
<SelectItem key={item.key} textValue={item.key} aria-label={item.label}>
<div className="flex gap-2 items-center">{item.value}</div>
<div className="flex items-center gap-2">{item.value}</div>
</SelectItem>
)}
</Select>
+1 -1
View File
@@ -6,7 +6,7 @@ export const filtersProviders = [
},
{
key: "connected",
labelCheckboxGroup: "Status provider",
labelCheckboxGroup: "Connection",
values: ["false", "true"],
},
// Add more filter categories as needed
+3 -2
View File
@@ -47,7 +47,7 @@ export const FilterControls: React.FC<FilterControlsProps> = ({
return (
<div className="flex flex-col gap-4">
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-x-4 gap-y-4 items-center">
<div className="grid grid-cols-1 items-center gap-x-4 gap-y-4 md:grid-cols-2 xl:grid-cols-4">
{search && <CustomSearchInput />}
{providers && <CustomSelectProvider />}
{date && <CustomDatePicker />}
@@ -57,7 +57,8 @@ export const FilterControls: React.FC<FilterControlsProps> = ({
{showClearButton && (
<CustomButton
className="w-fit"
ariaLabel="Reset"
className="w-full md:w-fit"
onPress={clearAllFilters}
variant="dashed"
size="sm"
+3 -3
View File
@@ -41,12 +41,12 @@ export const FindingsCard: React.FC<FindingsCardProps> = ({ selectedRow }) => {
className={clsx(
"max-h-[calc(100vh-146px)] overflow-y-auto rounded-md border bg-background transition-all duration-300",
{
"w-1/3 translate-x-0 ml-2 p-3 opacity-100": selectedRow,
"translate-x-full w-0 opacity-0": !selectedRow,
"ml-2 w-1/3 translate-x-0 p-3 opacity-100": selectedRow,
"w-0 translate-x-full opacity-0": !selectedRow,
},
)}
>
<p className="font-bold mb-3">{CheckTitle}</p>
<p className="mb-3 font-bold">{CheckTitle}</p>
<Divider />
<FindingsCardContent
+1 -1
View File
@@ -14,7 +14,7 @@ export const FindingsCardContent: React.FC<FindingsCardContentProps> = ({
}) => {
return (
<>
<p className="text-sm font-bold mt-3">{title}</p>
<p className="mt-3 text-sm font-bold">{title}</p>
{url ? (
<Link className="text-sm" href={url}>
{description}
+2 -2
View File
@@ -34,9 +34,9 @@ export const FindingsCardDetail: React.FC<FindingsCardDetailProps> = ({
<>
{description && (
<div
className={`text-sm mt-3 rounded-md border-2 ${getDetailColorClass(type)} p-2`}
className={`mt-3 rounded-md border-2 text-sm ${getDetailColorClass(type)} p-2`}
>
<p className="font-bold flex justify-between items-center mb-2">
<p className="mb-2 flex items-center justify-between font-bold">
<span>{title}</span>
{url && (
<Button
+1 -1
View File
@@ -16,7 +16,7 @@ export const FindingsCardScan: React.FC<FindingsCardScanProps> = ({
return (
<>
<p className="text-sm font-bold mt-3">{title}</p>
<p className="mt-3 text-sm font-bold">{title}</p>
<p className="text-sm">
{formattedDate} at {formattedTime}
</p>
+1 -1
View File
@@ -16,7 +16,7 @@ export const FindingsCardType: React.FC<FindingsCardTypeProps> = ({
return (
<>
<p className="text-sm font-bold mt-3">
<p className="mt-3 text-sm font-bold">
{type.length > 1 ? "Types:" : "Type:"}
</p>
<p className="text-sm">{typeContent()}</p>
@@ -47,7 +47,7 @@ export const ColumnsFindings: ColumnDef<FindingProps>[] = [
header: "Region",
cell: ({ row }) => {
const { region } = getFindingsAttributes(row);
return <p className="text-sm text-nowrap">{region}</p>;
return <p className="text-nowrap text-sm">{region}</p>;
},
},
{
@@ -69,8 +69,8 @@ export const ColumnsFindings: ColumnDef<FindingProps>[] = [
{
accessorKey: "actions",
header: () => (
<div className="relative flex justify-end items-center gap-2">
<Dropdown className="bg-background border-1 border-default-200">
<div className="relative flex items-center justify-end gap-2">
<Dropdown className="border-1 border-default-200 bg-background">
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
<VerticalDotsIcon className="text-default-400" />
@@ -48,7 +48,7 @@ export function DataTableFindings<TData extends FindingProps, TValue>({
return (
<>
<div className="flex flex-row w-full">
<div className="flex w-full flex-row">
<div
className={clsx("transition-all duration-300", {
"w-2/3": selectedRow,
@@ -3,9 +3,9 @@ import React from "react";
export const SkeletonTableFindings = () => {
return (
<Card className="w-full h-full space-y-5 p-4" radius="sm">
<Card className="h-full w-full space-y-5 p-4" radius="sm">
{/* Table headers */}
<div className="hidden md:flex justify-between">
<div className="hidden justify-between md:flex">
<Skeleton className="w-1/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
@@ -34,27 +34,27 @@ export const SkeletonTableFindings = () => {
{[...Array(3)].map((_, index) => (
<div
key={index}
className="flex flex-col md:flex-row justify-between items-center space-x-0 md:space-x-4"
className="flex flex-col items-center justify-between space-x-0 md:flex-row md:space-x-4"
>
<Skeleton className="w-full md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 w-full rounded-lg md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="w-full md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 w-full rounded-lg md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
</div>
+2 -1
View File
@@ -22,8 +22,9 @@ export const AddProvider = () => {
<AddForm setIsOpen={setIsAddOpen} />
</CustomAlertModal>
<div className="w-full flex items-center justify-end">
<div className="flex w-full items-center justify-end">
<CustomButton
ariaLabel="Add Account"
variant="solid"
color="action"
size="md"
@@ -12,7 +12,7 @@ import { CustomButton, CustomInput } from "@/components/ui/custom";
import { Form } from "@/components/ui/form";
import { addProviderFormSchema } from "@/types";
import { CustomRadioProvider } from "../CustomRadioProvider";
import { RadioGroupProvider } from "../radio-group-provider";
export const AddForm = ({
setIsOpen,
@@ -67,7 +67,7 @@ export const AddForm = ({
onSubmit={form.handleSubmit(onSubmitClient)}
className="flex flex-col space-y-4"
>
<CustomRadioProvider control={form.control} />
<RadioGroupProvider control={form.control} />
<CustomInput
control={form.control}
name="providerId"
@@ -91,9 +91,10 @@ export const AddForm = ({
isInvalid={!!form.formState.errors.providerAlias}
/>
<div className="w-full flex justify-center sm:space-x-6">
<div className="flex w-full justify-center sm:space-x-6">
<CustomButton
type="button"
ariaLabel="Cancel"
className="w-full bg-transparent"
variant="faded"
size="lg"
@@ -106,6 +107,7 @@ export const AddForm = ({
<CustomButton
type="submit"
ariaLabel="Confirm"
className="w-full"
variant="solid"
color="action"
@@ -54,9 +54,10 @@ export const DeleteForm = ({
<Form {...form}>
<form action={onSubmitClient}>
<input type="hidden" name="id" value={providerId} />
<div className="w-full flex justify-center sm:space-x-6">
<div className="flex w-full justify-center sm:space-x-6">
<CustomButton
type="button"
ariaLabel="Cancel"
className="w-full bg-transparent"
variant="faded"
size="lg"
@@ -69,6 +70,7 @@ export const DeleteForm = ({
<CustomButton
type="submit"
ariaLabel="Delete"
className="w-full"
variant="solid"
color="danger"
@@ -86,9 +86,10 @@ export const EditForm = ({
</div>
<input type="hidden" name="providerId" value={providerId} />
<div className="w-full flex justify-center sm:space-x-6">
<div className="flex w-full justify-center sm:space-x-6">
<CustomButton
type="button"
ariaLabel="Cancel"
className="w-full bg-transparent"
variant="faded"
size="lg"
@@ -101,6 +102,7 @@ export const EditForm = ({
<CustomButton
type="submit"
ariaLabel="Save"
className="w-full"
variant="solid"
color="action"
+3 -3
View File
@@ -1,3 +1,3 @@
export * from "./AddForm";
export * from "./DeleteForm";
export * from "./EditForm";
export * from "./add-form";
export * from "./delete-form";
export * from "./edit-form";
+6 -6
View File
@@ -1,8 +1,8 @@
export * from "./add-provider";
export * from "./CheckConnectionProvider";
export * from "./CustomRadioProvider";
export * from "./DateWithTime";
export * from "./forms/DeleteForm";
export * from "./ProviderInfo";
export * from "./ScanStatus";
export * from "./SnippetIdProvider";
export * from "./date-with-time";
export * from "./forms/delete-form";
export * from "./provider-info";
export * from "./radio-group-provider";
export * from "./scan-status";
export * from "./snippet-id-provider";
@@ -23,19 +23,19 @@ export const ProviderInfo: React.FC<ProviderInfoProps> = ({
switch (connected) {
case true:
return (
<div className="flex items-center justify-center rounded-medium border p-1 bg-system-success-lighter border-system-success">
<div className="flex items-center justify-center rounded-medium border border-system-success bg-system-success-lighter p-1">
<ConnectionIcon className="text-system-success" size={24} />
</div>
);
case false:
return (
<div className="flex items-center justify-center rounded-medium border p-1 bg-system-error-lighter border-danger">
<div className="flex items-center justify-center rounded-medium border border-danger bg-system-error-lighter p-1">
<ConnectionIcon className="text-danger" size={24} />
</div>
);
case null:
return (
<div className="flex items-center justify-center rounded-medium border p-1 bg-info-lighter border-info-lighter">
<div className="bg-info-lighter border-info-lighter flex items-center justify-center rounded-medium border p-1">
<ConnectionIcon className="text-info" size={24} />
</div>
);
@@ -35,8 +35,8 @@ export const CustomRadio: React.FC<CustomRadioProps> = (props) => {
<Component
{...getBaseProps()}
className={cn(
"group inline-flex items-center hover:opacity-70 active:opacity-50 justify-between flex-row-reverse tap-highlight-transparent",
"max-w-full cursor-pointer border-2 border-default rounded-lg gap-4 p-4",
"group inline-flex flex-row-reverse items-center justify-between tap-highlight-transparent hover:opacity-70 active:opacity-50",
"max-w-full cursor-pointer gap-4 rounded-lg border-2 border-default p-4",
"data-[selected=true]:border-primary",
)}
>
@@ -58,11 +58,11 @@ export const CustomRadio: React.FC<CustomRadioProps> = (props) => {
);
};
interface CustomRadioProviderProps {
interface RadioGroupProviderProps {
control: Control<z.infer<typeof addProviderFormSchema>>;
}
export const CustomRadioProvider: React.FC<CustomRadioProviderProps> = ({
export const RadioGroupProvider: React.FC<RadioGroupProviderProps> = ({
control,
}) => {
return (
@@ -22,7 +22,7 @@ export const SnippetIdProvider: React.FC<SnippetIdProviderProps> = ({
>
<p className="flex items-center space-x-2">
<IdIcon size={16} />
<span className="text-sm max-w-24 overflow-x-scroll no-scrollbar">
<span className="no-scrollbar max-w-24 overflow-x-scroll text-sm">
{providerId}
</span>
</p>
@@ -6,9 +6,9 @@ import { add } from "date-fns";
import { StatusBadge } from "@/components/ui/table";
import { ProviderProps } from "@/types";
import { DateWithTime } from "../DateWithTime";
import { ProviderInfo } from "../ProviderInfo";
import { SnippetIdProvider } from "../SnippetIdProvider";
import { DateWithTime } from "../date-with-time";
import { ProviderInfo } from "../provider-info";
import { SnippetIdProvider } from "../snippet-id-provider";
import { DataTableColumnHeader } from "./data-table-column-header";
import { DataTableRowActions } from "./data-table-row-actions";
@@ -18,7 +18,7 @@ const getProviderData = (row: { original: ProviderProps }) => {
export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
{
header: "n",
header: " ",
cell: ({ row }) => <p className="text-medium">{row.index + 1}</p>,
},
{
@@ -80,7 +80,7 @@ export const DataTableColumnHeader = <TData, TValue>({
return (
<Button
className="w-full justify-between px-0 text-left align-middle dark:text-slate-400 h-10 bg-transparent whitespace-nowrap text-foreground-500 text-tiny font-semibold outline-none"
className="h-10 w-full justify-between whitespace-nowrap bg-transparent px-0 text-left align-middle text-tiny font-semibold text-foreground-500 outline-none dark:text-slate-400"
onClick={getToggleSortingHandler}
>
<span>{title}</span>
@@ -1,6 +1,5 @@
"use client";
import { Divider } from "@nextui-org/react";
import { useRouter, useSearchParams } from "next/navigation";
import React, { useState } from "react";
import { useCallback } from "react";
@@ -37,25 +36,28 @@ export const DataTableFilterCustom = ({
);
return (
<div className="flex flex-row items-center gap-4">
<div className="flex flex-col gap-4 md:flex-row md:items-start">
<CustomButton
ariaLabel={showFilters ? "Hide Filters" : "Show Filters"}
variant="flat"
color={showFilters ? "action" : "primary"}
size="sm"
startContent={<CustomFilterIcon size={16} />}
onPress={() => setShowFilters(!showFilters)}
>
{showFilters ? "Hide Filters" : "Show Filters"}
<h3 className="text-small">
{showFilters ? "Hide Filters" : "Show Filters"}
</h3>
</CustomButton>
<div
className={`transition-all duration-500 ease-in-out ${
className={`transition-all duration-700 ease-in-out ${
showFilters
? "opacity-100 max-h-96 overflow-visible"
: "opacity-0 max-h-0 overflow-hidden"
? "max-h-96 w-full translate-x-0 overflow-visible opacity-100 md:max-w-80"
: "max-h-0 -translate-x-full overflow-hidden opacity-0"
}`}
>
<div className="flex flex-row gap-4">
<div className="flex flex-col gap-4 md:flex-row">
{filters.map((filter) => (
<CustomDropdownFilter
key={filter.key}
@@ -66,10 +68,6 @@ export const DataTableFilterCustom = ({
onFilterChange={pushDropdownFilter}
/>
))}
<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>
@@ -49,7 +49,7 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
<div className="flex items-center space-x-2">
<Link
aria-label="Go to first page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(1)}
aria-disabled="true"
>
@@ -57,7 +57,7 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
</Link>
<Link
aria-label="Go to previous page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(currentPage - 1)}
aria-disabled="true"
>
@@ -65,14 +65,14 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
</Link>
<Link
aria-label="Go to next page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(currentPage + 1)}
>
<ChevronRightIcon className="size-4" aria-hidden="true" />
</Link>
<Link
aria-label="Go to last page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(totalPages)}
>
<DoubleArrowRightIcon className="size-4" aria-hidden="true" />
@@ -56,7 +56,7 @@ export function DataTableProvider<TData, TValue>({
return (
<>
<div className="p-4 z-0 flex flex-col relative justify-between gap-4 bg-content1 overflow-auto rounded-large shadow-small w-full ">
<div className="relative z-0 flex w-full flex-col justify-between gap-4 overflow-auto rounded-large bg-content1 p-4 shadow-small">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
@@ -106,7 +106,7 @@ export function DataTableProvider<TData, TValue>({
</TableBody>
</Table>
</div>
<div className="flex items-center w-full space-x-2 py-4">
<div className="flex w-full items-center space-x-2 py-4">
<DataTablePagination metadata={metadata} />
</div>
</>
@@ -22,7 +22,7 @@ import { CustomAlertModal } from "@/components/ui/custom";
import { CheckConnectionProvider } from "../CheckConnectionProvider";
import { EditForm } from "../forms";
import { DeleteForm } from "../forms/DeleteForm";
import { DeleteForm } from "../forms/delete-form";
interface DataTableRowActionsProps<ProviderProps> {
row: Row<ProviderProps>;
@@ -60,7 +60,7 @@ export function DataTableRowActions<ProviderProps>({
<DeleteForm providerId={providerId} setIsOpen={setIsDeleteOpen} />
</CustomAlertModal>
<div className="relative flex justify-end items-center gap-2">
<div className="relative flex items-center justify-end gap-2">
<Dropdown className="shadow-xl" placement="bottom">
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
@@ -3,9 +3,9 @@ import React from "react";
export const SkeletonTableProvider = () => {
return (
<Card className="w-full h-full space-y-5 p-4" radius="sm">
<Card className="h-full w-full space-y-5 p-4" radius="sm">
{/* Table headers */}
<div className="hidden md:flex justify-between">
<div className="hidden justify-between md:flex">
<Skeleton className="w-1/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
@@ -34,27 +34,27 @@ export const SkeletonTableProvider = () => {
{[...Array(3)].map((_, index) => (
<div
key={index}
className="flex flex-col md:flex-row justify-between items-center space-x-0 md:space-x-4"
className="flex flex-col items-center justify-between space-x-0 md:flex-row md:space-x-4"
>
<Skeleton className="w-full md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 w-full rounded-lg md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="w-full md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 w-full rounded-lg md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
</div>
+3 -3
View File
@@ -12,11 +12,11 @@ export const ServiceCard: React.FC<CardServiceProps> = ({
}) => {
return (
<Card fullWidth isPressable isHoverable shadow="sm">
<CardBody className="flex flex-row items-center space-x-4 justify-between">
<div className="flex space-x-4 items-center">
<CardBody className="flex flex-row items-center justify-between space-x-4">
<div className="flex items-center space-x-4">
{getAWSIcon(serviceAlias)}
<div className="flex flex-col">
<h4 className="font-bold text-md leading-5">{serviceAlias}</h4>
<h4 className="text-md font-bold leading-5">{serviceAlias}</h4>
<small className="text-default-500">
{fidingsFailed > 0
? `${fidingsFailed} Failed Findings`
+2 -2
View File
@@ -3,8 +3,8 @@ import React from "react";
export const ServiceSkeletonGrid = () => {
return (
<Card className="w-full h-fit p-4">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
<Card className="h-fit w-full p-4">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{[...Array(25)].map((_, index) => (
<div key={index} className="flex flex-col space-y-4">
<Skeleton className="h-16 rounded-lg">
+1 -1
View File
@@ -60,7 +60,7 @@ export const ActionCard = React.forwardRef<HTMLDivElement, ActionCardProps>(
shadow="sm"
{...props}
>
<CardBody className="flex h-full flex-row gap-2 p-2 items-center">
<CardBody className="flex h-full flex-row items-center gap-2 p-2">
<div
className={cn(
"item-center flex rounded-medium border p-1",
+1 -1
View File
@@ -34,7 +34,7 @@ const AlertDialogContent = React.forwardRef<
<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",
"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%] dark:border-neutral-800 dark:bg-neutral-950 sm:rounded-lg",
className,
)}
{...props}
+1 -1
View File
@@ -57,7 +57,7 @@ const ChartContainer = React.forwardRef<
data-chart={chartId}
ref={ref}
className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
className,
)}
{...props}
+4 -4
View File
@@ -19,17 +19,17 @@ export const CustomBox = ({
<Card fullWidth {...props}>
{(preTitle || subTitle || title) && (
<>
<CardHeader className="pt-4 pb-3 px-3 flex-col items-start">
<CardHeader className="flex-col items-start px-3 pb-3 pt-4">
{preTitle && (
<p className="text-tiny uppercase font-bold">{preTitle}</p>
<p className="text-tiny font-bold uppercase">{preTitle}</p>
)}
{subTitle && <small className="text-default-500">{subTitle}</small>}
{title && <h4 className="font-bold text-large">{title}</h4>}
{title && <h4 className="text-large font-bold">{title}</h4>}
</CardHeader>
<Divider />
</>
)}
<CardBody className="px-3 pt-3 pb-4">{children}</CardBody>
<CardBody className="px-3 pb-4 pt-3">{children}</CardBody>
</Card>
);
};
@@ -17,7 +17,7 @@ export const CustomButtonClientAction = ({
return (
<Button
className={clsx("bg-transparent border-none p-0 m-0 h-fit min-w-min", {
className={clsx("m-0 h-fit min-w-min border-none bg-transparent p-0", {
"text-danger": danger,
})}
spinner={<CircularProgress aria-label="Loading..." size="sm" />}
@@ -5,7 +5,7 @@ import clsx from "clsx";
import { NextUIColors, NextUIVariants } from "@/types";
export const buttonClasses = {
base: "px-2 inline-flex items-center justify-center relative z-0 text-center whitespace-nowrap",
base: "px-4 inline-flex items-center justify-center relative z-0 text-center whitespace-nowrap",
primary: "bg-default-100 hover:bg-default-200 text-default-800",
secondary: "bg-prowler-grey-light dark:bg-prowler-grey-medium text-white",
action: "text-white bg-prowler-blue-smoky dark:bg-prowler-grey-medium",
@@ -18,6 +18,7 @@ export const buttonClasses = {
interface ButtonProps {
type?: "button" | "submit" | "reset";
ariaLabel: string;
className?: string;
variant?:
| "solid"
@@ -50,6 +51,7 @@ interface ButtonProps {
export const CustomButton = ({
type = "button",
ariaLabel,
className,
variant = "solid",
color = "primary",
@@ -66,6 +68,7 @@ export const CustomButton = ({
}: ButtonProps) => (
<Button
type={type}
aria-label={ariaLabel}
onPress={onPress}
variant={variant as NextUIVariants}
color={color as NextUIColors}
+39 -44
View File
@@ -1,7 +1,6 @@
"use client";
import {
Badge,
Button,
Checkbox,
CheckboxGroup,
@@ -9,13 +8,18 @@ import {
Popover,
PopoverContent,
PopoverTrigger,
ScrollShadow,
} from "@nextui-org/react";
import _ from "lodash";
import { useSearchParams } from "next/navigation";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { PlusCircleIcon } from "@/components/icons";
import { CustomDropdownFilterProps } from "@/types";
const filterSelectedClass =
"inline-flex items-center border py-0.5 text-xs transition-colors border-transparent bg-default-500 text-secondary-foreground hover:bg-default-500/80 rounded-md px-2 font-normal";
export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
filter,
onFilterChange,
@@ -89,45 +93,32 @@ export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
}
}, [groupSelected, allFilterKeys]);
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Popover placement="bottom">
<div className="flex w-full flex-col gap-2">
<Popover backdrop="transparent" placement="bottom-start">
<PopoverTrigger>
<Button
className="bg-default-100 text-default-800"
startContent={
<PlusCircleIcon className="text-default-400" width={16} />
}
className="border-input hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center justify-center whitespace-nowrap rounded-md border border-dashed bg-background px-3 text-xs font-medium shadow-sm transition-colors focus-visible:outline-none disabled:opacity-50"
startContent={<PlusCircleIcon size={16} />}
size="sm"
>
{filter?.labelCheckboxGroup}
<h3 className="text-small">{filter?.labelCheckboxGroup}</h3>
{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>
<div className="no-scrollbar hidden max-w-24 space-x-1 overflow-x-auto lg:flex">
{groupSelected.size > 3 ? (
<span
className={filterSelectedClass}
>{`+${groupSelected.size - 2} selected`}</span>
) : (
Array.from(groupSelected)
.filter((value) => value !== "all")
.map((value) => (
<Badge
variant="flat"
key={value}
className="rounded-sm px-1 font-normal"
>
{value}
</Badge>
<div key={value} className={filterSelectedClass}>
{_.capitalize(value)}
</div>
))
)}
</div>
@@ -136,32 +127,36 @@ export const CustomDropdownFilter: React.FC<CustomDropdownFilterProps> = ({
</Button>
</PopoverTrigger>
<PopoverContent className="w-80">
<div className="flex w-full flex-col gap-6 px-2 py-4">
<div className="flex w-full flex-col gap-6 p-2">
<CheckboxGroup
color="default"
label={filter?.labelCheckboxGroup}
value={Array.from(groupSelected)}
onValueChange={onSelectionChange}
className="font-bold"
>
<Checkbox value="all" onValueChange={handleSelectAllClick}>
<Checkbox
className="font-normal"
value="all"
onValueChange={handleSelectAllClick}
>
Select All
</Checkbox>
{allFilterKeys.map((value) => (
<Checkbox key={value} value={value}>
{value}
</Checkbox>
))}
<Divider orientation="horizontal" className="mt-2" />
<ScrollShadow
hideScrollBar
className="flex max-h-96 max-w-56 flex-col gap-y-2 py-2"
>
{allFilterKeys.map((value) => (
<Checkbox className="font-normal" key={value} value={value}>
{_.capitalize(value)}
</Checkbox>
))}
</ScrollShadow>
</CheckboxGroup>
</div>
</PopoverContent>
</Popover>
{groupSelected?.size > 0 && (
<p className="text-small text-default-500">
Selected:{" "}
{Array.from(groupSelected)
.filter((item) => item !== "all")
.join(", ")}
</p>
)}
</div>
);
};
+1 -1
View File
@@ -1,7 +1,7 @@
export * from "./custom-button";
export * from "./custom-dropdown-filter";
export * from "./CustomAlertModal";
export * from "./CustomBox";
export * from "./CustomButton";
export * from "./CustomButtonClientAction";
export * from "./CustomInput";
export * from "./CustomLoader";
+3 -3
View File
@@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
"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}
@@ -44,7 +44,7 @@ const DialogContent = React.forwardRef<
{...props}
>
{children}
<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">
<DialogPrimitive.Close className="focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground 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-offset-2 disabled:pointer-events-none">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
@@ -102,7 +102,7 @@ const DialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));
+7 -7
View File
@@ -27,7 +27,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
<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",
"focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
inset && "pl-8",
className,
)}
@@ -47,7 +47,7 @@ const DropdownMenuSubContent = React.forwardRef<
<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",
"bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 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}
@@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef<
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",
"bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 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}
@@ -83,7 +83,7 @@ const DropdownMenuItem = React.forwardRef<
<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",
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className,
)}
@@ -99,7 +99,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<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",
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
checked={checked}
@@ -123,7 +123,7 @@ const DropdownMenuRadioItem = React.forwardRef<
<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",
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
@@ -162,7 +162,7 @@ const DropdownMenuSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
className={cn("bg-muted -mx-1 my-1 h-px", className)}
{...props}
/>
));
+1 -1
View File
@@ -12,7 +12,7 @@ export const Header: React.FC<HeaderProps> = ({ title, icon }) => {
<>
<header className="flex items-center gap-3 py-4">
<Icon className="text-default-500" height={40} icon={icon} width={40} />
<h1 className="font-bold text-default-700 text-2xl">{title}</h1>
<h1 className="text-2xl font-bold text-default-700">{title}</h1>
</header>
<Divider className="mb-4" />
</>
+1 -1
View File
@@ -24,7 +24,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-slate-200 bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-white placeholder:text-slate-500 focus:outline-none focus:ring-1 focus:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 dark:border-slate-800 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus:ring-slate-300",
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-slate-200 bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-white placeholder:text-slate-500 focus:outline-none focus:ring-1 focus:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus:ring-slate-300 [&>span]:line-clamp-1",
className,
)}
{...props}
+7 -7
View File
@@ -113,7 +113,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
endContent={
isCompact || isNestType || hideEndContent
? null
: item.endContent ?? null
: (item.endContent ?? null)
}
startContent={
isCompact || isNestType ? null : item.icon ? (
@@ -127,7 +127,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
width={24}
/>
) : (
item.startContent ?? null
(item.startContent ?? null)
)
}
title={isCompact || isNestType ? null : item.title}
@@ -146,7 +146,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
width={24}
/>
) : (
item.startContent ?? null
(item.startContent ?? null)
)}
</div>
</Tooltip>
@@ -180,7 +180,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
</span>
</div>
) : (
item.startContent ?? null
(item.startContent ?? null)
)
}
>
@@ -223,7 +223,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
{...item}
key={item.key}
endContent={
isCompact || hideEndContent ? null : item.endContent ?? null
isCompact || hideEndContent ? null : (item.endContent ?? null)
}
startContent={
isCompact ? null : item.icon ? (
@@ -236,7 +236,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
width={24}
/>
) : (
item.startContent ?? null
(item.startContent ?? null)
)
}
textValue={item.title}
@@ -255,7 +255,7 @@ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(
width={24}
/>
) : (
item.startContent ?? null
(item.startContent ?? null)
)}
</div>
</Tooltip>
+5 -5
View File
@@ -42,7 +42,7 @@ export const SidebarWrap = () => {
return (
<div
className={clsx(
"relative flex h-screen flex-col !border-r-small border-divider transition-width bg-prowler-blue-midnight",
"relative flex h-screen flex-col !border-r-small border-divider transition-width",
{
"w-72 p-6": !isCompact,
"w-16 items-center px-2 py-6": isCompact,
@@ -50,7 +50,7 @@ export const SidebarWrap = () => {
)}
>
<div
className={clsx("flex items-center gap-3 px-3 justify-center", {
className={clsx("flex items-center justify-center gap-3 px-3", {
"gap-0": isCompact,
})}
>
@@ -268,9 +268,9 @@ export const SidebarWrap = () => {
>
<div
className={clsx(
"text-default-500 data-[hover=true]:text-foreground px-0",
"px-0 text-default-500 data-[hover=true]:text-foreground",
{
"justify-center mt-3": isCompact,
"mt-3 justify-center": isCompact,
},
)}
>
@@ -284,7 +284,7 @@ export const SidebarWrap = () => {
<Button
aria-label={isCompact ? "Open sidebar" : "Close sidebar"}
className={clsx(
"text-default-500 data-[hover=true]:text-foreground px-0",
"px-0 text-default-500 data-[hover=true]:text-foreground",
{
"justify-center": isCompact,
},
+1 -1
View File
@@ -36,7 +36,7 @@ export const SeverityBadge = ({ severity }: { severity: Severity }) => {
return (
<Chip
className={clsx("capitalize border-none gap-1 text-default-600", {
className={clsx("gap-1 border-none capitalize text-default-600", {
"bg-rose-700/20": severity === "critical",
})}
size="sm"
+1 -1
View File
@@ -30,7 +30,7 @@ export const StatusBadge = ({ status }: { status: Status }) => {
return (
<Chip
className="capitalize border-none gap-1 text-default-600"
className="gap-1 border-none capitalize text-default-600"
size="sm"
variant="flat"
color={color}
+2 -2
View File
@@ -45,7 +45,7 @@ const TableFooter = React.forwardRef<
<tfoot
ref={ref}
className={cn(
"font-medium [&>tr]:last:border-b-0 dark:bg-slate-800/50",
"font-medium dark:bg-slate-800/50 [&>tr]:last:border-b-0",
className,
)}
{...props}
@@ -75,7 +75,7 @@ const TableHead = React.forwardRef<
<th
ref={ref}
className={cn(
"px-4 text-left align-middle bg-default-100 [&:has([role=checkbox])]:pr-0 dark:text-slate-400 h-10 rtl:text-right whitespace-nowrap text-foreground-500 text-tiny font-semibold first:rounded-l-lg rtl:first:rounded-r-lg rtl:first:rounded-l-[unset] last:rounded-r-lg rtl:last:rounded-l-lg rtl:last:rounded-r-[unset] data-[hover=true]:text-foreground-400 outline-none data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2",
"h-10 whitespace-nowrap bg-default-100 px-4 text-left align-middle text-tiny font-semibold text-foreground-500 outline-none first:rounded-l-lg last:rounded-r-lg data-[focus-visible=true]:z-10 data-[hover=true]:text-foreground-400 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-offset-2 data-[focus-visible=true]:outline-focus dark:text-slate-400 rtl:text-right rtl:first:rounded-l-[unset] rtl:first:rounded-r-lg rtl:last:rounded-l-lg rtl:last:rounded-r-[unset] [&:has([role=checkbox])]:pr-0",
className,
)}
{...props}
+1 -1
View File
@@ -95,7 +95,7 @@ const ToastTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-lg font-semibold [&+div]:text-md", className)}
className={cn("[&+div]:text-md text-lg font-semibold", className)}
{...props}
/>
));
+3 -3
View File
@@ -30,10 +30,10 @@ export const AddUserModal = () => {
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>
<DialogTitle className="text-center text-2xl">Add User</DialogTitle>
</DialogHeader>
<form ref={ref} onSubmit={() => setOpen(false)}>
<div className="col-span-1 flex flex-col gap-y-2 my-auto">
<div className="col-span-1 my-auto flex flex-col gap-y-2">
<Input
type="text"
name="email"
@@ -52,7 +52,7 @@ export const AddUserModal = () => {
/>
<CustomSelectUser />
</div>
<div className="col-span-2 flex justify-center mt-4">
<div className="col-span-2 mt-4 flex justify-center">
<ButtonAddUser />
</div>
</form>
+1 -1
View File
@@ -22,7 +22,7 @@ export const CustomSelectUser: React.FC<CustomSelectUserProps> = ({
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">
<SelectTrigger className="h-12 rounded-xl border-transparent bg-zinc-100 text-foreground-500 shadow-none ring-0 hover:bg-zinc-200 focus:border-2 focus:border-white focus:ring-2 focus:ring-blue-600">
<SelectValue
placeholder={(userData && userData?.role) || "Select a role"}
/>
+3 -3
View File
@@ -34,10 +34,10 @@ export const EditUserModal: React.FC<EditUserModalProps> = ({
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>
<DialogTitle className="text-center text-2xl">Edit User</DialogTitle>
</DialogHeader>
<form ref={ref} onSubmit={() => setIsOpen(false)}>
<div className="col-span-1 flex flex-col gap-y-2 my-auto">
<div className="col-span-1 my-auto flex flex-col gap-y-2">
<Input
type="name"
name="name"
@@ -72,7 +72,7 @@ export const EditUserModal: React.FC<EditUserModalProps> = ({
/>
<CustomSelectUser userData={userData} />
</div>
<div className="col-span-2 flex justify-center mt-4">
<div className="col-span-2 mt-4 flex justify-center">
<ButtonEditUser />
</div>
</form>
@@ -49,7 +49,7 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
<div className="flex items-center space-x-2">
<Link
aria-label="Go to first page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(1)}
aria-disabled="true"
>
@@ -57,7 +57,7 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
</Link>
<Link
aria-label="Go to previous page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(currentPage - 1)}
aria-disabled="true"
>
@@ -65,14 +65,14 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
</Link>
<Link
aria-label="Go to next page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(currentPage + 1)}
>
<ChevronRightIcon className="size-4" aria-hidden="true" />
</Link>
<Link
aria-label="Go to last page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
className="page-link relative block rounded border-0 bg-transparent px-3 py-1.5 text-gray-800 outline-none transition-all duration-300 hover:bg-gray-200 hover:text-gray-800 focus:shadow-none"
href={createPageUrl(totalPages)}
>
<DoubleArrowRightIcon className="size-4" aria-hidden="true" />
+2 -2
View File
@@ -49,7 +49,7 @@ export function DataTableUser<TData, TValue>({
});
return (
<>
<div className="rounded-md border w-full">
<div className="w-full rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
@@ -99,7 +99,7 @@ export function DataTableUser<TData, TValue>({
</TableBody>
</Table>
</div>
<div className="flex items-center w-full space-x-2 py-4">
<div className="flex w-full items-center space-x-2 py-4">
<DataTablePagination metadata={metadata} />
</div>
</>
+9 -9
View File
@@ -3,9 +3,9 @@ import React from "react";
export const SkeletonTableUser = () => {
return (
<Card className="w-full h-full space-y-5 p-4" radius="sm">
<Card className="h-full w-full space-y-5 p-4" radius="sm">
{/* Table headers */}
<div className="hidden md:flex justify-between">
<div className="hidden justify-between md:flex">
<Skeleton className="w-2/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
@@ -31,24 +31,24 @@ export const SkeletonTableUser = () => {
{[...Array(10)].map((_, index) => (
<div
key={index}
className="flex flex-col md:flex-row justify-between items-center space-x-0 md:space-x-4"
className="flex flex-col items-center justify-between space-x-0 md:flex-row md:space-x-4"
>
<Skeleton className="w-full md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 w-full rounded-lg md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="w-full md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 w-full rounded-lg md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-2/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-1/12 rounded-lg mb-2 md:mb-0">
<Skeleton className="mb-2 hidden rounded-lg sm:flex md:mb-0 md:w-1/12">
<div className="h-12 bg-default-300"></div>
</Skeleton>
</div>
+4 -4
View File
@@ -21,22 +21,22 @@ export const UserActions: React.FC<UserActionsProps> = ({ userData }) => {
return (
<>
<div className="relative flex justify-end items-center gap-2">
<div className="relative flex items-center justify-end gap-2">
<DropdownMenu modal={false}>
<DropdownMenuTrigger>
<VerticalDotsIcon
size={28}
className="text-default-400 p-0.5 hover:bg-gray-200 hover:rounded-full"
className="p-0.5 text-default-400 hover:rounded-full hover:bg-gray-200"
/>
</DropdownMenuTrigger>
<DropdownMenuContent className="bg-white">
<DropdownMenuItem
className="hover:bg-gray-200 hover:cursor-pointer"
className="hover:cursor-pointer hover:bg-gray-200"
onClick={() => setIsEditOpen(true)}
>
Edit
</DropdownMenuItem>
<DropdownMenuItem className="hover:bg-gray-200 hover:cursor-pointer">
<DropdownMenuItem className="hover:cursor-pointer hover:bg-gray-200">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
+86 -4
View File
@@ -73,6 +73,8 @@
"husky": "^9.0.11",
"lint-staged": "^15.2.7",
"postcss": "8.4.38",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.8",
"tailwind-variants": "0.1.20",
"tailwindcss": "3.4.3",
"typescript": "^5.5.4",
@@ -7627,6 +7629,7 @@
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
"dev": true,
"license": "MIT",
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@@ -10880,11 +10883,11 @@
}
},
"node_modules/prettier": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
"integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
"peer": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -10907,6 +10910,85 @@
"node": ">=6.0.0"
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.8.tgz",
"integrity": "sha512-dGu3kdm7SXPkiW4nzeWKCl3uoImdd5CTZEJGxyypEPL37Wj0HT2pLqjrvSei1nTeuQfO4PUfjeW5cTUNRLZ4sA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14.21.3"
},
"peerDependencies": {
"@ianvs/prettier-plugin-sort-imports": "*",
"@prettier/plugin-pug": "*",
"@shopify/prettier-plugin-liquid": "*",
"@trivago/prettier-plugin-sort-imports": "*",
"@zackad/prettier-plugin-twig-melody": "*",
"prettier": "^3.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-import-sort": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-marko": "*",
"prettier-plugin-multiline-arrays": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-sort-imports": "*",
"prettier-plugin-style-order": "*",
"prettier-plugin-svelte": "*"
},
"peerDependenciesMeta": {
"@ianvs/prettier-plugin-sort-imports": {
"optional": true
},
"@prettier/plugin-pug": {
"optional": true
},
"@shopify/prettier-plugin-liquid": {
"optional": true
},
"@trivago/prettier-plugin-sort-imports": {
"optional": true
},
"@zackad/prettier-plugin-twig-melody": {
"optional": true
},
"prettier-plugin-astro": {
"optional": true
},
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-import-sort": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
"prettier-plugin-marko": {
"optional": true
},
"prettier-plugin-multiline-arrays": {
"optional": true
},
"prettier-plugin-organize-attributes": {
"optional": true
},
"prettier-plugin-organize-imports": {
"optional": true
},
"prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-style-order": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
}
}
},
"node_modules/pretty-format": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
+2
View File
@@ -65,6 +65,8 @@
"husky": "^9.0.11",
"lint-staged": "^15.2.7",
"postcss": "8.4.38",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.8",
"tailwind-variants": "0.1.20",
"tailwindcss": "3.4.3",
"typescript": "^5.5.4",