@soyfri/shared-library 2.0.0-beta.1 → 2.0.0-beta.2

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 (181) hide show
  1. package/dist/components/Icon/Icon.js +1 -1
  2. package/dist/components/Table/Table.js +1 -1
  3. package/package.json +32 -4
  4. package/.dockerignore +0 -8
  5. package/.github/workflows/publish.yml +0 -107
  6. package/.prettierrc +0 -3
  7. package/.storybook/main.ts +0 -19
  8. package/.storybook/preview.ts +0 -14
  9. package/.storybook/vitest.setup.ts +0 -9
  10. package/Dockerfile +0 -37
  11. package/build.js +0 -139
  12. package/chromatic.config.json +0 -5
  13. package/cleanDirectories.js +0 -40
  14. package/rollup.config.cjs +0 -87
  15. package/src/components/ActionMenu/ActionMenu.stories.tsx +0 -230
  16. package/src/components/ActionMenu/ActionMenu.tsx +0 -174
  17. package/src/components/ActionMenu/index.ts +0 -2
  18. package/src/components/AppBar/AppBar.stories.tsx +0 -272
  19. package/src/components/AppBar/AppBar.sx.ts +0 -32
  20. package/src/components/AppBar/AppBar.tsx +0 -123
  21. package/src/components/AppBar/AppBarBrand.tsx +0 -120
  22. package/src/components/AppBar/AppBarContext.ts +0 -25
  23. package/src/components/AppBar/AppBarMenuToggle.tsx +0 -90
  24. package/src/components/AppBar/AppBarUserMenu.tsx +0 -217
  25. package/src/components/AppBar/index.ts +0 -25
  26. package/src/components/Autocomplete/Autocomplete.definitions.ts +0 -477
  27. package/src/components/Autocomplete/Autocomplete.helpers.ts +0 -60
  28. package/src/components/Autocomplete/Autocomplete.stories.tsx +0 -748
  29. package/src/components/Autocomplete/Autocomplete.sx.ts +0 -30
  30. package/src/components/Autocomplete/Autocomplete.tsx +0 -361
  31. package/src/components/Autocomplete/Autocomplete.types.ts +0 -13
  32. package/src/components/Autocomplete/_parts/AutocompleteChips.tsx +0 -55
  33. package/src/components/Autocomplete/_parts/AutocompleteLoader.tsx +0 -17
  34. package/src/components/Autocomplete/_parts/AutocompleteOption.tsx +0 -31
  35. package/src/components/Autocomplete/index.ts +0 -12
  36. package/src/components/Avatar/Avatar.definitions.ts +0 -162
  37. package/src/components/Avatar/Avatar.stories.tsx +0 -258
  38. package/src/components/Avatar/Avatar.tsx +0 -206
  39. package/src/components/Avatar/index.ts +0 -1
  40. package/src/components/Button/Button.definition.ts +0 -97
  41. package/src/components/Button/Button.stories.tsx +0 -285
  42. package/src/components/Button/Button.tsx +0 -67
  43. package/src/components/Button/index.ts +0 -1
  44. package/src/components/Card/Card.definition.ts +0 -5
  45. package/src/components/Card/Card.stories.tsx +0 -221
  46. package/src/components/Card/Card.sx.ts +0 -104
  47. package/src/components/Card/Card.tsx +0 -200
  48. package/src/components/Card/index.ts +0 -9
  49. package/src/components/Chip/Chip.definitions.ts +0 -167
  50. package/src/components/Chip/Chip.stories.tsx +0 -265
  51. package/src/components/Chip/Chip.tsx +0 -61
  52. package/src/components/Chip/index.ts +0 -1
  53. package/src/components/Column/Column.tsx +0 -29
  54. package/src/components/Column/index.ts +0 -1
  55. package/src/components/DatePicker/DatePicker.definitions.ts +0 -228
  56. package/src/components/DatePicker/DatePicker.helpers.ts +0 -24
  57. package/src/components/DatePicker/DatePicker.stories.tsx +0 -309
  58. package/src/components/DatePicker/DatePicker.sx.ts +0 -33
  59. package/src/components/DatePicker/DatePicker.tsx +0 -189
  60. package/src/components/DatePicker/DatePicker.types.ts +0 -10
  61. package/src/components/DatePicker/index.ts +0 -9
  62. package/src/components/DateRangePicker/DateRangePicker.definitions.ts +0 -191
  63. package/src/components/DateRangePicker/DateRangePicker.stories.tsx +0 -252
  64. package/src/components/DateRangePicker/DateRangePicker.tsx +0 -56
  65. package/src/components/DateRangePicker/index.ts +0 -1
  66. package/src/components/DateTimePicker/DateTimePicker.definitions.ts +0 -256
  67. package/src/components/DateTimePicker/DateTimePicker.helpers.ts +0 -38
  68. package/src/components/DateTimePicker/DateTimePicker.stories.tsx +0 -418
  69. package/src/components/DateTimePicker/DateTimePicker.sx.ts +0 -30
  70. package/src/components/DateTimePicker/DateTimePicker.tsx +0 -225
  71. package/src/components/DateTimePicker/DateTimePicker.types.ts +0 -10
  72. package/src/components/DateTimePicker/index.ts +0 -9
  73. package/src/components/Drawer/Drawer.stories.tsx +0 -270
  74. package/src/components/Drawer/Drawer.sx.ts +0 -106
  75. package/src/components/Drawer/Drawer.tsx +0 -214
  76. package/src/components/Drawer/DrawerContext.ts +0 -26
  77. package/src/components/Drawer/DrawerItem.tsx +0 -110
  78. package/src/components/Drawer/index.ts +0 -10
  79. package/src/components/Flyout/Flyout.stories.tsx +0 -282
  80. package/src/components/Flyout/Flyout.tsx +0 -122
  81. package/src/components/Flyout/index.ts +0 -1
  82. package/src/components/Gallery/Gallery.definition.tsx +0 -37
  83. package/src/components/Gallery/Gallery.stories.tsx +0 -82
  84. package/src/components/Gallery/Gallery.tsx +0 -118
  85. package/src/components/Gallery/GalleryLightbox.tsx +0 -170
  86. package/src/components/Gallery/GalleryMain.tsx +0 -84
  87. package/src/components/Gallery/GalleryThumbnails.tsx +0 -106
  88. package/src/components/Gallery/index.ts +0 -1
  89. package/src/components/Icon/Icon.stories.tsx +0 -121
  90. package/src/components/Icon/Icon.tsx +0 -175
  91. package/src/components/Icon/index.ts +0 -2
  92. package/src/components/Input/Input.definitions.ts +0 -324
  93. package/src/components/Input/Input.helpers.ts +0 -49
  94. package/src/components/Input/Input.stories.tsx +0 -499
  95. package/src/components/Input/Input.sx.ts +0 -42
  96. package/src/components/Input/Input.tsx +0 -141
  97. package/src/components/Input/Input.types.ts +0 -10
  98. package/src/components/Input/index.ts +0 -9
  99. package/src/components/InputGroup/InputGroup.definitions.ts +0 -158
  100. package/src/components/InputGroup/InputGroup.stories.tsx +0 -267
  101. package/src/components/InputGroup/InputGroup.tsx +0 -179
  102. package/src/components/InputGroup/index.ts +0 -1
  103. package/src/components/MenuButton/MenuButton.stories.tsx +0 -197
  104. package/src/components/MenuButton/MenuButton.tsx +0 -100
  105. package/src/components/MenuButton/index.ts +0 -1
  106. package/src/components/Modal/Modal.stories.tsx +0 -721
  107. package/src/components/Modal/Modal.tsx +0 -355
  108. package/src/components/Modal/ModalBody.tsx +0 -16
  109. package/src/components/Modal/ModalFooter.tsx +0 -71
  110. package/src/components/Modal/ModalHeader.tsx +0 -18
  111. package/src/components/Modal/index.ts +0 -6
  112. package/src/components/PageLoader/PageLoader.stories.tsx +0 -217
  113. package/src/components/PageLoader/PageLoader.tsx +0 -96
  114. package/src/components/PageLoader/index.ts +0 -2
  115. package/src/components/ScrollTopButton/ScrollTopButton.stories.tsx +0 -158
  116. package/src/components/ScrollTopButton/ScrollTopButton.tsx +0 -135
  117. package/src/components/ScrollTopButton/index.ts +0 -8
  118. package/src/components/ScrollTopButton/scrollToTop.ts +0 -37
  119. package/src/components/Select/Select.definitions.ts +0 -602
  120. package/src/components/Select/Select.helpers.ts +0 -71
  121. package/src/components/Select/Select.stories.tsx +0 -687
  122. package/src/components/Select/Select.sx.ts +0 -14
  123. package/src/components/Select/Select.tsx +0 -429
  124. package/src/components/Select/Select.types.ts +0 -15
  125. package/src/components/Select/_parts/SelectMenuItem.tsx +0 -40
  126. package/src/components/Select/_parts/SelectSearchHeader.tsx +0 -51
  127. package/src/components/Select/_parts/SelectValue.tsx +0 -96
  128. package/src/components/Select/index.ts +0 -14
  129. package/src/components/Stat/Stat.stories.tsx +0 -85
  130. package/src/components/Stat/Stat.tsx +0 -117
  131. package/src/components/Stat/index.ts +0 -2
  132. package/src/components/StatusMessage/StatusMessage.stories.tsx +0 -130
  133. package/src/components/StatusMessage/StatusMessage.tsx +0 -162
  134. package/src/components/StatusMessage/index.ts +0 -2
  135. package/src/components/Stepper/Step.tsx +0 -21
  136. package/src/components/Stepper/Stepper.definition.ts +0 -75
  137. package/src/components/Stepper/Stepper.stories.tsx +0 -122
  138. package/src/components/Stepper/Stepper.tsx +0 -75
  139. package/src/components/Stepper/index.ts +0 -2
  140. package/src/components/Table/EmptyTable.png +0 -0
  141. package/src/components/Table/Table.definition.ts +0 -580
  142. package/src/components/Table/Table.stories.tsx +0 -853
  143. package/src/components/Table/Table.tsx +0 -495
  144. package/src/components/Table/data.ts +0 -134
  145. package/src/components/Table/exportsUtils.ts +0 -195
  146. package/src/components/Table/index.ts +0 -3
  147. package/src/components/Table/types.ts +0 -34
  148. package/src/components/Tabs/Tab.definition.ts +0 -53
  149. package/src/components/Tabs/Tab.tsx +0 -19
  150. package/src/components/Tabs/Tabs.stories.tsx +0 -118
  151. package/src/components/Tabs/Tabs.tsx +0 -99
  152. package/src/components/Tabs/_tabUtils.tsx +0 -4
  153. package/src/components/Tabs/index.ts +0 -2
  154. package/src/components/Timeline/Timeline.definition.ts +0 -43
  155. package/src/components/Timeline/Timeline.stories.tsx +0 -108
  156. package/src/components/Timeline/Timeline.tsx +0 -49
  157. package/src/components/Timeline/TimelineItem.tsx +0 -31
  158. package/src/components/Timeline/index.ts +0 -2
  159. package/src/components/Tooltip/Tooltip.stories.tsx +0 -129
  160. package/src/components/Tooltip/Tooltip.tsx +0 -58
  161. package/src/components/Tooltip/index.ts +0 -1
  162. package/src/components/_shared/formField.sx.ts +0 -118
  163. package/src/components/_shared/resolvePreset.ts +0 -35
  164. package/src/hooks/ClipBoard/ClipBoard.stories.tsx +0 -168
  165. package/src/hooks/ClipBoard/ClipBoard.tsx +0 -131
  166. package/src/hooks/ClipBoard/ClipboardUnifiedDemo.tsx +0 -111
  167. package/src/hooks/ClipBoard/index.ts +0 -1
  168. package/src/hooks/Wizard/Wizard.stories.tsx +0 -301
  169. package/src/hooks/Wizard/WizardContext.tsx +0 -166
  170. package/src/hooks/Wizard/index.ts +0 -6
  171. package/src/hooks/Wizard/useWizard.ts +0 -13
  172. package/src/index.ts +0 -17
  173. package/src/mui.ts +0 -44
  174. package/src/styles.css +0 -3
  175. package/src/theme/componentStyles.ts +0 -47
  176. package/src/theme/tokens.ts +0 -43
  177. package/tailwind.config.js +0 -10
  178. package/tsconfig.json +0 -48
  179. package/tsup.config.js +0 -41
  180. package/vite.config.js +0 -132
  181. package/vitest.config.ts +0 -35
