recursive-dropdown-mui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # Recursive Dropdown MUI
2
+
3
+ Menú desplegable recursivo con soporte para múltiples niveles,
4
+ navegación, scroll suave y total personalización. Construido sobre
5
+ **Material UI** y **React Router**.
6
+
7
+ ---
8
+
9
+ ## 📦 Instalación
10
+
11
+ ```bash
12
+ npm install recursive-dropdown-mui
13
+ # o
14
+ yarn add recursive-dropdown-mui
15
+ # o
16
+ pnpm add recursive-dropdown-mui
17
+ ```
18
+
19
+ ### Dependencias requeridas
20
+
21
+ Este paquete espera que tu proyecto ya tenga instalados:
22
+
23
+ - @mui/material
24
+ - @emotion/react
25
+ - @emotion/styled
26
+ - react-router-dom
27
+
28
+ ---
29
+
30
+ ## 🚀 Uso básico
31
+
32
+ ```tsx
33
+ import { DropdownWithSubmenu } from "recursive-dropdown-mui";
34
+ import { menuItems } from "./menuData"; // tu array de MenuItem
35
+
36
+ function App() {
37
+ return <DropdownWithSubmenu menuItems={menuItems} triggerText="Explorar" />;
38
+ }
39
+ ```
40
+
41
+ ---
42
+
43
+ ## 📘 Estructura de datos (MenuItem)
44
+
45
+ Cada ítem del menú sigue la interfaz:
46
+
47
+ ```ts
48
+ interface MenuItem {
49
+ label: string; // Texto visible
50
+ href?: string; // Ruta de navegación (React Router)
51
+ hash?: string; // Ancla para scroll interno (sin #)
52
+ icon: React.ReactNode; // Icono (elemento JSX)
53
+ children?: MenuItem[]; // Subítems anidados
54
+ }
55
+ ```
56
+
57
+ - ✅ Puedes combinar `href` y `hash`.
58
+ - ✅ Si solo usas `hash`, se tomará el `href` del ancestro más cercano
59
+ como base.
60
+ - ✅ Ítems sin `href/hash` y sin hijos → no hacen nada al hacer clic.
61
+ - ✅ Ítems sin `href/hash` pero con hijos → expanden/colapsan el
62
+ submenú.
63
+
64
+ ---
65
+
66
+ ## 🧩 Props principales
67
+
68
+ ### 1. Datos y contenido
69
+
70
+ | Prop | Tipo | Default | Descripción |
71
+ | ----------- | ------------------------- | ---------------- | ------------------------------------- |
72
+ | menuItems | MenuItem[] | defaultMenuItems | Array de ítems del menú |
73
+ | loading | boolean | false | Muestra estado de carga |
74
+ | loadingText | string | "Cargando..." | Texto del spinner |
75
+ | emptyState | React.ReactNode | undefined | Componente cuando no hay ítems |
76
+ | triggerText | string \| React.ReactNode | "EXPLORAR" | Texto o elemento del botón disparador |
77
+ | triggerIcon | React.ReactNode | undefined | Icono que acompaña al texto del botón |
78
+
79
+ ### 2. Comportamiento
80
+
81
+ | Prop | Tipo | Default | Descripción |
82
+ | ------------------- | -------------------- | ------- | --------------------------------- |
83
+ | onItemClick | (item, path) => void | - | Callback al hacer clic en un ítem |
84
+ | onHoverItem | (item, path) => void | - | Callback al pasar el mouse |
85
+ | onOpen | () => void | - | Al abrir el menú |
86
+ | onClose | () => void | - | Al cerrar el menú |
87
+ | maxDepth | number | 5 | Profundidad máxima |
88
+ | openOnHover | boolean | true | Abrir con hover |
89
+ | closeOnClickOutside | boolean | true | Cerrar al hacer clic fuera |
90
+ | closeDelay | number (ms) | 300 | Retraso para cerrar |
91
+
92
+ ### 3. Estilos y diseño
93
+
94
+ | Prop | Tipo | Default | Descripción |
95
+ | ------------ | ---------------------------------- | -------- | ---------------------- |
96
+ | sx | SxProps<Theme> | - | Estilos del contenedor |
97
+ | paperSx | SxProps<Theme> | - | Estilos del Paper |
98
+ | itemSx | SxProps<Theme> | - | Estilos del ítem |
99
+ | submenuSx | SxProps<Theme> | - | Estilos del submenú |
100
+ | density | compact \| standard \| comfortable | standard | Densidad vertical |
101
+ | showDividers | boolean | false | Mostrar separadores |
102
+ | dividerColor | string | divider | Color del divisor |
103
+
104
+ ### 4. Iconos
105
+
106
+ | Prop | Tipo | Default | Descripción |
107
+ | ------------ | -------------------- | --------------- | ------------------ |
108
+ | expandIcon | React.ReactNode | ChevronRight | Submenú cerrado |
109
+ | collapseIcon | React.ReactNode | ArrowDropUpIcon | Submenú abierto |
110
+ | submenuIcon | React.ReactNode | expandIcon | Icono del submenú |
111
+ | iconPosition | start \| end \| none | end | Posición del icono |
112
+
113
+ ### 5. Comportamiento avanzado
114
+
115
+ | Prop | Tipo | Default | Descripción |
116
+ | --------------- | -------------- | ------- | ------------------- |
117
+ | open | boolean | - | Control externo |
118
+ | defaultOpen | boolean | false | Estado inicial |
119
+ | initialDepth | number | 0 | Profundidad inicial |
120
+ | autoExpandDepth | number | 0 | Auto expansión |
121
+ | scrollIntoView | boolean | true | Scroll por hash |
122
+ | scrollOffset | number | 80 | Offset |
123
+ | scrollBehavior | auto \| smooth | smooth | Tipo de scroll |
124
+ | disabled | boolean | false | Deshabilitado |
125
+ | readOnly | boolean | false | Solo lectura |
126
+
127
+ ### 6. Accesibilidad y SEO
128
+
129
+ | Prop | Tipo | Default | Descripción |
130
+ | ------------------ | ------- | ---------------- | ------------------ |
131
+ | ariaLabel | string | Menú desplegable | aria-label |
132
+ | ariaLabelledBy | string | - | Etiqueta |
133
+ | ariaDescribedBy | string | - | Descripción |
134
+ | role | string | menu | Rol ARIA |
135
+ | keyboardNavigation | boolean | true | Navegación teclado |
136
+ | focusOnOpen | boolean | true | Foco inicial |
137
+ | useAnchorTags | boolean | true | Usa `<a>` |
138
+ | rel | string | - | Atributo rel |
139
+
140
+ ### 7. Internacionalización
141
+
142
+ | Prop | Tipo | Default | Descripción |
143
+ | ------------ | -------------------- | ------- | ----------- |
144
+ | translations | DropdownTranslations | - | Textos |
145
+ | direction | ltr \| rtl | ltr | Dirección |
146
+
147
+ ### 8. Renderizado personalizado
148
+
149
+ | Prop | Tipo | Descripción |
150
+ | ------------- | -------------------------- | --------------------- |
151
+ | renderTrigger | (props) => React.ReactNode | Trigger personalizado |
152
+ | renderItem | (props) => React.ReactNode | Ítem personalizado |
153
+ | renderSubmenu | (props) => React.ReactNode | Submenú personalizado |
154
+
155
+ ### 9. Temas y variantes
156
+
157
+ | Prop | Tipo | Default | Descripción |
158
+ | ----------- | ---------------------------------------------------------------- | ------- | ------------------ |
159
+ | variant | default \| minimal \| elevated \| borderless \| dark \| gradient | default | Variante visual |
160
+ | customTheme | CustomTheme | - | Tema personalizado |
161
+
162
+ ---
163
+
164
+ ---
165
+
166
+ ## 🎨 Ejemplos avanzados
167
+
168
+ ### Menú con apertura por click
169
+
170
+ ```tsx
171
+ <DropdownWithSubmenu
172
+ menuItems={menuItems}
173
+ openOnHover={false}
174
+ closeOnClickOutside={true}
175
+ />
176
+ ```
177
+
178
+ ### Densidad compacta
179
+
180
+ ```tsx
181
+ <DropdownWithSubmenu
182
+ menuItems={menuItems}
183
+ density="compact"
184
+ iconPosition="none"
185
+ />
186
+ ```
187
+
188
+ ### Tema oscuro
189
+
190
+ ```tsx
191
+ <DropdownWithSubmenu
192
+ menuItems={menuItems}
193
+ variant="dark"
194
+ customTheme={{
195
+ colors: { background: "#1e1e2f", text: "#ffffff" },
196
+ borderRadius: 8,
197
+ spacing: 1,
198
+ }}
199
+ />
200
+ ```
201
+
202
+ ### Trigger personalizado
203
+
204
+ ```tsx
205
+ <DropdownWithSubmenu
206
+ menuItems={menuItems}
207
+ renderTrigger={({ isOpen, toggle, ref }) => (
208
+ <button ref={ref} onClick={toggle} className="mi-boton">
209
+ {isOpen ? "Cerrar" : "Abrir"} menú
210
+ </button>
211
+ )}
212
+ />
213
+ ```
214
+
215
+ ### Enlaces reales para SEO
216
+
217
+ ```tsx
218
+ <DropdownWithSubmenu
219
+ menuItems={menuItems}
220
+ useAnchorTags={true}
221
+ rel="noopener noreferrer"
222
+ />
223
+ ```
224
+
225
+ ---
226
+
227
+ ## ♿ Accesibilidad
228
+
229
+ - Rol `menu` / `menuitem`
230
+ - Navegación por teclado
231
+ - Atributos ARIA
232
+ - Lectores de pantalla
233
+
234
+ ---
235
+
236
+ ## 📐 TypeScript
237
+
238
+ ```ts
239
+ import type {
240
+ MenuItem,
241
+ DropdownVariant,
242
+ DropdownDensity,
243
+ IconPosition,
244
+ ScrollBehavior,
245
+ CustomTheme,
246
+ DropdownTranslations,
247
+ DropdownWithSubmenuProps,
248
+ } from "recursive-dropdown-mui";
249
+ ```
250
+
251
+ ---
252
+
253
+ ## 🛠️ Desarrollo local
254
+
255
+ 1. Clona el repositorio\
256
+ 2. Instala dependencias: `pnpm install`\
257
+ 3. Construye: `pnpm build`\
258
+ 4. Dev: `pnpm dev`
259
+
260
+ ---
261
+
262
+ ## 📄 Licencia
263
+
264
+ MIT © Blackysensei
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import type { DropdownWithSubmenuProps } from "./core/types";
3
+ /**
4
+ * Componente de alto nivel que integra DropdownMenu, DropdownTrigger y DropdownContent.
5
+ * Expone una API simplificada para el usuario final.
6
+ */
7
+ declare const DropdownWithSubmenu: React.FC<DropdownWithSubmenuProps>;
8
+ export default DropdownWithSubmenu;
@@ -0,0 +1,71 @@
1
+ import React, { type ReactNode } from "react";
2
+ import { type SxProps, type Theme } from "@mui/material";
3
+ import type { MenuItem, DropdownContextType, DropdownVariant, DropdownDensity, IconPosition, ScrollBehavior, CustomTheme, DropdownTranslations } from "../types";
4
+ export declare const useDropdownContext: () => DropdownContextType;
5
+ interface DropdownMenuProps {
6
+ children: ReactNode;
7
+ menuItems: MenuItem[];
8
+ loading?: boolean;
9
+ loadingText?: string;
10
+ emptyState?: React.ReactNode;
11
+ onItemClick?: (item: MenuItem, path: number[]) => void;
12
+ onHoverItem?: (item: MenuItem, path: number[]) => void;
13
+ onOpen?: () => void;
14
+ onClose?: () => void;
15
+ maxDepth?: number;
16
+ openOnHover?: boolean;
17
+ closeOnClickOutside?: boolean;
18
+ closeDelay?: number;
19
+ sx?: SxProps<Theme>;
20
+ paperSx?: SxProps<Theme>;
21
+ itemSx?: SxProps<Theme>;
22
+ submenuSx?: SxProps<Theme>;
23
+ density?: DropdownDensity;
24
+ showDividers?: boolean;
25
+ dividerColor?: string;
26
+ expandIcon?: React.ReactNode;
27
+ collapseIcon?: React.ReactNode;
28
+ submenuIcon?: React.ReactNode;
29
+ iconPosition?: IconPosition;
30
+ open?: boolean;
31
+ defaultOpen?: boolean;
32
+ initialDepth?: number;
33
+ autoExpandDepth?: number;
34
+ scrollIntoView?: boolean;
35
+ scrollOffset?: number;
36
+ scrollBehavior?: ScrollBehavior;
37
+ disabled?: boolean;
38
+ readOnly?: boolean;
39
+ ariaLabel?: string;
40
+ ariaLabelledBy?: string;
41
+ ariaDescribedBy?: string;
42
+ role?: string;
43
+ keyboardNavigation?: boolean;
44
+ focusOnOpen?: boolean;
45
+ useAnchorTags?: boolean;
46
+ rel?: string;
47
+ translations?: DropdownTranslations;
48
+ direction?: "ltr" | "rtl";
49
+ renderItem?: (props: {
50
+ item: MenuItem;
51
+ path: number[];
52
+ depth: number;
53
+ isActive: boolean;
54
+ hasChildren: boolean;
55
+ onClick: () => void;
56
+ }) => React.ReactNode;
57
+ renderSubmenu?: (props: {
58
+ items: MenuItem[];
59
+ depth: number;
60
+ parentPath: number[];
61
+ }) => React.ReactNode;
62
+ variant?: DropdownVariant;
63
+ customTheme?: CustomTheme;
64
+ }
65
+ /**
66
+ * Proveedor del contexto de dropdown.
67
+ * Utiliza el hook `useDropdown` para obtener toda la lógica de estado e interacción.
68
+ * Las props se pasan directamente a `useDropdown` y también se usan para valores estáticos.
69
+ */
70
+ export declare const DropdownMenu: React.FC<DropdownMenuProps>;
71
+ export {};
@@ -0,0 +1,7 @@
1
+ export { useDropdownState } from "./useDropdownState";
2
+ export { useHover } from "./useHover";
3
+ export { useClickOutside } from "./useClickOutside";
4
+ export { useScroll } from "./useScroll";
5
+ export { useKeyboardNavigation } from "./useKeyboardNavigation";
6
+ export { useItemNavigation } from "./useItemNavigation";
7
+ export { useDropdown } from "./useDropdown";
@@ -0,0 +1,13 @@
1
+ import { RefObject } from "react";
2
+ interface UseClickOutsideProps {
3
+ isOpen: boolean;
4
+ closeOnClickOutside?: boolean;
5
+ setIsOpen: (open: boolean) => void;
6
+ rootRef: RefObject<HTMLElement | null>;
7
+ }
8
+ /**
9
+ * Hook que escucha clics fuera del componente raíz y cierra el menú.
10
+ * Respetar la prop `closeOnClickOutside` (true por defecto).
11
+ */
12
+ export declare const useClickOutside: ({ isOpen, closeOnClickOutside, setIsOpen, rootRef, }: UseClickOutsideProps) => void;
13
+ export {};
@@ -0,0 +1,37 @@
1
+ import type { MenuItem } from "../types";
2
+ interface UseDropdownProps {
3
+ defaultOpen?: boolean;
4
+ closeDelay?: number;
5
+ openOnHover?: boolean;
6
+ closeOnClickOutside?: boolean;
7
+ onOpen?: () => void;
8
+ onClose?: () => void;
9
+ menuItems: MenuItem[];
10
+ onItemClick?: (item: MenuItem, path: number[]) => void;
11
+ onHoverItem?: (item: MenuItem, path: number[]) => void;
12
+ scrollOffset?: number;
13
+ disabled?: boolean;
14
+ readOnly?: boolean;
15
+ }
16
+ /**
17
+ * Hook principal que orquesta todos los submódulos de comportamiento del dropdown.
18
+ * Expone el estado y los manejadores necesarios para el contexto.
19
+ */
20
+ export declare const useDropdown: (props: UseDropdownProps) => {
21
+ isOpen: boolean;
22
+ activePath: number[] | null;
23
+ setIsOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
24
+ setActivePath: import("react").Dispatch<import("react").SetStateAction<number[] | null>>;
25
+ handleMouseEnter: () => void;
26
+ handleMouseLeave: () => void;
27
+ handleItemMouseEnter: (path: number[]) => void;
28
+ handleItemMouseLeave: () => void;
29
+ handleItemClick: (item: MenuItem, itemPath: number[]) => void;
30
+ getItemByPath: (path: number[]) => MenuItem | null;
31
+ getBaseHrefForPath: (path: number[]) => string;
32
+ buildItemUrl: (item: MenuItem, baseHref?: string) => string;
33
+ getItemDepth: (path: number[]) => number;
34
+ itemHasChildren: (item: MenuItem) => boolean;
35
+ timeoutRef: import("react").RefObject<number | null>;
36
+ };
37
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Hook base para gestionar el estado local del dropdown.
3
+ *
4
+ * - `isOpen`: indica si el menú principal está visible.
5
+ * - `setIsOpen`: función para cambiar el estado de apertura.
6
+ * - `activePath`: array de índices que representa la ruta del submenú actualmente activo (hover o click).
7
+ * - `setActivePath`: función para actualizar la ruta activa.
8
+ */
9
+ export declare const useDropdownState: (defaultOpen?: boolean) => {
10
+ isOpen: boolean;
11
+ setIsOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
12
+ activePath: number[] | null;
13
+ setActivePath: import("react").Dispatch<import("react").SetStateAction<number[] | null>>;
14
+ };
@@ -0,0 +1,23 @@
1
+ interface UseHoverProps {
2
+ openOnHover?: boolean;
3
+ closeDelay?: number;
4
+ onOpen?: () => void;
5
+ onClose?: () => void;
6
+ setIsOpen: (open: boolean) => void;
7
+ setActivePath: (path: number[] | null) => void;
8
+ }
9
+ /**
10
+ * Hook que maneja toda la interacción por hover:
11
+ * - Apertura/cierre del menú principal con delay configurable.
12
+ * - Activación de submenús al pasar el ratón sobre items.
13
+ * - Limpieza de timeouts para evitar cierres abruptos.
14
+ */
15
+ export declare const useHover: ({ openOnHover, closeDelay, onOpen, onClose, setIsOpen, setActivePath, }: UseHoverProps) => {
16
+ handleRootMouseEnter: () => void;
17
+ handleRootMouseLeave: () => void;
18
+ handleItemMouseEnter: (path: number[]) => void;
19
+ handleItemMouseLeave: () => void;
20
+ timeoutRef: import("react").RefObject<number | null>;
21
+ intervalRef: import("react").RefObject<number | null>;
22
+ };
23
+ export {};
@@ -0,0 +1,27 @@
1
+ import { MenuItem } from "../types";
2
+ interface UseItemNavigationProps {
3
+ menuItems: MenuItem[];
4
+ onItemClick?: (item: MenuItem, path: number[]) => void;
5
+ onHoverItem?: (item: MenuItem, path: number[]) => void;
6
+ setIsOpen: (open: boolean) => void;
7
+ setActivePath: (path: number[] | null) => void;
8
+ activePath: number[] | null;
9
+ navigate: (url: string) => void;
10
+ locationPathname: string;
11
+ scrollToElement: (id: string, offset: number) => void;
12
+ scrollOffset: number;
13
+ disabled: boolean;
14
+ readOnly: boolean;
15
+ }
16
+ /**
17
+ * Hook que centraliza la lógica de navegación y expansión al hacer clic en un item.
18
+ * También construye URLs, obtiene items por path y maneja el hover.
19
+ */
20
+ export declare const useItemNavigation: ({ menuItems, onItemClick, onHoverItem, setIsOpen, setActivePath, activePath, navigate, locationPathname, scrollToElement, scrollOffset, disabled, readOnly, }: UseItemNavigationProps) => {
21
+ getItemByPath: (path: number[]) => MenuItem | null;
22
+ getBaseHrefForPath: (path: number[]) => string;
23
+ buildItemUrl: (item: MenuItem, baseHref?: string) => string;
24
+ handleItemClick: (item: MenuItem, itemPath: number[]) => void;
25
+ handleHoverItem: (item: MenuItem, path: number[]) => void;
26
+ };
27
+ export {};
@@ -0,0 +1,21 @@
1
+ import { RefObject } from "react";
2
+ import { MenuItem } from "../types";
3
+ interface UseKeyboardNavigationProps {
4
+ isOpen: boolean;
5
+ activePath: number[] | null;
6
+ menuItems: MenuItem[];
7
+ onItemSelect: (item: MenuItem, path: number[]) => void;
8
+ onClose: () => void;
9
+ rootRef: RefObject<HTMLElement | null>;
10
+ enabled?: boolean;
11
+ }
12
+ /**
13
+ * Hook que implementa la navegación por teclado:
14
+ * - Flechas arriba/abajo: movimiento vertical entre items del mismo nivel.
15
+ * - Flecha derecha: abre submenú del item activo.
16
+ * - Flecha izquierda: cierra submenú actual.
17
+ * - Enter: selecciona el item activo.
18
+ * - Escape: cierra todo el menú.
19
+ */
20
+ export declare const useKeyboardNavigation: ({ isOpen, activePath, menuItems, onItemSelect, onClose, rootRef, enabled, }: UseKeyboardNavigationProps) => void;
21
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Hook que proporciona funciones para realizar scroll suave:
3
+ * - `scrollToElement`: desplaza la ventana hasta un elemento con ID específico.
4
+ * - `scrollToTop`: vuelve al inicio de la página con un offset opcional.
5
+ */
6
+ export declare const useScroll: () => {
7
+ scrollToElement: (elementId: string, offset?: number) => void;
8
+ scrollToTop: (offset?: number) => void;
9
+ };
@@ -0,0 +1,170 @@
1
+ import { ReactNode } from "react";
2
+ import type { SxProps, Theme } from "@mui/material";
3
+ export interface MenuItem {
4
+ label: string;
5
+ href?: string;
6
+ hash?: string;
7
+ icon: ReactNode;
8
+ children?: MenuItem[];
9
+ }
10
+ export interface DropdownContextType {
11
+ isOpen: boolean;
12
+ activePath: number[] | null;
13
+ setIsOpen: (open: boolean) => void;
14
+ setActivePath: (path: number[] | null) => void;
15
+ handleMouseEnter: () => void;
16
+ handleMouseLeave: () => void;
17
+ handleItemMouseEnter: (path: number[]) => void;
18
+ handleItemMouseLeave: () => void;
19
+ handleItemClick: (item: MenuItem, itemPath: number[]) => void;
20
+ getItemDepth: (path: number[]) => number;
21
+ buildItemUrl: (item: MenuItem, baseHref?: string) => string;
22
+ itemHasChildren: (item: MenuItem) => boolean;
23
+ menuItems: MenuItem[];
24
+ loading?: boolean;
25
+ loadingText?: string;
26
+ emptyState?: React.ReactNode;
27
+ onItemClick?: (item: MenuItem, path: number[]) => void;
28
+ onHoverItem?: (item: MenuItem, path: number[]) => void;
29
+ maxDepth: number;
30
+ getItemByPath: (path: number[]) => MenuItem | null;
31
+ getBaseHrefForPath: (path: number[]) => string;
32
+ paperSx?: any;
33
+ itemSx?: any;
34
+ submenuSx?: any;
35
+ density: DropdownDensity;
36
+ showDividers: boolean;
37
+ dividerColor: string;
38
+ getDensityStyles: () => any;
39
+ expandIcon: React.ReactNode;
40
+ collapseIcon: React.ReactNode;
41
+ submenuIcon: React.ReactNode;
42
+ iconPosition: IconPosition;
43
+ openOnHover: boolean;
44
+ closeDelay: number;
45
+ scrollIntoView: boolean;
46
+ scrollOffset: number;
47
+ scrollBehavior: ScrollBehavior;
48
+ disabled: boolean;
49
+ readOnly: boolean;
50
+ initialDepth: number;
51
+ autoExpandDepth: number;
52
+ ariaLabel: string;
53
+ ariaLabelledBy?: string;
54
+ ariaDescribedBy?: string;
55
+ role: string;
56
+ keyboardNavigation: boolean;
57
+ focusOnOpen: boolean;
58
+ useAnchorTags: boolean;
59
+ rel?: string;
60
+ translations?: DropdownTranslations;
61
+ direction: "ltr" | "rtl";
62
+ renderItem?: (props: {
63
+ item: MenuItem;
64
+ path: number[];
65
+ depth: number;
66
+ isActive: boolean;
67
+ hasChildren: boolean;
68
+ onClick: () => void;
69
+ }) => React.ReactNode;
70
+ renderSubmenu?: (props: {
71
+ items: MenuItem[];
72
+ depth: number;
73
+ parentPath: number[];
74
+ }) => React.ReactNode;
75
+ variant: DropdownVariant;
76
+ customTheme?: CustomTheme;
77
+ LoadingState: React.FC;
78
+ EmptyState: React.FC;
79
+ }
80
+ export type DropdownVariant = "default" | "minimal" | "elevated" | "borderless" | "dark" | "gradient";
81
+ export type DropdownDensity = "compact" | "standard" | "comfortable";
82
+ export type IconPosition = "start" | "end" | "none";
83
+ export type ScrollBehavior = "auto" | "smooth";
84
+ export interface CustomTheme {
85
+ text?: string;
86
+ colors?: {
87
+ primary?: string;
88
+ secondary?: string;
89
+ background?: string;
90
+ text?: string;
91
+ };
92
+ spacing?: number;
93
+ borderRadius?: number;
94
+ }
95
+ export interface DropdownTranslations {
96
+ expand?: string;
97
+ collapse?: string;
98
+ loading?: string;
99
+ empty?: string;
100
+ }
101
+ export interface DropdownWithSubmenuProps {
102
+ menuItems?: MenuItem[];
103
+ triggerText?: string | React.ReactNode;
104
+ triggerIcon?: React.ReactNode;
105
+ emptyState?: React.ReactNode;
106
+ loading?: boolean;
107
+ loadingText?: string;
108
+ onItemClick?: (item: MenuItem, path: number[]) => void;
109
+ maxDepth?: number;
110
+ openOnHover?: boolean;
111
+ closeOnClickOutside?: boolean;
112
+ closeDelay?: number;
113
+ onOpen?: () => void;
114
+ onClose?: () => void;
115
+ onHoverItem?: (item: MenuItem, path: number[]) => void;
116
+ sx?: SxProps<Theme>;
117
+ triggerSx?: SxProps<Theme>;
118
+ paperSx?: SxProps<Theme>;
119
+ itemSx?: SxProps<Theme>;
120
+ submenuSx?: SxProps<Theme>;
121
+ buttonVariant?: "text" | "outlined" | "contained";
122
+ buttonColor?: "primary" | "secondary" | "inherit" | "success" | "error" | "info" | "warning";
123
+ buttonSize?: "small" | "medium" | "large";
124
+ density?: DropdownDensity;
125
+ expandIcon?: React.ReactNode;
126
+ collapseIcon?: React.ReactNode;
127
+ submenuIcon?: React.ReactNode;
128
+ iconPosition?: IconPosition;
129
+ showDividers?: boolean;
130
+ dividerColor?: string;
131
+ open?: boolean;
132
+ defaultOpen?: boolean;
133
+ initialDepth?: number;
134
+ autoExpandDepth?: number;
135
+ scrollIntoView?: boolean;
136
+ scrollOffset?: number;
137
+ scrollBehavior?: ScrollBehavior;
138
+ disabled?: boolean;
139
+ readOnly?: boolean;
140
+ ariaLabel?: string;
141
+ ariaLabelledBy?: string;
142
+ ariaDescribedBy?: string;
143
+ role?: string;
144
+ keyboardNavigation?: boolean;
145
+ focusOnOpen?: boolean;
146
+ useAnchorTags?: boolean;
147
+ rel?: string;
148
+ translations?: DropdownTranslations;
149
+ direction?: "ltr" | "rtl";
150
+ renderTrigger?: (props: {
151
+ isOpen: boolean;
152
+ toggle: () => void;
153
+ ref: React.Ref<HTMLElement>;
154
+ }) => React.ReactNode;
155
+ renderItem?: (props: {
156
+ item: MenuItem;
157
+ path: number[];
158
+ depth: number;
159
+ isActive: boolean;
160
+ hasChildren: boolean;
161
+ onClick: () => void;
162
+ }) => React.ReactNode;
163
+ renderSubmenu?: (props: {
164
+ items: MenuItem[];
165
+ depth: number;
166
+ parentPath: number[];
167
+ }) => React.ReactNode;
168
+ variant?: DropdownVariant;
169
+ customTheme?: CustomTheme;
170
+ }
@@ -0,0 +1,2 @@
1
+ import type { MenuItem } from "../core/types";
2
+ export declare const menuItems: MenuItem[];
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ /**
3
+ * Componente que renderiza el contenido del menú desplegable.
4
+ * Solo se muestra cuando `isOpen` es `true`.
5
+ */
6
+ export declare const DropdownContent: React.FC;