anima-ds-nucleus 1.0.0

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 (116) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +109 -0
  3. package/dist/anima-ds.cjs.js +1332 -0
  4. package/dist/anima-ds.esm.js +88297 -0
  5. package/dist/vite.svg +1 -0
  6. package/package.json +76 -0
  7. package/src/assets/charly.png +0 -0
  8. package/src/components/Atoms/Alert/Alert.jsx +52 -0
  9. package/src/components/Atoms/Alert/Alert.stories.jsx +62 -0
  10. package/src/components/Atoms/Avatar/Avatar.jsx +60 -0
  11. package/src/components/Atoms/Avatar/Avatar.stories.jsx +61 -0
  12. package/src/components/Atoms/Badge/Badge.jsx +34 -0
  13. package/src/components/Atoms/Badge/Badge.stories.jsx +55 -0
  14. package/src/components/Atoms/Button/Button.jsx +281 -0
  15. package/src/components/Atoms/Button/Button.stories.jsx +365 -0
  16. package/src/components/Atoms/Divider/Divider.jsx +49 -0
  17. package/src/components/Atoms/Divider/Divider.stories.jsx +62 -0
  18. package/src/components/Atoms/Icon/Icon.jsx +361 -0
  19. package/src/components/Atoms/Icon/Icon.stories.jsx +115 -0
  20. package/src/components/Atoms/Label/Label.jsx +22 -0
  21. package/src/components/Atoms/Progress/Progress.jsx +49 -0
  22. package/src/components/Atoms/Progress/Progress.stories.jsx +88 -0
  23. package/src/components/Atoms/Radios/Radios.jsx +39 -0
  24. package/src/components/Atoms/Radios/Radios.stories.jsx +119 -0
  25. package/src/components/Atoms/Shadow/Shadow.stories.jsx +25 -0
  26. package/src/components/Atoms/Skeleton/Skeleton.jsx +50 -0
  27. package/src/components/Atoms/Skeleton/Skeleton.stories.jsx +55 -0
  28. package/src/components/Atoms/Spacing/Spacing.jsx +56 -0
  29. package/src/components/Atoms/Spacing/Spacing.stories.jsx +78 -0
  30. package/src/components/Atoms/Spinner/Spinner.jsx +47 -0
  31. package/src/components/Atoms/Spinner/Spinner.stories.jsx +56 -0
  32. package/src/components/Atoms/Toast/Toast.jsx +74 -0
  33. package/src/components/Atoms/Toast/Toast.stories.jsx +101 -0
  34. package/src/components/Atoms/Tooltip/Tooltip.jsx +49 -0
  35. package/src/components/Atoms/Tooltip/Tooltip.stories.jsx +58 -0
  36. package/src/components/Atoms/Typography/Typography.jsx +52 -0
  37. package/src/components/Atoms/Typography/Typography.stories.jsx +267 -0
  38. package/src/components/DataDisplay/AreaChart/AreaChart.jsx +95 -0
  39. package/src/components/DataDisplay/AreaChart/AreaChart.stories.jsx +51 -0
  40. package/src/components/DataDisplay/BarChart/BarChart.jsx +90 -0
  41. package/src/components/DataDisplay/BarChart/BarChart.stories.jsx +60 -0
  42. package/src/components/DataDisplay/Card/Card.jsx +31 -0
  43. package/src/components/DataDisplay/Card/Card.stories.jsx +50 -0
  44. package/src/components/DataDisplay/ColumnChart/ColumnChart.jsx +92 -0
  45. package/src/components/DataDisplay/ColumnChart/ColumnChart.stories.jsx +65 -0
  46. package/src/components/DataDisplay/DBGrid/DBGrid.jsx +138 -0
  47. package/src/components/DataDisplay/DBGrid/DBGrid.stories.jsx +126 -0
  48. package/src/components/DataDisplay/DonutChart/DonutChart.jsx +83 -0
  49. package/src/components/DataDisplay/DonutChart/DonutChart.stories.jsx +48 -0
  50. package/src/components/DataDisplay/EmptyState/EmptyState.jsx +30 -0
  51. package/src/components/DataDisplay/EmptyState/EmptyState.stories.jsx +42 -0
  52. package/src/components/DataDisplay/LineChart/LineChart.jsx +86 -0
  53. package/src/components/DataDisplay/LineChart/LineChart.stories.jsx +67 -0
  54. package/src/components/DataDisplay/List/List.jsx +30 -0
  55. package/src/components/DataDisplay/List/List.stories.jsx +59 -0
  56. package/src/components/DataDisplay/PieChart/PieChart.jsx +64 -0
  57. package/src/components/DataDisplay/PieChart/PieChart.stories.jsx +47 -0
  58. package/src/components/DataDisplay/StatCard/StatCard.jsx +55 -0
  59. package/src/components/DataDisplay/StatCard/StatCard.stories.jsx +59 -0
  60. package/src/components/DataDisplay/TagList/TagList.jsx +37 -0
  61. package/src/components/DataDisplay/TagList/TagList.stories.jsx +48 -0
  62. package/src/components/DataDisplay/Timeline/Timeline.jsx +41 -0
  63. package/src/components/DataDisplay/Timeline/Timeline.stories.jsx +64 -0
  64. package/src/components/Inputs/Checkbox/Checkbox.jsx +27 -0
  65. package/src/components/Inputs/Checkbox/Checkbox.stories.jsx +51 -0
  66. package/src/components/Inputs/DatePicker/DatePicker.jsx +55 -0
  67. package/src/components/Inputs/DatePicker/DatePicker.stories.jsx +52 -0
  68. package/src/components/Inputs/FileUpload/FileUpload.jsx +108 -0
  69. package/src/components/Inputs/FileUpload/FileUpload.stories.jsx +52 -0
  70. package/src/components/Inputs/Input/Input.jsx +50 -0
  71. package/src/components/Inputs/Input/Input.stories.jsx +63 -0
  72. package/src/components/Inputs/RadioButton/RadioButton.jsx +31 -0
  73. package/src/components/Inputs/RadioButton/RadioButton.stories.jsx +59 -0
  74. package/src/components/Inputs/Select/Select.jsx +59 -0
  75. package/src/components/Inputs/Select/Select.stories.jsx +66 -0
  76. package/src/components/Inputs/Switch/Switch.jsx +44 -0
  77. package/src/components/Inputs/Switch/Switch.stories.jsx +51 -0
  78. package/src/components/Inputs/Textarea/Textarea.jsx +51 -0
  79. package/src/components/Inputs/Textarea/Textarea.stories.jsx +65 -0
  80. package/src/components/Layout/Accordion/Accordion.jsx +58 -0
  81. package/src/components/Layout/Accordion/Accordion.stories.jsx +55 -0
  82. package/src/components/Layout/Breadcrumbs/Breadcrumbs.jsx +49 -0
  83. package/src/components/Layout/Breadcrumbs/Breadcrumbs.stories.jsx +44 -0
  84. package/src/components/Layout/Breakpoint/Breakpoint.jsx +35 -0
  85. package/src/components/Layout/Breakpoint/Breakpoint.stories.jsx +348 -0
  86. package/src/components/Layout/Drawer/Drawer.jsx +75 -0
  87. package/src/components/Layout/Drawer/Drawer.stories.jsx +77 -0
  88. package/src/components/Layout/Dropdown/Dropdown.jsx +83 -0
  89. package/src/components/Layout/Dropdown/Dropdown.stories.jsx +53 -0
  90. package/src/components/Layout/Grid/Grid.jsx +39 -0
  91. package/src/components/Layout/Grid/Grid.stories.jsx +546 -0
  92. package/src/components/Layout/Header/Header.jsx +50 -0
  93. package/src/components/Layout/Header/Header.stories.jsx +36 -0
  94. package/src/components/Layout/Layout/Layout.jsx +14 -0
  95. package/src/components/Layout/Layout/Layout.stories.jsx +34 -0
  96. package/src/components/Layout/Modal/Modal.jsx +78 -0
  97. package/src/components/Layout/Modal/Modal.stories.jsx +98 -0
  98. package/src/components/Layout/Pagination/Pagination.jsx +109 -0
  99. package/src/components/Layout/Pagination/Pagination.stories.jsx +62 -0
  100. package/src/components/Layout/Sidebar/Sidebar.jsx +57 -0
  101. package/src/components/Layout/Sidebar/Sidebar.stories.jsx +51 -0
  102. package/src/components/Layout/Stepper/Stepper.jsx +132 -0
  103. package/src/components/Layout/Stepper/Stepper.stories.jsx +78 -0
  104. package/src/components/Layout/Tabs/Tabs.jsx +63 -0
  105. package/src/components/Layout/Tabs/Tabs.stories.jsx +62 -0
  106. package/src/components/Views/ChangePasswordForm/ChangePasswordForm.jsx +125 -0
  107. package/src/components/Views/ChangePasswordForm/ChangePasswordForm.stories.jsx +55 -0
  108. package/src/components/Views/Chat/Chat.jsx +134 -0
  109. package/src/components/Views/Chat/Chat.stories.jsx +143 -0
  110. package/src/components/Views/LoginForm/LoginForm.jsx +98 -0
  111. package/src/components/Views/LoginForm/LoginForm.stories.jsx +55 -0
  112. package/src/i18n/config.js +209 -0
  113. package/src/index.js +60 -0
  114. package/src/main.jsx +510 -0
  115. package/src/providers/I18nProvider.jsx +13 -0
  116. package/src/style.css +721 -0
