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.
- package/LICENSE.md +20 -0
- package/README.md +109 -0
- package/dist/anima-ds.cjs.js +1332 -0
- package/dist/anima-ds.esm.js +88297 -0
- package/dist/vite.svg +1 -0
- package/package.json +76 -0
- package/src/assets/charly.png +0 -0
- package/src/components/Atoms/Alert/Alert.jsx +52 -0
- package/src/components/Atoms/Alert/Alert.stories.jsx +62 -0
- package/src/components/Atoms/Avatar/Avatar.jsx +60 -0
- package/src/components/Atoms/Avatar/Avatar.stories.jsx +61 -0
- package/src/components/Atoms/Badge/Badge.jsx +34 -0
- package/src/components/Atoms/Badge/Badge.stories.jsx +55 -0
- package/src/components/Atoms/Button/Button.jsx +281 -0
- package/src/components/Atoms/Button/Button.stories.jsx +365 -0
- package/src/components/Atoms/Divider/Divider.jsx +49 -0
- package/src/components/Atoms/Divider/Divider.stories.jsx +62 -0
- package/src/components/Atoms/Icon/Icon.jsx +361 -0
- package/src/components/Atoms/Icon/Icon.stories.jsx +115 -0
- package/src/components/Atoms/Label/Label.jsx +22 -0
- package/src/components/Atoms/Progress/Progress.jsx +49 -0
- package/src/components/Atoms/Progress/Progress.stories.jsx +88 -0
- package/src/components/Atoms/Radios/Radios.jsx +39 -0
- package/src/components/Atoms/Radios/Radios.stories.jsx +119 -0
- package/src/components/Atoms/Shadow/Shadow.stories.jsx +25 -0
- package/src/components/Atoms/Skeleton/Skeleton.jsx +50 -0
- package/src/components/Atoms/Skeleton/Skeleton.stories.jsx +55 -0
- package/src/components/Atoms/Spacing/Spacing.jsx +56 -0
- package/src/components/Atoms/Spacing/Spacing.stories.jsx +78 -0
- package/src/components/Atoms/Spinner/Spinner.jsx +47 -0
- package/src/components/Atoms/Spinner/Spinner.stories.jsx +56 -0
- package/src/components/Atoms/Toast/Toast.jsx +74 -0
- package/src/components/Atoms/Toast/Toast.stories.jsx +101 -0
- package/src/components/Atoms/Tooltip/Tooltip.jsx +49 -0
- package/src/components/Atoms/Tooltip/Tooltip.stories.jsx +58 -0
- package/src/components/Atoms/Typography/Typography.jsx +52 -0
- package/src/components/Atoms/Typography/Typography.stories.jsx +267 -0
- package/src/components/DataDisplay/AreaChart/AreaChart.jsx +95 -0
- package/src/components/DataDisplay/AreaChart/AreaChart.stories.jsx +51 -0
- package/src/components/DataDisplay/BarChart/BarChart.jsx +90 -0
- package/src/components/DataDisplay/BarChart/BarChart.stories.jsx +60 -0
- package/src/components/DataDisplay/Card/Card.jsx +31 -0
- package/src/components/DataDisplay/Card/Card.stories.jsx +50 -0
- package/src/components/DataDisplay/ColumnChart/ColumnChart.jsx +92 -0
- package/src/components/DataDisplay/ColumnChart/ColumnChart.stories.jsx +65 -0
- package/src/components/DataDisplay/DBGrid/DBGrid.jsx +138 -0
- package/src/components/DataDisplay/DBGrid/DBGrid.stories.jsx +126 -0
- package/src/components/DataDisplay/DonutChart/DonutChart.jsx +83 -0
- package/src/components/DataDisplay/DonutChart/DonutChart.stories.jsx +48 -0
- package/src/components/DataDisplay/EmptyState/EmptyState.jsx +30 -0
- package/src/components/DataDisplay/EmptyState/EmptyState.stories.jsx +42 -0
- package/src/components/DataDisplay/LineChart/LineChart.jsx +86 -0
- package/src/components/DataDisplay/LineChart/LineChart.stories.jsx +67 -0
- package/src/components/DataDisplay/List/List.jsx +30 -0
- package/src/components/DataDisplay/List/List.stories.jsx +59 -0
- package/src/components/DataDisplay/PieChart/PieChart.jsx +64 -0
- package/src/components/DataDisplay/PieChart/PieChart.stories.jsx +47 -0
- package/src/components/DataDisplay/StatCard/StatCard.jsx +55 -0
- package/src/components/DataDisplay/StatCard/StatCard.stories.jsx +59 -0
- package/src/components/DataDisplay/TagList/TagList.jsx +37 -0
- package/src/components/DataDisplay/TagList/TagList.stories.jsx +48 -0
- package/src/components/DataDisplay/Timeline/Timeline.jsx +41 -0
- package/src/components/DataDisplay/Timeline/Timeline.stories.jsx +64 -0
- package/src/components/Inputs/Checkbox/Checkbox.jsx +27 -0
- package/src/components/Inputs/Checkbox/Checkbox.stories.jsx +51 -0
- package/src/components/Inputs/DatePicker/DatePicker.jsx +55 -0
- package/src/components/Inputs/DatePicker/DatePicker.stories.jsx +52 -0
- package/src/components/Inputs/FileUpload/FileUpload.jsx +108 -0
- package/src/components/Inputs/FileUpload/FileUpload.stories.jsx +52 -0
- package/src/components/Inputs/Input/Input.jsx +50 -0
- package/src/components/Inputs/Input/Input.stories.jsx +63 -0
- package/src/components/Inputs/RadioButton/RadioButton.jsx +31 -0
- package/src/components/Inputs/RadioButton/RadioButton.stories.jsx +59 -0
- package/src/components/Inputs/Select/Select.jsx +59 -0
- package/src/components/Inputs/Select/Select.stories.jsx +66 -0
- package/src/components/Inputs/Switch/Switch.jsx +44 -0
- package/src/components/Inputs/Switch/Switch.stories.jsx +51 -0
- package/src/components/Inputs/Textarea/Textarea.jsx +51 -0
- package/src/components/Inputs/Textarea/Textarea.stories.jsx +65 -0
- package/src/components/Layout/Accordion/Accordion.jsx +58 -0
- package/src/components/Layout/Accordion/Accordion.stories.jsx +55 -0
- package/src/components/Layout/Breadcrumbs/Breadcrumbs.jsx +49 -0
- package/src/components/Layout/Breadcrumbs/Breadcrumbs.stories.jsx +44 -0
- package/src/components/Layout/Breakpoint/Breakpoint.jsx +35 -0
- package/src/components/Layout/Breakpoint/Breakpoint.stories.jsx +348 -0
- package/src/components/Layout/Drawer/Drawer.jsx +75 -0
- package/src/components/Layout/Drawer/Drawer.stories.jsx +77 -0
- package/src/components/Layout/Dropdown/Dropdown.jsx +83 -0
- package/src/components/Layout/Dropdown/Dropdown.stories.jsx +53 -0
- package/src/components/Layout/Grid/Grid.jsx +39 -0
- package/src/components/Layout/Grid/Grid.stories.jsx +546 -0
- package/src/components/Layout/Header/Header.jsx +50 -0
- package/src/components/Layout/Header/Header.stories.jsx +36 -0
- package/src/components/Layout/Layout/Layout.jsx +14 -0
- package/src/components/Layout/Layout/Layout.stories.jsx +34 -0
- package/src/components/Layout/Modal/Modal.jsx +78 -0
- package/src/components/Layout/Modal/Modal.stories.jsx +98 -0
- package/src/components/Layout/Pagination/Pagination.jsx +109 -0
- package/src/components/Layout/Pagination/Pagination.stories.jsx +62 -0
- package/src/components/Layout/Sidebar/Sidebar.jsx +57 -0
- package/src/components/Layout/Sidebar/Sidebar.stories.jsx +51 -0
- package/src/components/Layout/Stepper/Stepper.jsx +132 -0
- package/src/components/Layout/Stepper/Stepper.stories.jsx +78 -0
- package/src/components/Layout/Tabs/Tabs.jsx +63 -0
- package/src/components/Layout/Tabs/Tabs.stories.jsx +62 -0
- package/src/components/Views/ChangePasswordForm/ChangePasswordForm.jsx +125 -0
- package/src/components/Views/ChangePasswordForm/ChangePasswordForm.stories.jsx +55 -0
- package/src/components/Views/Chat/Chat.jsx +134 -0
- package/src/components/Views/Chat/Chat.stories.jsx +143 -0
- package/src/components/Views/LoginForm/LoginForm.jsx +98 -0
- package/src/components/Views/LoginForm/LoginForm.stories.jsx +55 -0
- package/src/i18n/config.js +209 -0
- package/src/index.js +60 -0
- package/src/main.jsx +510 -0
- package/src/providers/I18nProvider.jsx +13 -0
- package/src/style.css +721 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Icon } from '../../Atoms/Icon/Icon';
|
|
2
|
+
import { Button } from '../../Atoms/Button/Button';
|
|
3
|
+
|
|
4
|
+
export const EmptyState = ({
|
|
5
|
+
icon = 'DocumentIcon',
|
|
6
|
+
title = 'No hay datos',
|
|
7
|
+
description = 'No se encontraron elementos para mostrar.',
|
|
8
|
+
actionLabel,
|
|
9
|
+
onAction,
|
|
10
|
+
className = '',
|
|
11
|
+
...props
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<div className={`flex flex-col items-center justify-center py-12 px-4 ${className}`} {...props}>
|
|
15
|
+
<div className="mb-4">
|
|
16
|
+
<Icon name={icon} className="h-16 w-16 text-gray-400" />
|
|
17
|
+
</div>
|
|
18
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">{title}</h3>
|
|
19
|
+
<p className="text-sm text-gray-500 text-center max-w-sm mb-4">{description}</p>
|
|
20
|
+
{actionLabel && onAction && (
|
|
21
|
+
<Button variant="primary" onClick={onAction}>
|
|
22
|
+
{actionLabel}
|
|
23
|
+
</Button>
|
|
24
|
+
)}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default EmptyState;
|
|
30
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EmptyState } from './EmptyState';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'DataDisplay/EmptyState',
|
|
5
|
+
component: EmptyState,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const Default = {
|
|
10
|
+
args: {
|
|
11
|
+
title: 'No hay datos',
|
|
12
|
+
description: 'No se encontraron elementos para mostrar.',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const WithAction = {
|
|
17
|
+
args: {
|
|
18
|
+
title: 'Sin resultados',
|
|
19
|
+
description: 'No se encontraron resultados para tu búsqueda.',
|
|
20
|
+
actionLabel: 'Crear nuevo',
|
|
21
|
+
onAction: () => alert('Acción ejecutada'),
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const CustomIcon = {
|
|
26
|
+
args: {
|
|
27
|
+
icon: 'BellIcon',
|
|
28
|
+
title: 'Sin notificaciones',
|
|
29
|
+
description: 'No tienes notificaciones pendientes.',
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const CustomContent = {
|
|
34
|
+
args: {
|
|
35
|
+
icon: 'SearchIcon',
|
|
36
|
+
title: 'Búsqueda sin resultados',
|
|
37
|
+
description: 'Intenta con otros términos de búsqueda.',
|
|
38
|
+
actionLabel: 'Limpiar búsqueda',
|
|
39
|
+
onAction: () => alert('Búsqueda limpiada'),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import Chart from 'react-apexcharts';
|
|
3
|
+
|
|
4
|
+
export const LineChart = ({
|
|
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: 'line',
|
|
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
|
+
stroke: {
|
|
34
|
+
curve: 'smooth',
|
|
35
|
+
width: 2,
|
|
36
|
+
},
|
|
37
|
+
xaxis: {
|
|
38
|
+
categories: categories,
|
|
39
|
+
labels: {
|
|
40
|
+
style: {
|
|
41
|
+
colors: '#6B7280',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
yaxis: {
|
|
46
|
+
labels: {
|
|
47
|
+
style: {
|
|
48
|
+
colors: '#6B7280',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
legend: {
|
|
53
|
+
show: showLegend,
|
|
54
|
+
position: 'top',
|
|
55
|
+
horizontalAlign: 'center',
|
|
56
|
+
},
|
|
57
|
+
grid: {
|
|
58
|
+
borderColor: '#E5E7EB',
|
|
59
|
+
strokeDashArray: 4,
|
|
60
|
+
},
|
|
61
|
+
tooltip: {
|
|
62
|
+
theme: 'light',
|
|
63
|
+
},
|
|
64
|
+
dataLabels: {
|
|
65
|
+
enabled: false,
|
|
66
|
+
},
|
|
67
|
+
}), [categories, colors, height, showLegend, showToolbar]);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div className={className}>
|
|
71
|
+
{title && (
|
|
72
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-4">{title}</h3>
|
|
73
|
+
)}
|
|
74
|
+
<Chart
|
|
75
|
+
options={chartOptions}
|
|
76
|
+
series={series}
|
|
77
|
+
type="line"
|
|
78
|
+
height={height}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default LineChart;
|
|
86
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { LineChart } from './LineChart';
|
|
2
|
+
|
|
3
|
+
const sampleSeries = [
|
|
4
|
+
{
|
|
5
|
+
name: 'Ventas',
|
|
6
|
+
data: [30, 40, 35, 50, 49, 60, 70, 91, 125],
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'Ingresos',
|
|
10
|
+
data: [20, 30, 25, 40, 39, 50, 60, 81, 105],
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const sampleCategories = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep'];
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
title: 'DataDisplay/LineChart',
|
|
18
|
+
component: LineChart,
|
|
19
|
+
tags: ['autodocs'],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const Default = {
|
|
23
|
+
args: {
|
|
24
|
+
series: sampleSeries,
|
|
25
|
+
categories: sampleCategories,
|
|
26
|
+
title: 'Gráfico de Líneas',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const WithoutTitle = {
|
|
31
|
+
args: {
|
|
32
|
+
series: sampleSeries,
|
|
33
|
+
categories: sampleCategories,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const SingleSeries = {
|
|
38
|
+
args: {
|
|
39
|
+
series: [
|
|
40
|
+
{
|
|
41
|
+
name: 'Usuarios',
|
|
42
|
+
data: [100, 120, 140, 160, 180, 200, 220],
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
categories: ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'],
|
|
46
|
+
title: 'Usuarios Activos por Día',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const CustomColors = {
|
|
51
|
+
args: {
|
|
52
|
+
series: sampleSeries,
|
|
53
|
+
categories: sampleCategories,
|
|
54
|
+
title: 'Gráfico con Colores Personalizados',
|
|
55
|
+
colors: ['#EF4444', '#10B981'],
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const WithoutLegend = {
|
|
60
|
+
args: {
|
|
61
|
+
series: sampleSeries,
|
|
62
|
+
categories: sampleCategories,
|
|
63
|
+
title: 'Sin Leyenda',
|
|
64
|
+
showLegend: false,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const List = ({
|
|
2
|
+
items = [],
|
|
3
|
+
variant = 'default',
|
|
4
|
+
className = '',
|
|
5
|
+
...props
|
|
6
|
+
}) => {
|
|
7
|
+
if (items.length === 0) return null;
|
|
8
|
+
|
|
9
|
+
const variantClasses = {
|
|
10
|
+
default: 'divide-y divide-gray-200',
|
|
11
|
+
none: '',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<ul className={`${variantClasses[variant]} ${className}`} {...props}>
|
|
16
|
+
{items.map((item, index) => (
|
|
17
|
+
<li key={index} className="py-3">
|
|
18
|
+
{typeof item === 'string' ? (
|
|
19
|
+
<span className="text-gray-900">{item}</span>
|
|
20
|
+
) : (
|
|
21
|
+
item
|
|
22
|
+
)}
|
|
23
|
+
</li>
|
|
24
|
+
))}
|
|
25
|
+
</ul>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default List;
|
|
30
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { List } from './List';
|
|
2
|
+
import { Avatar } from '../../Atoms/Avatar/Avatar';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'DataDisplay/List',
|
|
6
|
+
component: List,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = {
|
|
11
|
+
args: {
|
|
12
|
+
items: [
|
|
13
|
+
'Elemento 1',
|
|
14
|
+
'Elemento 2',
|
|
15
|
+
'Elemento 3',
|
|
16
|
+
'Elemento 4',
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const WithCustomItems = {
|
|
22
|
+
args: {
|
|
23
|
+
items: [
|
|
24
|
+
<div key="1" className="flex items-center space-x-3">
|
|
25
|
+
<Avatar name="John Doe" size="small" />
|
|
26
|
+
<div>
|
|
27
|
+
<p className="font-medium">John Doe</p>
|
|
28
|
+
<p className="text-sm text-gray-500">john@example.com</p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>,
|
|
31
|
+
<div key="2" className="flex items-center space-x-3">
|
|
32
|
+
<Avatar name="Jane Smith" size="small" />
|
|
33
|
+
<div>
|
|
34
|
+
<p className="font-medium">Jane Smith</p>
|
|
35
|
+
<p className="text-sm text-gray-500">jane@example.com</p>
|
|
36
|
+
</div>
|
|
37
|
+
</div>,
|
|
38
|
+
<div key="3" className="flex items-center space-x-3">
|
|
39
|
+
<Avatar name="Bob Johnson" size="small" />
|
|
40
|
+
<div>
|
|
41
|
+
<p className="font-medium">Bob Johnson</p>
|
|
42
|
+
<p className="text-sm text-gray-500">bob@example.com</p>
|
|
43
|
+
</div>
|
|
44
|
+
</div>,
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const WithoutDividers = {
|
|
50
|
+
args: {
|
|
51
|
+
items: [
|
|
52
|
+
'Elemento 1',
|
|
53
|
+
'Elemento 2',
|
|
54
|
+
'Elemento 3',
|
|
55
|
+
],
|
|
56
|
+
variant: 'none',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import Chart from 'react-apexcharts';
|
|
3
|
+
|
|
4
|
+
export const PieChart = ({
|
|
5
|
+
series = [],
|
|
6
|
+
labels = [],
|
|
7
|
+
title = '',
|
|
8
|
+
height = 350,
|
|
9
|
+
colors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#06B6D4'],
|
|
10
|
+
showLegend = true,
|
|
11
|
+
className = '',
|
|
12
|
+
...props
|
|
13
|
+
}) => {
|
|
14
|
+
const chartOptions = useMemo(() => ({
|
|
15
|
+
chart: {
|
|
16
|
+
type: 'pie',
|
|
17
|
+
height: height,
|
|
18
|
+
toolbar: {
|
|
19
|
+
show: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
colors: colors,
|
|
23
|
+
labels: labels,
|
|
24
|
+
legend: {
|
|
25
|
+
show: showLegend,
|
|
26
|
+
position: 'bottom',
|
|
27
|
+
},
|
|
28
|
+
dataLabels: {
|
|
29
|
+
enabled: true,
|
|
30
|
+
formatter: (val) => `${val.toFixed(1)}%`,
|
|
31
|
+
},
|
|
32
|
+
tooltip: {
|
|
33
|
+
theme: 'light',
|
|
34
|
+
y: {
|
|
35
|
+
formatter: (val) => `${val}`,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
plotOptions: {
|
|
39
|
+
pie: {
|
|
40
|
+
donut: {
|
|
41
|
+
size: '0%',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}), [labels, colors, height, showLegend]);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className={className}>
|
|
49
|
+
{title && (
|
|
50
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-4">{title}</h3>
|
|
51
|
+
)}
|
|
52
|
+
<Chart
|
|
53
|
+
options={chartOptions}
|
|
54
|
+
series={series}
|
|
55
|
+
type="pie"
|
|
56
|
+
height={height}
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default PieChart;
|
|
64
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PieChart } from './PieChart';
|
|
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/PieChart',
|
|
10
|
+
component: PieChart,
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const Default = {
|
|
15
|
+
args: {
|
|
16
|
+
series: sampleData.series,
|
|
17
|
+
labels: sampleData.labels,
|
|
18
|
+
title: 'Gráfico Circular',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const Simple = {
|
|
23
|
+
args: {
|
|
24
|
+
series: [30, 40, 30],
|
|
25
|
+
labels: ['A', 'B', 'C'],
|
|
26
|
+
title: 'Distribución Simple',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const CustomColors = {
|
|
31
|
+
args: {
|
|
32
|
+
series: sampleData.series,
|
|
33
|
+
labels: sampleData.labels,
|
|
34
|
+
title: 'Gráfico con Colores Personalizados',
|
|
35
|
+
colors: ['#EF4444', '#10B981', '#F59E0B', '#8B5CF6', '#EC4899'],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const WithoutLegend = {
|
|
40
|
+
args: {
|
|
41
|
+
series: sampleData.series,
|
|
42
|
+
labels: sampleData.labels,
|
|
43
|
+
title: 'Sin Leyenda',
|
|
44
|
+
showLegend: false,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Icon } from '../../Atoms/Icon/Icon';
|
|
2
|
+
import { Typography } from '../../Atoms/Typography/Typography';
|
|
3
|
+
|
|
4
|
+
export const StatCard = ({
|
|
5
|
+
title,
|
|
6
|
+
value,
|
|
7
|
+
change,
|
|
8
|
+
changeType = 'neutral',
|
|
9
|
+
icon,
|
|
10
|
+
iconColor = 'blue',
|
|
11
|
+
className = '',
|
|
12
|
+
...props
|
|
13
|
+
}) => {
|
|
14
|
+
const iconColorClasses = {
|
|
15
|
+
blue: 'bg-blue-100 text-blue-600',
|
|
16
|
+
green: 'bg-green-100 text-green-600',
|
|
17
|
+
yellow: 'bg-yellow-100 text-yellow-600',
|
|
18
|
+
red: 'bg-red-100 text-red-600',
|
|
19
|
+
purple: 'bg-purple-100 text-purple-600',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const changeTypeClasses = {
|
|
23
|
+
positive: 'text-green-600',
|
|
24
|
+
negative: 'text-red-600',
|
|
25
|
+
neutral: 'text-gray-600',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className={`bg-white rounded-lg shadow-md p-6 ${className}`} {...props}>
|
|
30
|
+
<div className="flex items-center justify-between">
|
|
31
|
+
<div className="flex-1">
|
|
32
|
+
<Typography variant="body2" className="text-gray-600 mb-1">
|
|
33
|
+
{title}
|
|
34
|
+
</Typography>
|
|
35
|
+
<Typography variant="h3" className="text-gray-900 mb-2">
|
|
36
|
+
{value}
|
|
37
|
+
</Typography>
|
|
38
|
+
{change && (
|
|
39
|
+
<div className={`flex items-center text-sm ${changeTypeClasses[changeType]}`}>
|
|
40
|
+
<span>{change}</span>
|
|
41
|
+
</div>
|
|
42
|
+
)}
|
|
43
|
+
</div>
|
|
44
|
+
{icon && (
|
|
45
|
+
<div className={`p-3 rounded-lg ${iconColorClasses[iconColor]}`}>
|
|
46
|
+
<Icon name={icon} className="h-6 w-6" />
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default StatCard;
|
|
55
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { StatCard } from './StatCard';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'DataDisplay/StatCard',
|
|
5
|
+
component: StatCard,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const Default = {
|
|
10
|
+
args: {
|
|
11
|
+
title: 'Total de Ventas',
|
|
12
|
+
value: '$45,231',
|
|
13
|
+
change: '+12.5% desde el mes pasado',
|
|
14
|
+
changeType: 'positive',
|
|
15
|
+
icon: 'ChartBarIcon',
|
|
16
|
+
iconColor: 'blue',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const Negative = {
|
|
21
|
+
args: {
|
|
22
|
+
title: 'Usuarios Activos',
|
|
23
|
+
value: '1,234',
|
|
24
|
+
change: '-5.2% desde la semana pasada',
|
|
25
|
+
changeType: 'negative',
|
|
26
|
+
icon: 'UserIcon',
|
|
27
|
+
iconColor: 'red',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const WithoutIcon = {
|
|
32
|
+
args: {
|
|
33
|
+
title: 'Total de Pedidos',
|
|
34
|
+
value: '567',
|
|
35
|
+
change: '+8.1%',
|
|
36
|
+
changeType: 'positive',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const WithoutChange = {
|
|
41
|
+
args: {
|
|
42
|
+
title: 'Total de Productos',
|
|
43
|
+
value: '1,234',
|
|
44
|
+
icon: 'DocumentIcon',
|
|
45
|
+
iconColor: 'green',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const CustomColors = {
|
|
50
|
+
args: {
|
|
51
|
+
title: 'Ingresos',
|
|
52
|
+
value: '$12,345',
|
|
53
|
+
change: '+20%',
|
|
54
|
+
changeType: 'positive',
|
|
55
|
+
icon: 'ChartBarIcon',
|
|
56
|
+
iconColor: 'purple',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Badge } from '../../Atoms/Badge/Badge';
|
|
2
|
+
|
|
3
|
+
export const TagList = ({
|
|
4
|
+
tags = [],
|
|
5
|
+
onRemove,
|
|
6
|
+
variant = 'default',
|
|
7
|
+
className = '',
|
|
8
|
+
...props
|
|
9
|
+
}) => {
|
|
10
|
+
if (tags.length === 0) return null;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className={`flex flex-wrap gap-2 ${className}`} {...props}>
|
|
14
|
+
{tags.map((tag, index) => {
|
|
15
|
+
const tagLabel = typeof tag === 'string' ? tag : tag.label;
|
|
16
|
+
const tagVariant = typeof tag === 'string' ? variant : tag.variant || variant;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Badge key={index} variant={tagVariant}>
|
|
20
|
+
{tagLabel}
|
|
21
|
+
{onRemove && (
|
|
22
|
+
<button
|
|
23
|
+
onClick={() => onRemove(index)}
|
|
24
|
+
className="ml-2 hover:text-gray-800"
|
|
25
|
+
>
|
|
26
|
+
×
|
|
27
|
+
</button>
|
|
28
|
+
)}
|
|
29
|
+
</Badge>
|
|
30
|
+
);
|
|
31
|
+
})}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default TagList;
|
|
37
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { TagList } from './TagList';
|
|
3
|
+
|
|
4
|
+
const sampleTags = ['React', 'JavaScript', 'TypeScript', 'Tailwind CSS', 'Storybook'];
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'DataDisplay/TagList',
|
|
8
|
+
component: TagList,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const Default = {
|
|
13
|
+
args: {
|
|
14
|
+
tags: sampleTags,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const WithRemove = {
|
|
19
|
+
render: () => {
|
|
20
|
+
const [tags, setTags] = useState(sampleTags);
|
|
21
|
+
return (
|
|
22
|
+
<TagList
|
|
23
|
+
tags={tags}
|
|
24
|
+
onRemove={(index) => {
|
|
25
|
+
setTags(tags.filter((_, i) => i !== index));
|
|
26
|
+
}}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const WithVariants = {
|
|
33
|
+
args: {
|
|
34
|
+
tags: [
|
|
35
|
+
{ label: 'React', variant: 'primary' },
|
|
36
|
+
{ label: 'JavaScript', variant: 'success' },
|
|
37
|
+
{ label: 'TypeScript', variant: 'warning' },
|
|
38
|
+
{ label: 'Tailwind', variant: 'danger' },
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const Empty = {
|
|
44
|
+
args: {
|
|
45
|
+
tags: [],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Icon } from '../../Atoms/Icon/Icon';
|
|
2
|
+
|
|
3
|
+
export const Timeline = ({
|
|
4
|
+
items = [],
|
|
5
|
+
className = '',
|
|
6
|
+
...props
|
|
7
|
+
}) => {
|
|
8
|
+
if (items.length === 0) return null;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div className={className} {...props}>
|
|
12
|
+
<ol className="relative border-l border-gray-200">
|
|
13
|
+
{items.map((item, index) => {
|
|
14
|
+
const isLast = index === items.length - 1;
|
|
15
|
+
return (
|
|
16
|
+
<li key={index} className={`mb-10 ml-6 ${isLast ? 'mb-0' : ''}`}>
|
|
17
|
+
<div className="absolute w-3 h-3 bg-gray-200 rounded-full mt-1.5 -left-1.5 border border-white" />
|
|
18
|
+
<time className="mb-1 text-sm font-normal leading-none text-gray-400">
|
|
19
|
+
{item.date}
|
|
20
|
+
</time>
|
|
21
|
+
<h3 className="text-lg font-semibold text-gray-900">{item.title}</h3>
|
|
22
|
+
{item.description && (
|
|
23
|
+
<p className="mb-4 text-base font-normal text-gray-500">
|
|
24
|
+
{item.description}
|
|
25
|
+
</p>
|
|
26
|
+
)}
|
|
27
|
+
{item.icon && (
|
|
28
|
+
<div className="absolute -left-8 top-0">
|
|
29
|
+
<Icon name={item.icon} className="h-6 w-6 text-gray-400" />
|
|
30
|
+
</div>
|
|
31
|
+
)}
|
|
32
|
+
</li>
|
|
33
|
+
);
|
|
34
|
+
})}
|
|
35
|
+
</ol>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default Timeline;
|
|
41
|
+
|