@@ -1,355 +0,0 @@
1
- import React, {
2
- useState,
3
- useImperativeHandle,
4
- forwardRef,
5
- type ReactNode,
6
- } from 'react';
7
- import {
8
- Modal as MuiModal,
9
- Paper,
10
- useTheme,
11
- useMediaQuery,
12
- Box,
13
- Stack,
14
- Typography,
15
- } from '@mui/material';
16
- import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
17
- import WarningAmberIcon from '@mui/icons-material/WarningAmber';
18
- import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
19
- import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
20
-
21
- import type { DialogProps } from '@mui/material/Dialog';
22
- import { ModalAction, ModalFooter, ModalFooterProps } from './ModalFooter';
23
- import { ModalHeader } from './ModalHeader';
24
- import { ModalBody } from './ModalBody';
25
-
26
- // Define la interfaz para los métodos que el padre puede llamar a través de la ref
27
- export interface ModalRef {
28
- open: () => void;
29
- close: () => void;
30
- }
31
-
32
- export type ModalMode = 'default' | 'confirm';
33
- export type ModalSeverity = 'info' | 'warning' | 'error' | 'success';
34
-
35
- interface ModalProps {
36
- /**
37
- * Modo del modal.
38
- * - `default` (default): modal genérico con slots `Header`/`Body`/`Footer` y
39
- * `actions` custom.
40
- * - `confirm`: reemplaza al `ConfirmModal` legacy. Renderiza un layout
41
- * focalizado con icono por severidad, mensaje y botones "Cancelar" /
42
- * "Confirmar".
43
- */
44
- mode?: ModalMode;
45
-
46
- // ── Props comunes ────────────────────────────────────────────────────
47
- /** Controlado externamente. Omitir si se usa vía ref. */
48
- open?: boolean;
49
- /** Callback al cerrar. También se dispara al confirmar/cancelar. */
50
- onClose?: () => void;
51
- title?: string;
52
- children?: ReactNode;
53
- showCloseButton?: boolean;
54
- closeButtonText?: string;
55
- closeButtonDisabled?: boolean;
56
- actions?: ModalAction[];
57
- maxWidth?: DialogProps['maxWidth'];
58
- hiddenFooter?: boolean;
59
-
60
- // ── Props del modo confirm ───────────────────────────────────────────
61
- /**
62
- * Callback de confirmación. Soporta promesa — si devuelve `Promise`, el
63
- * botón muestra estado `disabled` mientras resuelve.
64
- */
65
- onConfirm?: () => void | Promise<void>;
66
- /** Texto del botón primario en modo `confirm`. Default: "Confirmar". */
67
- confirmText?: string;
68
- /** Deshabilita el botón de confirmar. */
69
- confirmDisabled?: boolean;
70
- /**
71
- * Severidad visual en modo `confirm`. Controla el icono y el color del
72
- * botón de confirmación.
73
- * - `info` (default): primary
74
- * - `warning`: warning (amarillo)
75
- * - `error`: error (rojo) — típico para "Eliminar"
76
- * - `success`: success (verde) — típico para "Aprobar"
77
- */
78
- severity?: ModalSeverity;
79
- /**
80
- * Mensaje del confirm. Puede ser string o cualquier ReactNode. Si se omite,
81
- * se usa `children`.
82
- */
83
- confirmMessage?: ReactNode;
84
- }
85
-
86
- const modalStyle = {
87
- position: 'absolute' as const,
88
- top: '50%',
89
- left: '50%',
90
- transform: 'translate(-50%, -50%)',
91
- width: '90%',
92
- maxHeight: '90vh',
93
- display: 'flex',
94
- flexDirection: 'column' as const,
95
- outline: 'none',
96
- };
97
-
98
- const severityConfig: Record<
99
- ModalSeverity,
100
- { color: ModalAction['color']; icon: ReactNode; bg: string }
101
- > = {
102
- info: {
103
- color: 'primary',
104
- icon: <InfoOutlinedIcon sx={{ fontSize: 48 }} />,
105
- bg: 'primary.light',
106
- },
107
- warning: {
108
- color: 'warning',
109
- icon: <WarningAmberIcon sx={{ fontSize: 48 }} />,
110
- bg: 'warning.light',
111
- },
112
- error: {
113
- color: 'error',
114
- icon: <ErrorOutlineIcon sx={{ fontSize: 48 }} />,
115
- bg: 'error.light',
116
- },
117
- success: {
118
- color: 'success',
119
- icon: <CheckCircleOutlineIcon sx={{ fontSize: 48 }} />,
120
- bg: 'success.light',
121
- },
122
- };
123
-
124
- export const Modal = forwardRef<ModalRef, ModalProps>(
125
- (
126
- {
127
- mode = 'default',
128
- open: controlledOpen,
129
- onClose: controlledOnClose,
130
- title,
131
- children,
132
- showCloseButton = true,
133
- closeButtonText = 'Cerrar',
134
- closeButtonDisabled = false,
135
- actions = [],
136
- maxWidth = 'sm',
137
- hiddenFooter = false,
138
-
139
- // Props del modo confirm
140
- onConfirm,
141
- confirmText = 'Confirmar',
142
- confirmDisabled = false,
143
- severity = 'info',
144
- confirmMessage,
145
- },
146
- ref,
147
- ) => {
148
- const [internalOpen, setInternalOpen] = useState(false);
149
- const [confirmLoading, setConfirmLoading] = useState(false);
150
-
151
- const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;
152
-
153
- useImperativeHandle(ref, () => ({
154
- open: () => setInternalOpen(true),
155
- close: () => {
156
- setInternalOpen(false);
157
- controlledOnClose?.();
158
- },
159
- }));
160
-
161
- const handleCloseInternal = () => {
162
- setInternalOpen(false);
163
- controlledOnClose?.();
164
- };
165
-
166
- const handleConfirm = async () => {
167
- if (!onConfirm) {
168
- handleCloseInternal();
169
- return;
170
- }
171
- try {
172
- const result = onConfirm();
173
- if (result instanceof Promise) {
174
- setConfirmLoading(true);
175
- await result;
176
- }
177
- } finally {
178
- setConfirmLoading(false);
179
- handleCloseInternal();
180
- }
181
- };
182
-
183
- const theme = useTheme();
184
- const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
185
-
186
- const getWidth = () => {
187
- if (isMobile) return '95%';
188
- switch (maxWidth) {
189
- case 'xs':
190
- return 300;
191
- case 'sm':
192
- return 500;
193
- case 'md':
194
- return 700;
195
- case 'lg':
196
- return 900;
197
- case 'xl':
198
- return 1100;
199
- case false:
200
- return 'auto';
201
- default:
202
- return 500;
203
- }
204
- };
205
-
206
- // ── Render modo CONFIRM ─────────────────────────────────────────────
207
- if (mode === 'confirm') {
208
- const config = severityConfig[severity];
209
- const message = confirmMessage ?? children;
210
-
211
- return (
212
- <MuiModal
213
- open={isOpen}
214
- onClose={handleCloseInternal}
215
- aria-labelledby="modal-title"
216
- closeAfterTransition
217
- >
218
- <Paper sx={{ ...modalStyle, width: getWidth() }}>
219
- <Stack spacing={2.5} sx={{ p: 3, alignItems: 'center', textAlign: 'center' }}>
220
- <Box
221
- sx={{
222
- width: 72,
223
- height: 72,
224
- borderRadius: '50%',
225
- backgroundColor: (t) =>
226
- t.palette[severity === 'info' ? 'primary' : severity].light,
227
- color: (t) =>
228
- t.palette[severity === 'info' ? 'primary' : severity].dark,
229
- display: 'flex',
230
- alignItems: 'center',
231
- justifyContent: 'center',
232
- opacity: 0.9,
233
- }}
234
- >
235
- {config.icon}
236
- </Box>
237
- {title && (
238
- <Typography variant="h6" component="h2" sx={{ fontWeight: 700 }}>
239
- {title}
240
- </Typography>
241
- )}
242
- {message && (
243
- <Typography variant="body2" color="text.secondary">
244
- {message}
245
- </Typography>
246
- )}
247
- </Stack>
248
- <ModalFooter
249
- showCloseButton={showCloseButton}
250
- closeButtonText={closeButtonText}
251
- closeButtonDisabled={closeButtonDisabled || confirmLoading}
252
- onClose={handleCloseInternal}
253
- actions={[
254
- {
255
- text: confirmText,
256
- onClick: handleConfirm,
257
- disabled: confirmDisabled || confirmLoading,
258
- variant: 'contained',
259
- color: config.color,
260
- },
261
- ]}
262
- />
263
- </Paper>
264
- </MuiModal>
265
- );
266
- }
267
-
268
- // ── Render modo DEFAULT (legacy) ────────────────────────────────────
269
- const renderChildren = () => {
270
- let header: ReactNode | null = null;
271
- let body: ReactNode | null = null;
272
- let footer: ReactNode | null = null;
273
-
274
- React.Children.forEach(children, (child) => {
275
- if (React.isValidElement(child)) {
276
- if (child.type === ModalHeader) {
277
- header = child;
278
- } else if (child.type === ModalBody) {
279
- body = child;
280
- } else if (child.type === ModalFooter) {
281
- const footerChild = child as React.ReactElement<ModalFooterProps>;
282
- const {
283
- showCloseButton: childShowCloseButton,
284
- closeButtonText: childCloseButtonText,
285
- closeButtonDisabled: childCloseButtonDisabled,
286
- onClose: childOnClose,
287
- actions: childActions,
288
- ...restOfFooterProps
289
- } = footerChild.props;
290
-
291
- footer = React.cloneElement(footerChild, {
292
- showCloseButton,
293
- closeButtonText,
294
- closeButtonDisabled,
295
- onClose: handleCloseInternal,
296
- actions,
297
- ...restOfFooterProps,
298
- });
299
- }
300
- }
301
- });
302
-
303
- if (!footer && !hiddenFooter) {
304
- footer = (
305
- <ModalFooter
306
- showCloseButton={showCloseButton}
307
- closeButtonText={closeButtonText}
308
- closeButtonDisabled={closeButtonDisabled}
309
- onClose={handleCloseInternal}
310
- actions={actions}
311
- />
312
- );
313
- }
314
-
315
- return (
316
- <>
317
- {header || (title && <ModalHeader>{title}</ModalHeader>)}
318
- {body}
319
- {footer}
320
- </>
321
- );
322
- };
323
-
324
- return (
325
- <MuiModal
326
- open={isOpen}
327
- onClose={handleCloseInternal}
328
- aria-labelledby="modal-title"
329
- aria-describedby="modal-description"
330
- closeAfterTransition
331
- >
332
- <Paper sx={{ ...modalStyle, width: getWidth() }}>
333
- {renderChildren()}
334
- </Paper>
335
- </MuiModal>
336
- );
337
- },
338
- );
339
-
340
- // Define los sub-componentes como propiedades estáticas con tipos explícitos
341
- type ModalComponent = React.ForwardRefExoticComponent<
342
- ModalProps & React.RefAttributes<ModalRef>
343
- > & {
344
- Header: typeof ModalHeader;
345
- Body: typeof ModalBody;
346
- Footer: typeof ModalFooter;
347
- };
348
-
349
- const ModalWithStatics = Modal as ModalComponent;
350
-
351
- ModalWithStatics.Header = ModalHeader;
352
- ModalWithStatics.Body = ModalBody;
353
- ModalWithStatics.Footer = ModalFooter;
354
-
355
- export default ModalWithStatics;
@@ -1,16 +0,0 @@
1
- import React from 'react';
2
- import { Box } from '@mui/material';
3
-
4
- interface ModalBodyProps { // Renombrado
5
- children: React.ReactNode;
6
- }
7
-
8
- export const ModalBody: React.FC<ModalBodyProps> = ({ children }) => { // Renombrado
9
- return (
10
- <Box sx={{ padding: 2, overflowY: 'auto', flexGrow: 1 }}>
11
- {children}
12
- </Box>
13
- );
14
- };
15
-
16
- export default ModalBody;
@@ -1,71 +0,0 @@
1
- import React from 'react';
2
- import { Box, Button, Stack } from '@mui/material';
3
- import { ButtonProps } from '@mui/material/Button';
4
-
5
- // Interfaz para acciones personalizadas (se mantiene aquí)
6
- export interface ModalAction {
7
- text: string;
8
- onClick?: () => void;
9
- disabled?: boolean;
10
- variant?: ButtonProps['variant'];
11
- color?: ButtonProps['color'];
12
- /**
13
- * Props adicionales que se forwardean al `<Button>` interno. Útil para casos
14
- * avanzados como conectar el botón con un `<form id="...">` externo usando
15
- * `buttonProps={{ type: 'submit', form: 'my-form-id' }}`.
16
- */
17
- buttonProps?: Partial<ButtonProps> & { form?: string };
18
- }
19
-
20
- export interface ModalFooterProps { // Renombrado
21
- children?: React.ReactNode;
22
- showCloseButton?: boolean;
23
- closeButtonText?: string;
24
- closeButtonDisabled?: boolean;
25
- onClose: () => void;
26
- actions?: ModalAction[];
27
- }
28
-
29
- export const ModalFooter: React.FC<ModalFooterProps> = ({ // Renombrado
30
- children,
31
- showCloseButton = true,
32
- closeButtonText = "Cerrar",
33
- closeButtonDisabled = false,
34
- onClose,
35
- actions = [],
36
- }) => {
37
- return (
38
- <Box sx={{ padding: 2, borderTop: '1px solid #e0e0e0', display: 'flex', justifyContent: 'flex-end', gap: 1 }}>
39
- {children}
40
- <Stack direction="row" spacing={1}>
41
- {showCloseButton && (
42
- <Button
43
- onClick={onClose}
44
- disabled={closeButtonDisabled}
45
- variant="outlined"
46
- color="secondary"
47
- >
48
- {closeButtonText}
49
- </Button>
50
- )}
51
- {actions.map((action, index) => {
52
- const { buttonProps } = action;
53
- return (
54
- <Button
55
- key={index}
56
- onClick={action.onClick}
57
- disabled={action.disabled}
58
- variant={action.variant || 'contained'}
59
- color={action.color || 'primary'}
60
- {...(buttonProps as any)}
61
- >
62
- {action.text}
63
- </Button>
64
- );
65
- })}
66
- </Stack>
67
- </Box>
68
- );
69
- };
70
-
71
- export default ModalFooter;
@@ -1,18 +0,0 @@
1
- import React from 'react';
2
- import { Box, Typography } from '@mui/material';
3
-
4
- interface ModalHeaderProps { // Renombrado
5
- children: React.ReactNode;
6
- }
7
-
8
- export const ModalHeader: React.FC<ModalHeaderProps> = ({ children }) => { // Renombrado
9
- return (
10
- <Box sx={{ padding: 2, borderBottom: '1px solid #e0e0e0', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
11
- <Typography variant="h6" component="h2">
12
- {children}
13
- </Typography>
14
- </Box>
15
- );
16
- };
17
-
18
- export default ModalHeader;
@@ -1,6 +0,0 @@
1
- export { default as Modal } from './Modal';
2
- export type { ModalRef, ModalMode, ModalSeverity } from './Modal';
3
- export { ModalHeader } from './ModalHeader';
4
- export { ModalBody } from './ModalBody';
5
- export { ModalFooter } from './ModalFooter';
6
- export type { ModalAction, ModalFooterProps } from './ModalFooter';
@@ -1,217 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react';
3
- import { Box, Button, Paper, Typography } from '@mui/material';
4
-
5
- import { PageLoader } from './PageLoader';
6
-
7
- const meta: Meta<typeof PageLoader> = {
8
- title: 'Components/PageLoader',
9
- component: PageLoader,
10
- tags: ['autodocs'],
11
- parameters: {
12
- layout: 'fullscreen',
13
- docs: {
14
- description: {
15
- component:
16
- 'Loader visual para estados de carga, tanto a nivel de página completa (splash screen) como inline dentro de un contenedor. Reemplaza el `LayoutSplashScreen` de Metronic.',
17
- },
18
- },
19
- },
20
- argTypes: {
21
- fullscreen: {
22
- control: 'boolean',
23
- description: 'Ocupa toda la ventana con backdrop. Default: true.',
24
- },
25
- size: {
26
- control: { type: 'number', min: 16, max: 120, step: 4 },
27
- description: 'Tamaño del spinner en px.',
28
- },
29
- open: {
30
- control: 'boolean',
31
- description: 'Si es false, el loader se desmonta (con fade en fullscreen).',
32
- },
33
- },
34
- };
35
-
36
- export default meta;
37
- type Story = StoryObj<typeof PageLoader>;
38
-
39
- // ── Stories ──────────────────────────────────────────────────────────────
40
-
41
- export const FullscreenDefault: Story = {
42
- args: {
43
- fullscreen: true,
44
- open: true,
45
- },
46
- parameters: {
47
- docs: {
48
- description: {
49
- story: 'Loader full-page sin texto ni logo. Caso más minimal.',
50
- },
51
- },
52
- },
53
- };
54
-
55
- export const FullscreenWithMessage: Story = {
56
- args: {
57
- fullscreen: true,
58
- open: true,
59
- message: 'Cargando aplicación...',
60
- },
61
- parameters: {
62
- docs: {
63
- description: {
64
- story: 'Splash screen típico con mensaje bajo el spinner.',
65
- },
66
- },
67
- },
68
- };
69
-
70
- export const FullscreenWithLogo: Story = {
71
- args: {
72
- fullscreen: true,
73
- open: true,
74
- message: 'Inicializando...',
75
- logo: (
76
- <Box
77
- sx={{
78
- width: 120,
79
- height: 120,
80
- borderRadius: '50%',
81
- bgcolor: 'primary.main',
82
- color: '#fff',
83
- display: 'flex',
84
- alignItems: 'center',
85
- justifyContent: 'center',
86
- fontSize: 36,
87
- fontWeight: 700,
88
- }}
89
- >
90
- fri
91
- </Box>
92
- ),
93
- size: 40,
94
- },
95
- parameters: {
96
- docs: {
97
- description: {
98
- story:
99
- 'Splash de arranque de app con logo/branding arriba del spinner. Equivalente visual al `LayoutSplashScreen` de Metronic.',
100
- },
101
- },
102
- },
103
- };
104
-
105
- export const Inline: Story = {
106
- args: {
107
- fullscreen: false,
108
- open: true,
109
- message: 'Cargando datos',
110
- size: 32,
111
- },
112
- render: (args) => (
113
- <Paper sx={{ maxWidth: 480, mx: 'auto', mt: 4 }}>
114
- <Box sx={{ p: 2, borderBottom: 1, borderColor: 'divider' }}>
115
- <Typography variant="subtitle1" sx={{ fontWeight: 600 }}>
116
- Panel de resumen
117
- </Typography>
118
- </Box>
119
- <PageLoader {...args} />
120
- </Paper>
121
- ),
122
- parameters: {
123
- docs: {
124
- description: {
125
- story:
126
- 'Loader inline (no fullscreen). Ocupa el ancho del contenedor padre y tiene una altura mínima. Útil dentro de cards mientras se cargan datos.',
127
- },
128
- },
129
- },
130
- };
131
-
132
- export const ToggledFullscreen: Story = {
133
- render: () => {
134
- const [loading, setLoading] = useState(false);
135
-
136
- const simulate = () => {
137
- setLoading(true);
138
- setTimeout(() => setLoading(false), 1800);
139
- };
140
-
141
- return (
142
- <Box sx={{ p: 4, height: '100vh' }}>
143
- <Typography variant="h5" gutterBottom>
144
- Simulación de carga
145
- </Typography>
146
- <Typography color="text.secondary" sx={{ mb: 2 }}>
147
- Al hacer click, el loader aparece por 1.8s y luego desaparece con fade.
148
- </Typography>
149
- <Button variant="contained" onClick={simulate}>
150
- Simular carga
151
- </Button>
152
-
153
- <PageLoader
154
- fullscreen
155
- open={loading}
156
- message="Procesando..."
157
- logo={
158
- <Box
159
- sx={{
160
- width: 72,
161
- height: 72,
162
- borderRadius: 2,
163
- bgcolor: 'primary.main',
164
- color: '#fff',
165
- display: 'flex',
166
- alignItems: 'center',
167
- justifyContent: 'center',
168
- fontSize: 24,
169
- fontWeight: 700,
170
- }}
171
- >
172
- fri
173
- </Box>
174
- }
175
- />
176
- </Box>
177
- );
178
- },
179
- parameters: {
180
- docs: {
181
- description: {
182
- story:
183
- 'Ejemplo controlado: el loader se monta/desmonta según un estado externo, con fade de salida. Patrón típico para bloquear la app durante una operación crítica (auth, inicialización, navegación global).',
184
- },
185
- },
186
- },
187
- };
188
-
189
- export const AutoDismiss: Story = {
190
- render: () => {
191
- const [open, setOpen] = useState(true);
192
-
193
- useEffect(() => {
194
- const t = setTimeout(() => setOpen(false), 2000);
195
- return () => clearTimeout(t);
196
- }, []);
197
-
198
- return (
199
- <Box sx={{ p: 4, height: '100vh' }}>
200
- {!open && (
201
- <Typography variant="h5">
202
- App lista. (El loader se cerró tras 2s.)
203
- </Typography>
204
- )}
205
- <PageLoader open={open} message="Cargando..." />
206
- </Box>
207
- );
208
- },
209
- parameters: {
210
- docs: {
211
- description: {
212
- story:
213
- 'Arranque típico: el loader aparece al montar, y el consumer lo cierra cuando termina la inicialización. Aquí simulamos 2 segundos fijos.',
214
- },
215
- },
216
- },
217
- };