feat: upgrade to React 19, Next.js 15, React Compiler, HeroUI and Tailwind 4 (#8748)

Co-authored-by: Alan Buscaglia <alanbuscaglia@MacBook-Pro.local>
Co-authored-by: alejandrobailo <alejandrobailo94@gmail.com>
Co-authored-by: César Arroba <cesar@prowler.com>
Co-authored-by: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2025-09-30 09:59:51 +02:00
1 parent 2a4b62527a
commit 4d5676f00e
261 files changed
+6339 -6126

No files matched your search

@@ -1,4 +1,4 @@
import { Modal, ModalBody, ModalContent, ModalHeader } from "@nextui-org/react";
import { Modal, ModalBody, ModalContent, ModalHeader } from "@heroui/modal";
import React, { ReactNode } from "react";
interface CustomAlertModalProps {
+3 -3
View File
@@ -18,9 +18,9 @@ export const CustomBanner = ({
buttonLink = "/",
}: CustomBannerProps) => {
return (
<div className="flex items-center justify-start rounded-lg border-1 border-system-warning-light px-4 py-6 shadow-box dark:bg-prowler-blue-400">
<div className="border-system-warning-light shadow-box dark:bg-prowler-blue-400 flex items-center justify-start rounded-lg border px-4 py-6">
<div className="flex w-full flex-col items-start gap-6 md:flex-row md:items-center md:justify-between md:gap-8">
<div className="flex flex-col space-y-3">
<div className="flex flex-col gap-3">
<div className="flex items-center justify-start gap-3">
<InfoIcon className="h-6 w-6 text-gray-800 dark:text-white" />
<h2 className="text-lg font-bold text-gray-800 dark:text-white">
@@ -29,7 +29,7 @@ export const CustomBanner = ({
</div>
<p className="text-sm text-gray-600 dark:text-gray-300">{message}</p>
</div>
<div className="w-full md:w-auto md:flex-shrink-0">
<div className="w-full md:w-auto md:shrink-0">
<CustomButton
asLink={buttonLink}
className="w-full justify-center md:w-fit"
+4 -3
View File
@@ -1,5 +1,6 @@
import { Card, CardBody, CardHeader, Divider } from "@nextui-org/react";
import { CardProps as NextUICardProps } from "@nextui-org/react";
import type { CardProps as NextUICardProps } from "@heroui/card";
import { Card, CardBody, CardHeader } from "@heroui/card";
import { Divider } from "@heroui/divider";
import React from "react";
interface CustomBoxProps {
children: React.ReactNode;
@@ -29,7 +30,7 @@ export const CustomBox = ({
<Divider />
</>
)}
<CardBody className="px-3 pb-4 pt-3">{children}</CardBody>
<CardBody className="px-3 pt-3 pb-4">{children}</CardBody>
</Card>
);
};
+2 -1
View File
@@ -1,4 +1,5 @@
import { Button, CircularProgress } from "@nextui-org/react";
import { Button } from "@heroui/button";
import { CircularProgress } from "@heroui/progress";
import type { PressEvent } from "@react-types/shared";
import clsx from "clsx";
import Link from "next/link";
@@ -1,15 +1,10 @@
"use client";
import {
Button,
Checkbox,
CheckboxGroup,
Divider,
Popover,
PopoverContent,
PopoverTrigger,
ScrollShadow,
} from "@nextui-org/react";
import { Button } from "@heroui/button";
import { Checkbox, CheckboxGroup } from "@heroui/checkbox";
import { Divider } from "@heroui/divider";
import { Popover, PopoverContent, PopoverTrigger } from "@heroui/popover";
import { ScrollShadow } from "@heroui/scroll-shadow";
import { ChevronDown, X } from "lucide-react";
import { useSearchParams } from "next/navigation";
import React, {
@@ -221,7 +216,7 @@ export const CustomDropdownFilter = ({
>
<PopoverTrigger>
<Button
className="border-input hover:bg-accent hover:text-accent-foreground inline-flex h-auto min-h-10 items-center justify-between whitespace-nowrap rounded-md border border-dashed bg-background px-3 py-2 text-xs font-medium shadow-sm transition-colors focus-visible:outline-none disabled:opacity-50 dark:bg-prowler-blue-800"
className="border-input hover:bg-accent hover:text-accent-foreground bg-background dark:bg-prowler-blue-800 inline-flex h-auto min-h-10 items-center justify-between rounded-md border px-3 py-2 text-xs font-medium whitespace-nowrap shadow-sm transition-colors focus-visible:outline-none disabled:opacity-50"
endContent={
<ChevronDown
className={`h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`}
@@ -231,26 +226,23 @@ export const CustomDropdownFilter = ({
variant="flat"
>
<div className="flex min-w-0 flex-1 items-center gap-2">
<span className="flex-shrink-0 text-small">
<span className="text-small shrink-0">
{filter?.labelCheckboxGroup}
</span>
{selectedValues.length > 0 && (
<>
<Divider
orientation="vertical"
className="h-4 flex-shrink-0"
/>
<div className="flex min-w-0 flex-shrink items-center">
<Divider orientation="vertical" className="h-4 shrink-0" />
<div className="flex min-w-0 shrink items-center">
{selectedValues.length <= 2 ? (
<span
className="max-w-32 truncate text-xs text-default-500"
className="text-default-500 max-w-32 truncate text-xs"
title={selectedValues.map(getDisplayLabel).join(", ")}
>
{selectedValues.map(getDisplayLabel).join(", ")}
</span>
) : (
<span className="truncate text-xs text-default-500">
<span className="text-default-500 truncate text-xs">
{isAllSelected
? "All selected"
: `${selectedValues.length} selected`}
@@ -258,7 +250,7 @@ export const CustomDropdownFilter = ({
)}
<div
onClick={handleClearAll}
className="ml-1 flex h-4 w-4 flex-shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors hover:bg-default-200"
className="hover:bg-default-200 ml-1 flex h-4 w-4 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors"
aria-label="Clear selection"
role="button"
tabIndex={0}
@@ -269,7 +261,7 @@ export const CustomDropdownFilter = ({
}
}}
>
<X className="h-3 w-3 text-default-400 hover:text-default-600" />
<X className="text-default-400 hover:text-default-600 h-3 w-3" />
</div>
</div>
</>
@@ -277,7 +269,7 @@ export const CustomDropdownFilter = ({
</div>
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto min-w-80 dark:bg-prowler-blue-800">
<PopoverContent className="dark:bg-prowler-blue-800 w-auto min-w-80">
<div className="flex w-full flex-col gap-4 p-2">
<CheckboxGroup
color="default"
@@ -1,15 +1,10 @@
"use client";
import {
Button,
Checkbox,
CheckboxGroup,
Divider,
Popover,
PopoverContent,
PopoverTrigger,
ScrollShadow,
} from "@nextui-org/react";
import { Button } from "@heroui/button";
import { Checkbox, CheckboxGroup } from "@heroui/checkbox";
import { Divider } from "@heroui/divider";
import { Popover, PopoverContent, PopoverTrigger } from "@heroui/popover";
import { ScrollShadow } from "@heroui/scroll-shadow";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { PlusCircleIcon } from "@/components/icons";
@@ -81,14 +76,14 @@ export const CustomDropdownSelection: React.FC<
<Popover backdrop="transparent" placement="bottom-start">
<PopoverTrigger>
<Button
className="border-input hover:bg-accent hover:text-accent-foreground inline-flex h-10 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 dark:bg-prowler-blue-800"
className="border-input hover:bg-accent hover:text-accent-foreground bg-background dark:bg-prowler-blue-800 inline-flex h-10 items-center justify-center rounded-md border border-dashed px-3 text-xs font-medium whitespace-nowrap shadow-sm transition-colors focus-visible:outline-none disabled:opacity-50"
startContent={<PlusCircleIcon size={16} />}
size="md"
>
<h3 className="text-small">{label}</h3>
</Button>
</PopoverTrigger>
<PopoverContent className="w-80 dark:bg-prowler-blue-800">
<PopoverContent className="dark:bg-prowler-blue-800 w-80">
<div className="flex w-full flex-col gap-6 p-2">
<CheckboxGroup
color="default"
+5 -4
View File
@@ -1,7 +1,7 @@
"use client";
import { Input } from "@heroui/input";
import { Icon } from "@iconify/react";
import { Input } from "@nextui-org/react";
import React, { useState } from "react";
import { Control, FieldPath, FieldValues } from "react-hook-form";
@@ -79,7 +79,7 @@ export const CustomInput = <T extends FieldValues>({
const endContent = (password || confirmPassword) && (
<button type="button" onClick={toggleVisibility}>
<Icon
className="pointer-events-none text-2xl text-default-400"
className="text-default-400 pointer-events-none text-2xl"
icon={
(password && isPasswordVisible) ||
(confirmPassword && isConfirmPasswordVisible)
@@ -101,7 +101,7 @@ export const CustomInput = <T extends FieldValues>({
id={name}
classNames={{
label:
"tracking-tight font-light !text-default-500 text-xs !z-0",
"tracking-tight font-light !text-default-500 text-xs z-0!",
input: "text-default-500 text-small",
}}
isRequired={inputIsRequired}
@@ -117,10 +117,11 @@ export const CustomInput = <T extends FieldValues>({
isDisabled={isDisabled}
isReadOnly={isReadOnly}
{...field}
value={field.value ?? ""}
/>
</FormControl>
{showFormMessage && (
<FormMessage className="max-w-full text-xs text-system-error dark:text-system-error" />
<FormMessage className="text-system-error dark:text-system-error max-w-full text-xs" />
)}
</>
)}
+1 -1
View File
@@ -34,7 +34,7 @@ export const CustomLink = React.forwardRef<HTMLAnchorElement, CustomLinkProps>(
href={href}
scroll={scroll}
className={cn(
`text-${size} text-nowrap break-all font-medium text-primary decoration-1 hover:underline`,
`text-${size} text-primary font-medium text-nowrap break-all decoration-1 hover:underline`,
className,
)}
aria-label={ariaLabel}
+6 -4
View File
@@ -1,4 +1,6 @@
import { cn, useRadio, VisuallyHidden } from "@nextui-org/react";
import { useRadio } from "@heroui/radio";
import { cn } from "@heroui/theme";
import { VisuallyHidden } from "@react-aria/visually-hidden";
import React from "react";
interface CustomRadioProps {
@@ -24,9 +26,9 @@ export const CustomRadio: React.FC<CustomRadioProps> = (props) => {
<Component
{...getBaseProps()}
className={cn(
"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",
"w-full hover:border-action data-[selected=true]:border-action",
"group tap-highlight-transparent inline-flex flex-row-reverse items-center justify-between hover:opacity-70 active:opacity-50",
"border-default max-w-full cursor-pointer gap-4 rounded-lg border-2 p-4",
"hover:border-action data-[selected=true]:border-action w-full",
)}
>
<VisuallyHidden>
+2 -2
View File
@@ -9,9 +9,9 @@ export const CustomSection = ({
children,
action,
}: CustomSectionProps) => (
<div className="flex flex-col gap-4 rounded-lg p-4 shadow dark:bg-prowler-blue-400">
<div className="dark:bg-prowler-blue-400 flex flex-col gap-4 rounded-lg p-4 shadow">
<div className="flex items-center justify-between">
<h3 className="text-md font-medium text-gray-800 dark:text-prowler-theme-pale/90">
<h3 className="text-md dark:text-prowler-theme-pale/90 font-medium text-gray-800">
{title}
</h3>
{action && <div>{action}</div>}
@@ -1,6 +1,6 @@
"use client";
import { Input } from "@nextui-org/react";
import { Input } from "@heroui/input";
import React from "react";
interface CustomServerInputProps {
@@ -49,7 +49,7 @@ export const CustomServerInput = ({
value={value}
onChange={onChange}
classNames={{
label: "tracking-tight font-light !text-default-500 text-xs !z-0",
label: "tracking-tight font-light !text-default-500 text-xs z-0!",
input: "text-default-500 text-small",
}}
/>
@@ -15,7 +15,7 @@ export const TableLink = ({ href, label, isDisabled }: TableLinkProps) => {
asLink={href}
ariaLabel={label}
variant="ghost"
className="text-xs font-medium text-default-500 hover:text-primary disabled:opacity-30"
className="text-default-500 hover:text-primary text-xs font-medium disabled:opacity-30"
size="sm"
isDisabled={isDisabled}
>
+1 -1
View File
@@ -1,6 +1,6 @@
"use client";
import { Textarea } from "@nextui-org/react";
import { Textarea } from "@heroui/input";
import React from "react";
import { Control, FieldPath, FieldValues } from "react-hook-form";