anima-ds-nucleus 1.0.7 → 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.
@@ -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';
@@ -50,55 +50,6 @@ export const SidebarPoint = ({
50
50
  {...props}
51
51
  >
52
52
  <nav className="h-full flex flex-col" style={{ overflow: 'hidden' }}>
53
- {/* Barra superior con HEXA Point */}
54
- {!isCollapsed && (
55
- <div className="p-4 border-b border-gray-200 flex-shrink-0">
56
- <button
57
- onClick={onCompanyClick}
58
- className="w-full bg-white rounded-lg px-3 py-2.5
59
- flex items-center justify-between hover:bg-gray-50 transition-colors"
60
- >
61
- <div className="flex items-center space-x-3">
62
- {/* Logo hexagonal */}
63
- {companyLogo ? (
64
- <img
65
- src={companyLogo}
66
- alt={companyName}
67
- className="w-8 h-8 rounded"
68
- />
69
- ) : (
70
- <LogoHexa width={36} height={40} />
71
- )}
72
- {/* Nombre de la empresa */}
73
- <Typography
74
- variant="body-md"
75
- className="color-gray-900 font-medium"
76
- >
77
- {companyName}
78
- </Typography>
79
- </div>
80
- </button>
81
- </div>
82
- )}
83
-
84
- {/* Botón de colapsar/expandir - Solo visible cuando está expandido */}
85
- {!isCollapsed && (
86
- <div className="px-4 pt-2 pb-2 flex justify-end flex-shrink-0">
87
- <button
88
- onClick={toggleCollapse}
89
- className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
90
- aria-label="Colapsar sidebar"
91
- style={{ marginRight: '10px' }}
92
- >
93
- <Icon
94
- name="ChevronDoubleLeftIcon"
95
- variant="24-outline"
96
- size={20}
97
- className="color-teal"
98
- />
99
- </button>
100
- </div>
101
- )}
102
53
 
103
54
  {/* Header con logo de empresa cuando Client es true - entre botón colapsar y botón Inicio */}
104
55
  {Client && companyLogo && !isCollapsed && (
@@ -113,38 +64,7 @@ export const SidebarPoint = ({
113
64
  </div>
114
65
  )}
115
66
 
116
- {/* Logo cuando está colapsado */}
117
- {isCollapsed && (
118
- <div className="p-4 border-b border-gray-200 flex justify-center flex-shrink-0">
119
- {companyLogo ? (
120
- <img
121
- src={companyLogo}
122
- alt={companyName}
123
- className="w-8 h-8 rounded"
124
- />
125
- ) : (
126
- <LogoHexa width={36} height={40} />
127
- )}
128
- </div>
129
- )}
130
67
 
131
- {/* Botón para expandir - Solo visible cuando está colapsado */}
132
- {isCollapsed && (
133
- <div className="px-4 pt-2 pb-2 flex justify-center flex-shrink-0">
134
- <button
135
- onClick={toggleCollapse}
136
- className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
137
- aria-label="Expandir sidebar"
138
- >
139
- <Icon
140
- name="ChevronDoubleRightIcon"
141
- variant="24-outline"
142
- size={20}
143
- className="color-teal"
144
- />
145
- </button>
146
- </div>
147
- )}
148
68
 
149
69
  {/* Contenido del sidebar - Wrapper para controlar el espacio */}
150
70
  <div className="flex-1 min-h-0 flex flex-col overflow-hidden">
@@ -166,31 +86,34 @@ export const SidebarPoint = ({
166
86
  : {}
167
87
  }
168
88
  >
169
- <Icon
170
- name="HomeIcon"
171
- variant="24-outline"
172
- size={20}
173
- className={`${isCollapsed ? '' : 'mr-3'} ${
174
- activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
175
- }`}
176
- />
177
- {!isCollapsed && (
178
- <Typography
179
- variant="body-md"
180
- className={`font-medium ${
89
+ <div className="flex items-center">
90
+ <Icon
91
+ name="HomeIcon"
92
+ variant="24-outline"
93
+ size={20}
94
+ className={`${isCollapsed ? '' : 'mr-3'} ${
181
95
  activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
182
96
  }`}
183
- >
184
- Inicio
185
- </Typography>
186
- )}
97
+ />
98
+ {!isCollapsed && (
99
+ <Typography
100
+ variant="body-md"
101
+ className={`font-medium ${
102
+ activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
103
+ }`}
104
+ >
105
+ Inicio
106
+ </Typography>
107
+ )}
108
+ </div>
187
109
  {!isCollapsed && itemBadges['inicio'] !== undefined && itemBadges['inicio'] > 0 && (
188
110
  <span
189
111
  className="px-2 py-0.5 min-w-[20px] h-5
190
- text-white rounded-full flex items-center justify-center
112
+ rounded-full flex items-center justify-center
191
113
  text-body-sm font-medium"
192
114
  style={{
193
- backgroundColor: '#6D3856',
115
+ backgroundColor: activeItem === 'inicio' ? '#FFFFFF' : '#6D3856',
116
+ color: activeItem === 'inicio' ? '#6D3856' : '#FFFFFF',
194
117
  borderRadius: '12px'
195
118
  }}
196
119
  >
@@ -265,10 +188,11 @@ export const SidebarPoint = ({
265
188
  {!isCollapsed && ((itemBadges[item.id] !== undefined && itemBadges[item.id] > 0) || (item.id === 'empleados' && 2)) && (
266
189
  <span
267
190
  className="px-2 py-0.5 min-w-[20px] h-5
268
- text-white rounded-full flex items-center justify-center
191
+ rounded-full flex items-center justify-center
269
192
  text-body-sm font-medium"
270
193
  style={{
271
- backgroundColor: '#6D3856',
194
+ backgroundColor: activeItem === item.id ? '#FFFFFF' : '#6D3856',
195
+ color: activeItem === item.id ? '#6D3856' : '#FFFFFF',
272
196
  borderRadius: '12px'
273
197
  }}
274
198
  >
@@ -407,13 +331,44 @@ const SidebarPointMobile = ({
407
331
  companyLogo,
408
332
  onCompanyClick,
409
333
  itemBadges = {},
334
+ isOpen: controlledIsOpen,
335
+ onClose: controlledOnClose,
410
336
  className = '',
411
337
  ...props
412
338
  }) => {
413
- const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
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]);
414
365
 
415
366
  const toggleMobileMenu = () => {
416
- setIsMobileMenuOpen(!isMobileMenuOpen);
367
+ if (controlledOnClose) {
368
+ controlledOnClose();
369
+ } else {
370
+ setInternalIsOpen(!internalIsOpen);
371
+ }
417
372
  };
418
373
 
419
374
  // Formatear fecha de hoy
@@ -436,11 +391,20 @@ const SidebarPointMobile = ({
436
391
  top: 0;
437
392
  height: 100vh;
438
393
  z-index: 50;
439
- 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'};
440
404
  }
441
405
  `}</style>
442
- {/* Botón hamburguesa - solo visible cuando el menú está cerrado */}
443
- {!isMobileMenuOpen && (
406
+ {/* Botón hamburguesa - solo visible cuando el menú está cerrado y no hay control externo */}
407
+ {!isMobileMenuOpen && controlledIsOpen === undefined && (
444
408
  <button
445
409
  onClick={toggleMobileMenu}
446
410
  className="fixed top-4 left-4 z-50 p-2 bg-white border border-gray-200 rounded-lg shadow-md
@@ -456,19 +420,23 @@ const SidebarPointMobile = ({
456
420
  </button>
457
421
  )}
458
422
  {/* Overlay para cerrar el menú */}
459
- {isMobileMenuOpen && (
460
- <div
461
- className="fixed inset-0 bg-black bg-opacity-50 z-40"
462
- onClick={toggleMobileMenu}
463
- />
464
- )}
423
+ <div
424
+ className="sidebar-point-mobile-overlay"
425
+ onClick={() => {
426
+ if (controlledOnClose) {
427
+ controlledOnClose();
428
+ } else {
429
+ toggleMobileMenu();
430
+ }
431
+ }}
432
+ />
465
433
  <aside
466
434
  className={`bg-gray-100 border-r border-gray-200 sidebar-point-mobile ${className}`}
467
435
  {...props}
468
436
  >
469
437
  <nav className="h-full flex flex-col">
470
- {/* Header verde con "Point" y botón X */}
471
- <div className="bg-brand px-4 py-4 flex items-center justify-between" style={{ backgroundColor: '#56B676' }}>
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)' }}>
472
440
  <Typography
473
441
  variant="h5"
474
442
  className="color-white font-bold"
@@ -476,8 +444,15 @@ const SidebarPointMobile = ({
476
444
  Point
477
445
  </Typography>
478
446
  <button
479
- onClick={toggleMobileMenu}
447
+ onClick={() => {
448
+ if (controlledOnClose) {
449
+ controlledOnClose();
450
+ } else {
451
+ toggleMobileMenu();
452
+ }
453
+ }}
480
454
  className="p-1 hover:bg-opacity-80 rounded transition-colors"
455
+ style={{ cursor: 'pointer' }}
481
456
  aria-label="Cerrar menú"
482
457
  >
483
458
  <Icon
@@ -497,7 +472,7 @@ const SidebarPointMobile = ({
497
472
  {capitalizedDate}
498
473
  </Typography>
499
474
  </div>
500
- {/* Logo de empresa (si se proporciona) */}
475
+ {/* Logo de empresa (solo si se proporciona) */}
501
476
  {companyLogo && (
502
477
  <div className="bg-gray-100 px-4 py-6 flex justify-center border-b border-gray-200">
503
478
  <img
@@ -0,0 +1,92 @@
1
+ import { LogoHexa } from '../../Atoms/LogoHexa/LogoHexa';
2
+ import { Typography } from '../../Atoms/Typography/Typography';
3
+
4
+ export const TituloPoint = ({
5
+ backgroundColor = 'var(--color-main)',
6
+ textColor = '#FFFFFF',
7
+ borderBottomColor = 'var(--color-main-800)',
8
+ className = '',
9
+ ...props
10
+ }) => {
11
+ return (
12
+ <div
13
+ className={`titulo-point ${className}`}
14
+ style={{
15
+ backgroundColor: backgroundColor,
16
+ width: '100%',
17
+ display: 'none',
18
+ opacity: 1,
19
+ borderBottomColor: borderBottomColor
20
+ }}
21
+ {...props}
22
+ >
23
+ <style>{`
24
+ @media (min-width: 769px) {
25
+ .titulo-point {
26
+ display: flex !important;
27
+ align-items: center !important;
28
+ justify-content: center !important;
29
+ width: 100%;
30
+ height: calc(60px * (100vw / 1440px));
31
+ min-height: 40px;
32
+ max-height: 60px;
33
+ padding-top: 20px;
34
+ padding-right: 16px;
35
+ padding-left: 16px;
36
+ padding-bottom: 0;
37
+ border-bottom-width: 1px;
38
+ border-bottom-style: solid;
39
+ box-sizing: border-box;
40
+ position: relative;
41
+ }
42
+ .titulo-point-inner {
43
+ display: flex !important;
44
+ align-items: center !important;
45
+ justify-content: center !important;
46
+ gap: 12px;
47
+ width: 100%;
48
+ margin: 0 auto;
49
+ padding: 0;
50
+ flex-shrink: 0;
51
+ }
52
+ }
53
+ @media (min-width: 1440px) {
54
+ .titulo-point {
55
+ height: 60px;
56
+ }
57
+ }
58
+ @media (max-width: 768px) {
59
+ .titulo-point {
60
+ display: none !important;
61
+ }
62
+ }
63
+ `}</style>
64
+ <div className="titulo-point-inner" style={{ margin: 0, padding: 0 }}>
65
+ <LogoHexa
66
+ width={28}
67
+ height={32}
68
+ backgroundColor="#FFFFFF"
69
+ textColor="var(--color-main)"
70
+ />
71
+ <Typography
72
+ variant="h5"
73
+ style={{
74
+ color: textColor,
75
+ fontFamily: 'IBM Plex Sans',
76
+ fontWeight: 600,
77
+ fontSize: '18px',
78
+ lineHeight: '1.2',
79
+ margin: 0,
80
+ padding: 0,
81
+ display: 'flex',
82
+ alignItems: 'center'
83
+ }}
84
+ >
85
+ HEXA Point
86
+ </Typography>
87
+ </div>
88
+ </div>
89
+ );
90
+ };
91
+
92
+ export default TituloPoint;
@@ -0,0 +1,31 @@
1
+ import { TituloPoint } from './TituloPoint';
2
+
3
+ export default {
4
+ title: 'Layout/TituloPoint',
5
+ component: TituloPoint,
6
+ tags: ['autodocs'],
7
+ };
8
+
9
+ export const Default = {
10
+ render: () => (
11
+ <TituloPoint />
12
+ ),
13
+ };
14
+
15
+ export const ConColorPersonalizado = {
16
+ render: () => (
17
+ <TituloPoint
18
+ backgroundColor="#000000"
19
+ textColor="#FFFFFF"
20
+ />
21
+ ),
22
+ };
23
+
24
+ export const ConColorSecundario = {
25
+ render: () => (
26
+ <TituloPoint
27
+ backgroundColor="var(--color-secondary)"
28
+ textColor="#FFFFFF"
29
+ />
30
+ ),
31
+ };