@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,85 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Stat, StatChip } from './Stat';
|
|
3
|
+
import { Typography } from '@mui/material';
|
|
4
|
+
import { expect, within } from 'storybook/test';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Stat> = {
|
|
7
|
+
title: 'Components/Stat',
|
|
8
|
+
component: Stat,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof Stat>;
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
stat: 100,
|
|
21
|
+
label: 'Total Sales',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Simple: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
stat: 75,
|
|
28
|
+
stat2: 'Last Week',
|
|
29
|
+
label: 'Completed Orders',
|
|
30
|
+
simple: true,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const Chip: Story = {
|
|
35
|
+
args: {
|
|
36
|
+
stat: 42,
|
|
37
|
+
label: 'New Users',
|
|
38
|
+
chip: true,
|
|
39
|
+
chipColor: '#673AB7',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const ChipList: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
label: 'Status',
|
|
46
|
+
chipList: true,
|
|
47
|
+
chips: [
|
|
48
|
+
{ stat: 'Active', chipColor: '#4CAF50' },
|
|
49
|
+
{ stat: 'Pending', chipColor: '#FFC107' },
|
|
50
|
+
{ stat: 'Blocked', chipColor: '#F44336' },
|
|
51
|
+
] as StatChip[],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const WithCustomDisplay: Story = {
|
|
56
|
+
args: {
|
|
57
|
+
stat: 350,
|
|
58
|
+
label: 'Revenue',
|
|
59
|
+
chip: true,
|
|
60
|
+
chipColor: '#2E7D32',
|
|
61
|
+
statDisplay: (stat: any) => (
|
|
62
|
+
<Typography variant="h6" fontWeight="bold">
|
|
63
|
+
${stat.toLocaleString()}
|
|
64
|
+
</Typography>
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const aStat: Story = {
|
|
70
|
+
args: {
|
|
71
|
+
stat: 42,
|
|
72
|
+
label: 'New Users',
|
|
73
|
+
chip: true,
|
|
74
|
+
chipColor: '#673AB7',
|
|
75
|
+
},
|
|
76
|
+
play: async ({ canvasElement }) => {
|
|
77
|
+
const canvas = within(canvasElement);
|
|
78
|
+
|
|
79
|
+
const stat = canvas.getByTestId('chip-template-option-outlet');
|
|
80
|
+
expect(stat).toBeInTheDocument();
|
|
81
|
+
|
|
82
|
+
expect(canvas.getByText('42')).toBeInTheDocument();
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Chip, Stack, Typography, Box } from '@mui/material';
|
|
3
|
+
|
|
4
|
+
export interface StatChip {
|
|
5
|
+
stat: any;
|
|
6
|
+
chipColor: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface StatProps {
|
|
10
|
+
stat: any; // Replace 'any' with the actual type of 'stat'
|
|
11
|
+
stat2?: any; // Replace 'any' with the actual type of'stat2'
|
|
12
|
+
label: string; // Replace 'any' with the actual type of'label'
|
|
13
|
+
color?: string;
|
|
14
|
+
chipColor?: string;
|
|
15
|
+
chips?: StatChip[]; // Replace 'any' with the actual type of'chips'
|
|
16
|
+
simple?: boolean;
|
|
17
|
+
chip?: boolean;
|
|
18
|
+
chipList?: boolean;
|
|
19
|
+
children?: React.ReactNode;
|
|
20
|
+
statDisplay?: (stat: any) => React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const Stat: React.FC<StatProps> = ({
|
|
24
|
+
stat,
|
|
25
|
+
stat2,
|
|
26
|
+
label,
|
|
27
|
+
color = '#1469B8',
|
|
28
|
+
chipColor = '#1469B8',
|
|
29
|
+
chips = [],
|
|
30
|
+
simple = false,
|
|
31
|
+
chip = false,
|
|
32
|
+
chipList = false,
|
|
33
|
+
children,
|
|
34
|
+
statDisplay,
|
|
35
|
+
}) => {
|
|
36
|
+
const selectedTemplate = useMemo(() => {
|
|
37
|
+
if (simple) return 'simple';
|
|
38
|
+
if (chip) return 'chip';
|
|
39
|
+
if (chipList) return 'chipList';
|
|
40
|
+
return 'default';
|
|
41
|
+
}, [simple, chip, chipList]);
|
|
42
|
+
|
|
43
|
+
const renderStatDisplay = () => {
|
|
44
|
+
return statDisplay ? statDisplay(stat) : <Typography variant="h6">{stat}</Typography>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
{selectedTemplate === 'default' && (
|
|
50
|
+
<Box className="stat">
|
|
51
|
+
<Typography variant="h4" data-testid="selection-template-option-outlet">
|
|
52
|
+
{renderStatDisplay()}
|
|
53
|
+
</Typography>
|
|
54
|
+
<Box className="stat__label" display="flex" alignItems="center" gap={1}>
|
|
55
|
+
<Typography variant="body1">{label}</Typography>
|
|
56
|
+
<Box
|
|
57
|
+
width={40}
|
|
58
|
+
height={4}
|
|
59
|
+
bgcolor={color}
|
|
60
|
+
data-testid="stat-border"
|
|
61
|
+
borderRadius={2}
|
|
62
|
+
/>
|
|
63
|
+
</Box>
|
|
64
|
+
</Box>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
{selectedTemplate === 'simple' && (
|
|
68
|
+
<Stack direction="row" spacing={2} alignItems="center">
|
|
69
|
+
<Typography variant="body1">{label}</Typography>
|
|
70
|
+
<Typography data-testid="selection-template-option-outlet">
|
|
71
|
+
{renderStatDisplay()}
|
|
72
|
+
</Typography>
|
|
73
|
+
{stat2 && <Typography>{stat2}</Typography>}
|
|
74
|
+
</Stack>
|
|
75
|
+
)}
|
|
76
|
+
|
|
77
|
+
{selectedTemplate === 'chip' && (
|
|
78
|
+
<Stack direction="row" spacing={2} alignItems="center">
|
|
79
|
+
<Typography variant="body1">{label}</Typography>
|
|
80
|
+
<Chip
|
|
81
|
+
data-testid="chip-template-option-outlet"
|
|
82
|
+
label={renderStatDisplay()}
|
|
83
|
+
sx={{
|
|
84
|
+
backgroundColor: chipColor,
|
|
85
|
+
color: '#fff',
|
|
86
|
+
fontWeight: 'bold',
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
</Stack>
|
|
90
|
+
)}
|
|
91
|
+
|
|
92
|
+
{selectedTemplate === 'chipList' && (
|
|
93
|
+
<Stack direction="row" spacing={2} alignItems="center">
|
|
94
|
+
<Typography variant="body1">{label}</Typography>
|
|
95
|
+
<Stack direction="row" spacing={1}>
|
|
96
|
+
{chips.map((chip, i) => (
|
|
97
|
+
<Chip
|
|
98
|
+
key={i}
|
|
99
|
+
label={chip.stat}
|
|
100
|
+
sx={{
|
|
101
|
+
backgroundColor: chip.chipColor,
|
|
102
|
+
color: '#fff',
|
|
103
|
+
fontWeight: 'bold',
|
|
104
|
+
}}
|
|
105
|
+
/>
|
|
106
|
+
))}
|
|
107
|
+
</Stack>
|
|
108
|
+
</Stack>
|
|
109
|
+
)}
|
|
110
|
+
|
|
111
|
+
{/* Content projection (similar to ng-content) */}
|
|
112
|
+
{children}
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export default Stat;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { Button } from '@mui/material';
|
|
4
|
+
import StatusMessage from './StatusMessage';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/StatusMessage',
|
|
8
|
+
component: StatusMessage,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
argTypes: {
|
|
11
|
+
title: { control: 'text' },
|
|
12
|
+
description: { control: 'text' },
|
|
13
|
+
messageType: {
|
|
14
|
+
control: 'select',
|
|
15
|
+
options: ['success', 'danger', 'warning'],
|
|
16
|
+
},
|
|
17
|
+
displayType: {
|
|
18
|
+
control: 'select',
|
|
19
|
+
options: ['alert', 'modal'],
|
|
20
|
+
},
|
|
21
|
+
open: {
|
|
22
|
+
control: 'boolean',
|
|
23
|
+
if: { arg: 'displayType', eq: 'modal' },
|
|
24
|
+
},
|
|
25
|
+
close: { action: 'closed' },
|
|
26
|
+
},
|
|
27
|
+
args: {
|
|
28
|
+
title: 'Título del Mensaje',
|
|
29
|
+
description: 'Esta es una descripción detallada del mensaje de estado.',
|
|
30
|
+
},
|
|
31
|
+
} satisfies Meta<typeof StatusMessage>;
|
|
32
|
+
|
|
33
|
+
export default meta;
|
|
34
|
+
|
|
35
|
+
type Story = StoryObj<typeof meta>;
|
|
36
|
+
|
|
37
|
+
// --- Historias de Alerta (Alert) ---
|
|
38
|
+
export const AlertSuccess: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
messageType: 'success',
|
|
41
|
+
displayType: 'alert',
|
|
42
|
+
title: 'Operación Exitosa',
|
|
43
|
+
description: 'La operación se ha completado correctamente.',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const AlertWarning: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
messageType: 'warning',
|
|
50
|
+
displayType: 'alert',
|
|
51
|
+
title: 'Advertencia',
|
|
52
|
+
description: 'Esta acción podría tener consecuencias no deseadas.',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const AlertDanger: Story = {
|
|
57
|
+
args: {
|
|
58
|
+
messageType: 'danger',
|
|
59
|
+
displayType: 'alert',
|
|
60
|
+
title: 'Error de Procesamiento',
|
|
61
|
+
description: 'Se ha producido un error inesperado al procesar la solicitud.',
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// --- Historias de Modal (Dialog) ---
|
|
66
|
+
export const ModalSuccess: Story = {
|
|
67
|
+
render: (args) => {
|
|
68
|
+
const [open, setOpen] = useState(true);
|
|
69
|
+
const handleClose = () => setOpen(false);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<>
|
|
73
|
+
<Button onClick={() => setOpen(true)} variant="contained" color="success">
|
|
74
|
+
Mostrar Modal de Éxito
|
|
75
|
+
</Button>
|
|
76
|
+
<StatusMessage {...args} open={open} close={handleClose} />
|
|
77
|
+
</>
|
|
78
|
+
);
|
|
79
|
+
},
|
|
80
|
+
args: {
|
|
81
|
+
messageType: 'success',
|
|
82
|
+
displayType: 'modal',
|
|
83
|
+
title: 'Operación Exitosa',
|
|
84
|
+
description: 'La operación se ha completado correctamente.',
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const ModalWarning: Story = {
|
|
89
|
+
render: (args) => {
|
|
90
|
+
const [open, setOpen] = useState(false);
|
|
91
|
+
const handleClose = () => setOpen(false);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<>
|
|
95
|
+
<Button onClick={() => setOpen(true)} variant="contained" color="warning">
|
|
96
|
+
Mostrar Modal de Advertencia
|
|
97
|
+
</Button>
|
|
98
|
+
<StatusMessage {...args} open={open} close={handleClose} />
|
|
99
|
+
</>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
args: {
|
|
103
|
+
messageType: 'warning',
|
|
104
|
+
displayType: 'modal',
|
|
105
|
+
title: 'Advertencia',
|
|
106
|
+
description: 'Esta acción podría tener consecuencias no deseadas.',
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const ModalDanger: Story = {
|
|
111
|
+
render: (args) => {
|
|
112
|
+
const [open, setOpen] = useState(false);
|
|
113
|
+
const handleClose = () => setOpen(false);
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<>
|
|
117
|
+
<Button onClick={() => setOpen(true)} variant="contained" color="error">
|
|
118
|
+
Mostrar Modal de Error
|
|
119
|
+
</Button>
|
|
120
|
+
<StatusMessage {...args} open={open} close={handleClose} />
|
|
121
|
+
</>
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
args: {
|
|
125
|
+
messageType: 'danger',
|
|
126
|
+
displayType: 'modal',
|
|
127
|
+
title: 'Error de Procesamiento',
|
|
128
|
+
description: 'Se ha producido un error inesperado al procesar la solicitud.',
|
|
129
|
+
},
|
|
130
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Alert,
|
|
4
|
+
Box,
|
|
5
|
+
Typography,
|
|
6
|
+
Dialog,
|
|
7
|
+
DialogContent,
|
|
8
|
+
DialogActions,
|
|
9
|
+
Button
|
|
10
|
+
} from '@mui/material';
|
|
11
|
+
import {
|
|
12
|
+
ErrorOutline as ErrorOutlineIcon,
|
|
13
|
+
CheckCircleOutline as CheckCircleOutlineIcon,
|
|
14
|
+
WarningAmber as WarningAmberIcon
|
|
15
|
+
} from '@mui/icons-material';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `StatusMessage` es un componente de React que muestra mensajes de éxito, error o advertencia
|
|
19
|
+
* en un modal o una alerta, utilizando el sistema de diseño de Material-UI.
|
|
20
|
+
*
|
|
21
|
+
* El componente puede mostrar alertas con estilos específicos o un modal personalizable
|
|
22
|
+
* usando `Dialog` y otros componentes de MUI. También puede incluir una función opcional
|
|
23
|
+
* para cerrar el mensaje.
|
|
24
|
+
*
|
|
25
|
+
* @param {StatusMessageProps} props - Las propiedades del componente.
|
|
26
|
+
* @param {string | undefined} props.title - Título del mensaje que se muestra en el modal o alerta.
|
|
27
|
+
* @param {string} [props.description] - Descripción o contenido detallado del mensaje.
|
|
28
|
+
* @param {'success' | 'danger' | 'warning'} [props.messageType='success'] - Tipo de mensaje que determina el estilo visual. 'danger' se mapea a 'error' de MUI.
|
|
29
|
+
* @param {'alert' | 'modal'} [props.displayType='alert'] - Determina si el mensaje se muestra como alerta o modal.
|
|
30
|
+
* @param {() => void} [props.close] - Función opcional para ejecutar al cerrar el mensaje.
|
|
31
|
+
* @returns {React.FC<StatusMessageProps>} Un componente funcional de React que muestra mensajes personalizados.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Ejemplo de uso como una alerta:
|
|
35
|
+
* <StatusMessage
|
|
36
|
+
* title="Operación Exitosa"
|
|
37
|
+
* description="La operación se ha completado correctamente."
|
|
38
|
+
* messageType="success"
|
|
39
|
+
* displayType="alert"
|
|
40
|
+
* />
|
|
41
|
+
*
|
|
42
|
+
* // Ejemplo de uso como un modal:
|
|
43
|
+
* <StatusMessage
|
|
44
|
+
* title="Advertencia"
|
|
45
|
+
* description="Se ha producido un error inesperado."
|
|
46
|
+
* messageType="danger"
|
|
47
|
+
* displayType="modal"
|
|
48
|
+
* close={() => console.log('Modal cerrado')}
|
|
49
|
+
* />
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
export interface StatusMessageProps {
|
|
53
|
+
title: string | undefined;
|
|
54
|
+
description?: string;
|
|
55
|
+
messageType?: 'success' | 'danger' | 'warning';
|
|
56
|
+
displayType?: 'alert' | 'modal';
|
|
57
|
+
close?: () => void;
|
|
58
|
+
// Propiedad para controlar la visibilidad del modal desde el padre
|
|
59
|
+
open?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const StatusMessage = ({
|
|
63
|
+
title,
|
|
64
|
+
description,
|
|
65
|
+
messageType = 'success',
|
|
66
|
+
displayType = 'alert',
|
|
67
|
+
close,
|
|
68
|
+
open = true,
|
|
69
|
+
}: StatusMessageProps) => {
|
|
70
|
+
|
|
71
|
+
const getAlertVariant = () => {
|
|
72
|
+
switch (messageType) {
|
|
73
|
+
case 'success':
|
|
74
|
+
return 'success';
|
|
75
|
+
case 'danger':
|
|
76
|
+
return 'error';
|
|
77
|
+
case 'warning':
|
|
78
|
+
return 'warning';
|
|
79
|
+
default:
|
|
80
|
+
return 'info'; // Fallback
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const getIcon = () => {
|
|
85
|
+
switch (messageType) {
|
|
86
|
+
case 'success':
|
|
87
|
+
return <CheckCircleOutlineIcon sx={{ fontSize: '64px', color: 'success.main' }} />;
|
|
88
|
+
case 'danger':
|
|
89
|
+
return <ErrorOutlineIcon sx={{ fontSize: '64px', color: 'error.main' }} />;
|
|
90
|
+
case 'warning':
|
|
91
|
+
return <WarningAmberIcon sx={{ fontSize: '64px', color: 'warning.main' }} />;
|
|
92
|
+
default:
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const alertVariant = getAlertVariant();
|
|
98
|
+
|
|
99
|
+
if (!description) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<>
|
|
105
|
+
{displayType === 'modal' ? (
|
|
106
|
+
<Dialog
|
|
107
|
+
open={open}
|
|
108
|
+
onClose={close}
|
|
109
|
+
aria-labelledby="message-dialog-title"
|
|
110
|
+
maxWidth="md"
|
|
111
|
+
PaperProps={{
|
|
112
|
+
sx: {
|
|
113
|
+
borderRadius: '16px',
|
|
114
|
+
p: 2,
|
|
115
|
+
},
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<DialogContent sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', p: 4, gap: 2 }}>
|
|
119
|
+
<Box sx={{ mb: 2 }}>
|
|
120
|
+
{getIcon()}
|
|
121
|
+
</Box>
|
|
122
|
+
<Typography variant="h4" component="h2" sx={{ fontWeight: 'bold' }}>
|
|
123
|
+
{title || ''}
|
|
124
|
+
</Typography>
|
|
125
|
+
<Typography variant="body1" color="text.secondary">
|
|
126
|
+
{description}
|
|
127
|
+
</Typography>
|
|
128
|
+
</DialogContent>
|
|
129
|
+
{close && (
|
|
130
|
+
<DialogActions sx={{ justifyContent: 'center', p: 2 }}>
|
|
131
|
+
<Button onClick={close} variant="contained" color={alertVariant}>
|
|
132
|
+
Aceptar
|
|
133
|
+
</Button>
|
|
134
|
+
</DialogActions>
|
|
135
|
+
)}
|
|
136
|
+
</Dialog>
|
|
137
|
+
) : (
|
|
138
|
+
<Alert
|
|
139
|
+
severity={alertVariant}
|
|
140
|
+
sx={{ mb: 2, mt: 2 }}
|
|
141
|
+
onClose={close}
|
|
142
|
+
action={
|
|
143
|
+
close && (
|
|
144
|
+
<Button onClick={close} size="small" color="inherit">
|
|
145
|
+
Cerrar
|
|
146
|
+
</Button>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
>
|
|
150
|
+
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>
|
|
151
|
+
{title}
|
|
152
|
+
</Typography>
|
|
153
|
+
<Typography variant="body2" sx={{ mt: 1 }}>
|
|
154
|
+
{description}
|
|
155
|
+
</Typography>
|
|
156
|
+
</Alert>
|
|
157
|
+
)}
|
|
158
|
+
</>
|
|
159
|
+
);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export default StatusMessage;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StepProps as MuiStepProps } from "@mui/material";
|
|
3
|
+
|
|
4
|
+
type PickMuiStepProps = Pick<MuiStepProps, "completed" | "disabled" | "sx" | "className">;
|
|
5
|
+
|
|
6
|
+
export interface StepProps extends PickMuiStepProps {
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
sx?: object;
|
|
11
|
+
dotColor?: string; // dot base
|
|
12
|
+
activeDotColor?: string; // dot activa
|
|
13
|
+
completedDotColor?: string; // dot completada
|
|
14
|
+
iconTextColor?: string; // número o check dentro
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const Step = (_: StepProps): null => null;
|
|
18
|
+
|
|
19
|
+
Step.displayName = "Step";
|
|
20
|
+
|
|
21
|
+
export default Step;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export const defaultStepper = `
|
|
2
|
+
const [currentStep, setCurrentStep] = useState(0);
|
|
3
|
+
return (
|
|
4
|
+
<Box>
|
|
5
|
+
<Stepper currentStep={currentStep} {...args}>
|
|
6
|
+
<Step label="Paso 1">
|
|
7
|
+
<div>Contenido del paso 1</div>
|
|
8
|
+
</Step>
|
|
9
|
+
<Step label="Paso 2">
|
|
10
|
+
<div>Contenido del paso 2</div>
|
|
11
|
+
</Step>
|
|
12
|
+
<Step label="Paso 3">
|
|
13
|
+
<div>Contenido del paso 3</div>
|
|
14
|
+
</Step>
|
|
15
|
+
</Stepper>
|
|
16
|
+
<Button
|
|
17
|
+
type="button"
|
|
18
|
+
onClick={() => setCurrentStep((prev) => Math.max(prev - 1, 0))}
|
|
19
|
+
sx={{ marginTop: 16 }}
|
|
20
|
+
>
|
|
21
|
+
Atras
|
|
22
|
+
</Button>
|
|
23
|
+
<Button
|
|
24
|
+
type="button"
|
|
25
|
+
onClick={() => setCurrentStep((prev) => Math.min(prev + 1, 2))}
|
|
26
|
+
sx={{ marginTop: 16 }}
|
|
27
|
+
>
|
|
28
|
+
Siguiente
|
|
29
|
+
</Button>
|
|
30
|
+
</Box>
|
|
31
|
+
);
|
|
32
|
+
`.trim();
|
|
33
|
+
|
|
34
|
+
export const stepperWithColorDots = `
|
|
35
|
+
const [currentStep, setCurrentStep] = useState(0);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Box>
|
|
39
|
+
<Stepper currentStep={currentStep} {...args}>
|
|
40
|
+
<Step
|
|
41
|
+
label="Paso 1"
|
|
42
|
+
dotColor="#1976d2"
|
|
43
|
+
>
|
|
44
|
+
<div>Contenido del paso 1</div>
|
|
45
|
+
</Step>
|
|
46
|
+
<Step
|
|
47
|
+
label="Paso 2"
|
|
48
|
+
dotColor="#ffa726"
|
|
49
|
+
>
|
|
50
|
+
<div>Contenido del paso 2</div>
|
|
51
|
+
</Step>
|
|
52
|
+
<Step
|
|
53
|
+
label="Paso 3"
|
|
54
|
+
dotColor="#4caf50"
|
|
55
|
+
>
|
|
56
|
+
<div>Contenido del paso 3</div>
|
|
57
|
+
</Step>
|
|
58
|
+
</Stepper>
|
|
59
|
+
<Button
|
|
60
|
+
type="button"
|
|
61
|
+
onClick={() => setCurrentStep((prev) => Math.max(prev - 1, 0))}
|
|
62
|
+
sx={{ marginTop: 16 }}
|
|
63
|
+
>
|
|
64
|
+
Atras
|
|
65
|
+
</Button>
|
|
66
|
+
<Button
|
|
67
|
+
type="button"
|
|
68
|
+
onClick={() => setCurrentStep((prev) => Math.min(prev + 1, 2))}
|
|
69
|
+
sx={{ marginTop: 16 }}
|
|
70
|
+
>
|
|
71
|
+
Siguiente
|
|
72
|
+
</Button>
|
|
73
|
+
</Box>
|
|
74
|
+
);
|
|
75
|
+
`.trim();
|