New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

daemonui

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

daemonui - npm Package Compare versions

Comparing version
1.0.39
to
1.0.40
+168
registry/Modal.tsx
import React, {
useContext,
createContext,
type PropsWithChildren,
useState,
useRef,
useEffect,
useCallback,
} from "react";
import { twMerge } from "tailwind-merge";
import { clsx } from "clsx";
// Interfaz para el contexto del modal
interface Context {
isOpenModal: boolean; // Indica si el modal está abierto
openModal: () => void; // Función para abrir el modal
closeModal: () => void; // Función para cerrar el modal
classNameContent: string; // Clases CSS para el contenido del modal
classNameBackdrop: string; // Clases CSS para el fondo/exterior del modal
closeOnOutsideClick: boolean; // Cierra el modal al hacer clic fuera
closeOnEscape: boolean; // Cierra el modal al presionar Escape
}
// Contexto global para el estado del modal
const ModalContext = createContext<Context | null>(null);
// Hook para acceder al contexto del modal
export const useModal = () => {
const context = useContext(ModalContext);
if (!context) {
throw new Error("useModal debe usarse dentro de un ModalProvider");
}
return context;
};
/*
╔══════════════════════════════════════════════════════════════════════════╗
║ Componente proveedor del modal, maneja el estado abierto/cerrado ║
╚══════════════════════════════════════════════════════════════════════════╝
*/
interface ModalProps {
classNameContent?: string;
classNameBackdrop?: string;
closeOnOutsideClick?: boolean;
closeOnEscape?: boolean;
children: React.ReactNode;
}
export const Modal = ({
children,
classNameContent = "",
classNameBackdrop = "",
closeOnEscape = true,
closeOnOutsideClick = true,
}: Readonly<ModalProps>) => {
const [isOpenModal, setIsOpenModal] = useState<boolean>(false);
// Función para abrir el modal
const openModal = useCallback(() => setIsOpenModal(true), []);
// Función para cerrar el modal
const closeModal = useCallback(() => setIsOpenModal(false), []);
// Provee el contexto a los hijos
return (
<ModalContext.Provider
value={{
closeModal,
openModal,
isOpenModal,
classNameContent,
classNameBackdrop,
closeOnEscape,
closeOnOutsideClick,
}}
>
{children}
</ModalContext.Provider>
);
};
/*
╔══════════════════════════════════════════════════════════════════════════╗
║ Componente que activa la apertura del modal al hacer click ║
╚══════════════════════════════════════════════════════════════════════════╝
*/
interface ModalTriggerProps {
children: React.ReactElement<{ onClick: () => void }>;
}
export const ModalTrigger = ({ children }: Readonly<ModalTriggerProps>) => {
const { openModal } = useModal();
// Clona el hijo y le agrega el onClick para abrir el modal
return React.cloneElement(children, {
onClick: openModal,
});
};
/*
╔══════════════════════════════════════════════════════════════════════════╗
║ Componente que representa el contenido del modal ║
╚══════════════════════════════════════════════════════════════════════════╝
*/
export const ModalContent = ({ children }: Readonly<PropsWithChildren>) => {
const { isOpenModal, closeModal, closeOnOutsideClick, closeOnEscape, classNameContent, classNameBackdrop } =
useModal();
const modalRef = useRef<HTMLDivElement | null>(null);
// Maneja el cierre al hacer click fuera del modal
const handleClickOutside = useCallback(
(event: MouseEvent) => {
if (closeOnOutsideClick && modalRef.current && modalRef.current === event.target) {
closeModal();
}
},
[closeModal, closeOnOutsideClick]
);
// Maneja el cierre al presionar Escape
const handleEscapeKey = useCallback(
(event: KeyboardEvent) => {
if (closeOnEscape && event.key === "Escape") {
closeModal();
}
},
[closeModal, closeOnEscape]
);
// Efecto para listeners y bloqueo de scroll cuando el modal está abierto
useEffect(() => {
if (isOpenModal) {
// Listeners para cerrar el modal
closeOnOutsideClick && document.addEventListener("mousedown", handleClickOutside);
closeOnEscape && document.addEventListener("keydown", handleEscapeKey);
// Bloquea el scroll del body
const originalOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
return () => {
// Limpieza de listeners y restaurar scroll
closeOnOutsideClick && document.removeEventListener("mousedown", handleClickOutside);
closeOnEscape && document.removeEventListener("keydown", handleEscapeKey);
document.body.style.overflow = originalOverflow;
};
}
}, [isOpenModal, handleClickOutside, handleEscapeKey, closeOnOutsideClick, closeOnEscape]);
// Si el modal no está abierto, no renderiza nada
if (!isOpenModal) return null;
return (
<div
ref={modalRef}
className={twMerge(
clsx("fixed bg-black/50 inset-0 flex items-center justify-center z-50", classNameBackdrop)
)}
>
<div
className={twMerge(
clsx("bg-white overflow-hidden shadow-xl max-h-[90vh] max-w-[90vw]", classNameContent)
)}
>
{children}
</div>
</div>
);
};
+1
-0
export const dependenciesMap = {
button: ["clsx", "tailwind-merge", "tailwind-variants", "lucide-react"],
imagecropper: ["clsx", "lucide-react"],
modal: ["clsx", "tailwind-merge"],
};
+1
-1
{
"name": "daemonui",
"version": "1.0.39",
"version": "1.0.40",
"main": "index.js",

@@ -5,0 +5,0 @@ "type": "module",

@@ -60,2 +60,5 @@ <div align="center">

npx daemonui add imagecropper
# Agregar modal
npx daemonui add modal
```

@@ -67,6 +70,7 @@

| Componente | Descripción | Casos de uso |
| -------------- | --------------------------------------- | ----------------------------------------------- |
| `button` | Botón versátil con múltiples variantes | Acciones primarias, secundarias, enlaces |
| `imagecropper` | Editor avanzado de imágenes con recorte | Avatares, thumbnails, procesamiento de imágenes |
| Componente | Descripción | Casos de uso |
| -------------- | ------------------------------------------- | ----------------------------------------------- |
| `button` | Botón versátil con múltiples variantes | Acciones primarias, secundarias, enlaces |
| `imagecropper` | Editor avanzado de imágenes con recorte | Avatares, thumbnails, procesamiento de imágenes |
| `modal` | Modal accesible con backdrop personalizable | Confirmaciones, formularios, contenido overlay |

@@ -83,3 +87,5 @@ ---

│ └── component.tsx
└── imagecropper/
├── imagecropper/
│ └── component.tsx
└── modal/
└── component.tsx

@@ -180,2 +186,40 @@ ```

### Modal Component
```tsx
import { Modal, ModalContent, ModalTrigger, useModal } from "./components/ui/modal/component";
export default function ModalDemo() {
return (
<Modal
classNameContent="p-5 rounded-xl max-w-md"
classNameBackdrop="backdrop-blur-xs bg-black/25"
closeOnOutsideClick={true}
closeOnEscape={false}
>
<ModalTrigger>
<button className="bg-black text-white px-4 py-2 rounded-md">Abrir modal</button>
</ModalTrigger>
<ModalContent>
<Component />
</ModalContent>
</Modal>
);
}
// Componente de contenido personalizado
const Component = () => {
const { closeModal } = useModal();
return (
<div>
<h2 className="text-xl font-bold mb-4">¡Hola! Este es el contenido de tu modal</h2>
<p className="mb-4">Puedes colocar aquí cualquier contenido que desees.</p>
<button className="bg-black text-white px-4 py-2 rounded-md" onClick={closeModal}>
Cerrar Modal
</button>
</div>
);
};
```
---

@@ -227,3 +271,2 @@

- [ ] `input` - Campos de entrada con validación
- [ ] `modal` - Modales accesibles y responsivos
- [ ] `table` - Tablas con sorting y paginación

@@ -233,2 +276,4 @@ - [ ] `form` - Formularios con validación integrada

- [ ] `dropdown` - Menús desplegables
- [ ] `tooltip` - Tooltips accesibles
- [ ] `tabs` - Sistema de pestañas

@@ -235,0 +280,0 @@ ### Mejoras planeadas