anima-ds-nucleus 1.0.2 → 1.0.4

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.
Files changed (38) hide show
  1. package/dist/anima-ds-nucleus.css +1 -1
  2. package/dist/anima-ds.cjs.js +152 -34
  3. package/dist/anima-ds.esm.js +10124 -7528
  4. package/package.json +10 -2
  5. package/src/assets/nucleus-logo.svg +3 -0
  6. package/src/components/Atoms/LogoHexa/LogoHexa.jsx +34 -0
  7. package/src/components/Atoms/LogoHexa/LogoHexa.stories.jsx +36 -0
  8. package/src/components/Atoms/Typography/Typography.jsx +53 -18
  9. package/src/components/Atoms/Typography/Typography.stories.jsx +40 -4
  10. package/src/components/DataDisplay/Card/Card.jsx +117 -24
  11. package/src/components/DataDisplay/Card/Card.stories.jsx +119 -35
  12. package/src/components/DataDisplay/Card/CardError.jsx +142 -0
  13. package/src/components/DataDisplay/Card/CardSkeleton.jsx +96 -0
  14. package/src/components/DataDisplay/Card/CardTituloCorto.jsx +61 -0
  15. package/src/components/DataDisplay/Card/CardTituloCortoMasEstado.jsx +79 -0
  16. package/src/components/DataDisplay/Card/CardTituloLargo.jsx +61 -0
  17. package/src/components/DataDisplay/Card/CardTituloLargoMasEstado.jsx +77 -0
  18. package/src/components/DataDisplay/Card/CardVacia.jsx +111 -0
  19. package/src/components/Layout/Header/HeaderConBuscador.jsx +136 -0
  20. package/src/components/Layout/Header/HeaderConBuscador.stories.jsx +86 -0
  21. package/src/components/Layout/Header/HeaderCore.jsx +347 -0
  22. package/src/components/Layout/Header/HeaderCore.stories.jsx +59 -0
  23. package/src/components/Layout/Header/HeaderGeneral.jsx +92 -0
  24. package/src/components/Layout/Header/HeaderGeneral.stories.jsx +64 -0
  25. package/src/components/Layout/Header/HeaderPoint.jsx +120 -0
  26. package/src/components/Layout/Header/HeaderPoint.stories.jsx +110 -0
  27. package/src/components/Layout/NavPoint/NavPoint.jsx +64 -0
  28. package/src/components/Layout/NavPoint/NavPoint.stories.jsx +52 -0
  29. package/src/components/Layout/Sidebar/SidebarCore.jsx +779 -0
  30. package/src/components/Layout/Sidebar/SidebarCore.stories.jsx +167 -0
  31. package/src/components/Layout/Sidebar/SidebarPoint.jsx +645 -0
  32. package/src/components/Layout/Sidebar/SidebarPoint.stories.jsx +183 -0
  33. package/src/index.js +15 -2
  34. package/src/style.css +37 -0
  35. package/src/components/Layout/Header/Header.jsx +0 -50
  36. package/src/components/Layout/Header/Header.stories.jsx +0 -36
  37. package/src/components/Layout/Sidebar/Sidebar.jsx +0 -57
  38. package/src/components/Layout/Sidebar/Sidebar.stories.jsx +0 -51
