anima-ds-nucleus 1.0.8 → 1.0.10
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/dist/anima-ds-nucleus.css +1 -1
- package/dist/anima-ds.cjs.js +122 -94
- package/dist/anima-ds.esm.js +6319 -6211
- package/package.json +1 -1
- package/src/components/DataDisplay/Card/CardError.jsx +1 -2
- package/src/components/DataDisplay/Card/CardSkeleton.jsx +1 -2
- package/src/components/DataDisplay/Card/CardTituloCorto.jsx +1 -2
- package/src/components/DataDisplay/Card/CardTituloCortoMasEstado.jsx +1 -2
- package/src/components/DataDisplay/Card/CardTituloLargo.jsx +1 -2
- package/src/components/DataDisplay/Card/CardTituloLargoMasEstado.jsx +1 -2
- package/src/components/DataDisplay/Card/CardVacia.jsx +1 -2
- package/src/components/Layout/Header/HeaderCore.jsx +38 -0
- package/src/components/Layout/Header/HeaderPoint.jsx +51 -2
- package/src/components/Layout/Sidebar/SidebarCore.jsx +52 -16
- package/src/components/Layout/Sidebar/SidebarPoint.jsx +67 -16
package/package.json
CHANGED
|
@@ -14,8 +14,7 @@ export const CardError = ({
|
|
|
14
14
|
width: '379.5px',
|
|
15
15
|
height: '476px',
|
|
16
16
|
borderRadius: '14px',
|
|
17
|
-
border: '1px solid #
|
|
18
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
17
|
+
border: '1px solid #C4C4C4',
|
|
19
18
|
opacity: 1
|
|
20
19
|
}}
|
|
21
20
|
{...props}
|
|
@@ -9,8 +9,7 @@ export const CardSkeleton = ({
|
|
|
9
9
|
width: '379.5px',
|
|
10
10
|
height: '476px',
|
|
11
11
|
borderRadius: '14px',
|
|
12
|
-
border: '1px solid #
|
|
13
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
12
|
+
border: '1px solid #C4C4C4',
|
|
14
13
|
opacity: 1
|
|
15
14
|
}}
|
|
16
15
|
{...props}
|
|
@@ -13,8 +13,7 @@ export const CardTituloCorto = ({
|
|
|
13
13
|
width: '379.5px',
|
|
14
14
|
height: '476px',
|
|
15
15
|
borderRadius: '14px',
|
|
16
|
-
border: '1px solid #
|
|
17
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
16
|
+
border: '1px solid #C4C4C4',
|
|
18
17
|
opacity: 1
|
|
19
18
|
}}
|
|
20
19
|
{...props}
|
|
@@ -14,8 +14,7 @@ export const CardTituloCortoMasEstado = ({
|
|
|
14
14
|
width: '379.5px',
|
|
15
15
|
height: '476px',
|
|
16
16
|
borderRadius: '14px',
|
|
17
|
-
border: '1px solid #
|
|
18
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
17
|
+
border: '1px solid #C4C4C4',
|
|
19
18
|
opacity: 1
|
|
20
19
|
}}
|
|
21
20
|
{...props}
|
|
@@ -13,8 +13,7 @@ export const CardTituloLargo = ({
|
|
|
13
13
|
width: '379.5px',
|
|
14
14
|
height: '476px',
|
|
15
15
|
borderRadius: '14px',
|
|
16
|
-
border: '1px solid #
|
|
17
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
16
|
+
border: '1px solid #C4C4C4',
|
|
18
17
|
opacity: 1
|
|
19
18
|
}}
|
|
20
19
|
{...props}
|
|
@@ -14,8 +14,7 @@ export const CardTituloLargoMasEstado = ({
|
|
|
14
14
|
width: '379.5px',
|
|
15
15
|
height: '476px',
|
|
16
16
|
borderRadius: '14px',
|
|
17
|
-
border: '1px solid #
|
|
18
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
17
|
+
border: '1px solid #C4C4C4',
|
|
19
18
|
opacity: 1
|
|
20
19
|
}}
|
|
21
20
|
{...props}
|
|
@@ -13,8 +13,7 @@ export const CardVacia = ({
|
|
|
13
13
|
width: '379.5px',
|
|
14
14
|
height: '476px',
|
|
15
15
|
borderRadius: '14px',
|
|
16
|
-
border: '1px solid #
|
|
17
|
-
boxShadow: '0px 4px 6px -2px #0000001A, 0px 10px 15px -3px #0000001A',
|
|
16
|
+
border: '1px solid #C4C4C4',
|
|
18
17
|
opacity: 1
|
|
19
18
|
}}
|
|
20
19
|
{...props}
|
|
@@ -2,6 +2,7 @@ import { useState } from 'react';
|
|
|
2
2
|
import { Icon } from '../../Atoms/Icon/Icon';
|
|
3
3
|
import { Avatar } from '../../Atoms/Avatar/Avatar';
|
|
4
4
|
import { Typography } from '../../Atoms/Typography/Typography';
|
|
5
|
+
import { SidebarCoreMobile } from '../Sidebar/SidebarCore';
|
|
5
6
|
|
|
6
7
|
export const HeaderCore = ({
|
|
7
8
|
searchPlaceholder = 'Buscar empleados, reportes, configuraciones...',
|
|
@@ -11,10 +12,21 @@ export const HeaderCore = ({
|
|
|
11
12
|
onSearch,
|
|
12
13
|
onNotificationClick,
|
|
13
14
|
onUserClick,
|
|
15
|
+
sidebarSections,
|
|
16
|
+
sidebarActiveItem,
|
|
17
|
+
onSidebarItemClick,
|
|
18
|
+
sidebarItemBadges,
|
|
19
|
+
sidebarCompanyName,
|
|
20
|
+
sidebarCompanyLogo,
|
|
21
|
+
sidebarFooterText,
|
|
22
|
+
sidebarFooterCollapsedContent,
|
|
23
|
+
sidebarCoreContainerStyle,
|
|
24
|
+
sidebarCoreTextStyle,
|
|
14
25
|
className = '',
|
|
15
26
|
...props
|
|
16
27
|
}) => {
|
|
17
28
|
const [searchValue, setSearchValue] = useState('');
|
|
29
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
|
18
30
|
|
|
19
31
|
const handleSearchChange = (e) => {
|
|
20
32
|
const value = e.target.value;
|
|
@@ -217,6 +229,7 @@ export const HeaderCore = ({
|
|
|
217
229
|
<div className="flex items-center space-x-2">
|
|
218
230
|
{/* Botón menú hamburguesa */}
|
|
219
231
|
<button
|
|
232
|
+
onClick={() => setIsSidebarOpen(true)}
|
|
220
233
|
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
|
221
234
|
aria-label="Menú"
|
|
222
235
|
>
|
|
@@ -340,6 +353,31 @@ export const HeaderCore = ({
|
|
|
340
353
|
</div>
|
|
341
354
|
</div>
|
|
342
355
|
</div>
|
|
356
|
+
|
|
357
|
+
{/* SidebarCoreMobile - Solo visible en móvil cuando está abierto */}
|
|
358
|
+
{isSidebarOpen && (
|
|
359
|
+
<div className="header-core-mobile-sidebar-wrapper">
|
|
360
|
+
<SidebarCoreMobile
|
|
361
|
+
sections={sidebarSections}
|
|
362
|
+
activeItem={sidebarActiveItem}
|
|
363
|
+
onItemClick={(itemId) => {
|
|
364
|
+
if (onSidebarItemClick) {
|
|
365
|
+
onSidebarItemClick(itemId);
|
|
366
|
+
}
|
|
367
|
+
setIsSidebarOpen(false);
|
|
368
|
+
}}
|
|
369
|
+
itemBadges={sidebarItemBadges}
|
|
370
|
+
companyName={sidebarCompanyName}
|
|
371
|
+
companyLogo={sidebarCompanyLogo}
|
|
372
|
+
footerText={sidebarFooterText}
|
|
373
|
+
footerCollapsedContent={sidebarFooterCollapsedContent}
|
|
374
|
+
coreContainerStyle={sidebarCoreContainerStyle}
|
|
375
|
+
coreTextStyle={sidebarCoreTextStyle}
|
|
376
|
+
isOpen={isSidebarOpen}
|
|
377
|
+
onClose={() => setIsSidebarOpen(false)}
|
|
378
|
+
/>
|
|
379
|
+
</div>
|
|
380
|
+
)}
|
|
343
381
|
</header>
|
|
344
382
|
);
|
|
345
383
|
};
|
|
@@ -2,6 +2,7 @@ import { useState } from 'react';
|
|
|
2
2
|
import { Icon } from '../../Atoms/Icon/Icon';
|
|
3
3
|
import { Avatar } from '../../Atoms/Avatar/Avatar';
|
|
4
4
|
import { Typography } from '../../Atoms/Typography/Typography';
|
|
5
|
+
import { SidebarPointMobile } from '../Sidebar/SidebarPoint';
|
|
5
6
|
|
|
6
7
|
export const HeaderPoint = ({
|
|
7
8
|
searchPlaceholder = 'Buscar empleados, reportes, configuraciones...',
|
|
@@ -11,10 +12,17 @@ export const HeaderPoint = ({
|
|
|
11
12
|
onSearch,
|
|
12
13
|
onNotificationClick,
|
|
13
14
|
onUserClick,
|
|
15
|
+
sidebarSections,
|
|
16
|
+
sidebarActiveItem,
|
|
17
|
+
onSidebarItemClick,
|
|
18
|
+
sidebarItemBadges,
|
|
19
|
+
sidebarCompanyName,
|
|
20
|
+
sidebarCompanyLogo,
|
|
14
21
|
className = '',
|
|
15
22
|
...props
|
|
16
23
|
}) => {
|
|
17
24
|
const [searchValue, setSearchValue] = useState('');
|
|
25
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
|
18
26
|
|
|
19
27
|
const handleSearchChange = (e) => {
|
|
20
28
|
const value = e.target.value;
|
|
@@ -65,6 +73,12 @@ export const HeaderPoint = ({
|
|
|
65
73
|
background-color: transparent !important;
|
|
66
74
|
background: transparent !important;
|
|
67
75
|
border-bottom: none !important;
|
|
76
|
+
width: 100% !important;
|
|
77
|
+
max-width: 100% !important;
|
|
78
|
+
margin: 0 !important;
|
|
79
|
+
padding: 0 !important;
|
|
80
|
+
left: 0 !important;
|
|
81
|
+
right: 0 !important;
|
|
68
82
|
}
|
|
69
83
|
header.header-point-mobile[style*="background"],
|
|
70
84
|
.header-point-mobile[style*="background"],
|
|
@@ -72,9 +86,18 @@ export const HeaderPoint = ({
|
|
|
72
86
|
background-color: transparent !important;
|
|
73
87
|
background: transparent !important;
|
|
74
88
|
}
|
|
89
|
+
header.header-point-mobile > div {
|
|
90
|
+
width: 100% !important;
|
|
91
|
+
max-width: 100% !important;
|
|
92
|
+
padding-left: 0 !important;
|
|
93
|
+
padding-right: 0 !important;
|
|
94
|
+
margin: 0 !important;
|
|
95
|
+
}
|
|
75
96
|
.header-mobile-layout {
|
|
76
97
|
display: block !important;
|
|
77
98
|
position: relative !important;
|
|
99
|
+
width: 100% !important;
|
|
100
|
+
max-width: 100% !important;
|
|
78
101
|
}
|
|
79
102
|
.header-mobile-top-row {
|
|
80
103
|
display: flex !important;
|
|
@@ -83,6 +106,9 @@ export const HeaderPoint = ({
|
|
|
83
106
|
padding: 24px 24px 12px 24px !important;
|
|
84
107
|
min-height: 64px !important;
|
|
85
108
|
height: 64px !important;
|
|
109
|
+
width: 100% !important;
|
|
110
|
+
max-width: 100% !important;
|
|
111
|
+
box-sizing: border-box !important;
|
|
86
112
|
}
|
|
87
113
|
.header-mobile-menu-button,
|
|
88
114
|
.header-mobile-notification-button {
|
|
@@ -118,11 +144,12 @@ export const HeaderPoint = ({
|
|
|
118
144
|
.header-mobile-search-row {
|
|
119
145
|
position: relative;
|
|
120
146
|
z-index: 2 !important;
|
|
121
|
-
}
|
|
122
|
-
.header-mobile-search-row {
|
|
123
147
|
display: block;
|
|
124
148
|
padding: 12px 24px 0 24px;
|
|
125
149
|
margin-top: -8px;
|
|
150
|
+
width: 100% !important;
|
|
151
|
+
max-width: 100% !important;
|
|
152
|
+
box-sizing: border-box !important;
|
|
126
153
|
}
|
|
127
154
|
.header-desktop-layout {
|
|
128
155
|
display: none !important;
|
|
@@ -283,6 +310,7 @@ export const HeaderPoint = ({
|
|
|
283
310
|
{/* Lado izquierdo: Menú hamburguesa */}
|
|
284
311
|
<div className="flex items-center">
|
|
285
312
|
<button
|
|
313
|
+
onClick={() => setIsSidebarOpen(true)}
|
|
286
314
|
className="p-2 hover:bg-gray-100 rounded-lg transition-colors header-mobile-menu-button"
|
|
287
315
|
style={{ cursor: 'pointer', padding: '8px' }}
|
|
288
316
|
aria-label="Menú"
|
|
@@ -402,6 +430,27 @@ export const HeaderPoint = ({
|
|
|
402
430
|
</div>
|
|
403
431
|
</div>
|
|
404
432
|
</div>
|
|
433
|
+
|
|
434
|
+
{/* SidebarPointMobile - Solo visible en móvil cuando está abierto */}
|
|
435
|
+
{isSidebarOpen && (
|
|
436
|
+
<div className="header-mobile-sidebar-wrapper">
|
|
437
|
+
<SidebarPointMobile
|
|
438
|
+
sections={sidebarSections}
|
|
439
|
+
activeItem={sidebarActiveItem}
|
|
440
|
+
onItemClick={(itemId) => {
|
|
441
|
+
if (onSidebarItemClick) {
|
|
442
|
+
onSidebarItemClick(itemId);
|
|
443
|
+
}
|
|
444
|
+
setIsSidebarOpen(false);
|
|
445
|
+
}}
|
|
446
|
+
itemBadges={sidebarItemBadges}
|
|
447
|
+
companyName={sidebarCompanyName}
|
|
448
|
+
companyLogo={sidebarCompanyLogo}
|
|
449
|
+
isOpen={isSidebarOpen}
|
|
450
|
+
onClose={() => setIsSidebarOpen(false)}
|
|
451
|
+
/>
|
|
452
|
+
</div>
|
|
453
|
+
)}
|
|
405
454
|
</header>
|
|
406
455
|
);
|
|
407
456
|
};
|
|
@@ -34,13 +34,23 @@ const SidebarCoreMobile = ({
|
|
|
34
34
|
footerCollapsedContent, // Contenido a mostrar en el footer cuando está colapsado (puede ser string, ReactNode, o objeto con icon y text)
|
|
35
35
|
coreContainerStyle, // Estilos personalizados para el contenedor de LogoHexa y "Core"
|
|
36
36
|
coreTextStyle, // Estilos personalizados para el texto "Core"
|
|
37
|
+
isOpen: controlledIsOpen,
|
|
38
|
+
onClose: controlledOnClose,
|
|
37
39
|
className = '',
|
|
38
40
|
...props
|
|
39
41
|
}) => {
|
|
40
|
-
const [
|
|
42
|
+
const [internalIsOpen, setInternalIsOpen] = useState(false);
|
|
43
|
+
|
|
44
|
+
// Si se proporciona control externo, usarlo; si no, usar estado interno
|
|
45
|
+
const isMobileMenuOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;
|
|
46
|
+
const setIsMobileMenuOpen = controlledOnClose ? controlledOnClose : setInternalIsOpen;
|
|
41
47
|
|
|
42
48
|
const toggleMobileMenu = () => {
|
|
43
|
-
|
|
49
|
+
if (controlledOnClose) {
|
|
50
|
+
controlledOnClose();
|
|
51
|
+
} else {
|
|
52
|
+
setInternalIsOpen(!internalIsOpen);
|
|
53
|
+
}
|
|
44
54
|
};
|
|
45
55
|
|
|
46
56
|
// Generar footerCollapsedContent automáticamente si no se proporciona pero sí hay footerText
|
|
@@ -79,12 +89,13 @@ const SidebarCoreMobile = ({
|
|
|
79
89
|
transition: transform 0.3s ease-in-out;
|
|
80
90
|
}
|
|
81
91
|
`}</style>
|
|
82
|
-
{/* Botón hamburguesa - solo visible cuando el menú está cerrado */}
|
|
83
|
-
{!isMobileMenuOpen && (
|
|
92
|
+
{/* Botón hamburguesa - solo visible cuando el menú está cerrado y no hay control externo */}
|
|
93
|
+
{!isMobileMenuOpen && controlledIsOpen === undefined && (
|
|
84
94
|
<button
|
|
85
95
|
onClick={toggleMobileMenu}
|
|
86
|
-
className="fixed top-4 left-4 z-50 p-2 bg-white
|
|
96
|
+
className="fixed top-4 left-4 z-50 p-2 bg-white rounded-lg
|
|
87
97
|
hover:bg-gray-50 transition-colors"
|
|
98
|
+
style={{ border: '1px solid #C4C4C4' }}
|
|
88
99
|
aria-label="Toggle menu"
|
|
89
100
|
>
|
|
90
101
|
<Icon
|
|
@@ -96,14 +107,24 @@ const SidebarCoreMobile = ({
|
|
|
96
107
|
</button>
|
|
97
108
|
)}
|
|
98
109
|
{/* Overlay para cerrar el menú */}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
<div
|
|
111
|
+
className="fixed inset-0 bg-black bg-opacity-50 z-40"
|
|
112
|
+
style={{
|
|
113
|
+
opacity: isMobileMenuOpen ? 1 : 0,
|
|
114
|
+
pointerEvents: isMobileMenuOpen ? 'auto' : 'none',
|
|
115
|
+
transition: 'opacity 0.3s ease-in-out'
|
|
116
|
+
}}
|
|
117
|
+
onClick={() => {
|
|
118
|
+
if (controlledOnClose) {
|
|
119
|
+
controlledOnClose();
|
|
120
|
+
} else {
|
|
121
|
+
toggleMobileMenu();
|
|
122
|
+
}
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
105
125
|
<aside
|
|
106
|
-
className={`bg-white
|
|
126
|
+
className={`bg-white sidebar-core-mobile ${className}`}
|
|
127
|
+
style={{ border: '1px solid #C4C4C4', borderRadius: '16px' }}
|
|
107
128
|
{...props}
|
|
108
129
|
>
|
|
109
130
|
<nav className="h-full flex flex-col">
|
|
@@ -145,7 +166,13 @@ const SidebarCoreMobile = ({
|
|
|
145
166
|
|
|
146
167
|
{/* Lado derecho: Botón X */}
|
|
147
168
|
<button
|
|
148
|
-
onClick={
|
|
169
|
+
onClick={() => {
|
|
170
|
+
if (controlledOnClose) {
|
|
171
|
+
controlledOnClose();
|
|
172
|
+
} else {
|
|
173
|
+
toggleMobileMenu();
|
|
174
|
+
}
|
|
175
|
+
}}
|
|
149
176
|
className="p-1 hover:bg-gray-100 rounded transition-colors flex-shrink-0"
|
|
150
177
|
aria-label="Cerrar menú"
|
|
151
178
|
>
|
|
@@ -164,7 +191,11 @@ const SidebarCoreMobile = ({
|
|
|
164
191
|
<button
|
|
165
192
|
onClick={() => {
|
|
166
193
|
onItemClick && onItemClick('inicio');
|
|
167
|
-
|
|
194
|
+
if (controlledOnClose) {
|
|
195
|
+
controlledOnClose();
|
|
196
|
+
} else {
|
|
197
|
+
toggleMobileMenu();
|
|
198
|
+
}
|
|
168
199
|
}}
|
|
169
200
|
className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
|
|
170
201
|
activeItem === 'inicio'
|
|
@@ -232,7 +263,11 @@ const SidebarCoreMobile = ({
|
|
|
232
263
|
<button
|
|
233
264
|
onClick={() => {
|
|
234
265
|
onItemClick && onItemClick(item.id);
|
|
235
|
-
|
|
266
|
+
if (controlledOnClose) {
|
|
267
|
+
controlledOnClose();
|
|
268
|
+
} else {
|
|
269
|
+
toggleMobileMenu();
|
|
270
|
+
}
|
|
236
271
|
}}
|
|
237
272
|
className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
|
|
238
273
|
activeItem === item.id
|
|
@@ -431,9 +466,10 @@ export const SidebarCore = ({
|
|
|
431
466
|
|
|
432
467
|
return (
|
|
433
468
|
<aside
|
|
434
|
-
className={`bg-white
|
|
469
|
+
className={`bg-white transition-all duration-300 ease-in-out h-full ${
|
|
435
470
|
isCollapsed ? 'w-20' : 'w-64'
|
|
436
471
|
} ${className}`}
|
|
472
|
+
style={{ border: '1px solid #C4C4C4', borderRadius: '16px' }}
|
|
437
473
|
{...props}
|
|
438
474
|
>
|
|
439
475
|
<nav className="h-full flex flex-col" style={{ overflow: 'hidden' }}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
2
|
import { Icon } from '../../Atoms/Icon/Icon';
|
|
3
3
|
import { Typography } from '../../Atoms/Typography/Typography';
|
|
4
4
|
import { LogoHexa } from '../../Atoms/LogoHexa/LogoHexa';
|
|
@@ -331,13 +331,44 @@ const SidebarPointMobile = ({
|
|
|
331
331
|
companyLogo,
|
|
332
332
|
onCompanyClick,
|
|
333
333
|
itemBadges = {},
|
|
334
|
+
isOpen: controlledIsOpen,
|
|
335
|
+
onClose: controlledOnClose,
|
|
334
336
|
className = '',
|
|
335
337
|
...props
|
|
336
338
|
}) => {
|
|
337
|
-
const [
|
|
339
|
+
const [internalIsOpen, setInternalIsOpen] = useState(false);
|
|
340
|
+
const [shouldAnimate, setShouldAnimate] = useState(false);
|
|
341
|
+
|
|
342
|
+
// Si se proporciona control externo, usarlo; si no, usar estado interno
|
|
343
|
+
const isMobileMenuOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;
|
|
344
|
+
const setIsMobileMenuOpen = controlledOnClose ? controlledOnClose : setInternalIsOpen;
|
|
345
|
+
|
|
346
|
+
// Efecto para manejar la animación cuando se controla externamente
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
if (controlledIsOpen !== undefined) {
|
|
349
|
+
if (controlledIsOpen) {
|
|
350
|
+
// Cuando se abre, primero montamos sin animación, luego activamos la animación
|
|
351
|
+
setShouldAnimate(false);
|
|
352
|
+
// Pequeño delay para asegurar que el DOM esté listo antes de animar
|
|
353
|
+
const timer = setTimeout(() => {
|
|
354
|
+
setShouldAnimate(true);
|
|
355
|
+
}, 10);
|
|
356
|
+
return () => clearTimeout(timer);
|
|
357
|
+
} else {
|
|
358
|
+
// Cuando se cierra, desactivamos la animación inmediatamente
|
|
359
|
+
setShouldAnimate(false);
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
setShouldAnimate(internalIsOpen);
|
|
363
|
+
}
|
|
364
|
+
}, [controlledIsOpen, internalIsOpen]);
|
|
338
365
|
|
|
339
366
|
const toggleMobileMenu = () => {
|
|
340
|
-
|
|
367
|
+
if (controlledOnClose) {
|
|
368
|
+
controlledOnClose();
|
|
369
|
+
} else {
|
|
370
|
+
setInternalIsOpen(!internalIsOpen);
|
|
371
|
+
}
|
|
341
372
|
};
|
|
342
373
|
|
|
343
374
|
// Formatear fecha de hoy
|
|
@@ -360,11 +391,20 @@ const SidebarPointMobile = ({
|
|
|
360
391
|
top: 0;
|
|
361
392
|
height: 100vh;
|
|
362
393
|
z-index: 50;
|
|
363
|
-
transition: transform 0.3s ease-in-out;
|
|
394
|
+
transition: ${shouldAnimate ? 'transform 0.3s ease-in-out' : 'none'};
|
|
395
|
+
}
|
|
396
|
+
.sidebar-point-mobile-overlay {
|
|
397
|
+
position: fixed;
|
|
398
|
+
inset: 0;
|
|
399
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
400
|
+
z-index: 40;
|
|
401
|
+
transition: opacity 0.3s ease-in-out;
|
|
402
|
+
opacity: ${isMobileMenuOpen ? '1' : '0'};
|
|
403
|
+
pointer-events: ${isMobileMenuOpen ? 'auto' : 'none'};
|
|
364
404
|
}
|
|
365
405
|
`}</style>
|
|
366
|
-
{/* Botón hamburguesa - solo visible cuando el menú está cerrado */}
|
|
367
|
-
{!isMobileMenuOpen && (
|
|
406
|
+
{/* Botón hamburguesa - solo visible cuando el menú está cerrado y no hay control externo */}
|
|
407
|
+
{!isMobileMenuOpen && controlledIsOpen === undefined && (
|
|
368
408
|
<button
|
|
369
409
|
onClick={toggleMobileMenu}
|
|
370
410
|
className="fixed top-4 left-4 z-50 p-2 bg-white border border-gray-200 rounded-lg shadow-md
|
|
@@ -380,19 +420,23 @@ const SidebarPointMobile = ({
|
|
|
380
420
|
</button>
|
|
381
421
|
)}
|
|
382
422
|
{/* Overlay para cerrar el menú */}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
423
|
+
<div
|
|
424
|
+
className="sidebar-point-mobile-overlay"
|
|
425
|
+
onClick={() => {
|
|
426
|
+
if (controlledOnClose) {
|
|
427
|
+
controlledOnClose();
|
|
428
|
+
} else {
|
|
429
|
+
toggleMobileMenu();
|
|
430
|
+
}
|
|
431
|
+
}}
|
|
432
|
+
/>
|
|
389
433
|
<aside
|
|
390
434
|
className={`bg-gray-100 border-r border-gray-200 sidebar-point-mobile ${className}`}
|
|
391
435
|
{...props}
|
|
392
436
|
>
|
|
393
437
|
<nav className="h-full flex flex-col">
|
|
394
|
-
{/* Header
|
|
395
|
-
<div className="
|
|
438
|
+
{/* Header MAIN con "Point" y botón X */}
|
|
439
|
+
<div className="px-4 py-4 flex items-center justify-between" style={{ backgroundColor: 'var(--color-main)' }}>
|
|
396
440
|
<Typography
|
|
397
441
|
variant="h5"
|
|
398
442
|
className="color-white font-bold"
|
|
@@ -400,8 +444,15 @@ const SidebarPointMobile = ({
|
|
|
400
444
|
Point
|
|
401
445
|
</Typography>
|
|
402
446
|
<button
|
|
403
|
-
onClick={
|
|
447
|
+
onClick={() => {
|
|
448
|
+
if (controlledOnClose) {
|
|
449
|
+
controlledOnClose();
|
|
450
|
+
} else {
|
|
451
|
+
toggleMobileMenu();
|
|
452
|
+
}
|
|
453
|
+
}}
|
|
404
454
|
className="p-1 hover:bg-opacity-80 rounded transition-colors"
|
|
455
|
+
style={{ cursor: 'pointer' }}
|
|
405
456
|
aria-label="Cerrar menú"
|
|
406
457
|
>
|
|
407
458
|
<Icon
|
|
@@ -421,7 +472,7 @@ const SidebarPointMobile = ({
|
|
|
421
472
|
{capitalizedDate}
|
|
422
473
|
</Typography>
|
|
423
474
|
</div>
|
|
424
|
-
{/* Logo de empresa (si se proporciona) */}
|
|
475
|
+
{/* Logo de empresa (solo si se proporciona) */}
|
|
425
476
|
{companyLogo && (
|
|
426
477
|
<div className="bg-gray-100 px-4 py-6 flex justify-center border-b border-gray-200">
|
|
427
478
|
<img
|