anima-ds-nucleus 1.0.11 → 1.0.12

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.
@@ -34,17 +34,40 @@ 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
+ transitionDurationMs = 300,
38
+ transitionEasing = 'ease-in-out',
39
+ // UX: permitir que el item se pinte inmediatamente aunque el padre tarde en actualizar activeItem
40
+ enableOptimisticActiveItem = true,
41
+ closeOnItemClickAnimationFrame = true,
37
42
  isOpen: controlledIsOpen,
38
43
  onClose: controlledOnClose,
39
44
  className = '',
40
45
  ...props
41
46
  }) => {
42
47
  const [internalIsOpen, setInternalIsOpen] = useState(false);
48
+ const [optimisticActiveItem, setOptimisticActiveItem] = useState(null);
43
49
 
44
50
  // Si se proporciona control externo, usarlo; si no, usar estado interno
45
51
  const isMobileMenuOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;
46
52
  const setIsMobileMenuOpen = controlledOnClose ? controlledOnClose : setInternalIsOpen;
47
53
 
54
+ const effectiveActiveItem =
55
+ enableOptimisticActiveItem && optimisticActiveItem != null ? optimisticActiveItem : activeItem;
56
+
57
+ useEffect(() => {
58
+ if (!enableOptimisticActiveItem) return;
59
+ if (optimisticActiveItem != null && optimisticActiveItem === activeItem) {
60
+ setOptimisticActiveItem(null);
61
+ }
62
+ }, [activeItem, optimisticActiveItem, enableOptimisticActiveItem]);
63
+
64
+ useEffect(() => {
65
+ if (!enableOptimisticActiveItem) return;
66
+ if (!isMobileMenuOpen && optimisticActiveItem != null) {
67
+ setOptimisticActiveItem(null);
68
+ }
69
+ }, [isMobileMenuOpen, optimisticActiveItem, enableOptimisticActiveItem]);
70
+
48
71
  const toggleMobileMenu = () => {
49
72
  if (controlledOnClose) {
50
73
  controlledOnClose();
@@ -86,7 +109,7 @@ const SidebarCoreMobile = ({
86
109
  top: 0;
87
110
  height: 100vh;
88
111
  z-index: 50;
89
- transition: transform 0.3s ease-in-out;
112
+ transition: transform ${transitionDurationMs}ms ${transitionEasing};
90
113
  }
91
114
  `}</style>
92
115
  {/* Botón hamburguesa - solo visible cuando el menú está cerrado y no hay control externo */}
@@ -112,7 +135,7 @@ const SidebarCoreMobile = ({
112
135
  style={{
113
136
  opacity: isMobileMenuOpen ? 1 : 0,
114
137
  pointerEvents: isMobileMenuOpen ? 'auto' : 'none',
115
- transition: 'opacity 0.3s ease-in-out'
138
+ transition: `opacity ${transitionDurationMs}ms ${transitionEasing}`
116
139
  }}
117
140
  onClick={() => {
118
141
  if (controlledOnClose) {
@@ -132,7 +155,7 @@ const SidebarCoreMobile = ({
132
155
  <div className="bg-white px-4 py-4 flex items-center justify-between border-b border-gray-200">
133
156
  {/* Lado izquierdo: LogoHexa y "Core" */}
134
157
  <div
135
- className="flex items-center space-x-2"
158
+ className="flex items-center space-x-2 min-w-0 flex-1"
136
159
  style={coreContainerStyle}
137
160
  >
138
161
  {/* Logo Hexa */}
@@ -153,10 +176,10 @@ const SidebarCoreMobile = ({
153
176
  lineHeight: '1.2',
154
177
  margin: 0,
155
178
  marginLeft: '8px',
156
- width: '272px',
157
- height: '40px',
158
179
  display: 'flex',
159
180
  alignItems: 'center',
181
+ minWidth: 0,
182
+ flex: 1,
160
183
  ...coreTextStyle
161
184
  }}
162
185
  >
@@ -198,12 +221,12 @@ const SidebarCoreMobile = ({
198
221
  }
199
222
  }}
200
223
  className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
201
- activeItem === 'inicio'
224
+ effectiveActiveItem === 'inicio'
202
225
  ? ''
203
226
  : 'color-gray-700 hover:bg-gray-100'
204
227
  }`}
205
228
  style={
206
- activeItem === 'inicio'
229
+ effectiveActiveItem === 'inicio'
207
230
  ? { backgroundColor: '#2D5C63' }
208
231
  : {}
209
232
  }
@@ -214,13 +237,13 @@ const SidebarCoreMobile = ({
214
237
  variant="24-outline"
215
238
  size={20}
216
239
  className={`mr-3 ${
217
- activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
240
+ effectiveActiveItem === 'inicio' ? 'color-white' : 'color-gray-700'
218
241
  }`}
219
242
  />
220
243
  <Typography
221
244
  variant="body-md"
222
245
  className={`font-medium ${
223
- activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
246
+ effectiveActiveItem === 'inicio' ? 'color-white' : 'color-gray-700'
224
247
  }`}
225
248
  >
226
249
  Inicio
@@ -232,8 +255,8 @@ const SidebarCoreMobile = ({
232
255
  rounded-full flex items-center justify-center
233
256
  text-body-sm font-medium"
234
257
  style={{
235
- backgroundColor: activeItem === 'inicio' ? '#ffffff' : '#6D3856',
236
- color: activeItem === 'inicio' ? '#6D3856' : '#ffffff',
258
+ backgroundColor: effectiveActiveItem === 'inicio' ? '#ffffff' : '#6D3856',
259
+ color: effectiveActiveItem === 'inicio' ? '#6D3856' : '#ffffff',
237
260
  borderRadius: '12px'
238
261
  }}
239
262
  >
@@ -262,20 +285,27 @@ const SidebarCoreMobile = ({
262
285
  <div key={item.id} className="px-4">
263
286
  <button
264
287
  onClick={() => {
288
+ if (enableOptimisticActiveItem) {
289
+ setOptimisticActiveItem(item.id);
290
+ }
265
291
  onItemClick && onItemClick(item.id);
266
292
  if (controlledOnClose) {
267
- controlledOnClose();
293
+ if (closeOnItemClickAnimationFrame) {
294
+ requestAnimationFrame(() => controlledOnClose());
295
+ } else {
296
+ controlledOnClose();
297
+ }
268
298
  } else {
269
299
  toggleMobileMenu();
270
300
  }
271
301
  }}
272
302
  className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
273
- activeItem === item.id
303
+ effectiveActiveItem === item.id
274
304
  ? ''
275
305
  : 'color-gray-700 hover:bg-gray-100'
276
306
  }`}
277
307
  style={
278
- activeItem === item.id
308
+ effectiveActiveItem === item.id
279
309
  ? { backgroundColor: '#2D5C63' }
280
310
  : {}
281
311
  }
@@ -286,13 +316,13 @@ const SidebarCoreMobile = ({
286
316
  variant="24-outline"
287
317
  size={20}
288
318
  className={`mr-3 ${
289
- activeItem === item.id ? 'color-white' : 'color-gray-700'
319
+ effectiveActiveItem === item.id ? 'color-white' : 'color-gray-700'
290
320
  }`}
291
321
  />
292
322
  <Typography
293
323
  variant="body-md"
294
324
  className={`font-medium ${
295
- activeItem === item.id ? 'color-white' : 'color-gray-700'
325
+ effectiveActiveItem === item.id ? 'color-white' : 'color-gray-700'
296
326
  }`}
297
327
  >
298
328
  {item.label}
@@ -304,8 +334,8 @@ const SidebarCoreMobile = ({
304
334
  rounded-full flex items-center justify-center
305
335
  text-body-sm font-medium"
306
336
  style={{
307
- backgroundColor: activeItem === item.id ? '#ffffff' : '#6D3856',
308
- color: activeItem === item.id ? '#6D3856' : '#ffffff',
337
+ backgroundColor: effectiveActiveItem === item.id ? '#ffffff' : '#6D3856',
338
+ color: effectiveActiveItem === item.id ? '#6D3856' : '#ffffff',
309
339
  borderRadius: '12px'
310
340
  }}
311
341
  >
@@ -387,8 +417,28 @@ export const SidebarCore = ({
387
417
  companyLogo,
388
418
  onCompanyClick,
389
419
  // Overrides desktop para el header "HEXA Core"
420
+ desktopCompanyButtonClassName = '',
421
+ desktopCompanyButtonStyle,
390
422
  desktopCompanyNameClassName = '',
391
423
  desktopCompanyNameStyle,
424
+ // Desktop: overrides para el control de colapsar (solo cuando NO está colapsado)
425
+ desktopCollapseControlWrapperClassName = '',
426
+ desktopCollapseControlWrapperStyle,
427
+ desktopCollapseButtonClassName = '',
428
+ desktopCollapseButtonStyle,
429
+ desktopCollapseIconSize = 20,
430
+ desktopCollapseIconStrokeWidth = 1.5,
431
+ desktopCollapseIconColor = '#0F172A',
432
+ desktopCollapseIconClassName = '',
433
+ desktopCollapseIconStyle,
434
+ // Desktop: overrides para el control de expandir (solo cuando está colapsado)
435
+ desktopExpandButtonClassName = '',
436
+ desktopExpandButtonStyle,
437
+ desktopExpandIconSize = 20,
438
+ desktopExpandIconStrokeWidth = 1.5,
439
+ desktopExpandIconColor = '#0F172A',
440
+ desktopExpandIconClassName = '',
441
+ desktopExpandIconStyle,
392
442
  nucleusName = 'Nucleus AR',
393
443
  nucleusLogo,
394
444
  onNucleusClick,
@@ -481,8 +531,9 @@ export const SidebarCore = ({
481
531
  <div className="p-4 border-b border-gray-200 flex-shrink-0">
482
532
  <button
483
533
  onClick={onCompanyClick}
484
- className="w-full bg-white rounded-lg px-3 py-2.5
485
- flex items-center justify-between hover:bg-gray-50 transition-colors"
534
+ className={`w-full bg-white rounded-lg pl-0 pr-3 py-0 h-10
535
+ flex items-center justify-between hover:bg-gray-50 transition-colors ${desktopCompanyButtonClassName}`}
536
+ style={desktopCompanyButtonStyle}
486
537
  >
487
538
  <div className="flex items-center space-x-3">
488
539
  {/* Logo hexagonal */}
@@ -520,20 +571,54 @@ export const SidebarCore = ({
520
571
 
521
572
  {/* Botón de colapsar/expandir - Solo visible cuando está expandido */}
522
573
  {!isCollapsed && (
523
- <div className="px-4 pt-2 pb-2 flex justify-end flex-shrink-0">
524
- <button
525
- onClick={toggleCollapse}
526
- className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
527
- aria-label="Colapsar sidebar"
528
- style={{ marginRight: '10px' }}
574
+ <div className="px-4 pt-2 flex justify-end flex-shrink-0">
575
+ {/* Wrapper con medidas Figma (overrideable por props) */}
576
+ <div
577
+ className={`flex justify-end ${desktopCollapseControlWrapperClassName}`}
578
+ style={{
579
+ width: '228px',
580
+ height: '36px',
581
+ opacity: 1,
582
+ transform: 'rotate(0deg)',
583
+ paddingBottom: '16px',
584
+ boxSizing: 'border-box',
585
+ borderTopRightRadius: '8px',
586
+ borderBottomRightRadius: '8px',
587
+ ...(desktopCollapseControlWrapperStyle || {}),
588
+ }}
529
589
  >
530
- <Icon
531
- name="ChevronDoubleLeftIcon"
532
- variant="24-outline"
533
- size={20}
534
- className="color-teal"
535
- />
536
- </button>
590
+ <button
591
+ onClick={toggleCollapse}
592
+ className={`hover:bg-gray-100 transition-colors rounded-lg ${desktopCollapseButtonClassName}`}
593
+ aria-label="Colapsar sidebar"
594
+ style={{
595
+ width: '36px',
596
+ height: '36px',
597
+ display: 'flex',
598
+ alignItems: 'center',
599
+ justifyContent: 'center',
600
+ opacity: 1,
601
+ transform: 'rotate(0deg)',
602
+ ...(desktopCollapseButtonStyle || {}),
603
+ }}
604
+ >
605
+ <Icon
606
+ name="ChevronDoubleLeftIcon"
607
+ variant="24-outline"
608
+ size={desktopCollapseIconSize}
609
+ strokeWidth={desktopCollapseIconStrokeWidth}
610
+ className={desktopCollapseIconClassName}
611
+ style={{
612
+ width: '20px',
613
+ height: '20px',
614
+ opacity: 1,
615
+ transform: 'rotate(0deg)',
616
+ color: desktopCollapseIconColor,
617
+ ...(desktopCollapseIconStyle || {}),
618
+ }}
619
+ />
620
+ </button>
621
+ </div>
537
622
  </div>
538
623
  )}
539
624
 
@@ -557,14 +642,20 @@ export const SidebarCore = ({
557
642
  <div className="px-4 pt-2 pb-2 flex justify-center flex-shrink-0">
558
643
  <button
559
644
  onClick={toggleCollapse}
560
- className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
645
+ className={`p-1.5 hover:bg-gray-100 rounded-lg transition-colors ${desktopExpandButtonClassName}`}
561
646
  aria-label="Expandir sidebar"
647
+ style={desktopExpandButtonStyle}
562
648
  >
563
649
  <Icon
564
650
  name="ChevronDoubleRightIcon"
565
651
  variant="24-outline"
566
- size={20}
567
- className="color-teal"
652
+ size={desktopExpandIconSize}
653
+ strokeWidth={desktopExpandIconStrokeWidth}
654
+ className={desktopExpandIconClassName}
655
+ style={{
656
+ color: desktopExpandIconColor,
657
+ ...(desktopExpandIconStyle || {}),
658
+ }}
568
659
  />
569
660
  </button>
570
661
  </div>
@@ -601,7 +692,7 @@ export const SidebarCore = ({
601
692
  />
602
693
  {!isCollapsed && (
603
694
  <Typography
604
- variant="body-md"
695
+ variant="body-lg"
605
696
  className={`font-medium ${
606
697
  activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
607
698
  }`}
@@ -697,7 +788,7 @@ export const SidebarCore = ({
697
788
  />
698
789
  {!isCollapsed && (
699
790
  <Typography
700
- variant="body-md"
791
+ variant="body-lg"
701
792
  className={`font-medium ${
702
793
  activeItem === item.id ? 'color-white' : 'color-gray-700'
703
794
  }`}
package/src/index.js CHANGED
@@ -43,6 +43,7 @@ export { Pagination } from './components/Layout/Pagination/Pagination';
43
43
  export { Drawer } from './components/Layout/Drawer/Drawer';
44
44
  export { Dropdown } from './components/Layout/Dropdown/Dropdown';
45
45
  export { Stepper } from './components/Layout/Stepper/Stepper';
46
+ export { SaludoConFechaDashboard } from './components/Layout/SaludoConFechaDashboard/SaludoConFechaDashboard';
46
47
 
47
48
  // DataDisplay
48
49
  export { Card } from './components/DataDisplay/Card/Card';