@@ -0,0 +1,136 @@
1
+ import { useState } from 'react';
2
+ import { Icon } from '../../Atoms/Icon/Icon';
3
+ import { Avatar } from '../../Atoms/Avatar/Avatar';
4
+ import { Typography } from '../../Atoms/Typography/Typography';
5
+
6
+ export const HeaderConBuscador = ({
7
+ searchPlaceholder = 'Buscar empleados, reportes, configuraciones...',
8
+ userName,
9
+ userAvatar,
10
+ notificationCount = 0,
11
+ onSearch,
12
+ onNotificationClick,
13
+ onUserClick,
14
+ className = '',
15
+ ...props
16
+ }) => {
17
+ const [searchValue, setSearchValue] = useState('');
18
+
19
+ const handleSearchChange = (e) => {
20
+ const value = e.target.value;
21
+ setSearchValue(value);
22
+ if (onSearch) {
23
+ onSearch(value);
24
+ }
25
+ };
26
+
27
+ const handleSearchSubmit = (e) => {
28
+ e.preventDefault();
29
+ if (onSearch) {
30
+ onSearch(searchValue);
31
+ }
32
+ };
33
+
34
+ return (
35
+ <header
36
+ className={`bg-white border-b border-gray-200 ${className}`}
37
+ {...props}
38
+ >
39
+ <div className="container mx-auto px-4 sm:px-6 lg:px-8">
40
+ <div className="flex items-center justify-between h-16">
41
+ {/* Barra de búsqueda */}
42
+ <div className="flex-1 max-w-2xl mr-8">
43
+ <form onSubmit={handleSearchSubmit} className="relative">
44
+ <input
45
+ type="text"
46
+ value={searchValue}
47
+ onChange={handleSearchChange}
48
+ placeholder={searchPlaceholder}
49
+ className="w-full pl-4 pr-12 py-2.5 bg-slate-50 border border-gray-200 rounded-lg
50
+ focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
51
+ text-body-md color-gray-700 placeholder:color-gray-400"
52
+ />
53
+ <button
54
+ type="submit"
55
+ className="absolute right-3 top-1/2 transform -translate-y-1/2
56
+ hover:opacity-70 transition-opacity"
57
+ aria-label="Buscar"
58
+ >
59
+ <Icon
60
+ name="MagnifyingGlassIcon"
61
+ variant="24-outline"
62
+ size={20}
63
+ className="color-gray-400"
64
+ />
65
+ </button>
66
+ </form>
67
+ </div>
68
+
69
+ {/* Notificaciones y Perfil */}
70
+ <div className="flex items-center space-x-6">
71
+ {/* Icono de notificaciones */}
72
+ {notificationCount !== undefined && (
73
+ <button
74
+ onClick={onNotificationClick}
75
+ className="flex items-center space-x-2 p-2 hover:bg-gray-100 rounded-lg transition-colors"
76
+ aria-label="Notificaciones"
77
+ >
78
+ <Icon
79
+ name="BellIcon"
80
+ variant="24-outline"
81
+ size={24}
82
+ className="color-gray-600"
83
+ />
84
+ {notificationCount > 0 && (
85
+ <span
86
+ className="px-2 py-0.5 min-w-[20px] h-5
87
+ text-white rounded-full flex items-center justify-center
88
+ text-body-sm font-medium"
89
+ style={{
90
+ backgroundColor: '#6D3856',
91
+ borderRadius: '12px'
92
+ }}
93
+ >
94
+ {notificationCount > 9 ? '9+' : notificationCount}
95
+ </span>
96
+ )}
97
+ </button>
98
+ )}
99
+
100
+ {/* Perfil de usuario */}
101
+ {userName && (
102
+ <button
103
+ onClick={onUserClick}
104
+ className="flex items-center space-x-3 hover:bg-gray-50
105
+ rounded-lg px-2 py-1.5 transition-colors"
106
+ aria-label="Perfil de usuario"
107
+ >
108
+ <Avatar
109
+ src={userAvatar}
110
+ name={userName}
111
+ size="medium"
112
+ variant="circle"
113
+ />
114
+ <Typography
115
+ variant="body-md"
116
+ className="color-teal font-medium hidden sm:block"
117
+ >
118
+ {userName}
119
+ </Typography>
120
+ <Icon
121
+ name="ChevronDownIcon"
122
+ variant="24-outline"
123
+ size={20}
124
+ className="color-gray-500 hidden sm:block"
125
+ />
126
+ </button>
127
+ )}
128
+ </div>
129
+ </div>
130
+ </div>
131
+ </header>
132
+ );
133
+ };
134
+
135
+ export default HeaderConBuscador;
136
+
@@ -0,0 +1,86 @@
1
+ import { useState } from 'react';
2
+ import { HeaderConBuscador } from './HeaderConBuscador';
3
+
4
+ export default {
5
+ title: 'Layout/HeaderConBuscador',
6
+ component: HeaderConBuscador,
7
+ tags: ['autodocs'],
8
+ };
9
+
10
+ export const Default = {
11
+ render: () => {
12
+ const [searchValue, setSearchValue] = useState('');
13
+ return (
14
+ <HeaderConBuscador
15
+ searchPlaceholder="Buscar empleados, reportes, configuraciones..."
16
+ userName="Maria Garcia Alonso"
17
+ userAvatar="https://i.pravatar.cc/150?img=47"
18
+ notificationCount={2}
19
+ onSearch={(value) => {
20
+ setSearchValue(value);
21
+ console.log('Buscando:', value);
22
+ }}
23
+ onNotificationClick={() => {
24
+ console.log('Notificaciones clickeadas');
25
+ }}
26
+ onUserClick={() => {
27
+ console.log('Perfil clickeado');
28
+ }}
29
+ />
30
+ );
31
+ },
32
+ };
33
+
34
+ export const SinNotificaciones = {
35
+ render: () => (
36
+ <HeaderConBuscador
37
+ userName="Juan Pérez"
38
+ notificationCount={0}
39
+ />
40
+ ),
41
+ };
42
+
43
+ export const SinNotificacionesProp = {
44
+ render: () => (
45
+ <HeaderConBuscador
46
+ userName="Ana López"
47
+ />
48
+ ),
49
+ };
50
+
51
+ export const ConMuchasNotificaciones = {
52
+ render: () => (
53
+ <HeaderConBuscador
54
+ userName="Carlos Rodríguez"
55
+ notificationCount={15}
56
+ />
57
+ ),
58
+ };
59
+
60
+ export const SinAvatar = {
61
+ render: () => (
62
+ <HeaderConBuscador
63
+ userName="Laura Martínez"
64
+ notificationCount={3}
65
+ />
66
+ ),
67
+ };
68
+
69
+ export const CustomSearchPlaceholder = {
70
+ render: () => (
71
+ <HeaderConBuscador
72
+ searchPlaceholder="Buscar en el sistema..."
73
+ userName="Pedro Sánchez"
74
+ notificationCount={1}
75
+ />
76
+ ),
77
+ };
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
@@ -0,0 +1,347 @@
1
+ import { useState } from 'react';
2
+ import { Icon } from '../../Atoms/Icon/Icon';
3
+ import { Avatar } from '../../Atoms/Avatar/Avatar';
4
+ import { Typography } from '../../Atoms/Typography/Typography';
5
+
6
+ export const HeaderCore = ({
7
+ searchPlaceholder = 'Buscar empleados, reportes, configuraciones...',
8
+ userName,
9
+ userAvatar,
10
+ notificationCount = 0,
11
+ onSearch,
12
+ onNotificationClick,
13
+ onUserClick,
14
+ className = '',
15
+ ...props
16
+ }) => {
17
+ const [searchValue, setSearchValue] = useState('');
18
+
19
+ const handleSearchChange = (e) => {
20
+ const value = e.target.value;
21
+ setSearchValue(value);
22
+ if (onSearch) {
23
+ onSearch(value);
24
+ }
25
+ };
26
+
27
+ const handleSearchSubmit = (e) => {
28
+ e.preventDefault();
29
+ if (onSearch) {
30
+ onSearch(searchValue);
31
+ }
32
+ };
33
+
34
+ return (
35
+ <header
36
+ className={`bg-white border-b border-gray-200 ${className}`}
37
+ {...props}
38
+ >
39
+ <style>{`
40
+ .header-search-input {
41
+ border-color: #9ca3af;
42
+ }
43
+ .header-search-input::placeholder {
44
+ color: #9ca3af !important;
45
+ opacity: 1 !important;
46
+ }
47
+ .header-search-icon-container {
48
+ border-color: #9ca3af;
49
+ }
50
+ .header-search-form:focus-within .header-search-input {
51
+ border-color: #3b82f6 !important;
52
+ box-shadow: 0 0 0 1px #3b82f6;
53
+ }
54
+ .header-search-form:focus-within .header-search-icon-container {
55
+ border-color: #3b82f6 !important;
56
+ box-shadow: 0 0 0 1px #3b82f6;
57
+ }
58
+ @media (max-width: 768px) {
59
+ .header-search-input {
60
+ font-size: 12px !important;
61
+ padding-left: 8px !important;
62
+ padding-right: 8px !important;
63
+ }
64
+ .header-search-icon-container {
65
+ width: 36px !important;
66
+ }
67
+ }
68
+ @media (max-width: 480px) {
69
+ .header-mobile-top-row {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: space-between;
73
+ padding: 8px 4px;
74
+ min-height: 48px;
75
+ }
76
+ .header-mobile-search-row {
77
+ display: block;
78
+ padding: 12px 4px 8px 4px;
79
+ }
80
+ .header-desktop-layout {
81
+ display: none;
82
+ }
83
+ }
84
+ @media (min-width: 481px) {
85
+ .header-mobile-layout {
86
+ display: none;
87
+ }
88
+ }
89
+ `}</style>
90
+
91
+ <div className="w-full" style={{ paddingLeft: '4px', paddingRight: '4px' }}>
92
+ {/* Layout Desktop (más de 480px) */}
93
+ <div className="header-desktop-layout flex items-center justify-between h-16">
94
+ {/* Barra de búsqueda con icono a la derecha */}
95
+ <div className="flex-1 mr-2 md:mr-4" style={{ maxWidth: 'none', minWidth: '0' }}>
96
+ <form onSubmit={handleSearchSubmit} className="header-search-form flex items-center w-full">
97
+ {/* Input de búsqueda */}
98
+ <input
99
+ type="text"
100
+ value={searchValue}
101
+ onChange={handleSearchChange}
102
+ placeholder={searchPlaceholder}
103
+ className="header-search-input flex-1 pl-2 md:pl-4 pr-2 md:pr-4 py-2 md:py-2.5 bg-white border border-gray-400 rounded-l-lg
104
+ focus:outline-none text-sm md:text-base"
105
+ style={{
106
+ height: '40px',
107
+ borderRight: 'none',
108
+ borderTopRightRadius: '0',
109
+ borderBottomRightRadius: '0',
110
+ color: '#374151',
111
+ fontFamily: 'IBM Plex Sans',
112
+ fontWeight: 400,
113
+ fontStyle: 'italic',
114
+ fontSize: '14px',
115
+ lineHeight: '20px',
116
+ letterSpacing: '0px'
117
+ }}
118
+ />
119
+
120
+ {/* Recuadro con icono de buscar a la derecha */}
121
+ <div
122
+ className="header-search-icon-container flex items-center justify-center border border-gray-400 rounded-r-lg bg-white"
123
+ style={{
124
+ width: '40px',
125
+ height: '40px',
126
+ borderTopLeftRadius: '0',
127
+ borderBottomLeftRadius: '0'
128
+ }}
129
+ >
130
+ <Icon
131
+ name="MagnifyingGlassIcon"
132
+ variant="24-outline"
133
+ size={20}
134
+ className="color-gray-600"
135
+ />
136
+ </div>
137
+ </form>
138
+ </div>
139
+
140
+ {/* Notificaciones y Perfil */}
141
+ <div className="flex items-center space-x-3 md:space-x-6 flex-shrink-0" style={{ marginLeft: 'auto', paddingRight: '0px' }}>
142
+ {/* Icono de notificaciones */}
143
+ {notificationCount !== undefined && (
144
+ <button
145
+ onClick={onNotificationClick}
146
+ className="relative p-2 hover:bg-gray-100 rounded-lg transition-colors"
147
+ aria-label="Notificaciones"
148
+ >
149
+ <Icon
150
+ name="BellIcon"
151
+ variant="24-outline"
152
+ size={24}
153
+ className="color-gray-600"
154
+ />
155
+ {notificationCount > 0 && (
156
+ <span
157
+ className="absolute -top-1 -right-1 px-1.5 py-0.5 min-w-[20px] h-5
158
+ text-white rounded-full flex items-center justify-center
159
+ text-body-sm font-medium"
160
+ style={{
161
+ backgroundColor: '#6D3856',
162
+ borderRadius: '12px'
163
+ }}
164
+ >
165
+ {notificationCount > 9 ? '9+' : notificationCount}
166
+ </span>
167
+ )}
168
+ </button>
169
+ )}
170
+
171
+ {/* Perfil de usuario */}
172
+ {userName && (
173
+ <button
174
+ onClick={onUserClick}
175
+ className="flex items-center space-x-3 hover:bg-gray-50
176
+ rounded-lg px-2 py-1.5 transition-colors"
177
+ aria-label="Perfil de usuario"
178
+ >
179
+ <Avatar
180
+ src={userAvatar}
181
+ name={userName}
182
+ size="medium"
183
+ variant="circle"
184
+ />
185
+ <Typography
186
+ variant="body-lg"
187
+ className="color-gray-700 hidden md:block"
188
+ style={{
189
+ fontFamily: 'IBM Plex Sans',
190
+ fontWeight: 400,
191
+ fontStyle: 'normal',
192
+ fontSize: '16px',
193
+ lineHeight: '24px',
194
+ letterSpacing: '0%',
195
+ verticalAlign: 'middle'
196
+ }}
197
+ >
198
+ {userName}
199
+ </Typography>
200
+ <Icon
201
+ name="ChevronDownIcon"
202
+ variant="24-outline"
203
+ size={20}
204
+ className="color-gray-500"
205
+ />
206
+ </button>
207
+ )}
208
+ </div>
209
+ </div>
210
+
211
+ {/* Layout Mobile (480px o menos) */}
212
+ <div className="header-mobile-layout">
213
+ {/* Primera fila: Menú, Core, Notificaciones y Avatar */}
214
+ <div className="header-mobile-top-row">
215
+ {/* Lado izquierdo: Menú hamburguesa y Core */}
216
+ <div className="flex items-center space-x-2">
217
+ {/* Botón menú hamburguesa */}
218
+ <button
219
+ className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
220
+ aria-label="Menú"
221
+ >
222
+ <Icon
223
+ name="Bars3Icon"
224
+ variant="24-outline"
225
+ size={24}
226
+ className="color-gray-700"
227
+ />
228
+ </button>
229
+
230
+ {/* Texto "Core" */}
231
+ <Typography
232
+ variant="h6"
233
+ style={{
234
+ color: '#2D5C63',
235
+ fontSize: '24px',
236
+ fontFamily: 'IBM Plex Sans',
237
+ fontWeight: 600,
238
+ lineHeight: '1.2',
239
+ margin: 0
240
+ }}
241
+ >
242
+ Core
243
+ </Typography>
244
+ </div>
245
+
246
+ {/* Lado derecho: Notificaciones y Avatar */}
247
+ <div className="flex items-center space-x-3">
248
+ {/* Icono de notificaciones */}
249
+ {notificationCount !== undefined && (
250
+ <button
251
+ onClick={onNotificationClick}
252
+ className="relative p-2 hover:bg-gray-100 rounded-lg transition-colors"
253
+ aria-label="Notificaciones"
254
+ >
255
+ <Icon
256
+ name="BellIcon"
257
+ variant="24-outline"
258
+ size={24}
259
+ className="color-gray-600"
260
+ />
261
+ {notificationCount > 0 && (
262
+ <span
263
+ className="absolute -top-1 -right-1 px-1.5 py-0.5 min-w-[20px] h-5
264
+ text-white rounded-full flex items-center justify-center
265
+ text-body-sm font-medium"
266
+ style={{
267
+ backgroundColor: '#6D3856',
268
+ borderRadius: '12px'
269
+ }}
270
+ >
271
+ {notificationCount > 9 ? '9+' : notificationCount}
272
+ </span>
273
+ )}
274
+ </button>
275
+ )}
276
+
277
+ {/* Avatar (sin nombre) */}
278
+ {userAvatar && (
279
+ <button
280
+ onClick={onUserClick}
281
+ className="hover:bg-gray-50 rounded-lg transition-colors"
282
+ aria-label="Perfil de usuario"
283
+ >
284
+ <Avatar
285
+ src={userAvatar}
286
+ name={userName || ''}
287
+ size="medium"
288
+ variant="circle"
289
+ />
290
+ </button>
291
+ )}
292
+ </div>
293
+ </div>
294
+
295
+ {/* Segunda fila: Barra de búsqueda */}
296
+ <div className="header-mobile-search-row">
297
+ <form onSubmit={handleSearchSubmit} className="header-search-form flex items-center w-full">
298
+ {/* Input de búsqueda */}
299
+ <input
300
+ type="text"
301
+ value={searchValue}
302
+ onChange={handleSearchChange}
303
+ placeholder={searchPlaceholder}
304
+ className="header-search-input flex-1 pl-3 pr-3 py-2 bg-white border border-gray-400 rounded-l-lg
305
+ focus:outline-none text-sm"
306
+ style={{
307
+ height: '40px',
308
+ borderRight: 'none',
309
+ borderTopRightRadius: '0',
310
+ borderBottomRightRadius: '0',
311
+ color: '#374151',
312
+ fontFamily: 'IBM Plex Sans',
313
+ fontWeight: 400,
314
+ fontStyle: 'italic',
315
+ fontSize: '14px',
316
+ lineHeight: '20px',
317
+ letterSpacing: '0px'
318
+ }}
319
+ />
320
+
321
+ {/* Recuadro con icono de buscar a la derecha */}
322
+ <div
323
+ className="header-search-icon-container flex items-center justify-center border border-gray-400 rounded-r-lg bg-white"
324
+ style={{
325
+ width: '40px',
326
+ height: '40px',
327
+ borderTopLeftRadius: '0',
328
+ borderBottomLeftRadius: '0'
329
+ }}
330
+ >
331
+ <Icon
332
+ name="MagnifyingGlassIcon"
333
+ variant="24-outline"
334
+ size={20}
335
+ className="color-gray-600"
336
+ />
337
+ </div>
338
+ </form>
339
+ </div>
340
+ </div>
341
+ </div>
342
+ </header>
343
+ );
344
+ };
345
+
346
+ export default HeaderCore;
347
+
@@ -0,0 +1,59 @@
1
+ import { HeaderCore } from './HeaderCore';
2
+
3
+ export default {
4
+ title: 'Layout/HeaderCore',
5
+ component: HeaderCore,
6
+ tags: ['autodocs'],
7
+ };
8
+
9
+ export const Default = {
10
+ render: () => (
11
+ <HeaderCore
12
+ searchPlaceholder="Buscar empleados, reportes, configuraciones..."
13
+ userName="Maria García Alonso"
14
+ userAvatar="https://i.pravatar.cc/150?img=12"
15
+ notificationCount={7}
16
+ onSearch={(value) => console.log('Búsqueda:', value)}
17
+ onNotificationClick={() => console.log('Notificaciones clickeadas')}
18
+ onUserClick={() => console.log('Usuario clickeado')}
19
+ />
20
+ ),
21
+ };
22
+
23
+ export const SinNotificaciones = {
24
+ render: () => (
25
+ <HeaderCore
26
+ searchPlaceholder="Buscar empleados, reportes, configuraciones..."
27
+ userName="Juan Pérez"
28
+ userAvatar="https://i.pravatar.cc/150?img=33"
29
+ notificationCount={0}
30
+ />
31
+ ),
32
+ };
33
+
34
+ export const ConMuchasNotificaciones = {
35
+ render: () => (
36
+ <HeaderCore
37
+ searchPlaceholder="Buscar empleados, reportes, configuraciones..."
38
+ userName="Ana Martínez"
39
+ userAvatar="https://i.pravatar.cc/150?img=47"
40
+ notificationCount={15}
41
+ />
42
+ ),
43
+ };
44
+
45
+ export const SinUsuario = {
46
+ render: () => (
47
+ <HeaderCore
48
+ searchPlaceholder="Buscar empleados, reportes, configuraciones..."
49
+ notificationCount={3}
50
+ />
51
+ ),
52
+ };
53
+
54
+
55
+
56
+
57
+
58
+
59
+