@@ -0,0 +1,361 @@
1
+ import * as Outline24 from '@heroicons/react/24/outline';
2
+ import * as Solid24 from '@heroicons/react/24/solid';
3
+ import * as Solid20 from '@heroicons/react/20/solid';
4
+ import * as Solid16 from '@heroicons/react/16/solid';
5
+
6
+ const colorClasses = {
7
+ black: 'color-black',
8
+ white: 'color-white',
9
+ 'gray-900': 'color-gray-900',
10
+ 'gray-700': 'color-gray-700',
11
+ 'gray-600': 'color-gray-600',
12
+ 'gray-500': 'color-gray-500',
13
+ 'gray-400': 'color-gray-400',
14
+ 'red-600': 'color-red-600',
15
+ 'red-500': 'color-red-500',
16
+ 'blue-600': 'color-blue-600',
17
+ 'green-600': 'color-green-600',
18
+ 'green-100': 'color-green-100',
19
+ 'yellow-500': 'text-yellow-500',
20
+ 'orange-500': 'text-orange-500',
21
+ };
22
+
23
+ const colorHex = {
24
+ black: '#111827',
25
+ white: '#ffffff',
26
+ 'gray-900': '#111827',
27
+ 'gray-700': '#374151',
28
+ 'gray-600': '#4b5563',
29
+ 'gray-500': '#6b7280',
30
+ 'gray-400': '#9ca3af',
31
+ 'red-600': '#dc2626',
32
+ 'red-500': '#ef4444',
33
+ 'blue-600': '#2563eb',
34
+ 'green-600': '#16a34a',
35
+ 'green-100': '#dcfce7',
36
+ 'yellow-500': '#f59e0b',
37
+ 'orange-500': '#f97316',
38
+ };
39
+
40
+ const iconSections = {
41
+ header: [
42
+ { name: 'header-bell', component: 'BellIcon' },
43
+ { name: 'header-dropdown', component: 'ChevronDownIcon' },
44
+ ],
45
+ subheader: [
46
+ { name: 'subheader-calendar', component: 'CalendarDaysIcon' },
47
+ { name: 'subheader-chevron-right', component: 'ChevronRightIcon' },
48
+ { name: 'subheader-swap', component: 'ArrowsRightLeftIcon' },
49
+ { name: 'subheader-refresh', component: 'ArrowPathIcon' },
50
+ { name: 'subheader-settings', component: 'AdjustmentsHorizontalIcon' },
51
+ ],
52
+ 'sidebar-core': [
53
+ { name: 'sidebar-core-collapse', component: 'ChevronDoubleLeftIcon' },
54
+ { name: 'sidebar-core-dashboard', component: 'Squares2X2Icon' },
55
+ { name: 'sidebar-core-directory', component: 'UserGroupIcon' },
56
+ { name: 'sidebar-core-inbox', component: 'InboxStackIcon' },
57
+ { name: 'sidebar-core-favorites', component: 'HeartIcon' },
58
+ { name: 'sidebar-core-announcements', component: 'MegaphoneIcon' },
59
+ { name: 'sidebar-core-files', component: 'DocumentTextIcon' },
60
+ { name: 'sidebar-core-tasks', component: 'ClipboardDocumentCheckIcon' },
61
+ { name: 'sidebar-core-reports', component: 'ChartBarSquareIcon' },
62
+ { name: 'sidebar-core-team', component: 'UsersIcon' },
63
+ { name: 'sidebar-core-support', component: 'LifebuoyIcon' },
64
+ { name: 'sidebar-core-sync', component: 'ArrowPathIcon' },
65
+ { name: 'sidebar-core-settings', component: 'Cog8ToothIcon' },
66
+ { name: 'sidebar-core-security', component: 'ShieldCheckIcon' },
67
+ { name: 'sidebar-core-analytics', component: 'ChartBarIcon' },
68
+ { name: 'sidebar-core-terminal', component: 'CommandLineIcon' },
69
+ { name: 'sidebar-core-expand', component: 'ChevronDoubleRightIcon' },
70
+ { name: 'sidebar-core-gear', component: 'Cog6ToothIcon' },
71
+ ],
72
+ 'sidebar-point': [
73
+ { name: 'sidebar-point-collapse', component: 'ChevronDoubleLeftIcon' },
74
+ { name: 'sidebar-point-dashboard', component: 'SquaresPlusIcon' },
75
+ { name: 'sidebar-point-up', component: 'ChevronUpIcon' },
76
+ { name: 'sidebar-point-messages', component: 'ChatBubbleLeftRightIcon' },
77
+ { name: 'sidebar-point-docs', component: 'DocumentDuplicateIcon' },
78
+ ],
79
+ modules: [
80
+ { name: 'modules-progress', component: 'ArrowPathRoundedSquareIcon' },
81
+ { name: 'modules-success', component: 'CheckCircleIcon' },
82
+ { name: 'modules-info', component: 'InformationCircleIcon' },
83
+ { name: 'modules-time', component: 'ClockIcon' },
84
+ ],
85
+ nuevos: [{ name: 'nuevos-eye', component: 'EyeIcon' }],
86
+ };
87
+
88
+ const curatedIcons = Object.values(iconSections)
89
+ .flat()
90
+ .reduce((acc, item) => {
91
+ acc[item.name] = item.component;
92
+ return acc;
93
+ }, {});
94
+
95
+ const curatedIconNames = Object.keys(curatedIcons);
96
+ const iconLibraries = [
97
+ { key: '24-outline', weight: 24, style: 'outline', lib: Outline24, defaultSize: 24 },
98
+ { key: '24-solid', weight: 24, style: 'solid', lib: Solid24, defaultSize: 24 },
99
+ { key: '20-solid', weight: 20, style: 'solid', lib: Solid20, defaultSize: 20 },
100
+ { key: '16-solid', weight: 16, style: 'solid', lib: Solid16, defaultSize: 16 },
101
+ ];
102
+ const heroiconComponentNames = Array.from(
103
+ new Set(iconLibraries.flatMap(({ lib }) => Object.keys(lib)))
104
+ ).sort();
105
+ const VARIANT_KEYS = iconLibraries.map(({ key }) => key);
106
+
107
+ const statusPalette = [
108
+ { key: 'critical', fill: '#EF4444', subtle: '#FEE2E2' },
109
+ { key: 'high', fill: '#F97316', subtle: '#FFEDD5' },
110
+ { key: 'medium', fill: '#FACC15', subtle: '#FEF9C3' },
111
+ { key: 'low', fill: '#22C55E', subtle: '#DCFCE7' },
112
+ { key: 'info', fill: '#2563EB', subtle: '#DBEAFE' },
113
+ { key: 'neutral', fill: '#94A3B8', subtle: '#E2E8F0' },
114
+ ];
115
+
116
+ const statusIndicators = statusPalette.flatMap((status) => {
117
+ const base = [
118
+ {
119
+ id: `status-${status.key}`,
120
+ shape: 'circle',
121
+ fill: status.fill,
122
+ stroke: status.fill,
123
+ variant: 'solid',
124
+ group: 'circle',
125
+ tone: status.key,
126
+ },
127
+ {
128
+ id: `status-${status.key}-outline`,
129
+ shape: 'circle',
130
+ fill: status.subtle,
131
+ stroke: status.fill,
132
+ variant: 'outline',
133
+ group: 'circle',
134
+ tone: status.key,
135
+ },
136
+ {
137
+ id: `status-${status.key}-triangle`,
138
+ shape: 'triangle',
139
+ fill: status.fill,
140
+ stroke: status.fill,
141
+ variant: 'solid',
142
+ group: 'triangle',
143
+ tone: status.key,
144
+ },
145
+ {
146
+ id: `status-${status.key}-triangle-outline`,
147
+ shape: 'triangle',
148
+ fill: status.subtle,
149
+ stroke: status.fill,
150
+ variant: 'outline',
151
+ group: 'triangle',
152
+ tone: status.key,
153
+ },
154
+ {
155
+ id: `status-${status.key}-square`,
156
+ shape: 'square',
157
+ fill: status.fill,
158
+ stroke: status.fill,
159
+ variant: 'solid',
160
+ group: 'square',
161
+ tone: status.key,
162
+ },
163
+ {
164
+ id: `status-${status.key}-square-outline`,
165
+ shape: 'square',
166
+ fill: status.subtle,
167
+ stroke: status.fill,
168
+ variant: 'outline',
169
+ group: 'square',
170
+ tone: status.key,
171
+ },
172
+ ];
173
+
174
+ return base;
175
+ });
176
+
177
+ const statusIndicatorMap = statusIndicators.reduce((acc, item) => {
178
+ acc[item.id] = item;
179
+ return acc;
180
+ }, {});
181
+
182
+ const capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
183
+
184
+ const toPascalIconName = (value) => {
185
+ if (!value) return value;
186
+ const trimmed = value.replace(/icon$/i, '').trim();
187
+ if (!trimmed) return value;
188
+
189
+ const parts = trimmed
190
+ .split(/[\s-_]+/)
191
+ .filter(Boolean)
192
+ .map((part) => capitalize(part.toLowerCase()));
193
+
194
+ if (!parts.length) return value;
195
+ return `${parts.join('')}Icon`;
196
+ };
197
+
198
+ const getHeroiconName = (name) => {
199
+ if (curatedIcons[name]) return curatedIcons[name];
200
+ if (HEROICON_COMPONENT_NAMES.includes(name)) return name;
201
+
202
+ const candidate = toPascalIconName(name);
203
+ return HEROICON_COMPONENT_NAMES.includes(candidate) ? candidate : name;
204
+ };
205
+
206
+ const resolveHexColor = (desiredColor, fallback) => {
207
+ if (!desiredColor) return fallback;
208
+ return colorHex[desiredColor] || desiredColor;
209
+ };
210
+
211
+ const renderStatus = (config, size, className, overrideColor, props) => {
212
+ const viewBox = 24;
213
+ const fillColor = resolveHexColor(overrideColor, config.fill);
214
+ const strokeColor = resolveHexColor(overrideColor, config.stroke || config.fill);
215
+ const strokeWidth = config.variant === 'outline' ? 2 : 0;
216
+
217
+ if (config.shape === 'triangle') {
218
+ return (
219
+ <svg
220
+ width={size}
221
+ height={size}
222
+ viewBox={`0 0 ${viewBox} ${viewBox}`}
223
+ role="img"
224
+ aria-hidden="true"
225
+ className={className}
226
+ {...props}
227
+ >
228
+ <polygon
229
+ points="12,4 22,20 2,20"
230
+ fill={fillColor}
231
+ stroke={strokeWidth ? strokeColor : 'none'}
232
+ strokeWidth={strokeWidth}
233
+ strokeLinejoin="round"
234
+ />
235
+ </svg>
236
+ );
237
+ }
238
+
239
+ if (config.shape === 'diamond') {
240
+ return (
241
+ <svg
242
+ width={size}
243
+ height={size}
244
+ viewBox={`0 0 ${viewBox} ${viewBox}`}
245
+ role="img"
246
+ aria-hidden="true"
247
+ className={className}
248
+ {...props}
249
+ >
250
+ <polygon
251
+ points="12,2 22,12 12,22 2,12"
252
+ fill={fillColor}
253
+ stroke={strokeWidth ? strokeColor : 'none'}
254
+ strokeWidth={strokeWidth}
255
+ strokeLinejoin="round"
256
+ />
257
+ </svg>
258
+ );
259
+ }
260
+
261
+ if (config.shape === 'square') {
262
+ return (
263
+ <svg
264
+ width={size}
265
+ height={size}
266
+ viewBox={`0 0 ${viewBox} ${viewBox}`}
267
+ role="img"
268
+ aria-hidden="true"
269
+ className={className}
270
+ {...props}
271
+ >
272
+ <rect
273
+ x="5"
274
+ y="5"
275
+ width="14"
276
+ height="14"
277
+ rx={4}
278
+ fill={fillColor}
279
+ stroke={strokeWidth ? strokeColor : 'none'}
280
+ strokeWidth={strokeWidth}
281
+ />
282
+ </svg>
283
+ );
284
+ }
285
+
286
+ return (
287
+ <svg
288
+ width={size}
289
+ height={size}
290
+ viewBox={`0 0 ${viewBox} ${viewBox}`}
291
+ role="img"
292
+ aria-hidden="true"
293
+ className={className}
294
+ {...props}
295
+ >
296
+ <circle
297
+ cx="12"
298
+ cy="12"
299
+ r="9"
300
+ fill={fillColor}
301
+ stroke={strokeWidth ? strokeColor : 'none'}
302
+ strokeWidth={strokeWidth}
303
+ />
304
+ </svg>
305
+ );
306
+ };
307
+
308
+ export const ICON_CATALOG = curatedIconNames;
309
+ export const ICON_SECTIONS = iconSections;
310
+ export const STATUS_INDICATORS = statusIndicators;
311
+ export const STATUS_CATALOG = statusIndicators.map(({ id }) => id);
312
+ export const ICON_COLOR_TOKENS = Object.keys(colorClasses);
313
+ export const HEROICON_COMPONENT_NAMES = heroiconComponentNames;
314
+ export const ICON_VARIANTS = VARIANT_KEYS;
315
+
316
+ export const Icon = ({
317
+ name,
318
+ variant = '24-outline',
319
+ size,
320
+ className = '',
321
+ color,
322
+ ...props
323
+ }) => {
324
+ if (!name) {
325
+ return null;
326
+ }
327
+
328
+ const statusConfig = statusIndicatorMap[name];
329
+ if (statusConfig) {
330
+ const statusSize = size ?? 18;
331
+ return renderStatus(statusConfig, statusSize, className, color, props);
332
+ }
333
+
334
+ const iconName = getHeroiconName(name);
335
+ const selectedLibrary = iconLibraries.find(({ key }) => key === variant) || iconLibraries[0];
336
+ const fallbackLibrary = iconLibraries.find(
337
+ ({ weight, style }) =>
338
+ weight === selectedLibrary.weight && style !== selectedLibrary.style
339
+ );
340
+ const IconComponent =
341
+ selectedLibrary.lib[iconName] ||
342
+ (fallbackLibrary ? fallbackLibrary.lib[iconName] : null) ||
343
+ Outline24[iconName] ||
344
+ Solid24[iconName] ||
345
+ Solid20[iconName] ||
346
+ Solid16[iconName];
347
+
348
+ if (!IconComponent) {
349
+ console.warn(`Icon "${name}" not found in catalog`);
350
+ return null;
351
+ }
352
+
353
+ const colorClass = color && colorClasses[color] ? colorClasses[color] : '';
354
+ const classes = `${colorClass} ${className}`.trim();
355
+
356
+ const finalSize = size ?? selectedLibrary.defaultSize;
357
+
358
+ return <IconComponent className={classes} width={finalSize} height={finalSize} {...props} />;
359
+ };
360
+
361
+ export default Icon;
@@ -0,0 +1,115 @@
1
+ import {
2
+ Icon,
3
+ ICON_CATALOG,
4
+ ICON_SECTIONS,
5
+ STATUS_CATALOG,
6
+ STATUS_INDICATORS,
7
+ ICON_COLOR_TOKENS,
8
+ HEROICON_COMPONENT_NAMES,
9
+ ICON_VARIANTS,
10
+ } from './Icon';
11
+
12
+ export default {
13
+ title: 'Atoms/Icon',
14
+ component: Icon,
15
+ tags: ['autodocs'],
16
+ argTypes: {
17
+ name: {
18
+ control: 'select',
19
+ options: [...ICON_CATALOG, ...STATUS_CATALOG],
20
+ },
21
+ variant: {
22
+ control: 'select',
23
+ options: ICON_VARIANTS,
24
+ },
25
+ color: {
26
+ control: 'select',
27
+ options: ICON_COLOR_TOKENS,
28
+ },
29
+ size: {
30
+ control: { type: 'number', min: 12, max: 64, step: 4 },
31
+ },
32
+ },
33
+ };
34
+
35
+ export const Playground = {
36
+ args: {
37
+ name: 'home',
38
+ variant: '24-outline',
39
+ color: 'gray-600',
40
+ size: 32,
41
+ className: '',
42
+ },
43
+ };
44
+
45
+ export const IconGallery = {
46
+ render: () => (
47
+ <div className="space-y-10">
48
+ {Object.entries(ICON_SECTIONS).map(([section, icons]) => (
49
+ <div key={section}>
50
+ <p className="text-body-md font-semibold uppercase tracking-wide text-gray-500 mb-4">
51
+ {section.replace('-', ' ')}
52
+ </p>
53
+ <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
54
+ {icons.map(({ name }) => (
55
+ <div
56
+ key={name}
57
+ className="flex flex-col items-center gap-2 rounded-lg border border-gray-100 bg-white p-4 shadow-sm"
58
+ >
59
+ <Icon name={name} size={32} className="text-gray-800" />
60
+ <code className="text-xs font-medium text-gray-600">{name}</code>
61
+ </div>
62
+ ))}
63
+ </div>
64
+ </div>
65
+ ))}
66
+ </div>
67
+ ),
68
+ };
69
+
70
+ export const StatusIndicators = {
71
+ render: () => {
72
+ const grouped = STATUS_INDICATORS.reduce((acc, item) => {
73
+ acc[item.group] = acc[item.group] || [];
74
+ acc[item.group].push(item);
75
+ return acc;
76
+ }, {});
77
+
78
+ return (
79
+ <div className="space-y-8">
80
+ {Object.entries(grouped).map(([group, items]) => (
81
+ <div key={group}>
82
+ <p className="text-body-md font-medium capitalize text-gray-700 mb-3">{group}</p>
83
+ <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-4">
84
+ {items.map((indicator) => (
85
+ <div
86
+ key={indicator.id}
87
+ className="flex flex-col items-center gap-2 rounded-lg border border-gray-100 bg-white p-3 text-center shadow-sm"
88
+ >
89
+ <Icon name={indicator.id} size={18} />
90
+ <code className="text-[11px] text-gray-600 leading-tight">{indicator.id}</code>
91
+ </div>
92
+ ))}
93
+ </div>
94
+ </div>
95
+ ))}
96
+ </div>
97
+ );
98
+ },
99
+ };
100
+
101
+ export const HeroiconsFullCatalog = {
102
+ render: () => (
103
+ <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
104
+ {HEROICON_COMPONENT_NAMES.map((iconName) => (
105
+ <div
106
+ key={iconName}
107
+ className="flex flex-col items-center gap-2 rounded-lg border border-gray-100 bg-white p-4 shadow-sm"
108
+ >
109
+ <Icon name={iconName} size={28} className="text-gray-800" />
110
+ <code className="text-[11px] font-medium text-gray-600">{iconName}</code>
111
+ </div>
112
+ ))}
113
+ </div>
114
+ ),
115
+ };
@@ -0,0 +1,22 @@
1
+ export const Label = ({
2
+ children,
3
+ htmlFor,
4
+ required = false,
5
+ className = '',
6
+ ...props
7
+ }) => {
8
+ const baseClasses = 'block mb-1 font-medium text-sm leading-[21px] tracking-[0.14px] text-[#29474C]';
9
+
10
+ const classes = `${baseClasses} ${className}`;
11
+
12
+ return (
13
+ <label htmlFor={htmlFor} className={classes} {...props}>
14
+ {children}
15
+ {required && <span className="text-red-500 ml-1">*</span>}
16
+ </label>
17
+ );
18
+ };
19
+
20
+ export default Label;
21
+
22
+
@@ -0,0 +1,49 @@
1
+ export const Progress = ({
2
+ value = 0,
3
+ max = 100,
4
+ size = 'medium',
5
+ variant = 'primary',
6
+ showLabel = false,
7
+ label,
8
+ className = '',
9
+ ...props
10
+ }) => {
11
+ const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
12
+
13
+ const sizeClasses = {
14
+ small: 'h-1',
15
+ medium: 'h-2',
16
+ large: 'h-3',
17
+ };
18
+
19
+ const variantClasses = {
20
+ primary: 'bg-blue-600',
21
+ success: 'bg-green-600',
22
+ warning: 'bg-yellow-600',
23
+ danger: 'bg-red-600',
24
+ };
25
+
26
+ return (
27
+ <div className={`w-full ${className}`} {...props}>
28
+ {showLabel && (
29
+ <div className="flex justify-between items-center mb-1">
30
+ <span className="text-sm text-gray-700">
31
+ {label || `${Math.round(percentage)}%`}
32
+ </span>
33
+ <span className="text-sm text-gray-500">
34
+ {value} / {max}
35
+ </span>
36
+ </div>
37
+ )}
38
+ <div className={`w-full bg-gray-200 rounded-full overflow-hidden ${sizeClasses[size]}`}>
39
+ <div
40
+ className={`${variantClasses[variant]} transition-all duration-300 ease-out ${sizeClasses[size]}`}
41
+ style={{ width: `${percentage}%` }}
42
+ />
43
+ </div>
44
+ </div>
45
+ );
46
+ };
47
+
48
+ export default Progress;
49
+
@@ -0,0 +1,88 @@
1
+ import { Progress } from './Progress';
2
+
3
+ export default {
4
+ title: 'Atoms/Progress',
5
+ component: Progress,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ size: {
9
+ control: 'select',
10
+ options: ['small', 'medium', 'large'],
11
+ },
12
+ variant: {
13
+ control: 'select',
14
+ options: ['primary', 'success', 'warning', 'danger'],
15
+ },
16
+ },
17
+ };
18
+
19
+ export const Default = {
20
+ args: {
21
+ value: 50,
22
+ max: 100,
23
+ },
24
+ };
25
+
26
+ export const WithLabel = {
27
+ args: {
28
+ value: 75,
29
+ max: 100,
30
+ showLabel: true,
31
+ },
32
+ };
33
+
34
+ export const CustomLabel = {
35
+ args: {
36
+ value: 60,
37
+ max: 100,
38
+ showLabel: true,
39
+ label: 'Progreso',
40
+ },
41
+ };
42
+
43
+ export const Small = {
44
+ args: {
45
+ value: 40,
46
+ size: 'small',
47
+ },
48
+ };
49
+
50
+ export const Large = {
51
+ args: {
52
+ value: 80,
53
+ size: 'large',
54
+ },
55
+ };
56
+
57
+ export const Success = {
58
+ args: {
59
+ value: 90,
60
+ variant: 'success',
61
+ showLabel: true,
62
+ },
63
+ };
64
+
65
+ export const Warning = {
66
+ args: {
67
+ value: 50,
68
+ variant: 'warning',
69
+ showLabel: true,
70
+ },
71
+ };
72
+
73
+ export const Danger = {
74
+ args: {
75
+ value: 25,
76
+ variant: 'danger',
77
+ showLabel: true,
78
+ },
79
+ };
80
+
81
+ export const Complete = {
82
+ args: {
83
+ value: 100,
84
+ variant: 'success',
85
+ showLabel: true,
86
+ },
87
+ };
88
+
@@ -0,0 +1,39 @@
1
+ const SCALE = [
2
+ { key: '4', px: '4px', rem: '0.25rem' },
3
+ { key: '8', px: '8px', rem: '0.5rem' },
4
+ { key: '12', px: '12px', rem: '0.75rem' },
5
+ { key: '16', px: '16px', rem: '1rem' },
6
+ { key: '24', px: '24px', rem: '1.5rem' },
7
+ { key: '32', px: '32px', rem: '2rem' },
8
+ ];
9
+
10
+ const scaleMap = SCALE.reduce((acc, token) => {
11
+ acc[token.key] = token;
12
+ acc[`radius-${token.key}`] = token;
13
+ return acc;
14
+ }, {});
15
+
16
+ export const RADIOS_SCALE = SCALE;
17
+
18
+ export const Radios = ({
19
+ size = '16',
20
+ as: Component = 'div',
21
+ className = '',
22
+ style = {},
23
+ ...props
24
+ }) => {
25
+ const normalized = typeof size === 'number' ? String(size) : size;
26
+ const token = scaleMap[normalized] || scaleMap['16'];
27
+ const cssVar = `var(--radius-${token.key})`;
28
+
29
+ return (
30
+ <Component
31
+ className={className}
32
+ style={{ borderRadius: cssVar, ...style }}
33
+ {...props}
34
+ />
35
+ );
36
+ };
37
+
38
+ export default Radios;
39
+