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,60 @@
1
+ import { BarChart } from './BarChart';
2
+
3
+ const sampleSeries = [
4
+ {
5
+ name: 'Producto A',
6
+ data: [44, 55, 41, 67, 22, 43],
7
+ },
8
+ {
9
+ name: 'Producto B',
10
+ data: [13, 23, 20, 8, 13, 27],
11
+ },
12
+ ];
13
+
14
+ const sampleCategories = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun'];
15
+
16
+ export default {
17
+ title: 'DataDisplay/BarChart',
18
+ component: BarChart,
19
+ tags: ['autodocs'],
20
+ };
21
+
22
+ export const Default = {
23
+ args: {
24
+ series: sampleSeries,
25
+ categories: sampleCategories,
26
+ title: 'Gráfico de Barras',
27
+ },
28
+ };
29
+
30
+ export const Horizontal = {
31
+ args: {
32
+ series: sampleSeries,
33
+ categories: sampleCategories,
34
+ title: 'Gráfico de Barras Horizontal',
35
+ horizontal: true,
36
+ },
37
+ };
38
+
39
+ export const SingleSeries = {
40
+ args: {
41
+ series: [
42
+ {
43
+ name: 'Ventas',
44
+ data: [400, 430, 448, 470, 540, 580],
45
+ },
46
+ ],
47
+ categories: ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
48
+ title: 'Ventas Semanales',
49
+ },
50
+ };
51
+
52
+ export const CustomColors = {
53
+ args: {
54
+ series: sampleSeries,
55
+ categories: sampleCategories,
56
+ title: 'Gráfico con Colores Personalizados',
57
+ colors: ['#EF4444', '#10B981'],
58
+ },
59
+ };
60
+
@@ -0,0 +1,31 @@
1
+ export const Card = ({
2
+ title,
3
+ children,
4
+ footer,
5
+ className = '',
6
+ headerClassName = '',
7
+ bodyClassName = '',
8
+ footerClassName = '',
9
+ ...props
10
+ }) => {
11
+ return (
12
+ <div className={`bg-white rounded-lg shadow-md border border-gray-200 ${className}`} {...props}>
13
+ {title && (
14
+ <div className={`px-6 py-4 border-b border-gray-200 ${headerClassName}`}>
15
+ <h3 className="text-lg font-semibold text-gray-900">{title}</h3>
16
+ </div>
17
+ )}
18
+ <div className={`px-6 py-4 ${bodyClassName}`}>
19
+ {children}
20
+ </div>
21
+ {footer && (
22
+ <div className={`px-6 py-4 border-t border-gray-200 bg-gray-50 ${footerClassName}`}>
23
+ {footer}
24
+ </div>
25
+ )}
26
+ </div>
27
+ );
28
+ };
29
+
30
+ export default Card;
31
+
@@ -0,0 +1,50 @@
1
+ import { Card } from './Card';
2
+ import { Button } from '../../Atoms/Button/Button';
3
+
4
+ export default {
5
+ title: 'DataDisplay/Card',
6
+ component: Card,
7
+ tags: ['autodocs'],
8
+ };
9
+
10
+ export const Default = {
11
+ args: {
12
+ title: 'Card Title',
13
+ children: 'This is the card content. It can contain any React elements.',
14
+ },
15
+ };
16
+
17
+ export const WithFooter = {
18
+ args: {
19
+ title: 'Card with Footer',
20
+ children: 'This card has a footer section.',
21
+ footer: (
22
+ <div className="flex justify-end">
23
+ <Button size="small">Action</Button>
24
+ </div>
25
+ ),
26
+ },
27
+ };
28
+
29
+ export const WithoutTitle = {
30
+ args: {
31
+ children: 'This card does not have a title.',
32
+ },
33
+ };
34
+
35
+ export const ComplexContent = {
36
+ args: {
37
+ title: 'Complex Card',
38
+ children: (
39
+ <div>
40
+ <p className="mb-4">This card contains more complex content.</p>
41
+ <ul className="list-disc list-inside space-y-2">
42
+ <li>Item 1</li>
43
+ <li>Item 2</li>
44
+ <li>Item 3</li>
45
+ </ul>
46
+ </div>
47
+ ),
48
+ },
49
+ };
50
+
@@ -0,0 +1,92 @@
1
+ import { useMemo } from 'react';
2
+ import Chart from 'react-apexcharts';
3
+
4
+ export const ColumnChart = ({
5
+ series = [],
6
+ categories = [],
7
+ title = '',
8
+ height = 350,
9
+ colors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6'],
10
+ showLegend = true,
11
+ showToolbar = true,
12
+ className = '',
13
+ ...props
14
+ }) => {
15
+ const chartOptions = useMemo(() => ({
16
+ chart: {
17
+ type: 'column',
18
+ height: height,
19
+ toolbar: {
20
+ show: showToolbar,
21
+ tools: {
22
+ download: true,
23
+ selection: true,
24
+ zoom: true,
25
+ zoomin: true,
26
+ zoomout: true,
27
+ pan: true,
28
+ reset: true,
29
+ },
30
+ },
31
+ },
32
+ colors: colors,
33
+ plotOptions: {
34
+ bar: {
35
+ horizontal: false,
36
+ borderRadius: 4,
37
+ columnWidth: '55%',
38
+ dataLabels: {
39
+ position: 'top',
40
+ },
41
+ },
42
+ },
43
+ xaxis: {
44
+ categories: categories,
45
+ labels: {
46
+ style: {
47
+ colors: '#6B7280',
48
+ },
49
+ },
50
+ },
51
+ yaxis: {
52
+ labels: {
53
+ style: {
54
+ colors: '#6B7280',
55
+ },
56
+ },
57
+ },
58
+ legend: {
59
+ show: showLegend,
60
+ position: 'top',
61
+ horizontalAlign: 'center',
62
+ },
63
+ grid: {
64
+ borderColor: '#E5E7EB',
65
+ strokeDashArray: 4,
66
+ },
67
+ tooltip: {
68
+ theme: 'light',
69
+ },
70
+ dataLabels: {
71
+ enabled: false,
72
+ },
73
+ }), [categories, colors, height, showLegend, showToolbar]);
74
+
75
+ return (
76
+ <div className={className}>
77
+ {title && (
78
+ <h3 className="text-lg font-semibold text-gray-900 mb-4">{title}</h3>
79
+ )}
80
+ <Chart
81
+ options={chartOptions}
82
+ series={series}
83
+ type="bar"
84
+ height={height}
85
+ {...props}
86
+ />
87
+ </div>
88
+ );
89
+ };
90
+
91
+ export default ColumnChart;
92
+
@@ -0,0 +1,65 @@
1
+ import { ColumnChart } from './ColumnChart';
2
+
3
+ const sampleSeries = [
4
+ {
5
+ name: 'Ventas',
6
+ data: [44, 55, 41, 67, 22, 43, 21],
7
+ },
8
+ {
9
+ name: 'Gastos',
10
+ data: [13, 23, 20, 8, 13, 27, 33],
11
+ },
12
+ ];
13
+
14
+ const sampleCategories = ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
15
+
16
+ export default {
17
+ title: 'DataDisplay/ColumnChart',
18
+ component: ColumnChart,
19
+ tags: ['autodocs'],
20
+ };
21
+
22
+ export const Default = {
23
+ args: {
24
+ series: sampleSeries,
25
+ categories: sampleCategories,
26
+ title: 'Gráfico de Columnas',
27
+ },
28
+ };
29
+
30
+ export const SingleSeries = {
31
+ args: {
32
+ series: [
33
+ {
34
+ name: 'Usuarios',
35
+ data: [400, 430, 448, 470, 540, 580, 690],
36
+ },
37
+ ],
38
+ categories: sampleCategories,
39
+ title: 'Usuarios por Día',
40
+ },
41
+ };
42
+
43
+ export const CustomColors = {
44
+ args: {
45
+ series: sampleSeries,
46
+ categories: sampleCategories,
47
+ title: 'Gráfico con Colores Personalizados',
48
+ colors: ['#8B5CF6', '#F59E0B'],
49
+ },
50
+ };
51
+
52
+ export const WithoutLegend = {
53
+ args: {
54
+ series: [
55
+ {
56
+ name: 'Ventas',
57
+ data: [44, 55, 41, 67, 22, 43, 21],
58
+ },
59
+ ],
60
+ categories: sampleCategories,
61
+ title: 'Sin Leyenda',
62
+ showLegend: false,
63
+ },
64
+ };
65
+
@@ -0,0 +1,138 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { DataGrid } from '@mui/x-data-grid';
3
+ import { Box } from '@mui/material';
4
+
5
+ // Localización en español para MUI DataGrid
6
+ const dataGridLocaleTextES = {
7
+ // Paginación
8
+ MuiTablePagination: {
9
+ labelRowsPerPage: 'Filas por página',
10
+ labelDisplayedRows: ({ from, to, count }) =>
11
+ `${from}–${to} de ${count !== -1 ? count : `más de ${to}`}`,
12
+ },
13
+ // Toolbar
14
+ toolbarDensity: 'Densidad',
15
+ toolbarDensityLabel: 'Densidad',
16
+ toolbarDensityCompact: 'Compacta',
17
+ toolbarDensityStandard: 'Estándar',
18
+ toolbarDensityComfortable: 'Cómoda',
19
+ toolbarFilters: 'Filtros',
20
+ toolbarFiltersLabel: 'Mostrar filtros',
21
+ toolbarFiltersTooltipHide: 'Ocultar filtros',
22
+ toolbarFiltersTooltipShow: 'Mostrar filtros',
23
+ toolbarExport: 'Exportar',
24
+ toolbarExportLabel: 'Exportar',
25
+ toolbarExportCSV: 'Descargar como CSV',
26
+ toolbarExportPrint: 'Imprimir',
27
+ toolbarColumns: 'Columnas',
28
+ toolbarColumnsLabel: 'Seleccionar columnas',
29
+ // Filtros
30
+ filterPanelAddFilter: 'Agregar filtro',
31
+ filterPanelDeleteIconLabel: 'Eliminar',
32
+ filterPanelOperators: 'Operadores',
33
+ filterPanelOperatorAnd: 'Y',
34
+ filterPanelOperatorOr: 'O',
35
+ filterPanelColumns: 'Columnas',
36
+ filterPanelInputLabel: 'Valor',
37
+ filterPanelInputPlaceholder: 'Valor del filtro',
38
+ filterPanelInputPlaceholderOperator: 'Operador',
39
+ // Sin datos
40
+ noRowsLabel: 'No hay datos disponibles',
41
+ noResultsOverlayLabel: 'No se encontraron resultados',
42
+ // Errores
43
+ errorOverlayDefaultLabel: 'Ocurrió un error',
44
+ // Cargando
45
+ loadingOverlayLabel: 'Cargando...',
46
+ // Footer
47
+ footerRowSelected: (count) =>
48
+ count !== 1
49
+ ? `${count} filas seleccionadas`
50
+ : `${count} fila seleccionada`,
51
+ };
52
+
53
+ export const DBGrid = ({
54
+ columns = [],
55
+ rows = [],
56
+ loading = false,
57
+ emptyMessage,
58
+ pageSize = 10,
59
+ pageSizeOptions = [5, 10, 25, 50],
60
+ className = '',
61
+ ...props
62
+ }) => {
63
+ const { t } = useTranslation();
64
+
65
+ // Traducir las columnas si tienen traducciones
66
+ const translatedColumns = columns.map((col) => {
67
+ const translatedLabel = col.translationKey
68
+ ? t(col.translationKey)
69
+ : col.label || col.headerName;
70
+
71
+ return {
72
+ ...col,
73
+ headerName: translatedLabel,
74
+ label: translatedLabel,
75
+ };
76
+ });
77
+
78
+ // Si no hay columnas, usar columnas por defecto traducidas
79
+ const defaultColumns = [
80
+ {
81
+ field: 'id',
82
+ headerName: t('table.id'),
83
+ width: 90,
84
+ translationKey: 'table.id',
85
+ },
86
+ {
87
+ field: 'name',
88
+ headerName: t('table.name'),
89
+ width: 200,
90
+ translationKey: 'table.name',
91
+ },
92
+ {
93
+ field: 'email',
94
+ headerName: t('table.email'),
95
+ width: 250,
96
+ translationKey: 'table.email',
97
+ },
98
+ {
99
+ field: 'role',
100
+ headerName: t('table.role'),
101
+ width: 150,
102
+ translationKey: 'table.role',
103
+ },
104
+ ];
105
+
106
+ const finalColumns = translatedColumns.length > 0 ? translatedColumns : defaultColumns;
107
+
108
+ // Usar la localización en español (dataGridLocaleTextES)
109
+ // y personalizar solo los mensajes que necesitamos
110
+ const localeText = {
111
+ ...dataGridLocaleTextES,
112
+ // Personalizar mensaje de sin datos si se proporciona
113
+ ...(emptyMessage && { noRowsLabel: emptyMessage }),
114
+ };
115
+
116
+ return (
117
+ <Box className={className} sx={{ height: 400, width: '100%' }}>
118
+ <DataGrid
119
+ rows={rows}
120
+ columns={finalColumns}
121
+ loading={loading}
122
+ pageSizeOptions={pageSizeOptions}
123
+ initialState={{
124
+ pagination: {
125
+ paginationModel: {
126
+ pageSize: pageSize,
127
+ },
128
+ },
129
+ }}
130
+ localeText={localeText}
131
+ disableRowSelectionOnClick
132
+ {...props}
133
+ />
134
+ </Box>
135
+ );
136
+ };
137
+
138
+ export default DBGrid;
@@ -0,0 +1,126 @@
1
+ import { DBGrid } from './DBGrid';
2
+ import { I18nProvider } from '../../../providers/I18nProvider';
3
+ import { Button } from '../../Atoms/Button/Button';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ const SampleColumnsWithTranslation = () => {
7
+ const { t } = useTranslation();
8
+ return [
9
+ {
10
+ field: 'id',
11
+ headerName: t('table.id'),
12
+ width: 90,
13
+ translationKey: 'table.id',
14
+ },
15
+ {
16
+ field: 'name',
17
+ headerName: t('table.name'),
18
+ width: 200,
19
+ translationKey: 'table.name',
20
+ },
21
+ {
22
+ field: 'email',
23
+ headerName: t('table.email'),
24
+ width: 250,
25
+ translationKey: 'table.email',
26
+ },
27
+ {
28
+ field: 'role',
29
+ headerName: t('table.role'),
30
+ width: 150,
31
+ translationKey: 'table.role',
32
+ },
33
+ {
34
+ field: 'actions',
35
+ headerName: t('table.actions'),
36
+ width: 200,
37
+ translationKey: 'table.actions',
38
+ renderCell: (params) => (
39
+ <div className="flex space-x-2">
40
+ <Button size="small" variant="outline">{t('table.edit')}</Button>
41
+ <Button size="small" variant="danger">{t('table.delete')}</Button>
42
+ </div>
43
+ ),
44
+ },
45
+ ];
46
+ };
47
+
48
+ const GridWithColumns = ({ rows, loading, emptyMessage }) => {
49
+ const columns = SampleColumnsWithTranslation();
50
+ return (
51
+ <DBGrid
52
+ columns={columns}
53
+ rows={rows}
54
+ loading={loading}
55
+ emptyMessage={emptyMessage}
56
+ />
57
+ );
58
+ };
59
+
60
+ const sampleRows = [
61
+ { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
62
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
63
+ { id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'User' },
64
+ { id: 4, name: 'Alice Williams', email: 'alice@example.com', role: 'Admin' },
65
+ { id: 5, name: 'Charlie Brown', email: 'charlie@example.com', role: 'User' },
66
+ ];
67
+
68
+ export default {
69
+ title: 'DataDisplay/DBGrid',
70
+ component: DBGrid,
71
+ tags: ['autodocs'],
72
+ decorators: [
73
+ (Story) => (
74
+ <I18nProvider>
75
+ <Story />
76
+ </I18nProvider>
77
+ ),
78
+ ],
79
+ };
80
+
81
+ export const Default = {
82
+ render: () => (
83
+ <GridWithColumns rows={sampleRows} />
84
+ ),
85
+ };
86
+
87
+ export const Empty = {
88
+ render: () => (
89
+ <GridWithColumns rows={[]} />
90
+ ),
91
+ };
92
+
93
+ export const Loading = {
94
+ render: () => (
95
+ <GridWithColumns rows={[]} loading={true} />
96
+ ),
97
+ };
98
+
99
+ export const WithCustomEmptyMessage = {
100
+ render: () => (
101
+ <GridWithColumns
102
+ rows={[]}
103
+ emptyMessage="No se encontraron registros"
104
+ />
105
+ ),
106
+ };
107
+
108
+ export const WithPagination = {
109
+ render: () => {
110
+ const columns = SampleColumnsWithTranslation();
111
+ const manyRows = Array.from({ length: 50 }, (_, i) => ({
112
+ id: i + 1,
113
+ name: `Usuario ${i + 1}`,
114
+ email: `usuario${i + 1}@example.com`,
115
+ role: i % 2 === 0 ? 'Admin' : 'User',
116
+ }));
117
+ return (
118
+ <DBGrid
119
+ columns={columns}
120
+ rows={manyRows}
121
+ pageSize={10}
122
+ pageSizeOptions={[5, 10, 25, 50]}
123
+ />
124
+ );
125
+ },
126
+ };
@@ -0,0 +1,83 @@
1
+ import { useMemo } from 'react';
2
+ import Chart from 'react-apexcharts';
3
+
4
+ export const DonutChart = ({
5
+ series = [],
6
+ labels = [],
7
+ title = '',
8
+ height = 350,
9
+ colors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#06B6D4'],
10
+ showLegend = true,
11
+ donutSize = '70%',
12
+ className = '',
13
+ ...props
14
+ }) => {
15
+ const chartOptions = useMemo(() => ({
16
+ chart: {
17
+ type: 'donut',
18
+ height: height,
19
+ toolbar: {
20
+ show: false,
21
+ },
22
+ },
23
+ colors: colors,
24
+ labels: labels,
25
+ legend: {
26
+ show: showLegend,
27
+ position: 'bottom',
28
+ },
29
+ dataLabels: {
30
+ enabled: true,
31
+ formatter: (val) => `${val.toFixed(1)}%`,
32
+ },
33
+ tooltip: {
34
+ theme: 'light',
35
+ y: {
36
+ formatter: (val) => `${val}`,
37
+ },
38
+ },
39
+ plotOptions: {
40
+ pie: {
41
+ donut: {
42
+ size: donutSize,
43
+ labels: {
44
+ show: true,
45
+ name: {
46
+ show: true,
47
+ },
48
+ value: {
49
+ show: true,
50
+ formatter: (val) => `${val}`,
51
+ },
52
+ total: {
53
+ show: true,
54
+ label: 'Total',
55
+ formatter: () => {
56
+ const total = series.reduce((sum, val) => sum + val, 0);
57
+ return total.toString();
58
+ },
59
+ },
60
+ },
61
+ },
62
+ },
63
+ },
64
+ }), [labels, colors, height, showLegend, donutSize, series]);
65
+
66
+ return (
67
+ <div className={className}>
68
+ {title && (
69
+ <h3 className="text-lg font-semibold text-gray-900 mb-4">{title}</h3>
70
+ )}
71
+ <Chart
72
+ options={chartOptions}
73
+ series={series}
74
+ type="donut"
75
+ height={height}
76
+ {...props}
77
+ />
78
+ </div>
79
+ );
80
+ };
81
+
82
+ export default DonutChart;
83
+
@@ -0,0 +1,48 @@
1
+ import { DonutChart } from './DonutChart';
2
+
3
+ const sampleData = {
4
+ series: [44, 55, 13, 43, 22],
5
+ labels: ['Producto A', 'Producto B', 'Producto C', 'Producto D', 'Producto E'],
6
+ };
7
+
8
+ export default {
9
+ title: 'DataDisplay/DonutChart',
10
+ component: DonutChart,
11
+ tags: ['autodocs'],
12
+ };
13
+
14
+ export const Default = {
15
+ args: {
16
+ series: sampleData.series,
17
+ labels: sampleData.labels,
18
+ title: 'Gráfico de Dona',
19
+ },
20
+ };
21
+
22
+ export const LargeDonut = {
23
+ args: {
24
+ series: sampleData.series,
25
+ labels: sampleData.labels,
26
+ title: 'Dona Grande',
27
+ donutSize: '80%',
28
+ },
29
+ };
30
+
31
+ export const SmallDonut = {
32
+ args: {
33
+ series: sampleData.series,
34
+ labels: sampleData.labels,
35
+ title: 'Dona Pequeña',
36
+ donutSize: '50%',
37
+ },
38
+ };
39
+
40
+ export const CustomColors = {
41
+ args: {
42
+ series: sampleData.series,
43
+ labels: sampleData.labels,
44
+ title: 'Gráfico con Colores Personalizados',
45
+ colors: ['#EF4444', '#10B981', '#F59E0B', '#8B5CF6', '#EC4899'],
46
+ },
47
+ };
48
+