anima-ds-nucleus 1.0.2 → 1.0.3

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.
@@ -0,0 +1,440 @@
1
+ import { useState } from 'react';
2
+ import { Icon } from '../../Atoms/Icon/Icon';
3
+ import { Typography } from '../../Atoms/Typography/Typography';
4
+
5
+ // Mock data con 2 títulos y 2 secciones
6
+ const MOCK_SECTIONS = [
7
+ {
8
+ title: 'PERSONAS',
9
+ items: [
10
+ { id: 'empleados', label: 'Empleados', icon: 'UserGroupIcon' },
11
+ { id: 'organizacion', label: 'Organización', icon: 'BuildingOfficeIcon' },
12
+ ],
13
+ },
14
+ {
15
+ title: 'TALENTO',
16
+ items: [
17
+ { id: 'reclutamiento', label: 'Reclutamiento', icon: 'UserPlusIcon' },
18
+ { id: 'desarrollo', label: 'Desarrollo', icon: 'AcademicCapIcon' },
19
+ ],
20
+ },
21
+ ];
22
+
23
+ export const SidebarPoint = ({
24
+ sections = MOCK_SECTIONS,
25
+ activeItem,
26
+ onItemClick,
27
+ defaultCollapsed = false,
28
+ companyName = 'HEXA Point',
29
+ companyLogo,
30
+ onCompanyClick,
31
+ itemBadges = {}, // Objeto con { itemId: number } para los badges
32
+ className = '',
33
+ ...props
34
+ }) => {
35
+ const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
36
+
37
+ const toggleCollapse = () => {
38
+ setIsCollapsed(!isCollapsed);
39
+ };
40
+
41
+ return (
42
+ <>
43
+ <style>{`
44
+ /* SidebarPoint Responsive Styles - Preparado para diseño distinto */
45
+ .sidebar-point-responsive {
46
+ /* Tablet (481px-768px) - breakpoint-md */
47
+ width: ${isCollapsed ? '5rem' : '16rem'};
48
+ }
49
+
50
+ /* Desktop Small/Medium (769px-1440px) - breakpoint-base */
51
+ @media (min-width: 769px) and (max-width: 1440px) {
52
+ .sidebar-point-responsive {
53
+ width: ${isCollapsed ? '5rem' : '16rem'};
54
+ }
55
+ }
56
+
57
+ /* Desktop Large (1441px+) - breakpoint-lg */
58
+ @media (min-width: 1441px) {
59
+ .sidebar-point-responsive {
60
+ width: ${isCollapsed ? '5rem' : '16rem'};
61
+ }
62
+ }
63
+ `}</style>
64
+ <aside
65
+ className={`bg-white border-r border-gray-200 transition-all duration-300 ease-in-out sidebar-point-responsive hidden md:block ${className}`}
66
+ {...props}
67
+ >
68
+ <nav className="h-full flex flex-col">
69
+
70
+ {/* Contenido del sidebar */}
71
+ <div className="flex-1 overflow-y-auto py-4">
72
+ {/* Item "Inicio" destacado */}
73
+ <div className="px-4 mb-4">
74
+ <button
75
+ onClick={() => onItemClick && onItemClick('inicio')}
76
+ className={`w-full flex items-center ${
77
+ isCollapsed ? 'justify-center px-2' : 'px-4'
78
+ } py-2.5 rounded-lg transition-all duration-200 ${
79
+ activeItem === 'inicio'
80
+ ? ''
81
+ : 'color-gray-700 hover:bg-gray-100'
82
+ }`}
83
+ style={
84
+ activeItem === 'inicio'
85
+ ? { backgroundColor: '#2D5C63' }
86
+ : {}
87
+ }
88
+ >
89
+ <Icon
90
+ name="HomeIcon"
91
+ variant="24-outline"
92
+ size={20}
93
+ className={`${isCollapsed ? '' : 'mr-3'} ${
94
+ activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
95
+ }`}
96
+ />
97
+ {!isCollapsed && (
98
+ <>
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
+ {itemBadges['inicio'] !== undefined && itemBadges['inicio'] > 0 && (
108
+ <span
109
+ className="px-2 py-0.5 min-w-[20px] h-5
110
+ text-white rounded-full flex items-center justify-center
111
+ text-body-sm font-medium ml-2"
112
+ style={{
113
+ backgroundColor: '#6D3856',
114
+ borderRadius: '12px'
115
+ }}
116
+ >
117
+ {itemBadges['inicio'] > 9 ? '9+' : itemBadges['inicio']}
118
+ </span>
119
+ )}
120
+ </>
121
+ )}
122
+ </button>
123
+ </div>
124
+
125
+ {/* Secciones */}
126
+ {sections.map((section, sectionIndex) => (
127
+ <div key={sectionIndex} className="mb-6">
128
+ {/* Título de la sección */}
129
+ {!isCollapsed && (
130
+ <div className="px-4 mb-2">
131
+ <Typography
132
+ variant="body-sm"
133
+ className="color-gray-500 uppercase font-medium tracking-wider"
134
+ >
135
+ {section.title}
136
+ </Typography>
137
+ </div>
138
+ )}
139
+
140
+ {/* Items de la sección */}
141
+ <div className="space-y-1">
142
+ {section.items.map((item) => (
143
+ <div key={item.id} className="px-4">
144
+ <button
145
+ onClick={() => onItemClick && onItemClick(item.id)}
146
+ className={`w-full flex items-center ${
147
+ isCollapsed ? 'justify-center px-2' : 'px-4 justify-between'
148
+ } py-2.5 rounded-lg transition-all duration-200 ${
149
+ activeItem === item.id
150
+ ? ''
151
+ : 'color-gray-700 hover:bg-gray-100'
152
+ }`}
153
+ style={
154
+ activeItem === item.id
155
+ ? { backgroundColor: '#2D5C63' }
156
+ : {}
157
+ }
158
+ title={isCollapsed ? item.label : ''}
159
+ >
160
+ <div className="flex items-center">
161
+ <Icon
162
+ name={item.icon}
163
+ variant="24-outline"
164
+ size={20}
165
+ className={`${isCollapsed ? '' : 'mr-3'} ${
166
+ activeItem === item.id ? 'color-white' : 'color-gray-700'
167
+ }`}
168
+ />
169
+ {!isCollapsed && (
170
+ <Typography
171
+ variant="body-md"
172
+ className={`font-medium ${
173
+ activeItem === item.id ? 'color-white' : 'color-gray-700'
174
+ }`}
175
+ >
176
+ {item.label}
177
+ </Typography>
178
+ )}
179
+ </div>
180
+ {!isCollapsed && ((itemBadges[item.id] !== undefined && itemBadges[item.id] > 0) || (item.id === 'empleados' && 2)) && (
181
+ <span
182
+ className="px-2 py-0.5 min-w-[20px] h-5
183
+ text-white rounded-full flex items-center justify-center
184
+ text-body-sm font-medium"
185
+ style={{
186
+ backgroundColor: '#6D3856',
187
+ borderRadius: '12px'
188
+ }}
189
+ >
190
+ {item.id === 'empleados' ? 2 : (itemBadges[item.id] > 9 ? '9+' : itemBadges[item.id])}
191
+ </span>
192
+ )}
193
+ </button>
194
+ </div>
195
+ ))}
196
+ </div>
197
+ </div>
198
+ ))}
199
+ </div>
200
+ </nav>
201
+ </aside>
202
+ </>
203
+ );
204
+ };
205
+
206
+ // Componente SidebarPoint Mobile
207
+ const SidebarPointMobile = ({
208
+ sections = MOCK_SECTIONS,
209
+ activeItem,
210
+ onItemClick,
211
+ companyName = 'HEXA Point',
212
+ companyLogo,
213
+ onCompanyClick,
214
+ itemBadges = {},
215
+ className = '',
216
+ ...props
217
+ }) => {
218
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
219
+
220
+ const toggleMobileMenu = () => {
221
+ setIsMobileMenuOpen(!isMobileMenuOpen);
222
+ };
223
+
224
+ // Formatear fecha de hoy
225
+ const formattedDate = new Date().toLocaleDateString('es-AR', {
226
+ weekday: 'long',
227
+ year: 'numeric',
228
+ month: 'long',
229
+ day: 'numeric',
230
+ });
231
+ const capitalizedDate = formattedDate.charAt(0).toUpperCase() + formattedDate.slice(1);
232
+
233
+ return (
234
+ <>
235
+ <style>{`
236
+ .sidebar-point-mobile {
237
+ width: 100%;
238
+ transform: ${isMobileMenuOpen ? 'translateX(0)' : 'translateX(-100%)'};
239
+ position: fixed;
240
+ left: 0;
241
+ top: 0;
242
+ height: 100vh;
243
+ z-index: 50;
244
+ transition: transform 0.3s ease-in-out;
245
+ }
246
+ `}</style>
247
+ {/* Botón hamburguesa - solo visible cuando el menú está cerrado */}
248
+ {!isMobileMenuOpen && (
249
+ <button
250
+ onClick={toggleMobileMenu}
251
+ className="fixed top-4 left-4 z-50 p-2 bg-white border border-gray-200 rounded-lg shadow-md
252
+ hover:bg-gray-50 transition-colors"
253
+ aria-label="Toggle menu"
254
+ >
255
+ <Icon
256
+ name="Bars3Icon"
257
+ variant="24-outline"
258
+ size={24}
259
+ className="color-gray-700"
260
+ />
261
+ </button>
262
+ )}
263
+ {/* Overlay para cerrar el menú */}
264
+ {isMobileMenuOpen && (
265
+ <div
266
+ className="fixed inset-0 bg-black bg-opacity-50 z-40"
267
+ onClick={toggleMobileMenu}
268
+ />
269
+ )}
270
+ <aside
271
+ className={`bg-gray-100 border-r border-gray-200 sidebar-point-mobile ${className}`}
272
+ {...props}
273
+ >
274
+ <nav className="h-full flex flex-col">
275
+ {/* Header verde con "Point" y botón X */}
276
+ <div className="bg-brand px-4 py-4 flex items-center justify-between" style={{ backgroundColor: '#56B676' }}>
277
+ <Typography
278
+ variant="h5"
279
+ className="color-white font-bold"
280
+ >
281
+ Point
282
+ </Typography>
283
+ <button
284
+ onClick={toggleMobileMenu}
285
+ className="p-1 hover:bg-opacity-80 rounded transition-colors"
286
+ aria-label="Cerrar menú"
287
+ >
288
+ <Icon
289
+ name="XMarkIcon"
290
+ variant="24-outline"
291
+ size={24}
292
+ className="color-white"
293
+ />
294
+ </button>
295
+ </div>
296
+ {/* Sección gris con fecha */}
297
+ <div className="bg-gray-100 px-4 py-3 border-b border-gray-200">
298
+ <Typography
299
+ variant="body-md"
300
+ className="color-gray-700"
301
+ >
302
+ {capitalizedDate}
303
+ </Typography>
304
+ </div>
305
+ {/* Contenido del sidebar mobile */}
306
+ <div className="flex-1 overflow-y-auto py-4">
307
+ {/* Item "Inicio" destacado */}
308
+ <div className="px-4 mb-4">
309
+ <button
310
+ onClick={() => {
311
+ onItemClick && onItemClick('inicio');
312
+ toggleMobileMenu();
313
+ }}
314
+ className={`w-full flex items-center px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
315
+ activeItem === 'inicio'
316
+ ? ''
317
+ : 'color-gray-700 hover:bg-gray-100'
318
+ }`}
319
+ style={
320
+ activeItem === 'inicio'
321
+ ? { backgroundColor: '#2D5C63' }
322
+ : {}
323
+ }
324
+ >
325
+ <div className="flex items-center">
326
+ <Icon
327
+ name="HomeIcon"
328
+ variant="24-outline"
329
+ size={20}
330
+ className={`mr-3 ${
331
+ activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
332
+ }`}
333
+ />
334
+ <Typography
335
+ variant="body-md"
336
+ className={`font-medium ${
337
+ activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
338
+ }`}
339
+ >
340
+ Inicio
341
+ </Typography>
342
+ </div>
343
+ {itemBadges['inicio'] !== undefined && itemBadges['inicio'] > 0 && (
344
+ <span
345
+ className="px-2 py-0.5 min-w-[20px] h-5
346
+ text-white rounded-full flex items-center justify-center
347
+ text-body-sm font-medium"
348
+ style={{
349
+ backgroundColor: '#6D3856',
350
+ borderRadius: '12px'
351
+ }}
352
+ >
353
+ {itemBadges['inicio'] > 9 ? '9+' : itemBadges['inicio']}
354
+ </span>
355
+ )}
356
+ </button>
357
+ </div>
358
+
359
+ {/* Secciones */}
360
+ {sections.map((section, sectionIndex) => (
361
+ <div key={sectionIndex} className="mb-6">
362
+ {/* Título de la sección */}
363
+ <div className="px-4 mb-2">
364
+ <Typography
365
+ variant="body-sm"
366
+ className="color-gray-500 uppercase font-medium tracking-wider"
367
+ >
368
+ {section.title}
369
+ </Typography>
370
+ </div>
371
+
372
+ {/* Items de la sección */}
373
+ <div className="space-y-1">
374
+ {section.items.map((item) => (
375
+ <div key={item.id} className="px-4">
376
+ <button
377
+ onClick={() => {
378
+ onItemClick && onItemClick(item.id);
379
+ toggleMobileMenu();
380
+ }}
381
+ className={`w-full flex items-center px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
382
+ activeItem === item.id
383
+ ? ''
384
+ : 'color-gray-700 hover:bg-gray-100'
385
+ }`}
386
+ style={
387
+ activeItem === item.id
388
+ ? { backgroundColor: '#2D5C63' }
389
+ : {}
390
+ }
391
+ >
392
+ <div className="flex items-center">
393
+ <Icon
394
+ name={item.icon}
395
+ variant="24-outline"
396
+ size={20}
397
+ className={`mr-3 ${
398
+ activeItem === item.id ? 'color-white' : 'color-gray-700'
399
+ }`}
400
+ />
401
+ <Typography
402
+ variant="body-md"
403
+ className={`font-medium ${
404
+ activeItem === item.id ? 'color-white' : 'color-gray-700'
405
+ }`}
406
+ >
407
+ {item.label}
408
+ </Typography>
409
+ </div>
410
+ {((itemBadges[item.id] !== undefined && itemBadges[item.id] > 0) || (item.id === 'empleados' && 2)) && (
411
+ <span
412
+ className="px-2 py-0.5 min-w-[20px] h-5
413
+ text-white rounded-full flex items-center justify-center
414
+ text-body-sm font-medium"
415
+ style={{
416
+ backgroundColor: '#6D3856',
417
+ borderRadius: '12px'
418
+ }}
419
+ >
420
+ {item.id === 'empleados' ? 2 : (itemBadges[item.id] > 9 ? '9+' : itemBadges[item.id])}
421
+ </span>
422
+ )}
423
+ </button>
424
+ </div>
425
+ ))}
426
+ </div>
427
+ </div>
428
+ ))}
429
+ </div>
430
+ </nav>
431
+ </aside>
432
+ </>
433
+ );
434
+ };
435
+
436
+ // Exportar ambos componentes
437
+ export { SidebarPointMobile };
438
+ export default SidebarPoint;
439
+
440
+
@@ -0,0 +1,114 @@
1
+ import { useState } from 'react';
2
+ import { SidebarPoint, SidebarPointMobile } from './SidebarPoint';
3
+
4
+ export default {
5
+ title: 'Layout/SidebarPoint',
6
+ component: SidebarPoint,
7
+ tags: ['autodocs'],
8
+ };
9
+
10
+ // Mock data con 2 títulos y 2 secciones
11
+ const mockSections = [
12
+ {
13
+ title: 'PERSONAS',
14
+ items: [
15
+ { id: 'empleados', label: 'Empleados', icon: 'UserGroupIcon' },
16
+ { id: 'organizacion', label: 'Organización', icon: 'BuildingOfficeIcon' },
17
+ ],
18
+ },
19
+ {
20
+ title: 'TALENTO',
21
+ items: [
22
+ { id: 'reclutamiento', label: 'Reclutamiento', icon: 'UserPlusIcon' },
23
+ { id: 'desarrollo', label: 'Desarrollo', icon: 'AcademicCapIcon' },
24
+ ],
25
+ },
26
+ ];
27
+
28
+ export const Default = {
29
+ render: () => {
30
+ const [activeItem, setActiveItem] = useState('inicio');
31
+ return (
32
+ <div className="h-screen bg-gray-100">
33
+ <SidebarPoint
34
+ sections={mockSections}
35
+ activeItem={activeItem}
36
+ onItemClick={setActiveItem}
37
+ companyName="HEXA Point"
38
+ onCompanyClick={() => console.log('Company clicked')}
39
+ />
40
+ </div>
41
+ );
42
+ },
43
+ };
44
+
45
+ export const Colapsado = {
46
+ render: () => {
47
+ const [activeItem, setActiveItem] = useState('inicio');
48
+ return (
49
+ <div className="h-screen bg-gray-100">
50
+ <SidebarPoint
51
+ sections={mockSections}
52
+ activeItem={activeItem}
53
+ onItemClick={setActiveItem}
54
+ defaultCollapsed={true}
55
+ />
56
+ </div>
57
+ );
58
+ },
59
+ };
60
+
61
+ export const ConSeccionesPersonalizadas = {
62
+ render: () => {
63
+ const [activeItem, setActiveItem] = useState('item1');
64
+ const customSections = [
65
+ {
66
+ title: 'ADMINISTRACIÓN',
67
+ items: [
68
+ { id: 'item1', label: 'Usuarios', icon: 'UserIcon' },
69
+ { id: 'item2', label: 'Roles', icon: 'ShieldCheckIcon' },
70
+ ],
71
+ },
72
+ {
73
+ title: 'REPORTES',
74
+ items: [
75
+ { id: 'item3', label: 'Analíticas', icon: 'ChartBarIcon' },
76
+ { id: 'item4', label: 'Exportar', icon: 'ArrowDownTrayIcon' },
77
+ ],
78
+ },
79
+ ];
80
+ return (
81
+ <div className="h-screen bg-gray-100">
82
+ <SidebarPoint
83
+ sections={customSections}
84
+ activeItem={activeItem}
85
+ onItemClick={setActiveItem}
86
+ />
87
+ </div>
88
+ );
89
+ },
90
+ };
91
+
92
+ export const Mobile = {
93
+ render: () => {
94
+ const [activeItem, setActiveItem] = useState('inicio');
95
+ return (
96
+ <div className="h-screen bg-gray-100 relative">
97
+ <SidebarPointMobile
98
+ sections={mockSections}
99
+ activeItem={activeItem}
100
+ onItemClick={setActiveItem}
101
+ companyName="HEXA Point"
102
+ onCompanyClick={() => console.log('Company clicked')}
103
+ />
104
+ <div className="p-4">
105
+ <p className="text-sm text-gray-600">
106
+ Haz clic en el botón hamburguesa (esquina superior izquierda) para abrir el menú mobile.
107
+ </p>
108
+ </div>
109
+ </div>
110
+ );
111
+ },
112
+ };
113
+
114
+
package/src/index.js CHANGED
@@ -28,7 +28,11 @@ export { FileUpload } from './components/Inputs/FileUpload/FileUpload';
28
28
  // Layout
