@soyfri/shared-library 2.0.0-beta.2 → 2.0.0-beta.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.
- package/.dockerignore +8 -0
- package/.github/workflows/publish.yml +107 -0
- package/.prettierrc +3 -0
- package/.storybook/main.ts +19 -0
- package/.storybook/preview.ts +14 -0
- package/.storybook/vitest.setup.ts +9 -0
- package/Dockerfile +37 -0
- package/build.js +102 -0
- package/chromatic.config.json +5 -0
- package/cleanDirectories.js +40 -0
- package/dist/README.md +243 -0
- package/dist/components/Icon/Icon.js +1 -1
- package/dist/components/Table/Table.js +1 -1
- package/dist/index.cjs +24 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -1
- package/dist/mui.d.ts +1 -0
- package/dist/package.json +197 -0
- package/package.json +4 -32
- package/rollup.config.cjs +87 -0
- package/src/components/ActionMenu/ActionMenu.stories.tsx +230 -0
- package/src/components/ActionMenu/ActionMenu.tsx +174 -0
- package/src/components/ActionMenu/index.ts +2 -0
- package/src/components/AppBar/AppBar.stories.tsx +272 -0
- package/src/components/AppBar/AppBar.sx.ts +32 -0
- package/src/components/AppBar/AppBar.tsx +123 -0
- package/src/components/AppBar/AppBarBrand.tsx +120 -0
- package/src/components/AppBar/AppBarContext.ts +25 -0
- package/src/components/AppBar/AppBarMenuToggle.tsx +90 -0
- package/src/components/AppBar/AppBarUserMenu.tsx +217 -0
- package/src/components/AppBar/index.ts +25 -0
- package/src/components/Autocomplete/Autocomplete.definitions.ts +477 -0
- package/src/components/Autocomplete/Autocomplete.helpers.ts +60 -0
- package/src/components/Autocomplete/Autocomplete.stories.tsx +748 -0
- package/src/components/Autocomplete/Autocomplete.sx.ts +30 -0
- package/src/components/Autocomplete/Autocomplete.tsx +361 -0
- package/src/components/Autocomplete/Autocomplete.types.ts +13 -0
- package/src/components/Autocomplete/_parts/AutocompleteChips.tsx +55 -0
- package/src/components/Autocomplete/_parts/AutocompleteLoader.tsx +17 -0
- package/src/components/Autocomplete/_parts/AutocompleteOption.tsx +31 -0
- package/src/components/Autocomplete/index.ts +12 -0
- package/src/components/Avatar/Avatar.definitions.ts +162 -0
- package/src/components/Avatar/Avatar.stories.tsx +258 -0
- package/src/components/Avatar/Avatar.tsx +206 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Button/Button.definition.ts +97 -0
- package/src/components/Button/Button.stories.tsx +285 -0
- package/src/components/Button/Button.tsx +67 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/Card.definition.ts +5 -0
- package/src/components/Card/Card.stories.tsx +221 -0
- package/src/components/Card/Card.sx.ts +104 -0
- package/src/components/Card/Card.tsx +200 -0
- package/src/components/Card/index.ts +9 -0
- package/src/components/Chip/Chip.definitions.ts +167 -0
- package/src/components/Chip/Chip.stories.tsx +265 -0
- package/src/components/Chip/Chip.tsx +61 -0
- package/src/components/Chip/index.ts +1 -0
- package/src/components/Column/Column.tsx +29 -0
- package/src/components/Column/index.ts +1 -0
- package/src/components/DatePicker/DatePicker.definitions.ts +228 -0
- package/src/components/DatePicker/DatePicker.helpers.ts +24 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +309 -0
- package/src/components/DatePicker/DatePicker.sx.ts +33 -0
- package/src/components/DatePicker/DatePicker.tsx +189 -0
- package/src/components/DatePicker/DatePicker.types.ts +10 -0
- package/src/components/DatePicker/index.ts +9 -0
- package/src/components/DateRangePicker/DateRangePicker.definitions.ts +191 -0
- package/src/components/DateRangePicker/DateRangePicker.stories.tsx +252 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +56 -0
- package/src/components/DateRangePicker/index.ts +1 -0
- package/src/components/DateTimePicker/DateTimePicker.definitions.ts +256 -0
- package/src/components/DateTimePicker/DateTimePicker.helpers.ts +38 -0
- package/src/components/DateTimePicker/DateTimePicker.stories.tsx +418 -0
- package/src/components/DateTimePicker/DateTimePicker.sx.ts +30 -0
- package/src/components/DateTimePicker/DateTimePicker.tsx +225 -0
- package/src/components/DateTimePicker/DateTimePicker.types.ts +10 -0
- package/src/components/DateTimePicker/index.ts +9 -0
- package/src/components/Drawer/Drawer.stories.tsx +270 -0
- package/src/components/Drawer/Drawer.sx.ts +106 -0
- package/src/components/Drawer/Drawer.tsx +214 -0
- package/src/components/Drawer/DrawerContext.ts +26 -0
- package/src/components/Drawer/DrawerItem.tsx +110 -0
- package/src/components/Drawer/index.ts +10 -0
- package/src/components/Flyout/Flyout.stories.tsx +282 -0
- package/src/components/Flyout/Flyout.tsx +122 -0
- package/src/components/Flyout/index.ts +1 -0
- package/src/components/Gallery/Gallery.definition.tsx +37 -0
- package/src/components/Gallery/Gallery.stories.tsx +82 -0
- package/src/components/Gallery/Gallery.tsx +118 -0
- package/src/components/Gallery/GalleryLightbox.tsx +170 -0
- package/src/components/Gallery/GalleryMain.tsx +84 -0
- package/src/components/Gallery/GalleryThumbnails.tsx +106 -0
- package/src/components/Gallery/index.ts +1 -0
- package/src/components/Icon/Icon.stories.tsx +121 -0
- package/src/components/Icon/Icon.tsx +175 -0
- package/src/components/Icon/index.ts +2 -0
- package/src/components/Input/Input.definitions.ts +324 -0
- package/src/components/Input/Input.helpers.ts +49 -0
- package/src/components/Input/Input.stories.tsx +499 -0
- package/src/components/Input/Input.sx.ts +42 -0
- package/src/components/Input/Input.tsx +141 -0
- package/src/components/Input/Input.types.ts +10 -0
- package/src/components/Input/index.ts +9 -0
- package/src/components/InputGroup/InputGroup.definitions.ts +158 -0
- package/src/components/InputGroup/InputGroup.stories.tsx +267 -0
- package/src/components/InputGroup/InputGroup.tsx +179 -0
- package/src/components/InputGroup/index.ts +1 -0
- package/src/components/MenuButton/MenuButton.stories.tsx +197 -0
- package/src/components/MenuButton/MenuButton.tsx +100 -0
- package/src/components/MenuButton/index.ts +1 -0
- package/src/components/Modal/Modal.stories.tsx +721 -0
- package/src/components/Modal/Modal.tsx +355 -0
- package/src/components/Modal/ModalBody.tsx +16 -0
- package/src/components/Modal/ModalFooter.tsx +71 -0
- package/src/components/Modal/ModalHeader.tsx +18 -0
- package/src/components/Modal/index.ts +6 -0
- package/src/components/PageLoader/PageLoader.stories.tsx +217 -0
- package/src/components/PageLoader/PageLoader.tsx +96 -0
- package/src/components/PageLoader/index.ts +2 -0
- package/src/components/ScrollTopButton/ScrollTopButton.stories.tsx +158 -0
- package/src/components/ScrollTopButton/ScrollTopButton.tsx +135 -0
- package/src/components/ScrollTopButton/index.ts +8 -0
- package/src/components/ScrollTopButton/scrollToTop.ts +37 -0
- package/src/components/Select/Select.definitions.ts +602 -0
- package/src/components/Select/Select.helpers.ts +71 -0
- package/src/components/Select/Select.stories.tsx +687 -0
- package/src/components/Select/Select.sx.ts +14 -0
- package/src/components/Select/Select.tsx +429 -0
- package/src/components/Select/Select.types.ts +15 -0
- package/src/components/Select/_parts/SelectMenuItem.tsx +40 -0
- package/src/components/Select/_parts/SelectSearchHeader.tsx +51 -0
- package/src/components/Select/_parts/SelectValue.tsx +96 -0
- package/src/components/Select/index.ts +14 -0
- package/src/components/Stat/Stat.stories.tsx +85 -0
- package/src/components/Stat/Stat.tsx +117 -0
- package/src/components/Stat/index.ts +2 -0
- package/src/components/StatusMessage/StatusMessage.stories.tsx +130 -0
- package/src/components/StatusMessage/StatusMessage.tsx +162 -0
- package/src/components/StatusMessage/index.ts +2 -0
- package/src/components/Stepper/Step.tsx +21 -0
- package/src/components/Stepper/Stepper.definition.ts +75 -0
- package/src/components/Stepper/Stepper.stories.tsx +122 -0
- package/src/components/Stepper/Stepper.tsx +75 -0
- package/src/components/Stepper/index.ts +2 -0
- package/src/components/Table/EmptyTable.png +0 -0
- package/src/components/Table/Table.definition.ts +580 -0
- package/src/components/Table/Table.stories.tsx +853 -0
- package/src/components/Table/Table.tsx +495 -0
- package/src/components/Table/data.ts +134 -0
- package/src/components/Table/exportsUtils.ts +195 -0
- package/src/components/Table/index.ts +3 -0
- package/src/components/Table/types.ts +34 -0
- package/src/components/Tabs/Tab.definition.ts +53 -0
- package/src/components/Tabs/Tab.tsx +19 -0
- package/src/components/Tabs/Tabs.stories.tsx +118 -0
- package/src/components/Tabs/Tabs.tsx +99 -0
- package/src/components/Tabs/_tabUtils.tsx +4 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Timeline/Timeline.definition.ts +43 -0
- package/src/components/Timeline/Timeline.stories.tsx +108 -0
- package/src/components/Timeline/Timeline.tsx +49 -0
- package/src/components/Timeline/TimelineItem.tsx +31 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +129 -0
- package/src/components/Tooltip/Tooltip.tsx +58 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/_shared/formField.sx.ts +118 -0
- package/src/components/_shared/resolvePreset.ts +35 -0
- package/src/hooks/ClipBoard/ClipBoard.stories.tsx +168 -0
- package/src/hooks/ClipBoard/ClipBoard.tsx +131 -0
- package/src/hooks/ClipBoard/ClipboardUnifiedDemo.tsx +111 -0
- package/src/hooks/ClipBoard/index.ts +1 -0
- package/src/hooks/Wizard/Wizard.stories.tsx +301 -0
- package/src/hooks/Wizard/WizardContext.tsx +166 -0
- package/src/hooks/Wizard/index.ts +6 -0
- package/src/hooks/Wizard/useWizard.ts +13 -0
- package/src/index.ts +17 -0
- package/src/mui.ts +54 -0
- package/src/styles.css +3 -0
- package/src/theme/componentStyles.ts +47 -0
- package/src/theme/tokens.ts +43 -0
- package/tailwind.config.js +10 -0
- package/tsconfig.json +48 -0
- package/tsup.config.js +41 -0
- package/vite.config.js +132 -0
- package/vitest.config.ts +35 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AlertProps } from '@mui/material/Alert';
|
|
3
|
+
import { ColumnProps } from '../Column/Column'; // Importa ColumnProps y FieldName desde Column.tsx
|
|
4
|
+
|
|
5
|
+
// Define las propiedades comunes para las funciones de exportación
|
|
6
|
+
interface ExportOptions<T> {
|
|
7
|
+
data: T[]; // Los datos a exportar
|
|
8
|
+
columns: React.ReactElement<ColumnProps<T>>[]; // Las definiciones de las columnas
|
|
9
|
+
fileName: string; // El nombre del archivo a descargar
|
|
10
|
+
exportColumns?: string[]; // Nombres de columnas específicas para exportar
|
|
11
|
+
setSnackbarOpen: React.Dispatch<React.SetStateAction<boolean>>; // Setter para abrir/cerrar el Snackbar
|
|
12
|
+
setSnackbarMessage: React.Dispatch<React.SetStateAction<string>>; // Setter para el mensaje del Snackbar
|
|
13
|
+
setSnackbarSeverity: React.Dispatch<React.SetStateAction<AlertProps['severity']>>; // Setter para la severidad del Snackbar
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Función para exportar datos a un archivo CSV.
|
|
18
|
+
* @param options Opciones de exportación, incluyendo datos, columnas, nombre de archivo y setters de Snackbar.
|
|
19
|
+
*/
|
|
20
|
+
export const exportToCSV = <T>(options: ExportOptions<T>) => {
|
|
21
|
+
const { data, columns, fileName, exportColumns, setSnackbarOpen, setSnackbarMessage, setSnackbarSeverity } = options;
|
|
22
|
+
|
|
23
|
+
if (!data || data.length === 0) {
|
|
24
|
+
setSnackbarMessage("No hay datos para exportar a CSV.");
|
|
25
|
+
setSnackbarSeverity('warning');
|
|
26
|
+
setSnackbarOpen(true);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setSnackbarMessage("Exportando datos a CSV...");
|
|
31
|
+
setSnackbarSeverity('info');
|
|
32
|
+
setSnackbarOpen(true);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Filtra las columnas si se especifican columnas para exportar, de lo contrario, usa todas las columnas definidas.
|
|
36
|
+
const columnsToExport = exportColumns
|
|
37
|
+
? columns.filter(col => exportColumns.includes(col.props.name))
|
|
38
|
+
: columns;
|
|
39
|
+
|
|
40
|
+
// Obtiene los encabezados (nombres de las columnas) y los escapa para CSV.
|
|
41
|
+
const headers = columnsToExport.map(col => `"${col.props.name.replace(/"/g, '""')}"`).join(',');
|
|
42
|
+
|
|
43
|
+
// Mapea los datos a filas CSV.
|
|
44
|
+
const csvRows = data.map(row => {
|
|
45
|
+
const values = columnsToExport.map(col => {
|
|
46
|
+
const field = col.props.field;
|
|
47
|
+
let cellValue: any;
|
|
48
|
+
|
|
49
|
+
// Si 'field' es un array, toma el valor del primer campo para la exportación.
|
|
50
|
+
if (Array.isArray(field)) {
|
|
51
|
+
cellValue = (row as any)[field[0]];
|
|
52
|
+
} else {
|
|
53
|
+
cellValue = (row as any)[field];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Convierte a string y maneja comas, comillas dobles y saltos de línea para CSV.
|
|
57
|
+
let formattedValue = String(cellValue || '');
|
|
58
|
+
if (formattedValue.includes(',') || formattedValue.includes('"') || formattedValue.includes('\n')) {
|
|
59
|
+
formattedValue = `"${formattedValue.replace(/"/g, '""')}"`;
|
|
60
|
+
}
|
|
61
|
+
return formattedValue;
|
|
62
|
+
});
|
|
63
|
+
return values.join(',');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const csvContent = [headers, ...csvRows].join('\n'); // Une los encabezados y las filas.
|
|
67
|
+
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
|
68
|
+
const link = document.createElement('a');
|
|
69
|
+
|
|
70
|
+
if (link.download !== undefined) {
|
|
71
|
+
const url = URL.createObjectURL(blob);
|
|
72
|
+
link.setAttribute('href', url);
|
|
73
|
+
link.setAttribute('download', fileName + '.csv');
|
|
74
|
+
link.style.visibility = 'hidden';
|
|
75
|
+
document.body.appendChild(link);
|
|
76
|
+
link.click();
|
|
77
|
+
document.body.removeChild(link);
|
|
78
|
+
URL.revokeObjectURL(url);
|
|
79
|
+
|
|
80
|
+
setSnackbarMessage("¡Exportación a CSV completada!");
|
|
81
|
+
setSnackbarSeverity('success');
|
|
82
|
+
} else {
|
|
83
|
+
setSnackbarMessage("Tu navegador no soporta la descarga directa para CSV. Por favor, copia el contenido manualmente.");
|
|
84
|
+
setSnackbarSeverity('error');
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error("Error al exportar los datos a CSV:", error);
|
|
88
|
+
setSnackbarMessage("Error al exportar los datos a CSV.");
|
|
89
|
+
setSnackbarSeverity('error');
|
|
90
|
+
} finally {
|
|
91
|
+
setSnackbarOpen(true);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Función para exportar datos a un archivo Excel (formato XLSX).
|
|
97
|
+
* Genera una tabla HTML que luego se descarga como un archivo .xlsx.
|
|
98
|
+
* @param options Opciones de exportación, incluyendo datos, columnas, nombre de archivo y setters de Snackbar.
|
|
99
|
+
*/
|
|
100
|
+
export const exportToExcel = <T>(options: ExportOptions<T>) => {
|
|
101
|
+
const { data, columns, fileName, exportColumns, setSnackbarOpen, setSnackbarMessage, setSnackbarSeverity } = options;
|
|
102
|
+
|
|
103
|
+
if (!data || data.length === 0) {
|
|
104
|
+
setSnackbarMessage("No hay datos para exportar a Excel.");
|
|
105
|
+
setSnackbarSeverity('warning');
|
|
106
|
+
setSnackbarOpen(true);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
setSnackbarMessage("Exportando datos a Excel (XLSX)...");
|
|
111
|
+
setSnackbarSeverity('info');
|
|
112
|
+
setSnackbarOpen(true);
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const columnsToExport = exportColumns
|
|
116
|
+
? columns.filter(col => exportColumns.includes(col.props.name))
|
|
117
|
+
: columns;
|
|
118
|
+
|
|
119
|
+
// Construye el contenido HTML de la tabla.
|
|
120
|
+
let tableHTML = `
|
|
121
|
+
<html xmlns:o="urn:schemas-microsoft-com:office:office"
|
|
122
|
+
xmlns:x="urn:schemas-microsoft-com:office:excel"
|
|
123
|
+
xmlns="http://www.w3.org/TR/REC-html40">
|
|
124
|
+
<head>
|
|
125
|
+
<meta charset="utf-8" />
|
|
126
|
+
<!--[if gte mso 9]><xml>
|
|
127
|
+
<x:ExcelWorkbook>
|
|
128
|
+
<x:ExcelWorksheets>
|
|
129
|
+
<x:ExcelWorksheet>
|
|
130
|
+
<x:Name>Hoja1</x:Name>
|
|
131
|
+
<x:WorksheetOptions>
|
|
132
|
+
<x:DisplayGridlines/>
|
|
133
|
+
</x:WorksheetOptions>
|
|
134
|
+
</x:ExcelWorksheet>
|
|
135
|
+
</x:ExcelWorksheets>
|
|
136
|
+
</x:ExcelWorkbook>
|
|
137
|
+
</xml><![endif]-->
|
|
138
|
+
</head>
|
|
139
|
+
<body>
|
|
140
|
+
<table>
|
|
141
|
+
<thead>
|
|
142
|
+
<tr>
|
|
143
|
+
${columnsToExport.map(col => `<th>${col.props.name}</th>`).join('')}
|
|
144
|
+
</tr>
|
|
145
|
+
</thead>
|
|
146
|
+
<tbody>
|
|
147
|
+
${data.map(row => `
|
|
148
|
+
<tr>
|
|
149
|
+
${columnsToExport.map(col => {
|
|
150
|
+
const field = col.props.field;
|
|
151
|
+
let cellValue: any;
|
|
152
|
+
if (Array.isArray(field)) {
|
|
153
|
+
cellValue = (row as any)[field[0]];
|
|
154
|
+
} else {
|
|
155
|
+
cellValue = (row as any)[field];
|
|
156
|
+
}
|
|
157
|
+
// Escapa caracteres HTML para el contenido de la celda.
|
|
158
|
+
return `<td>${String(cellValue || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')}</td>`;
|
|
159
|
+
}).join('')}
|
|
160
|
+
</tr>
|
|
161
|
+
`).join('')}
|
|
162
|
+
</tbody>
|
|
163
|
+
</table>
|
|
164
|
+
</body>
|
|
165
|
+
</html>
|
|
166
|
+
`;
|
|
167
|
+
|
|
168
|
+
// Crea un Blob con el contenido HTML y el tipo MIME de XLSX.
|
|
169
|
+
const blob = new Blob([tableHTML], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8;' });
|
|
170
|
+
|
|
171
|
+
const link = document.createElement('a');
|
|
172
|
+
if (link.download !== undefined) {
|
|
173
|
+
const url = URL.createObjectURL(blob);
|
|
174
|
+
link.setAttribute('href', url);
|
|
175
|
+
link.setAttribute('download', fileName + '.xlsx'); // Usa la extensión .xlsx
|
|
176
|
+
link.style.visibility = 'hidden';
|
|
177
|
+
document.body.appendChild(link);
|
|
178
|
+
link.click();
|
|
179
|
+
document.body.removeChild(link);
|
|
180
|
+
URL.revokeObjectURL(url);
|
|
181
|
+
|
|
182
|
+
setSnackbarMessage("¡Exportación a Excel (XLSX) completada!");
|
|
183
|
+
setSnackbarSeverity('success');
|
|
184
|
+
} else {
|
|
185
|
+
setSnackbarMessage("Tu navegador no soporta la descarga directa para Excel (XLSX). Por favor, copia el contenido manualmente.");
|
|
186
|
+
setSnackbarSeverity('error');
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error("Error al exportar los datos a Excel (XLSX):", error);
|
|
190
|
+
setSnackbarMessage("Error al exportar los datos a Excel (XLSX).");
|
|
191
|
+
setSnackbarSeverity('error');
|
|
192
|
+
} finally {
|
|
193
|
+
setSnackbarOpen(true);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Interfaces de ejemplo
|
|
2
|
+
interface Usuario {
|
|
3
|
+
id: number
|
|
4
|
+
nombre: string
|
|
5
|
+
email: string
|
|
6
|
+
avatar: string
|
|
7
|
+
edad: number
|
|
8
|
+
activo: boolean
|
|
9
|
+
rol: 'admin' | 'usuario' | 'moderador'
|
|
10
|
+
fechaRegistro: string
|
|
11
|
+
puntuacion: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Producto {
|
|
15
|
+
id: number
|
|
16
|
+
nombre: string
|
|
17
|
+
precio: number
|
|
18
|
+
categoria: string
|
|
19
|
+
stock: number
|
|
20
|
+
imagen: string
|
|
21
|
+
enOferta: boolean
|
|
22
|
+
rating: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface Empleado {
|
|
26
|
+
id: number
|
|
27
|
+
nombre: string
|
|
28
|
+
apellido: string
|
|
29
|
+
departamento: string
|
|
30
|
+
salario: number
|
|
31
|
+
fechaIngreso: string
|
|
32
|
+
activo: boolean
|
|
33
|
+
avatar: string
|
|
34
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ScrollTab } from './Tabs.stories';
|
|
2
|
+
export const DefaultTabDefinition = `
|
|
3
|
+
<Tabs>
|
|
4
|
+
<Tab label="Home" icon={<Home />}>
|
|
5
|
+
<div>
|
|
6
|
+
hola 1
|
|
7
|
+
</div>
|
|
8
|
+
</Tab>
|
|
9
|
+
<Tab label="Settings" icon={<Settings />}>
|
|
10
|
+
<div>
|
|
11
|
+
hola 2
|
|
12
|
+
</div>
|
|
13
|
+
</Tab>
|
|
14
|
+
<Tab label="Profile" icon={<Settings />}>
|
|
15
|
+
<div>
|
|
16
|
+
hola 3
|
|
17
|
+
</div>
|
|
18
|
+
</Tab>
|
|
19
|
+
</Tabs>`.trim();
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export const ScrollTabDefinition = `
|
|
23
|
+
<Tabs {...args} variant="scrollable" scrollButtons="auto" allowScrollButtonsMobile>
|
|
24
|
+
{Array.from({ length: 20 }).map((_, idx) => (
|
|
25
|
+
<Tab key={idx} label={\`Tab \${idx + 1}\`} icon={<Settings />}>
|
|
26
|
+
<div>
|
|
27
|
+
hola {idx + 1}
|
|
28
|
+
</div>
|
|
29
|
+
</Tab>
|
|
30
|
+
))}
|
|
31
|
+
</Tabs>
|
|
32
|
+
`.trim();
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
export const VeriticalTabDefinition = `
|
|
36
|
+
<Tabs orientation="vertical">
|
|
37
|
+
<Tab label="Home" >
|
|
38
|
+
<div>
|
|
39
|
+
hola 1
|
|
40
|
+
</div>
|
|
41
|
+
</Tab>
|
|
42
|
+
<Tab label="Settings" >
|
|
43
|
+
<div>
|
|
44
|
+
hola 2
|
|
45
|
+
</div>
|
|
46
|
+
</Tab>
|
|
47
|
+
<Tab label="Profile" >
|
|
48
|
+
<div>
|
|
49
|
+
hola 3
|
|
50
|
+
</div>
|
|
51
|
+
</Tab>
|
|
52
|
+
</Tabs>
|
|
53
|
+
`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { TabProps as MuiTabProps } from "@mui/material";
|
|
3
|
+
|
|
4
|
+
type PickMuiTabProps = Pick<
|
|
5
|
+
MuiTabProps,
|
|
6
|
+
"label" | "icon" | "disabled" | "sx" | "value" | "wrapped" | "iconPosition" | "className" | "disabled"| 'disableRipple'
|
|
7
|
+
>;
|
|
8
|
+
|
|
9
|
+
export interface TabProps extends PickMuiTabProps {
|
|
10
|
+
value?: number;
|
|
11
|
+
onChange?: () => void;
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Tab = (_: TabProps): null => null;
|
|
16
|
+
|
|
17
|
+
Tab.displayName = "Tab";
|
|
18
|
+
|
|
19
|
+
export default Tab;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import Tabs from "./Tabs";
|
|
3
|
+
import Tab from "./Tab";
|
|
4
|
+
import { Home, Settings } from "@mui/icons-material";
|
|
5
|
+
import { DefaultTabDefinition, ScrollTabDefinition, VeriticalTabDefinition } from "./Tab.definition";
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Tabs> = {
|
|
8
|
+
title: "Components/Tabs",
|
|
9
|
+
component: Tabs,
|
|
10
|
+
tags: ["autodocs"]
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof Tabs>;
|
|
14
|
+
|
|
15
|
+
export const DefaultTab: Story = {
|
|
16
|
+
render: (args) => {
|
|
17
|
+
return (
|
|
18
|
+
<Tabs {...args}>
|
|
19
|
+
<Tab label="Home" icon={<Home />} >
|
|
20
|
+
<div>
|
|
21
|
+
hola 1
|
|
22
|
+
</div>
|
|
23
|
+
</Tab>
|
|
24
|
+
<Tab label="Settings" icon={<Settings />} >
|
|
25
|
+
<div>
|
|
26
|
+
hola 2
|
|
27
|
+
</div>
|
|
28
|
+
</Tab>
|
|
29
|
+
<Tab label="Profile" icon={<Settings />}>
|
|
30
|
+
<div>
|
|
31
|
+
hola 3
|
|
32
|
+
</div>
|
|
33
|
+
</Tab>
|
|
34
|
+
</Tabs>
|
|
35
|
+
);
|
|
36
|
+
},
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: {
|
|
39
|
+
description: {
|
|
40
|
+
story: "Ejemplo básico de timeline"
|
|
41
|
+
},
|
|
42
|
+
source: {
|
|
43
|
+
code: DefaultTabDefinition,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
argTypes: {
|
|
48
|
+
children: { control: false, description: 'Componentes `TabItems` que definen la estructura de el timeline' },
|
|
49
|
+
orientation: { description: 'Indica si la posicion de los tabs, es horizontal o vertical' },
|
|
50
|
+
defaultValue: { description: 'Indica si, se requiere iniciar con alguna tab preseleccionada, se inicia' },
|
|
51
|
+
variant: { description: 'Indica el estilo de los tabs "standard" | "scrollable" | "fullWidth" ' },
|
|
52
|
+
indicatorColor: { description: 'Indica el color del indicador de los tabs "primary" | "secondary"' },
|
|
53
|
+
labelColor: { description: 'Indica el color de las etiquetas de los tabs "primary" | "secondary" | "inherit"' },
|
|
54
|
+
sx: { description: 'Estilos personalizados para el tab' },
|
|
55
|
+
allowScrollButtonsMobile: { description: 'Si se usan scrollButtons, permite que se muestren en dispositivos móviles' },
|
|
56
|
+
onChange: { control: false, description: 'Permite enviar una función, al cambiar entre tabs, para obtener el id actual' },
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const ScrollTab: Story = {
|
|
61
|
+
render: (args) => {
|
|
62
|
+
return (
|
|
63
|
+
<Tabs {...args} variant="scrollable" scrollButtons="auto" allowScrollButtonsMobile>
|
|
64
|
+
{Array.from({ length: 20 }).map((_, idx) => (
|
|
65
|
+
<Tab key={idx} label={`Tab ${idx + 1}`} icon={<Settings />}>
|
|
66
|
+
<div>
|
|
67
|
+
hola {idx + 1}
|
|
68
|
+
</div>
|
|
69
|
+
</Tab>
|
|
70
|
+
))}
|
|
71
|
+
</Tabs>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
parameters: {
|
|
75
|
+
docs: {
|
|
76
|
+
description: {
|
|
77
|
+
story: "Ejemplo tab con scroll"
|
|
78
|
+
},
|
|
79
|
+
source: {
|
|
80
|
+
code: ScrollTabDefinition,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const VeriticalTab: Story = {
|
|
87
|
+
render: (args) => {
|
|
88
|
+
return (
|
|
89
|
+
<Tabs {...args} orientation="vertical">
|
|
90
|
+
<Tab label="Home" >
|
|
91
|
+
<div>
|
|
92
|
+
hola 1
|
|
93
|
+
</div>
|
|
94
|
+
</Tab>
|
|
95
|
+
<Tab label="Settings" >
|
|
96
|
+
<div>
|
|
97
|
+
hola 2
|
|
98
|
+
</div>
|
|
99
|
+
</Tab>
|
|
100
|
+
<Tab label="Profile" >
|
|
101
|
+
<div>
|
|
102
|
+
hola 3
|
|
103
|
+
</div>
|
|
104
|
+
</Tab>
|
|
105
|
+
</Tabs>
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
parameters: {
|
|
109
|
+
docs: {
|
|
110
|
+
description: {
|
|
111
|
+
story: "Ejemplo tab vertical"
|
|
112
|
+
},
|
|
113
|
+
source: {
|
|
114
|
+
code: VeriticalTabDefinition,
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { useState, ReactElement } from "react";
|
|
2
|
+
import { Tabs as MuiTabs, Tab as MuiTab, Box, TabsProps as MuiTabsProps } from "@mui/material";
|
|
3
|
+
import { TabProps } from "./Tab";
|
|
4
|
+
import { TAB_DISPLAY_MAP } from "./_tabUtils";
|
|
5
|
+
|
|
6
|
+
type PickTabsProps = Pick<
|
|
7
|
+
MuiTabsProps,
|
|
8
|
+
"centered" | "indicatorColor" | "orientation" | "scrollButtons" | "variant" | "className" | "sx" | "visibleScrollbar" | 'indicatorColor'| 'allowScrollButtonsMobile'
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
interface MyTabsProps extends PickTabsProps {
|
|
12
|
+
children: ReactElement<TabProps>[];
|
|
13
|
+
defaultValue?: number;
|
|
14
|
+
onChange?: () => void;
|
|
15
|
+
centered?: boolean;
|
|
16
|
+
orientation?: "horizontal" | "vertical";
|
|
17
|
+
scrollButtons?: "auto" | false | true;
|
|
18
|
+
variant?: "standard" | "scrollable" | "fullWidth";
|
|
19
|
+
indicatorColor?: "primary" | "secondary";
|
|
20
|
+
labelColor?: "primary" | "secondary" | "inherit";
|
|
21
|
+
onChangeValue?: (newValue: number) => void;
|
|
22
|
+
allowScrollButtonsMobile?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const Tabs: React.FC<MyTabsProps> = ({
|
|
26
|
+
children,
|
|
27
|
+
defaultValue,
|
|
28
|
+
onChange,
|
|
29
|
+
centered = true,
|
|
30
|
+
orientation = 'horizontal',
|
|
31
|
+
scrollButtons = "auto",
|
|
32
|
+
variant = "standard",
|
|
33
|
+
indicatorColor = "primary",
|
|
34
|
+
labelColor = "primary",
|
|
35
|
+
className,
|
|
36
|
+
onChangeValue,
|
|
37
|
+
allowScrollButtonsMobile = true,
|
|
38
|
+
sx,
|
|
39
|
+
}) => {
|
|
40
|
+
const firstValue = children[0]?.props.value;
|
|
41
|
+
const [currentValue, setCurrentValue] = useState<string | number>(
|
|
42
|
+
defaultValue ?? firstValue ?? 0
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
|
|
46
|
+
setCurrentValue(newValue);
|
|
47
|
+
onChange?.();
|
|
48
|
+
onChangeValue?.(newValue);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Box sx={{ display: TAB_DISPLAY_MAP[orientation].display, flexDirection: TAB_DISPLAY_MAP[orientation].flexDirection}}>
|
|
53
|
+
<MuiTabs
|
|
54
|
+
value={currentValue}
|
|
55
|
+
onChange={handleChange}
|
|
56
|
+
centered={centered}
|
|
57
|
+
indicatorColor={indicatorColor}
|
|
58
|
+
orientation={orientation}
|
|
59
|
+
scrollButtons={scrollButtons}
|
|
60
|
+
variant={variant}
|
|
61
|
+
className={className}
|
|
62
|
+
textColor={labelColor}
|
|
63
|
+
sx={{ ...sx }}
|
|
64
|
+
allowScrollButtonsMobile={allowScrollButtonsMobile}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
>
|
|
68
|
+
{children.map((child, idx) => {
|
|
69
|
+
const { label, icon, value = idx, disabled, wrapped, iconPosition, className: tabClassName, sx: tabSx } = child.props;
|
|
70
|
+
return (
|
|
71
|
+
<MuiTab
|
|
72
|
+
key={value}
|
|
73
|
+
label={label}
|
|
74
|
+
icon={icon}
|
|
75
|
+
value={value}
|
|
76
|
+
disabled={disabled}
|
|
77
|
+
wrapped={wrapped}
|
|
78
|
+
iconPosition={iconPosition}
|
|
79
|
+
className={tabClassName}
|
|
80
|
+
sx={tabSx}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
})}
|
|
84
|
+
</MuiTabs>
|
|
85
|
+
|
|
86
|
+
<Box m={2} role="tabpanel" sx={{width:'100%'}} >
|
|
87
|
+
{children.map((child, idx) => {
|
|
88
|
+
const value = child.props.value ?? idx;
|
|
89
|
+
return value === currentValue ? (
|
|
90
|
+
<Box key={value}>{child.props.children}</Box>
|
|
91
|
+
) : null;
|
|
92
|
+
})}
|
|
93
|
+
</Box>
|
|
94
|
+
</Box>
|
|
95
|
+
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default Tabs;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ColorVariant, PositionVariant } from './Timeline.stories';
|
|
2
|
+
export const DefaultTimelineDefinition = `
|
|
3
|
+
<Timeline>
|
|
4
|
+
<TimelineItem dotColor="primary" connectorColor="primary">
|
|
5
|
+
Primer paso
|
|
6
|
+
</TimelineItem>
|
|
7
|
+
<TimelineItem dotColor="secondary" connectorColor="secondary">
|
|
8
|
+
Segundo paso
|
|
9
|
+
</TimelineItem>
|
|
10
|
+
<TimelineItem dotColor="success">
|
|
11
|
+
Tercer paso
|
|
12
|
+
</TimelineItem>
|
|
13
|
+
</Timeline>
|
|
14
|
+
`.trim();
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
export const ColorVariantTimelineDefinition = `
|
|
18
|
+
<Timeline>
|
|
19
|
+
<TimelineItem dotColor="success" connectorColor="error">
|
|
20
|
+
eat
|
|
21
|
+
</TimelineItem>
|
|
22
|
+
<TimelineItem dotColor="primary" connectorColor="success">
|
|
23
|
+
code
|
|
24
|
+
</TimelineItem>
|
|
25
|
+
<TimelineItem dotColor="warning">
|
|
26
|
+
repeat
|
|
27
|
+
</TimelineItem>
|
|
28
|
+
</Timeline>`.trim();
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export const PositionVariantTimelineDefinition = `
|
|
32
|
+
<Timeline position="alternate">
|
|
33
|
+
<TimelineItem>
|
|
34
|
+
eat
|
|
35
|
+
</TimelineItem>
|
|
36
|
+
<TimelineItem>
|
|
37
|
+
code
|
|
38
|
+
</TimelineItem>
|
|
39
|
+
<TimelineItem>
|
|
40
|
+
repeat
|
|
41
|
+
</TimelineItem>
|
|
42
|
+
</Timeline>
|
|
43
|
+
`.trim();
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { TimelineItem } from "./TimelineItem";
|
|
3
|
+
import { DefaultTimelineDefinition } from "./Timeline.definition";
|
|
4
|
+
import { Timeline } from "./Timeline";
|
|
5
|
+
import { Box } from "@mui/material";
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Timeline> = {
|
|
8
|
+
title: "Components/Timeline",
|
|
9
|
+
component: Timeline,
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: "centered"
|
|
12
|
+
},
|
|
13
|
+
tags: ["autodocs"]
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<typeof Timeline>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
args: {
|
|
22
|
+
position: "right"
|
|
23
|
+
},
|
|
24
|
+
render: (args) => (
|
|
25
|
+
<Box sx={{ width: 300 }}>
|
|
26
|
+
<Timeline {...args}>
|
|
27
|
+
<TimelineItem>
|
|
28
|
+
eat
|
|
29
|
+
</TimelineItem>
|
|
30
|
+
<TimelineItem>
|
|
31
|
+
code
|
|
32
|
+
</TimelineItem>
|
|
33
|
+
<TimelineItem>
|
|
34
|
+
sleep
|
|
35
|
+
</TimelineItem>
|
|
36
|
+
</Timeline>
|
|
37
|
+
</Box>
|
|
38
|
+
),
|
|
39
|
+
parameters: {
|
|
40
|
+
docs: {
|
|
41
|
+
description: {
|
|
42
|
+
story: "Ejemplo básico de timeline"
|
|
43
|
+
},
|
|
44
|
+
source: {
|
|
45
|
+
code: DefaultTimelineDefinition
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const ColorVariant: Story = {
|
|
52
|
+
render: () => (
|
|
53
|
+
<Box sx={{ width: 300 }}>
|
|
54
|
+
<Timeline>
|
|
55
|
+
<TimelineItem dotColor="success" connectorColor="error">
|
|
56
|
+
eat
|
|
57
|
+
</TimelineItem>
|
|
58
|
+
<TimelineItem dotColor="primary" connectorColor="success">
|
|
59
|
+
code
|
|
60
|
+
</TimelineItem>
|
|
61
|
+
<TimelineItem dotColor="warning">
|
|
62
|
+
repeat
|
|
63
|
+
</TimelineItem>
|
|
64
|
+
</Timeline>
|
|
65
|
+
</Box>
|
|
66
|
+
),
|
|
67
|
+
parameters: {
|
|
68
|
+
docs: {
|
|
69
|
+
description: {
|
|
70
|
+
story: "Variantes de color en los dots y conectores"
|
|
71
|
+
},
|
|
72
|
+
source: {
|
|
73
|
+
code: DefaultTimelineDefinition
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const PositionVariant: Story = {
|
|
80
|
+
render: () => (
|
|
81
|
+
<Box sx={{ width: 300 }}>
|
|
82
|
+
<Timeline position="alternate">
|
|
83
|
+
<TimelineItem>
|
|
84
|
+
eat
|
|
85
|
+
</TimelineItem>
|
|
86
|
+
<TimelineItem>
|
|
87
|
+
code
|
|
88
|
+
</TimelineItem>
|
|
89
|
+
<TimelineItem>
|
|
90
|
+
repeat
|
|
91
|
+
</TimelineItem>
|
|
92
|
+
</Timeline>
|
|
93
|
+
</Box>
|
|
94
|
+
),
|
|
95
|
+
args: {
|
|
96
|
+
position: "alternate"
|
|
97
|
+
},
|
|
98
|
+
parameters: {
|
|
99
|
+
docs: {
|
|
100
|
+
description: {
|
|
101
|
+
story: "Variantes de color en los dots y conectores"
|
|
102
|
+
},
|
|
103
|
+
source: {
|
|
104
|
+
code: DefaultTimelineDefinition
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|