@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,189 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import type { SxProps, Theme } from '@mui/material';
|
|
3
|
+
import { useTheme } from '@mui/material/styles';
|
|
4
|
+
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
5
|
+
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
|
6
|
+
import {
|
|
7
|
+
DatePicker as MuiDatePicker,
|
|
8
|
+
type DatePickerProps as MuiDatePickerProps,
|
|
9
|
+
} from '@mui/x-date-pickers/DatePicker';
|
|
10
|
+
import { DateValidationError } from '@mui/x-date-pickers/models';
|
|
11
|
+
import { Dayjs } from 'dayjs';
|
|
12
|
+
import { Controller, type Control, type RegisterOptions } from 'react-hook-form';
|
|
13
|
+
import 'dayjs/locale/en-gb';
|
|
14
|
+
|
|
15
|
+
import { buildDatePickerSx } from './DatePicker.sx';
|
|
16
|
+
import { getDateValidationMessage } from './DatePicker.helpers';
|
|
17
|
+
import { resolvePreset } from '../_shared/resolvePreset';
|
|
18
|
+
|
|
19
|
+
// ── Tipos de dominio ─────────────────────────────────────────────────────
|
|
20
|
+
export type LabelPosition = 'outside' | 'floating';
|
|
21
|
+
export type DatePickerSize = 'small' | 'medium';
|
|
22
|
+
|
|
23
|
+
// ── Props base ───────────────────────────────────────────────────────────
|
|
24
|
+
export interface BaseDatePickerProps
|
|
25
|
+
extends Omit<MuiDatePickerProps, 'value' | 'onChange' | 'slotProps'> {
|
|
26
|
+
label?: string;
|
|
27
|
+
minDate?: Dayjs;
|
|
28
|
+
maxDate?: Dayjs;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
readOnly?: boolean;
|
|
31
|
+
/** Border radius del input. Default: 10 */
|
|
32
|
+
borderRadius?: number | string;
|
|
33
|
+
/** "outside" = label arriba del campo (default). "floating" = label clásico MUI dentro del borde */
|
|
34
|
+
labelPosition?: LabelPosition;
|
|
35
|
+
/** Tamaño del TextField renderizado. Default: 'small' */
|
|
36
|
+
size?: DatePickerSize;
|
|
37
|
+
/** helperText pasado al TextField (se sobrescribe por el error de validación si hay). */
|
|
38
|
+
helperText?: string;
|
|
39
|
+
/** Error external override. */
|
|
40
|
+
error?: boolean;
|
|
41
|
+
/** sx que se mergea al TextField interno del picker. */
|
|
42
|
+
sx?: SxProps<Theme>;
|
|
43
|
+
className?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Nombre del preset de estilo registrado en `theme.styles.DatePicker`.
|
|
46
|
+
* - `"default"` (o ausente) = estilo built-in del paquete.
|
|
47
|
+
* - Cualquier otro string = mergea el preset encima del estilo built-in.
|
|
48
|
+
*/
|
|
49
|
+
preset?: string;
|
|
50
|
+
/** Locale para el adaptador dayjs. Default: 'en-gb'. */
|
|
51
|
+
adapterLocale?: string;
|
|
52
|
+
/** Passthrough a slotProps.textField. */
|
|
53
|
+
textFieldProps?: Record<string, any>;
|
|
54
|
+
/** Passthrough completo a slotProps del MuiDatePicker. */
|
|
55
|
+
slotProps?: MuiDatePickerProps['slotProps'];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────
|
|
59
|
+
export interface RHFDatePickerProps extends BaseDatePickerProps {
|
|
60
|
+
name: string;
|
|
61
|
+
control: Control<any>;
|
|
62
|
+
validation?: RegisterOptions;
|
|
63
|
+
selectedDate?: never;
|
|
64
|
+
onDateChange?: never;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ControlledDatePickerProps extends BaseDatePickerProps {
|
|
68
|
+
name?: string;
|
|
69
|
+
control?: never;
|
|
70
|
+
validation?: never;
|
|
71
|
+
selectedDate: Dayjs | null;
|
|
72
|
+
onDateChange: (date: Dayjs | null) => void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ── API pública final ────────────────────────────────────────────────────
|
|
76
|
+
export type DatePickerProps = RHFDatePickerProps | ControlledDatePickerProps;
|
|
77
|
+
|
|
78
|
+
export const DatePicker: React.FC<DatePickerProps> = (props) => {
|
|
79
|
+
const {
|
|
80
|
+
label,
|
|
81
|
+
minDate,
|
|
82
|
+
maxDate,
|
|
83
|
+
disabled,
|
|
84
|
+
readOnly,
|
|
85
|
+
borderRadius = 10,
|
|
86
|
+
labelPosition = 'outside',
|
|
87
|
+
size = 'small',
|
|
88
|
+
helperText,
|
|
89
|
+
error: errorProp,
|
|
90
|
+
sx,
|
|
91
|
+
className,
|
|
92
|
+
preset,
|
|
93
|
+
adapterLocale = 'en-gb',
|
|
94
|
+
textFieldProps,
|
|
95
|
+
slotProps: slotPropsProp,
|
|
96
|
+
...rest
|
|
97
|
+
} = props as ControlledDatePickerProps & {
|
|
98
|
+
control?: Control<any>;
|
|
99
|
+
validation?: RegisterOptions;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const [validationError, setValidationError] = React.useState<DateValidationError | null>(null);
|
|
103
|
+
|
|
104
|
+
const validationErrorMessage = useMemo(
|
|
105
|
+
() => getDateValidationMessage(validationError),
|
|
106
|
+
[validationError],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const theme = useTheme();
|
|
110
|
+
const presetSx = resolvePreset('DatePicker', preset, theme);
|
|
111
|
+
|
|
112
|
+
const mergedSx = [
|
|
113
|
+
buildDatePickerSx(borderRadius, labelPosition),
|
|
114
|
+
...(presetSx ? [presetSx] : []),
|
|
115
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
const renderPicker = (
|
|
119
|
+
value: Dayjs | null,
|
|
120
|
+
onChange: (date: Dayjs | null) => void,
|
|
121
|
+
onBlur?: () => void,
|
|
122
|
+
inputRef?: React.Ref<any>,
|
|
123
|
+
rhfError?: boolean,
|
|
124
|
+
rhfHelperText?: string,
|
|
125
|
+
) => {
|
|
126
|
+
const finalError = rhfError || !!validationErrorMessage || !!errorProp;
|
|
127
|
+
const finalHelperText = rhfHelperText || validationErrorMessage || helperText;
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={adapterLocale}>
|
|
131
|
+
<MuiDatePicker
|
|
132
|
+
label={label}
|
|
133
|
+
value={value}
|
|
134
|
+
onChange={onChange}
|
|
135
|
+
minDate={minDate}
|
|
136
|
+
maxDate={maxDate}
|
|
137
|
+
onError={setValidationError}
|
|
138
|
+
disabled={disabled}
|
|
139
|
+
readOnly={readOnly}
|
|
140
|
+
className={className}
|
|
141
|
+
sx={mergedSx}
|
|
142
|
+
slotProps={{
|
|
143
|
+
...slotPropsProp,
|
|
144
|
+
textField: {
|
|
145
|
+
fullWidth: true,
|
|
146
|
+
size,
|
|
147
|
+
variant: 'outlined',
|
|
148
|
+
onBlur,
|
|
149
|
+
inputRef,
|
|
150
|
+
error: !!finalError,
|
|
151
|
+
helperText: finalHelperText,
|
|
152
|
+
...(slotPropsProp?.textField as Record<string, any> | undefined),
|
|
153
|
+
...textFieldProps,
|
|
154
|
+
} as any,
|
|
155
|
+
}}
|
|
156
|
+
{...(rest as any)}
|
|
157
|
+
/>
|
|
158
|
+
</LocalizationProvider>
|
|
159
|
+
);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// --- RHF mode ---
|
|
163
|
+
if ('control' in props && props.control) {
|
|
164
|
+
const { name, control, validation } = props as RHFDatePickerProps;
|
|
165
|
+
return (
|
|
166
|
+
<Controller
|
|
167
|
+
name={name}
|
|
168
|
+
control={control}
|
|
169
|
+
rules={validation}
|
|
170
|
+
render={({ field, fieldState: { error: fieldError } }) =>
|
|
171
|
+
renderPicker(
|
|
172
|
+
field.value ?? null,
|
|
173
|
+
field.onChange,
|
|
174
|
+
field.onBlur,
|
|
175
|
+
field.ref,
|
|
176
|
+
!!fieldError,
|
|
177
|
+
fieldError?.message,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// --- Controlado ---
|
|
185
|
+
const { selectedDate, onDateChange } = props as ControlledDatePickerProps;
|
|
186
|
+
return renderPicker(selectedDate, onDateChange);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export default DatePicker;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Re-export barrel para compatibilidad con imports antiguos.
|
|
2
|
+
// Los tipos ahora viven dentro de DatePicker.tsx.
|
|
3
|
+
export type {
|
|
4
|
+
LabelPosition,
|
|
5
|
+
DatePickerSize,
|
|
6
|
+
BaseDatePickerProps,
|
|
7
|
+
RHFDatePickerProps,
|
|
8
|
+
ControlledDatePickerProps,
|
|
9
|
+
DatePickerProps,
|
|
10
|
+
} from './DatePicker';
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
export const BasicDateRangePickerDefinition = `
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { DateRangePicker } from './DateRangePicker'; // Ajusta la ruta si es necesario
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
|
+
import { Box, Typography } from '@mui/material';
|
|
6
|
+
|
|
7
|
+
export const BasicDateRangePickerExample = () => {
|
|
8
|
+
const [startDate, setStartDate] = useState(dayjs('2023-01-01'));
|
|
9
|
+
const [endDate, setEndDate] = useState(dayjs('2023-01-31'));
|
|
10
|
+
|
|
11
|
+
const handleDateRangeChange = (start, end) => {
|
|
12
|
+
setStartDate(start);
|
|
13
|
+
setEndDate(end);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
18
|
+
<DateRangePicker
|
|
19
|
+
label="Seleccionar Rango"
|
|
20
|
+
startDate={startDate}
|
|
21
|
+
endDate={endDate}
|
|
22
|
+
onDateRangeChange={handleDateRangeChange}
|
|
23
|
+
/>
|
|
24
|
+
<Typography sx={{ mt: 2 }}>
|
|
25
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
26
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
27
|
+
</Typography>
|
|
28
|
+
</Box>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
export const DateRangePickerWithMinMaxDefinition = `
|
|
34
|
+
import React, { useState } from 'react';
|
|
35
|
+
import { DateRangePicker } from './DateRangePicker'; // Ajusta la ruta si es necesario
|
|
36
|
+
import dayjs from 'dayjs';
|
|
37
|
+
import { Box, Typography } from '@mui/material';
|
|
38
|
+
|
|
39
|
+
export const DateRangePickerWithMinMaxExample = () => {
|
|
40
|
+
const [startDate, setStartDate] = useState(dayjs('2023-06-10'));
|
|
41
|
+
const [endDate, setEndDate] = useState(dayjs('2023-06-20'));
|
|
42
|
+
const minDate = dayjs('2023-06-01');
|
|
43
|
+
const maxDate = dayjs('2023-06-30');
|
|
44
|
+
|
|
45
|
+
const handleDateRangeChange = (start, end) => {
|
|
46
|
+
setStartDate(start);
|
|
47
|
+
setEndDate(end);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
52
|
+
<DateRangePicker
|
|
53
|
+
label="Rango de Junio"
|
|
54
|
+
startDate={startDate}
|
|
55
|
+
endDate={endDate}
|
|
56
|
+
onDateRangeChange={handleDateRangeChange}
|
|
57
|
+
minDate={minDate}
|
|
58
|
+
maxDate={maxDate}
|
|
59
|
+
/>
|
|
60
|
+
<Typography sx={{ mt: 2 }}>
|
|
61
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
62
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
63
|
+
</Typography>
|
|
64
|
+
<Typography variant="caption" color="text.secondary">
|
|
65
|
+
(Rango permitido: \${minDate.format('YYYY-MM-DD')} a \${maxDate.format('YYYY-MM-DD')})
|
|
66
|
+
</Typography>
|
|
67
|
+
</Box>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
export const DateRangePickerDisabledDefinition = `
|
|
73
|
+
import React, { useState } from 'react';
|
|
74
|
+
import { DateRangePicker } from './DateRangePicker'; // Ajusta la ruta si es necesario
|
|
75
|
+
import dayjs from 'dayjs';
|
|
76
|
+
import { Box, Typography } from '@mui/material';
|
|
77
|
+
|
|
78
|
+
export const DateRangePickerDisabledExample = () => {
|
|
79
|
+
const [startDate, setStartDate] = useState(dayjs('2023-01-01'));
|
|
80
|
+
const [endDate, setEndDate] = useState(dayjs('2023-01-31'));
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
84
|
+
<DateRangePicker
|
|
85
|
+
label="Rango Deshabilitado"
|
|
86
|
+
startDate={startDate}
|
|
87
|
+
endDate={endDate}
|
|
88
|
+
onDateRangeChange={() => {}}
|
|
89
|
+
disabled
|
|
90
|
+
/>
|
|
91
|
+
<Typography sx={{ mt: 2 }}>
|
|
92
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
93
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
94
|
+
</Typography>
|
|
95
|
+
</Box>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
`;
|
|
99
|
+
|
|
100
|
+
export const DateRangePickerReadOnlyDefinition = `
|
|
101
|
+
import React, { useState } from 'react';
|
|
102
|
+
import { DateRangePicker } from './DateRangePicker'; // Ajusta la ruta si es necesario
|
|
103
|
+
import dayjs from 'dayjs';
|
|
104
|
+
import { Box, Typography } from '@mui/material';
|
|
105
|
+
|
|
106
|
+
export const DateRangePickerReadOnlyExample = () => {
|
|
107
|
+
const [startDate, setStartDate] = useState(dayjs('2024-07-01'));
|
|
108
|
+
const [endDate, setEndDate] = useState(dayjs('2024-07-15'));
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
112
|
+
<DateRangePicker
|
|
113
|
+
label="Rango Solo Lectura"
|
|
114
|
+
startDate={startDate}
|
|
115
|
+
endDate={endDate}
|
|
116
|
+
onDateRangeChange={() => {}}
|
|
117
|
+
readOnly
|
|
118
|
+
/>
|
|
119
|
+
<Typography sx={{ mt: 2 }}>
|
|
120
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
121
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
122
|
+
</Typography>
|
|
123
|
+
</Box>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
export const DateRangePickerWithInitialNullDefinition = `
|
|
129
|
+
import React, { useState } from 'react';
|
|
130
|
+
import { DateRangePicker } from './DateRangePicker'; // Ajusta la ruta si es necesario
|
|
131
|
+
import dayjs from 'dayjs';
|
|
132
|
+
import { Box, Typography } from '@mui/material';
|
|
133
|
+
|
|
134
|
+
export const DateRangePickerWithInitialNullExample = () => {
|
|
135
|
+
const [startDate, setStartDate] = useState(null);
|
|
136
|
+
const [endDate, setEndDate] = useState(null);
|
|
137
|
+
|
|
138
|
+
const handleDateRangeChange = (start, end) => {
|
|
139
|
+
setStartDate(start);
|
|
140
|
+
setEndDate(end);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
145
|
+
<DateRangePicker
|
|
146
|
+
label="Rango Sin Selección Inicial"
|
|
147
|
+
startDate={startDate}
|
|
148
|
+
endDate={endDate}
|
|
149
|
+
onDateRangeChange={handleDateRangeChange}
|
|
150
|
+
/>
|
|
151
|
+
<Typography sx={{ mt: 2 }}>
|
|
152
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
153
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
154
|
+
</Typography>
|
|
155
|
+
</Box>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
`;
|
|
159
|
+
|
|
160
|
+
export const DateRangePickerWithSizeDefinition = `
|
|
161
|
+
import React, { useState } from 'react';
|
|
162
|
+
import { DateRangePicker } from './DateRangePicker'; // Adjust path if necessary
|
|
163
|
+
import dayjs from 'dayjs';
|
|
164
|
+
import { Box, Typography } from '@mui/material';
|
|
165
|
+
|
|
166
|
+
export const DateRangePickerWithSizeExample = () => {
|
|
167
|
+
const [startDate, setStartDate] = useState(dayjs('2023-01-01'));
|
|
168
|
+
const [endDate, setEndDate] = useState(dayjs('2023-01-31'));
|
|
169
|
+
|
|
170
|
+
const handleDateRangeChange = (start, end) => {
|
|
171
|
+
setStartDate(start);
|
|
172
|
+
setEndDate(end);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
177
|
+
<DateRangePicker
|
|
178
|
+
label="Rango de Fechas (Tamaño Pequeño)"
|
|
179
|
+
startDate={startDate}
|
|
180
|
+
endDate={endDate}
|
|
181
|
+
onDateRangeChange={handleDateRangeChange}
|
|
182
|
+
slotProps={{ textField: { size: 'small' } }}
|
|
183
|
+
/>
|
|
184
|
+
<Typography sx={{ mt: 2 }}>
|
|
185
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
186
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
187
|
+
</Typography>
|
|
188
|
+
</Box>
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
`;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { Box, Typography } from '@mui/material';
|
|
4
|
+
import { Dayjs } from 'dayjs';
|
|
5
|
+
import dayjs from 'dayjs';
|
|
6
|
+
|
|
7
|
+
import DateRangePicker from "./DateRangePicker";
|
|
8
|
+
import { BasicDateRangePickerDefinition, DateRangePickerWithMinMaxDefinition, DateRangePickerDisabledDefinition, DateRangePickerReadOnlyDefinition, DateRangePickerWithInitialNullDefinition, DateRangePickerWithSizeDefinition } from './DateRangePicker.definitions';
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
const meta: Meta<typeof DateRangePicker> = {
|
|
12
|
+
title: 'Components/DateRangePicker',
|
|
13
|
+
component: DateRangePicker,
|
|
14
|
+
tags: ['autodocs'],
|
|
15
|
+
parameters: {
|
|
16
|
+
layout: 'centered',
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: 'Un componente `DateRangePicker` personalizado que permite seleccionar un rango de fechas con un solo campo de entrada (visualmente dos inputs interconectados) y gestiona las fechas de inicio y fin.',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
argTypes: {
|
|
24
|
+
label: { control: 'text', description: 'Etiqueta para el campo de entrada del rango de fechas.' },
|
|
25
|
+
startDate: { control: 'object', description: 'La fecha de inicio del rango.', type: { name: 'object', required: false, value: {} } },
|
|
26
|
+
endDate: { control: 'object', description: 'La fecha de fin del rango.', type: { name: 'object', required: false, value: {} } },
|
|
27
|
+
onDateRangeChange: { action: 'dateRangeChanged', description: 'Callback que se dispara cuando el rango de fechas cambia.' },
|
|
28
|
+
minDate: { control: 'object', description: 'La fecha mínima permitida para cualquier fecha en el rango.' },
|
|
29
|
+
maxDate: { control: 'object', description: 'La fecha máxima permitida para cualquier fecha en el rango.' },
|
|
30
|
+
disabled: { control: 'boolean', description: 'Si es verdadero, el selector de rango estará deshabilitado.' },
|
|
31
|
+
readOnly: { control: 'boolean', description: 'Si es verdadero, el selector de rango estará en modo de solo lectura.' },
|
|
32
|
+
slotProps: { control: 'object', description: 'Propiedades pasadas a los slots internos del DateRangePicker (e.g., `textField`).' },
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default meta;
|
|
37
|
+
type Story = StoryObj<typeof DateRangePicker>;
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// Historias
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
export const BasicDateRangePicker: Story = {
|
|
44
|
+
render: () => {
|
|
45
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(dayjs('2023-01-01'));
|
|
46
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(dayjs('2023-01-31'));
|
|
47
|
+
|
|
48
|
+
const handleDateRangeChange = (start: Dayjs | null, end: Dayjs | null) => {
|
|
49
|
+
setStartDate(start);
|
|
50
|
+
setEndDate(end);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
55
|
+
<DateRangePicker
|
|
56
|
+
label="Seleccionar Rango"
|
|
57
|
+
startDate={startDate}
|
|
58
|
+
endDate={endDate}
|
|
59
|
+
onDateRangeChange={handleDateRangeChange}
|
|
60
|
+
/>
|
|
61
|
+
<Typography sx={{ mt: 2 }}>
|
|
62
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
63
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
64
|
+
</Typography>
|
|
65
|
+
</Box>
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
parameters: {
|
|
69
|
+
docs: {
|
|
70
|
+
description: {
|
|
71
|
+
story: "Un `DateRangePicker` básico que permite seleccionar un rango de fechas."
|
|
72
|
+
},
|
|
73
|
+
source: { code: BasicDateRangePickerDefinition.trim() }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const DateRangePickerWithMinMax: Story = {
|
|
79
|
+
render: () => {
|
|
80
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(dayjs('2023-06-10'));
|
|
81
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(dayjs('2023-06-20'));
|
|
82
|
+
const minDate = dayjs('2023-06-01');
|
|
83
|
+
const maxDate = dayjs('2023-06-30');
|
|
84
|
+
|
|
85
|
+
const handleDateRangeChange = (start: Dayjs | null, end: Dayjs | null) => {
|
|
86
|
+
setStartDate(start);
|
|
87
|
+
setEndDate(end);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
92
|
+
<DateRangePicker
|
|
93
|
+
label="Rango de Junio"
|
|
94
|
+
startDate={startDate}
|
|
95
|
+
endDate={endDate}
|
|
96
|
+
onDateRangeChange={handleDateRangeChange}
|
|
97
|
+
minDate={minDate}
|
|
98
|
+
maxDate={maxDate}
|
|
99
|
+
/>
|
|
100
|
+
<Typography sx={{ mt: 2 }}>
|
|
101
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
102
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
103
|
+
</Typography>
|
|
104
|
+
<Typography variant="caption" color="text.secondary">
|
|
105
|
+
(Rango permitido: ${minDate.format('YYYY-MM-DD')} a ${maxDate.format('YYYY-MM-DD')})
|
|
106
|
+
</Typography>
|
|
107
|
+
</Box>
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
parameters: {
|
|
111
|
+
docs: {
|
|
112
|
+
description: {
|
|
113
|
+
story: "Muestra un `DateRangePicker` con fechas mínimas y máximas permitidas para el rango completo."
|
|
114
|
+
},
|
|
115
|
+
source: { code: DateRangePickerWithMinMaxDefinition.trim() }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export const DateRangePickerDisabled: Story = {
|
|
121
|
+
render: () => {
|
|
122
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(dayjs('2023-01-01'));
|
|
123
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(dayjs('2023-01-31'));
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
127
|
+
<DateRangePicker
|
|
128
|
+
label="Rango Deshabilitado"
|
|
129
|
+
startDate={startDate}
|
|
130
|
+
endDate={endDate}
|
|
131
|
+
onDateRangeChange={() => {}}
|
|
132
|
+
disabled
|
|
133
|
+
/>
|
|
134
|
+
<Typography sx={{ mt: 2 }}>
|
|
135
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
136
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
137
|
+
</Typography>
|
|
138
|
+
</Box>
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
parameters: {
|
|
142
|
+
docs: {
|
|
143
|
+
description: {
|
|
144
|
+
story: "Demuestra un `DateRangePicker` en estado deshabilitado."
|
|
145
|
+
},
|
|
146
|
+
source: { code: DateRangePickerDisabledDefinition.trim() }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const DateRangePickerReadOnly: Story = {
|
|
152
|
+
render: () => {
|
|
153
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(dayjs('2024-07-01'));
|
|
154
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(dayjs('2024-07-15'));
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
158
|
+
<DateRangePicker
|
|
159
|
+
label="Rango Solo Lectura"
|
|
160
|
+
startDate={startDate}
|
|
161
|
+
endDate={endDate}
|
|
162
|
+
onDateRangeChange={() => {}}
|
|
163
|
+
readOnly
|
|
164
|
+
/>
|
|
165
|
+
<Typography sx={{ mt: 2 }}>
|
|
166
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
167
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
168
|
+
</Typography>
|
|
169
|
+
</Box>
|
|
170
|
+
);
|
|
171
|
+
},
|
|
172
|
+
parameters: {
|
|
173
|
+
docs: {
|
|
174
|
+
description: {
|
|
175
|
+
story: "Muestra el `DateRangePicker` en modo de solo lectura. El usuario puede ver el rango pero no modificarlo."
|
|
176
|
+
},
|
|
177
|
+
source: { code: DateRangePickerReadOnlyDefinition.trim() }
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const DateRangePickerWithInitialNull: Story = {
|
|
183
|
+
render: () => {
|
|
184
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(null);
|
|
185
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(null);
|
|
186
|
+
|
|
187
|
+
const handleDateRangeChange = (start: Dayjs | null, end: Dayjs | null) => {
|
|
188
|
+
setStartDate(start);
|
|
189
|
+
setEndDate(end);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
194
|
+
<DateRangePicker
|
|
195
|
+
label="Rango Sin Selección Inicial"
|
|
196
|
+
startDate={startDate}
|
|
197
|
+
endDate={endDate}
|
|
198
|
+
onDateRangeChange={handleDateRangeChange}
|
|
199
|
+
/>
|
|
200
|
+
<Typography sx={{ mt: 2 }}>
|
|
201
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
202
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
203
|
+
</Typography>
|
|
204
|
+
</Box>
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
parameters: {
|
|
208
|
+
docs: {
|
|
209
|
+
description: {
|
|
210
|
+
story: "Muestra un `DateRangePicker` sin fechas de inicio o fin seleccionadas inicialmente."
|
|
211
|
+
},
|
|
212
|
+
source: { code: DateRangePickerWithInitialNullDefinition.trim() }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export const DateRangePickerWithSize: Story = {
|
|
218
|
+
render: () => {
|
|
219
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(dayjs('2023-01-01'));
|
|
220
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(dayjs('2023-01-31'));
|
|
221
|
+
|
|
222
|
+
const handleDateRangeChange = (start: Dayjs | null, end: Dayjs | null) => {
|
|
223
|
+
setStartDate(start);
|
|
224
|
+
setEndDate(end);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<Box sx={{ width: 400, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
229
|
+
<DateRangePicker
|
|
230
|
+
label="Rango de Fechas (Tamaño Pequeño)"
|
|
231
|
+
startDate={startDate}
|
|
232
|
+
endDate={endDate}
|
|
233
|
+
onDateRangeChange={handleDateRangeChange}
|
|
234
|
+
slotProps={{ textField: { size: 'small' } }} // Aplica el tamaño 'small' a los TextFields internos
|
|
235
|
+
/>
|
|
236
|
+
<Typography sx={{ mt: 2 }}>
|
|
237
|
+
Inicio: {startDate ? startDate.format('YYYY-MM-DD') : 'N/A'} |
|
|
238
|
+
Fin: {endDate ? endDate.format('YYYY-MM-DD') : 'N/A'}
|
|
239
|
+
</Typography>
|
|
240
|
+
</Box>
|
|
241
|
+
);
|
|
242
|
+
},
|
|
243
|
+
parameters: {
|
|
244
|
+
docs: {
|
|
245
|
+
description: {
|
|
246
|
+
story: "Demuestra cómo aplicar diferentes tamaños (`small` o `medium`) a los campos de entrada del `DateRangePicker`."
|
|
247
|
+
},
|
|
248
|
+
source: { code: DateRangePickerWithSizeDefinition.trim() }
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|