anima-ds-nucleus 1.0.8 → 1.0.9
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 +119 -91
- package/dist/anima-ds.esm.js +6322 -6210
- package/package.json +1 -1
- 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 +46 -13
- package/src/components/Layout/Sidebar/SidebarPoint.jsx +67 -16
package/package.json
CHANGED
|
@@ -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,8 +89,8 @@ 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
96
|
className="fixed top-4 left-4 z-50 p-2 bg-white border border-gray-200 rounded-lg shadow-md
|
|
@@ -96,12 +106,21 @@ const SidebarCoreMobile = ({
|
|
|
96
106
|
</button>
|
|
97
107
|
)}
|
|
98
108
|
{/* Overlay para cerrar el menú */}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
<div
|
|
110
|
+
className="fixed inset-0 bg-black bg-opacity-50 z-40"
|
|
111
|
+
style={{
|
|
112
|
+
opacity: isMobileMenuOpen ? 1 : 0,
|
|
113
|
+
pointerEvents: isMobileMenuOpen ? 'auto' : 'none',
|
|
114
|
+
transition: 'opacity 0.3s ease-in-out'
|
|
115
|
+
}}
|
|
116
|
+
onClick={() => {
|
|
117
|
+
if (controlledOnClose) {
|
|
118
|
+
controlledOnClose();
|
|
119
|
+
} else {
|
|
120
|
+
toggleMobileMenu();
|
|
121
|
+
}
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
105
124
|
<aside
|
|
106
125
|
className={`bg-white border-r border-gray-200 sidebar-core-mobile ${className}`}
|
|
107
126
|
{...props}
|
|
@@ -145,7 +164,13 @@ const SidebarCoreMobile = ({
|
|
|
145
164
|
|
|
146
165
|
{/* Lado derecho: Botón X */}
|
|
147
166
|
<button
|
|
148
|
-
onClick={
|
|
167
|
+
onClick={() => {
|
|
168
|
+
if (controlledOnClose) {
|
|
169
|
+
controlledOnClose();
|
|
170
|
+
} else {
|
|
171
|
+
toggleMobileMenu();
|
|
172
|
+
}
|
|
173
|
+
}}
|
|
149
174
|
className="p-1 hover:bg-gray-100 rounded transition-colors flex-shrink-0"
|
|
150
175
|
aria-label="Cerrar menú"
|
|
151
176
|
>
|
|
@@ -164,7 +189,11 @@ const SidebarCoreMobile = ({
|
|
|
164
189
|
<button
|
|
165
190
|
onClick={() => {
|
|
166
191
|
onItemClick && onItemClick('inicio');
|
|
167
|
-
|
|
192
|
+
if (controlledOnClose) {
|
|
193
|
+
controlledOnClose();
|
|
194
|
+
} else {
|
|
195
|
+
toggleMobileMenu();
|
|
196
|
+
}
|
|
168
197
|
}}
|
|
169
198
|
className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
|
|
170
199
|
activeItem === 'inicio'
|
|
@@ -232,7 +261,11 @@ const SidebarCoreMobile = ({
|
|
|
232
261
|
<button
|
|
233
262
|
onClick={() => {
|
|
234
263
|
onItemClick && onItemClick(item.id);
|
|
235
|
-
|
|
264
|
+
if (controlledOnClose) {
|
|
265
|
+
controlledOnClose();
|
|
266
|
+
} else {
|
|
267
|
+
toggleMobileMenu();
|
|
268
|
+
}
|
|
236
269
|
}}
|
|
237
270
|
className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
|
|
238
271
|
activeItem === item.id
|
|
@@ -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
|