29
29
  export { Layout } from './components/Layout/Layout/Layout';
30
30
  export { Header } from './components/Layout/Header/Header';
31
+ export { HeaderConBuscador } from './components/Layout/Header/HeaderConBuscador';
32
+ export { HeaderCore } from './components/Layout/Header/HeaderCore';
31
33
  export { Sidebar } from './components/Layout/Sidebar/Sidebar';
34
+ export { SidebarCore } from './components/Layout/Sidebar/SidebarCore';
35
+ export { SidebarPoint, SidebarPointMobile } from './components/Layout/Sidebar/SidebarPoint';
32
36
  export { Modal } from './components/Layout/Modal/Modal';
33
37
  export { Tabs } from './components/Layout/Tabs/Tabs';
34
38
  export { Accordion } from './components/Layout/Accordion/Accordion';
package/src/style.css CHANGED
@@ -153,6 +153,18 @@
153
153
  color: #dcfce7;
154
154
  }
155
155
 
156
+ .color-brand {
157
+ color: #56B676; /* Brand color principal */
158
+ }
159
+
160
+ .color-main {
161
+ color: #38656D; /* Main color (verde-azulado oscuro) */
162
+ }
163
+
164
+ .color-teal {
165
+ color: #2D5C63; /* Teal color (usado en botones) */
166
+ }
167
+
156
168
  /* --- FONT WEIGHTS PERMITIDOS (según Figma) --- */
157
169
  .font-light {
158
170
  font-weight: 300;