@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,477 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// SIMPLE
|
|
3
|
+
// =============================================================================
|
|
4
|
+
export const SimpleAutocompleteDefinition = `
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
import Autocomplete from './Autocomplete';
|
|
7
|
+
import { Box, Typography } from '@mui/material';
|
|
8
|
+
|
|
9
|
+
const options = [
|
|
10
|
+
{ value: '10', label: '10' },
|
|
11
|
+
{ value: '25', label: '25' },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export const SimpleExample = () => {
|
|
15
|
+
const [value, setValue] = useState(options[1]);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Box sx={{ width: 250 }}>
|
|
19
|
+
<Autocomplete
|
|
20
|
+
label="Registros por página"
|
|
21
|
+
options={options}
|
|
22
|
+
value={value}
|
|
23
|
+
onChange={(val) => {
|
|
24
|
+
setValue(val as string);
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
<Typography sx={{ mt: 2 }}>
|
|
28
|
+
Valor: {value}
|
|
29
|
+
</Typography>
|
|
30
|
+
</Box>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// PLACEHOLDER
|
|
37
|
+
// =============================================================================
|
|
38
|
+
export const WithPlaceholderAutocompleteDefinition = `
|
|
39
|
+
import React, { useState } from 'react';
|
|
40
|
+
import Autocomplete from './Autocomplete';
|
|
41
|
+
import { Box, Typography } from '@mui/material';
|
|
42
|
+
|
|
43
|
+
export const WithPlaceholderExample = () => {
|
|
44
|
+
const [value, setValue] = useState(null);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Box sx={{ width: 300 }}>
|
|
48
|
+
<Autocomplete
|
|
49
|
+
label="Seleccione una opción"
|
|
50
|
+
options={[]}
|
|
51
|
+
value={value}
|
|
52
|
+
onChange={(val) => {
|
|
53
|
+
setValue(val as string);
|
|
54
|
+
}}
|
|
55
|
+
placeholder="Ninguna opción seleccionada"
|
|
56
|
+
/>
|
|
57
|
+
<Typography sx={{ mt: 2 }}>
|
|
58
|
+
{value || 'Ninguno'}
|
|
59
|
+
</Typography>
|
|
60
|
+
</Box>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// MULTIPLE
|
|
67
|
+
// =============================================================================
|
|
68
|
+
export const MultipleAutocompleteDefinition = `
|
|
69
|
+
import React, { useState } from 'react';
|
|
70
|
+
import Autocomplete from './Autocomplete';
|
|
71
|
+
import { Box } from '@mui/material';
|
|
72
|
+
|
|
73
|
+
const options = [
|
|
74
|
+
{ value: 'pending', label: 'Pendiente' },
|
|
75
|
+
{ value: 'approved', label: 'Aprobado' },
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
export const MultipleExample = () => {
|
|
79
|
+
const [value, setValue] = useState([]);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Box sx={{ width: 400 }}>
|
|
83
|
+
<Autocomplete
|
|
84
|
+
multiple
|
|
85
|
+
options={options}
|
|
86
|
+
value={value}
|
|
87
|
+
onChange={(val) => {
|
|
88
|
+
setValue(val as string[]);
|
|
89
|
+
}}
|
|
90
|
+
/>
|
|
91
|
+
</Box>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
`;
|
|
95
|
+
|
|
96
|
+
// =============================================================================
|
|
97
|
+
// MULTIPLE LIMIT
|
|
98
|
+
// =============================================================================
|
|
99
|
+
export const MultipleWithLimitAutocompleteDefinition = `
|
|
100
|
+
import React, { useState } from 'react';
|
|
101
|
+
import Autocomplete from './Autocomplete';
|
|
102
|
+
|
|
103
|
+
export const MultipleWithLimitExample = () => {
|
|
104
|
+
const [value, setValue] = useState([]);
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<Autocomplete
|
|
108
|
+
multiple
|
|
109
|
+
maxChipsToShow={2}
|
|
110
|
+
options={[]}
|
|
111
|
+
value={value}
|
|
112
|
+
onChange={(val) => {
|
|
113
|
+
setValue(val as string[]);
|
|
114
|
+
}}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
// =============================================================================
|
|
121
|
+
// CUSTOM OPTION
|
|
122
|
+
// =============================================================================
|
|
123
|
+
export const CustomRenderOptionAutocompleteDefinition = `
|
|
124
|
+
import React, { useState } from 'react';
|
|
125
|
+
import Autocomplete from './Autocomplete';
|
|
126
|
+
import { Avatar, Box } from '@mui/material';
|
|
127
|
+
|
|
128
|
+
const users = [
|
|
129
|
+
{ value: 'admin', label: 'Administrador', img: '...' },
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
export const CustomRenderExample = () => {
|
|
133
|
+
const [value, setValue] = useState([]);
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<Autocomplete
|
|
137
|
+
multiple
|
|
138
|
+
options={users}
|
|
139
|
+
value={value}
|
|
140
|
+
onChange={(val) => {
|
|
141
|
+
setValue(val as string[]);
|
|
142
|
+
}}
|
|
143
|
+
renderOptionItem={(item) => (
|
|
144
|
+
<Box sx={{ display: 'flex', gap: 1 }}>
|
|
145
|
+
<Avatar src={item.img} />
|
|
146
|
+
{item.label}
|
|
147
|
+
</Box>
|
|
148
|
+
)}
|
|
149
|
+
/>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
`;
|
|
153
|
+
|
|
154
|
+
// =============================================================================
|
|
155
|
+
// CUSTOM CHIP
|
|
156
|
+
// =============================================================================
|
|
157
|
+
export const CustomChipRenderAutocompleteDefinition = `
|
|
158
|
+
import React, { useState } from 'react';
|
|
159
|
+
import Autocomplete from './Autocomplete';
|
|
160
|
+
import { Typography } from '@mui/material';
|
|
161
|
+
|
|
162
|
+
export const CustomChipExample = () => {
|
|
163
|
+
const [value, setValue] = useState([]);
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<Autocomplete
|
|
167
|
+
multiple
|
|
168
|
+
options={[]}
|
|
169
|
+
value={value}
|
|
170
|
+
onChange={(val) => {
|
|
171
|
+
setValue(val as string[]);
|
|
172
|
+
}}
|
|
173
|
+
renderChipLabel={(item) => (
|
|
174
|
+
<Typography variant="caption">
|
|
175
|
+
{item.label.charAt(0)}
|
|
176
|
+
</Typography>
|
|
177
|
+
)}
|
|
178
|
+
/>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
181
|
+
`;
|
|
182
|
+
|
|
183
|
+
// =============================================================================
|
|
184
|
+
// LOADING
|
|
185
|
+
// =============================================================================
|
|
186
|
+
export const LoadingAutocompleteDefinition = `
|
|
187
|
+
import React, { useState } from 'react';
|
|
188
|
+
import Autocomplete from './Autocomplete';
|
|
189
|
+
|
|
190
|
+
export const LoadingExample = () => {
|
|
191
|
+
const [value, setValue] = useState(null);
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<Autocomplete
|
|
195
|
+
loading
|
|
196
|
+
options={[]}
|
|
197
|
+
value={value}
|
|
198
|
+
onChange={(val) => {
|
|
199
|
+
setValue(val as string);
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
`;
|
|
205
|
+
|
|
206
|
+
// =============================================================================
|
|
207
|
+
// EMPTY
|
|
208
|
+
// =============================================================================
|
|
209
|
+
export const EmptyOptionsAutocompleteDefinition = `
|
|
210
|
+
import React, { useState } from 'react';
|
|
211
|
+
import Autocomplete from './Autocomplete';
|
|
212
|
+
|
|
213
|
+
export const EmptyExample = () => {
|
|
214
|
+
const [value, setValue] = useState(null);
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<Autocomplete
|
|
218
|
+
options={[]}
|
|
219
|
+
value={value}
|
|
220
|
+
onChange={(val) => {
|
|
221
|
+
setValue(val as string);
|
|
222
|
+
}}
|
|
223
|
+
placeholder="No hay opciones"
|
|
224
|
+
/>
|
|
225
|
+
);
|
|
226
|
+
};
|
|
227
|
+
`;
|
|
228
|
+
|
|
229
|
+
// =============================================================================
|
|
230
|
+
// MANY
|
|
231
|
+
// =============================================================================
|
|
232
|
+
export const ManyOptionsAutocompleteDefinition = `
|
|
233
|
+
import React, { useState } from 'react';
|
|
234
|
+
import Autocomplete from './Autocomplete';
|
|
235
|
+
|
|
236
|
+
const options = Array.from({ length: 50 }, (_, i) => ({
|
|
237
|
+
value: i,
|
|
238
|
+
label: 'Opción ' + i,
|
|
239
|
+
}));
|
|
240
|
+
|
|
241
|
+
export const ManyOptionsExample = () => {
|
|
242
|
+
const [value, setValue] = useState(null);
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
<Autocomplete
|
|
246
|
+
options={options}
|
|
247
|
+
value={value}
|
|
248
|
+
onChange={(val) => {
|
|
249
|
+
setValue(val as string);
|
|
250
|
+
}}
|
|
251
|
+
/>
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
`;
|
|
255
|
+
|
|
256
|
+
// =============================================================================
|
|
257
|
+
// WITH ERROR / HELPER TEXT
|
|
258
|
+
// =============================================================================
|
|
259
|
+
export const WithErrorAutocompleteDefinition = `
|
|
260
|
+
import React, { useState } from 'react';
|
|
261
|
+
import Autocomplete from './Autocomplete';
|
|
262
|
+
import { Box } from '@mui/material';
|
|
263
|
+
|
|
264
|
+
const options = [
|
|
265
|
+
{ value: '10', label: '10' },
|
|
266
|
+
{ value: '25', label: '25' },
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
export const WithErrorExample = () => {
|
|
270
|
+
const [value, setValue] = useState<string | null>(null);
|
|
271
|
+
return (
|
|
272
|
+
<Box sx={{ width: 300 }}>
|
|
273
|
+
<Autocomplete
|
|
274
|
+
label="Cantidad"
|
|
275
|
+
options={options}
|
|
276
|
+
value={value}
|
|
277
|
+
onChange={(val) => setValue(val as string | null)}
|
|
278
|
+
error={\!value}
|
|
279
|
+
helperText={\!value ? 'Debes seleccionar una cantidad' : ' '}
|
|
280
|
+
/>
|
|
281
|
+
</Box>
|
|
282
|
+
);
|
|
283
|
+
};
|
|
284
|
+
`;
|
|
285
|
+
|
|
286
|
+
// =============================================================================
|
|
287
|
+
// LABEL POSITION
|
|
288
|
+
// =============================================================================
|
|
289
|
+
export const LabelPositionAutocompleteDefinition = `
|
|
290
|
+
import React, { useState } from 'react';
|
|
291
|
+
import Autocomplete from './Autocomplete';
|
|
292
|
+
import { Box, Stack } from '@mui/material';
|
|
293
|
+
|
|
294
|
+
const options = [
|
|
295
|
+
{ value: 'a', label: 'Opción A' },
|
|
296
|
+
{ value: 'b', label: 'Opción B' },
|
|
297
|
+
];
|
|
298
|
+
|
|
299
|
+
export const LabelPositionExample = () => {
|
|
300
|
+
const [a, setA] = useState<string | null>(null);
|
|
301
|
+
const [b, setB] = useState<string | null>(null);
|
|
302
|
+
return (
|
|
303
|
+
<Stack spacing={3} sx={{ width: 320 }}>
|
|
304
|
+
<Autocomplete
|
|
305
|
+
label="Outside (default)"
|
|
306
|
+
labelPosition="outside"
|
|
307
|
+
options={options}
|
|
308
|
+
value={a}
|
|
309
|
+
onChange={(val) => setA(val as string | null)}
|
|
310
|
+
/>
|
|
311
|
+
<Autocomplete
|
|
312
|
+
label="Floating"
|
|
313
|
+
labelPosition="floating"
|
|
314
|
+
options={options}
|
|
315
|
+
value={b}
|
|
316
|
+
onChange={(val) => setB(val as string | null)}
|
|
317
|
+
/>
|
|
318
|
+
</Stack>
|
|
319
|
+
);
|
|
320
|
+
};
|
|
321
|
+
`;
|
|
322
|
+
|
|
323
|
+
// =============================================================================
|
|
324
|
+
// CUSTOM BORDER RADIUS
|
|
325
|
+
// =============================================================================
|
|
326
|
+
export const CustomBorderRadiusAutocompleteDefinition = `
|
|
327
|
+
import React, { useState } from 'react';
|
|
328
|
+
import Autocomplete from './Autocomplete';
|
|
329
|
+
import { Box, Stack } from '@mui/material';
|
|
330
|
+
|
|
331
|
+
const options = [
|
|
332
|
+
{ value: '10', label: '10' },
|
|
333
|
+
{ value: '25', label: '25' },
|
|
334
|
+
];
|
|
335
|
+
|
|
336
|
+
export const CustomBorderRadiusExample = () => {
|
|
337
|
+
const [a, setA] = useState<string | null>(null);
|
|
338
|
+
const [b, setB] = useState<string | null>(null);
|
|
339
|
+
const [c, setC] = useState<string | null>(null);
|
|
340
|
+
return (
|
|
341
|
+
<Stack spacing={2} sx={{ width: 300 }}>
|
|
342
|
+
<Autocomplete label="0" borderRadius={0} options={options} value={a} onChange={(v) => setA(v as string | null)} />
|
|
343
|
+
<Autocomplete label="10 (default)" borderRadius={10} options={options} value={b} onChange={(v) => setB(v as string | null)} />
|
|
344
|
+
<Autocomplete label="24 (pill)" borderRadius={24} options={options} value={c} onChange={(v) => setC(v as string | null)} />
|
|
345
|
+
</Stack>
|
|
346
|
+
);
|
|
347
|
+
};
|
|
348
|
+
`;
|
|
349
|
+
|
|
350
|
+
// =============================================================================
|
|
351
|
+
// EMPTY WITH PLACEHOLDER
|
|
352
|
+
// =============================================================================
|
|
353
|
+
export const EmptyWithPlaceholderAutocompleteDefinition = `
|
|
354
|
+
import React, { useState } from 'react';
|
|
355
|
+
import Autocomplete from './Autocomplete';
|
|
356
|
+
import { Box } from '@mui/material';
|
|
357
|
+
|
|
358
|
+
const options = [
|
|
359
|
+
{ value: 'mx', label: 'México' },
|
|
360
|
+
{ value: 'co', label: 'Colombia' },
|
|
361
|
+
{ value: 'ar', label: 'Argentina' },
|
|
362
|
+
];
|
|
363
|
+
|
|
364
|
+
export const EmptyWithPlaceholderExample = () => {
|
|
365
|
+
const [value, setValue] = useState<string | null>(null);
|
|
366
|
+
return (
|
|
367
|
+
<Box sx={{ width: 300 }}>
|
|
368
|
+
<Autocomplete
|
|
369
|
+
label="País"
|
|
370
|
+
placeholder="Buscar país..."
|
|
371
|
+
options={options}
|
|
372
|
+
value={value}
|
|
373
|
+
onChange={(val) => setValue(val as string | null)}
|
|
374
|
+
/>
|
|
375
|
+
</Box>
|
|
376
|
+
);
|
|
377
|
+
};
|
|
378
|
+
`;
|
|
379
|
+
|
|
380
|
+
// =============================================================================
|
|
381
|
+
// REACT HOOK FORM
|
|
382
|
+
// =============================================================================
|
|
383
|
+
export const RHFAutocompleteDefinition = `
|
|
384
|
+
import React from 'react';
|
|
385
|
+
import { useForm } from 'react-hook-form';
|
|
386
|
+
import Autocomplete from './Autocomplete';
|
|
387
|
+
import { Box, Button, Stack } from '@mui/material';
|
|
388
|
+
|
|
389
|
+
const options = [
|
|
390
|
+
{ value: 'mx', label: 'México' },
|
|
391
|
+
{ value: 'co', label: 'Colombia' },
|
|
392
|
+
{ value: 'ar', label: 'Argentina' },
|
|
393
|
+
];
|
|
394
|
+
|
|
395
|
+
type FormValues = { country: string | null };
|
|
396
|
+
|
|
397
|
+
export const RHFExample = () => {
|
|
398
|
+
const { control, handleSubmit, watch } = useForm<FormValues>({
|
|
399
|
+
defaultValues: { country: null },
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
<Box component="form" onSubmit={handleSubmit((data) => console.log(data))}>
|
|
404
|
+
<Stack spacing={2} sx={{ width: 320 }}>
|
|
405
|
+
<Autocomplete
|
|
406
|
+
name="country"
|
|
407
|
+
control={control}
|
|
408
|
+
validation={{ required: 'Campo requerido' }}
|
|
409
|
+
label="País"
|
|
410
|
+
placeholder="Seleccione..."
|
|
411
|
+
options={options}
|
|
412
|
+
/>
|
|
413
|
+
<Button type="submit" variant="contained">Guardar</Button>
|
|
414
|
+
<Box>Valor actual: {JSON.stringify(watch('country'))}</Box>
|
|
415
|
+
</Stack>
|
|
416
|
+
</Box>
|
|
417
|
+
);
|
|
418
|
+
};
|
|
419
|
+
`;
|
|
420
|
+
|
|
421
|
+
// =============================================================================
|
|
422
|
+
// ASYNC — búsqueda remota contra un servicio
|
|
423
|
+
// =============================================================================
|
|
424
|
+
export const AsyncServiceAutocompleteDefinition = [
|
|
425
|
+
'import React, { useState, useEffect, useMemo } from ', "'react'", ';',
|
|
426
|
+
'import Autocomplete from ', "'./Autocomplete'", ';',
|
|
427
|
+
'import { Box } from ', "'@mui/material'", ';',
|
|
428
|
+
'import debounce from ', "'lodash/debounce'", ';',
|
|
429
|
+
'',
|
|
430
|
+
'// Supón que tienes un servicio:',
|
|
431
|
+
'// await fetch(`/api/users?q=${query}`).then(r => r.json())',
|
|
432
|
+
'async function fetchUsers(query: string) {',
|
|
433
|
+
' const res = await fetch(`/api/users?q=${encodeURIComponent(query)}`);',
|
|
434
|
+
' const data = await res.json();',
|
|
435
|
+
' return data.map((u: any) => ({ value: u.id, label: u.name }));',
|
|
436
|
+
'}',
|
|
437
|
+
'',
|
|
438
|
+
'export const AsyncServiceExample = () => {',
|
|
439
|
+
' const [value, setValue] = useState<string | null>(null);',
|
|
440
|
+
' const [input, setInput] = useState("");',
|
|
441
|
+
' const [options, setOptions] = useState<any[]>([]);',
|
|
442
|
+
' const [loading, setLoading] = useState(false);',
|
|
443
|
+
'',
|
|
444
|
+
' const search = useMemo(',
|
|
445
|
+
' () =>',
|
|
446
|
+
' debounce(async (q: string) => {',
|
|
447
|
+
' if (\!q) { setOptions([]); return; }',
|
|
448
|
+
' setLoading(true);',
|
|
449
|
+
' try {',
|
|
450
|
+
' setOptions(await fetchUsers(q));',
|
|
451
|
+
' } finally {',
|
|
452
|
+
' setLoading(false);',
|
|
453
|
+
' }',
|
|
454
|
+
' }, 300),',
|
|
455
|
+
' [],',
|
|
456
|
+
' );',
|
|
457
|
+
'',
|
|
458
|
+
' useEffect(() => { search(input); }, [input, search]);',
|
|
459
|
+
'',
|
|
460
|
+
' return (',
|
|
461
|
+
' <Box sx={{ width: 320 }}>',
|
|
462
|
+
' <Autocomplete',
|
|
463
|
+
' label="Usuario"',
|
|
464
|
+
' placeholder="Buscar usuario..."',
|
|
465
|
+
' options={options}',
|
|
466
|
+
' value={value}',
|
|
467
|
+
' onChange={(v) => setValue(v as string | null)}',
|
|
468
|
+
' inputValue={input}',
|
|
469
|
+
' onInputChange={(_, v) => setInput(v)}',
|
|
470
|
+
' loading={loading}',
|
|
471
|
+
' // Desactiva el filtro cliente: el servicio ya filtra.',
|
|
472
|
+
' filterOptions={(x) => x}',
|
|
473
|
+
' />',
|
|
474
|
+
' </Box>',
|
|
475
|
+
' );',
|
|
476
|
+
'};',
|
|
477
|
+
].join('\n');
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
2
|
+
import type { SelectOption } from './Autocomplete';
|
|
3
|
+
|
|
4
|
+
/** Resuelve un value único a su SelectOption dentro del pool. */
|
|
5
|
+
export const resolveSingleValue = (
|
|
6
|
+
options: SelectOption[],
|
|
7
|
+
value: SelectOption['value'] | null | undefined,
|
|
8
|
+
): SelectOption | null => options.find((o) => o.value === value) ?? null;
|
|
9
|
+
|
|
10
|
+
/** Resuelve un array de values a sus SelectOption dentro del pool. */
|
|
11
|
+
export const resolveMultipleValue = (
|
|
12
|
+
options: SelectOption[],
|
|
13
|
+
value: SelectOption['value'][] | null | undefined,
|
|
14
|
+
): SelectOption[] => {
|
|
15
|
+
if (!Array.isArray(value)) return [];
|
|
16
|
+
return options.filter((o) => value.includes(o.value));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Merge de sx base + extra del consumer, respetando el contrato de MUI. */
|
|
20
|
+
export const mergeSx = (
|
|
21
|
+
base: SxProps<Theme>,
|
|
22
|
+
extra?: SxProps<Theme>,
|
|
23
|
+
): SxProps<Theme> => {
|
|
24
|
+
if (!extra) return base;
|
|
25
|
+
return [base, ...(Array.isArray(extra) ? extra : [extra])] as SxProps<Theme>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compara dos valores resueltos (single o multiple) por value para decidir
|
|
30
|
+
* si son estructuralmente iguales. Se usa para estabilizar la referencia que
|
|
31
|
+
* se pasa a MUI Autocomplete (MUI compara value por referencia con `!==`,
|
|
32
|
+
* y una nueva referencia — aunque el contenido sea igual — dispara
|
|
33
|
+
* `resetInputValue` y borra el texto mientras el usuario tipea).
|
|
34
|
+
*/
|
|
35
|
+
export const areResolvedValuesEqual = (
|
|
36
|
+
prev: SelectOption | SelectOption[] | null,
|
|
37
|
+
next: SelectOption | SelectOption[] | null,
|
|
38
|
+
multiple: boolean,
|
|
39
|
+
): boolean => {
|
|
40
|
+
if (multiple) {
|
|
41
|
+
if (!Array.isArray(prev) || !Array.isArray(next)) return false;
|
|
42
|
+
if (prev.length !== next.length) return false;
|
|
43
|
+
return prev.every((o, i) => o.value === next[i]?.value);
|
|
44
|
+
}
|
|
45
|
+
return (
|
|
46
|
+
(prev as SelectOption | null)?.value ===
|
|
47
|
+
(next as SelectOption | null)?.value
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Determina si un valor resuelto está vacío (para placeholder/shrink). */
|
|
52
|
+
export const isResolvedValueEmpty = (
|
|
53
|
+
resolvedValue: unknown,
|
|
54
|
+
multiple: boolean,
|
|
55
|
+
): boolean => {
|
|
56
|
+
if (multiple) {
|
|
57
|
+
return !Array.isArray(resolvedValue) || resolvedValue.length === 0;
|
|
58
|
+
}
|
|
59
|
+
return !resolvedValue;
|
|
60
|
+
};
|