@soyfri/shared-library 2.0.0-beta.26 → 2.0.0-beta.28
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/{Select-Dycmh9vt.js → Select-BY5Y0qZ1.js} +140 -20
- package/Select-BY5Y0qZ1.js.map +1 -0
- package/{Select-kqR48jZU.cjs → Select-CURrHSyl.cjs} +138 -18
- package/Select-CURrHSyl.cjs.map +1 -0
- package/components/Select/Select.cjs +1 -1
- package/components/Select/Select.d.ts +23 -1
- package/components/Select/Select.js +1 -1
- package/components/Select/index.d.ts +1 -1
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/Select-Dycmh9vt.js.map +0 -1
- package/Select-kqR48jZU.cjs.map +0 -1
|
@@ -29,14 +29,16 @@ var __objRest = (source, exclude) => {
|
|
|
29
29
|
}
|
|
30
30
|
return target;
|
|
31
31
|
};
|
|
32
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
32
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
33
33
|
import { useMemo, Children, isValidElement, useState } from "react";
|
|
34
|
-
import { MenuItem, ListItemIcon, FormControl, InputLabel, Select as Select$1,
|
|
34
|
+
import { MenuItem, ListItemIcon, Typography, Box, Chip, Avatar, FormControl, InputLabel, Select as Select$1, TextField, InputAdornment, FormHelperText, ListSubheader, FilledInput, OutlinedInput } from "@mui/material";
|
|
35
|
+
import SearchIcon from "@mui/icons-material/Search";
|
|
35
36
|
import { useTheme } from "@mui/material/styles";
|
|
36
37
|
import { Controller } from "react-hook-form";
|
|
37
38
|
import { b as buildFormFieldSx } from "./formField.sx-8_QRnKxv.js";
|
|
38
39
|
import { r as resolvePreset } from "./resolvePreset-K6_BfWHD.js";
|
|
39
40
|
import CheckIcon from "@mui/icons-material/Check";
|
|
41
|
+
import ClearIcon from "@mui/icons-material/Clear";
|
|
40
42
|
const buildSelectSx = (borderRadius, labelPosition) => buildFormFieldSx({ borderRadius, labelPosition });
|
|
41
43
|
const groupOptions = (options) => {
|
|
42
44
|
const groups = {};
|
|
@@ -66,6 +68,56 @@ const renderSelectMenuItem = ({
|
|
|
66
68
|
},
|
|
67
69
|
String(option.value)
|
|
68
70
|
);
|
|
71
|
+
function SelectValue(props) {
|
|
72
|
+
var _a;
|
|
73
|
+
const {
|
|
74
|
+
selected,
|
|
75
|
+
options,
|
|
76
|
+
multiple,
|
|
77
|
+
placeholder,
|
|
78
|
+
maxChipsToShow,
|
|
79
|
+
chipVariant,
|
|
80
|
+
renderChipLabel,
|
|
81
|
+
onDeleteChip,
|
|
82
|
+
currentValues
|
|
83
|
+
} = props;
|
|
84
|
+
const isEmpty = !selected || Array.isArray(selected) && selected.length === 0;
|
|
85
|
+
if (isEmpty) {
|
|
86
|
+
return /* @__PURE__ */ jsx(Typography, { sx: { color: "text.disabled" }, children: placeholder || "" });
|
|
87
|
+
}
|
|
88
|
+
if (!multiple) {
|
|
89
|
+
const item = options.find((opt) => opt.value === selected);
|
|
90
|
+
if (renderChipLabel && item) return /* @__PURE__ */ jsx(Fragment, { children: renderChipLabel(item) });
|
|
91
|
+
return /* @__PURE__ */ jsx(Fragment, { children: (_a = item == null ? void 0 : item.label) != null ? _a : String(selected) });
|
|
92
|
+
}
|
|
93
|
+
const selectedValuesArray = selected;
|
|
94
|
+
const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);
|
|
95
|
+
const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;
|
|
96
|
+
const handleDelete = (chipValue) => {
|
|
97
|
+
if (!onDeleteChip || !currentValues) return;
|
|
98
|
+
onDeleteChip(currentValues.filter((v) => v !== chipValue));
|
|
99
|
+
};
|
|
100
|
+
return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexWrap: "wrap", gap: 0.5 }, children: [
|
|
101
|
+
displayedChips.map((val) => {
|
|
102
|
+
const item = options.find((o) => o.value === val);
|
|
103
|
+
if (!item) return null;
|
|
104
|
+
return /* @__PURE__ */ jsx(
|
|
105
|
+
Chip,
|
|
106
|
+
{
|
|
107
|
+
variant: chipVariant,
|
|
108
|
+
color: "primary",
|
|
109
|
+
size: "small",
|
|
110
|
+
label: renderChipLabel ? renderChipLabel(item) : item.label,
|
|
111
|
+
avatar: item.img ? /* @__PURE__ */ jsx(Avatar, { src: item.img }) : void 0,
|
|
112
|
+
onDelete: () => handleDelete(val),
|
|
113
|
+
deleteIcon: /* @__PURE__ */ jsx(ClearIcon, { fontSize: "small" })
|
|
114
|
+
},
|
|
115
|
+
String(val)
|
|
116
|
+
);
|
|
117
|
+
}),
|
|
118
|
+
hiddenChipsCount > 0 && /* @__PURE__ */ jsx(Chip, { size: "small", variant: chipVariant, label: `+${hiddenChipsCount} más` })
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
69
121
|
function Option(_props) {
|
|
70
122
|
return null;
|
|
71
123
|
}
|
|
@@ -89,6 +141,11 @@ function Select(props) {
|
|
|
89
141
|
variant = "outlined",
|
|
90
142
|
sx,
|
|
91
143
|
className,
|
|
144
|
+
multiple = false,
|
|
145
|
+
maxChipsToShow = 3,
|
|
146
|
+
chipVariant = "filled",
|
|
147
|
+
renderChipLabel,
|
|
148
|
+
filterable = false,
|
|
92
149
|
name: _nameIgnored,
|
|
93
150
|
control: _controlIgnored,
|
|
94
151
|
validation: _validationIgnored,
|
|
@@ -112,6 +169,11 @@ function Select(props) {
|
|
|
112
169
|
"variant",
|
|
113
170
|
"sx",
|
|
114
171
|
"className",
|
|
172
|
+
"multiple",
|
|
173
|
+
"maxChipsToShow",
|
|
174
|
+
"chipVariant",
|
|
175
|
+
"renderChipLabel",
|
|
176
|
+
"filterable",
|
|
115
177
|
// Separamos estos aunque no se usen directamente acá — evita que lleguen
|
|
116
178
|
// al DOM del MuiSelect via `{...rest}` y generen warnings de React.
|
|
117
179
|
"name",
|
|
@@ -135,7 +197,16 @@ function Select(props) {
|
|
|
135
197
|
}, [children]);
|
|
136
198
|
const [isOpen, setIsOpen] = useState(false);
|
|
137
199
|
const [isFocused, setIsFocused] = useState(false);
|
|
138
|
-
const
|
|
200
|
+
const [searchText, setSearchText] = useState("");
|
|
201
|
+
const filteredOptions = useMemo(() => {
|
|
202
|
+
if (!filterable || !searchText.trim()) return options;
|
|
203
|
+
const q = searchText.trim().toLowerCase();
|
|
204
|
+
return options.filter((opt) => opt.label.toLowerCase().includes(q));
|
|
205
|
+
}, [options, filterable, searchText]);
|
|
206
|
+
const groupedOptions = useMemo(
|
|
207
|
+
() => groupOptions(filteredOptions),
|
|
208
|
+
[filteredOptions]
|
|
209
|
+
);
|
|
139
210
|
const buildMenuItems = (currentValue) => {
|
|
140
211
|
const items = [];
|
|
141
212
|
Object.entries(groupedOptions).forEach(([group, opts]) => {
|
|
@@ -145,7 +216,7 @@ function Select(props) {
|
|
|
145
216
|
);
|
|
146
217
|
}
|
|
147
218
|
opts.forEach((opt) => {
|
|
148
|
-
const selected = currentValue === opt.value;
|
|
219
|
+
const selected = Array.isArray(currentValue) ? currentValue.includes(opt.value) : currentValue === opt.value;
|
|
149
220
|
items.push(
|
|
150
221
|
renderSelectMenuItem({
|
|
151
222
|
option: opt,
|
|
@@ -161,12 +232,12 @@ function Select(props) {
|
|
|
161
232
|
...presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)],
|
|
162
233
|
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
163
234
|
];
|
|
164
|
-
const renderSelect = (selectValue, selectOnChange, onBlur, inputRef, rhfError, rhfHelperText) => {
|
|
235
|
+
const renderSelect = (selectValue, selectOnChange, onBlur, inputRef, rhfError, rhfHelperText, onValuesChange) => {
|
|
165
236
|
const finalError = !!rhfError || !!error;
|
|
166
237
|
const finalHelperText = rhfHelperText != null ? rhfHelperText : helperText;
|
|
167
238
|
const inputElement = variant === "filled" ? /* @__PURE__ */ jsx(FilledInput, {}) : labelPosition === "floating" ? /* @__PURE__ */ jsx(OutlinedInput, { label }) : /* @__PURE__ */ jsx(OutlinedInput, {});
|
|
168
|
-
const normalizedValue = normalizeSelectValue(selectValue);
|
|
169
|
-
const isEmpty = isSelectValueEmpty(normalizedValue);
|
|
239
|
+
const normalizedValue = multiple ? selectValue != null ? selectValue : [] : normalizeSelectValue(selectValue);
|
|
240
|
+
const isEmpty = multiple ? normalizedValue.length === 0 : isSelectValueEmpty(normalizedValue);
|
|
170
241
|
const shouldShrink = !isEmpty || isFocused || isOpen;
|
|
171
242
|
const shouldDisplayPlaceholder = isEmpty && (isFocused || isOpen) && !!placeholder;
|
|
172
243
|
return /* @__PURE__ */ jsxs(
|
|
@@ -181,9 +252,10 @@ function Select(props) {
|
|
|
181
252
|
sx: mergedSx,
|
|
182
253
|
children: [
|
|
183
254
|
label && /* @__PURE__ */ jsx(InputLabel, { shrink: shouldShrink, children: label }),
|
|
184
|
-
/* @__PURE__ */
|
|
255
|
+
/* @__PURE__ */ jsxs(
|
|
185
256
|
Select$1,
|
|
186
257
|
__spreadProps(__spreadValues({
|
|
258
|
+
multiple,
|
|
187
259
|
value: normalizedValue,
|
|
188
260
|
onChange: selectOnChange,
|
|
189
261
|
onBlur: (e) => {
|
|
@@ -192,15 +264,24 @@ function Select(props) {
|
|
|
192
264
|
},
|
|
193
265
|
onFocus: () => setIsFocused(true),
|
|
194
266
|
onOpen: () => setIsOpen(true),
|
|
195
|
-
onClose: () =>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (isSelectValueEmpty(selected)) {
|
|
199
|
-
return /* @__PURE__ */ jsx(Typography, { sx: { color: "text.disabled" }, children: placeholder != null ? placeholder : "" });
|
|
200
|
-
}
|
|
201
|
-
const item = options.find((opt) => opt.value === selected);
|
|
202
|
-
return (_a2 = item == null ? void 0 : item.label) != null ? _a2 : String(selected);
|
|
267
|
+
onClose: () => {
|
|
268
|
+
setIsOpen(false);
|
|
269
|
+
if (filterable) setSearchText("");
|
|
203
270
|
},
|
|
271
|
+
renderValue: (selected) => /* @__PURE__ */ jsx(
|
|
272
|
+
SelectValue,
|
|
273
|
+
{
|
|
274
|
+
selected,
|
|
275
|
+
options,
|
|
276
|
+
multiple,
|
|
277
|
+
placeholder,
|
|
278
|
+
maxChipsToShow,
|
|
279
|
+
chipVariant,
|
|
280
|
+
renderChipLabel,
|
|
281
|
+
currentValues: multiple ? selected : void 0,
|
|
282
|
+
onDeleteChip: onValuesChange
|
|
283
|
+
}
|
|
284
|
+
),
|
|
204
285
|
displayEmpty: shouldDisplayPlaceholder,
|
|
205
286
|
input: inputElement,
|
|
206
287
|
disabled,
|
|
@@ -211,7 +292,33 @@ function Select(props) {
|
|
|
211
292
|
},
|
|
212
293
|
inputRef
|
|
213
294
|
}, rest), {
|
|
214
|
-
children:
|
|
295
|
+
children: [
|
|
296
|
+
filterable && /* @__PURE__ */ jsx(
|
|
297
|
+
Box,
|
|
298
|
+
{
|
|
299
|
+
sx: { px: 1.5, py: 1, position: "sticky", top: 0, zIndex: 1, bgcolor: "background.paper" },
|
|
300
|
+
onClick: (e) => e.stopPropagation(),
|
|
301
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
302
|
+
children: /* @__PURE__ */ jsx(
|
|
303
|
+
TextField,
|
|
304
|
+
{
|
|
305
|
+
size: "small",
|
|
306
|
+
fullWidth: true,
|
|
307
|
+
autoFocus: true,
|
|
308
|
+
placeholder: "Buscar...",
|
|
309
|
+
value: searchText,
|
|
310
|
+
onChange: (e) => setSearchText(e.target.value),
|
|
311
|
+
slotProps: {
|
|
312
|
+
input: {
|
|
313
|
+
startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { fontSize: "small" }) })
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
}
|
|
319
|
+
),
|
|
320
|
+
buildMenuItems(normalizedValue)
|
|
321
|
+
]
|
|
215
322
|
})
|
|
216
323
|
),
|
|
217
324
|
finalHelperText && /* @__PURE__ */ jsx(FormHelperText, { children: finalHelperText })
|
|
@@ -240,17 +347,30 @@ function Select(props) {
|
|
|
240
347
|
field.onBlur,
|
|
241
348
|
field.ref,
|
|
242
349
|
!!fieldError,
|
|
243
|
-
fieldError == null ? void 0 : fieldError.message
|
|
350
|
+
fieldError == null ? void 0 : fieldError.message,
|
|
351
|
+
(nextVals) => {
|
|
352
|
+
field.onChange(nextVals);
|
|
353
|
+
onValueChange == null ? void 0 : onValueChange(nextVals);
|
|
354
|
+
}
|
|
244
355
|
);
|
|
245
356
|
}
|
|
246
357
|
}
|
|
247
358
|
);
|
|
248
359
|
}
|
|
249
360
|
const { value, onChange } = props;
|
|
250
|
-
|
|
361
|
+
const handleChange = onChange;
|
|
362
|
+
return renderSelect(
|
|
363
|
+
value,
|
|
364
|
+
(e) => handleChange(e.target.value),
|
|
365
|
+
void 0,
|
|
366
|
+
void 0,
|
|
367
|
+
void 0,
|
|
368
|
+
void 0,
|
|
369
|
+
(next) => onChange(next)
|
|
370
|
+
);
|
|
251
371
|
}
|
|
252
372
|
export {
|
|
253
373
|
Option as O,
|
|
254
374
|
Select as S
|
|
255
375
|
};
|
|
256
|
-
//# sourceMappingURL=Select-
|
|
376
|
+
//# sourceMappingURL=Select-BY5Y0qZ1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select-BY5Y0qZ1.js","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/_parts/SelectValue.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import { Avatar, Box, Chip, Typography } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n ChipVariant,\n} from '../Select';\n\ninterface SelectValueProps<TValue extends SelectOption['value']> {\n selected: TValue | TValue[] | null | undefined;\n options: SelectOption[];\n multiple: boolean;\n placeholder?: string;\n maxChipsToShow: number;\n chipVariant: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n /** Solo relevante en modo multiple. Recibe el nuevo array de valores. */\n onDeleteChip?: (nextValues: TValue[]) => void;\n /** Array de valores actuales (para componer el nuevo array al borrar chips). */\n currentValues?: TValue[];\n}\n\n/**\n * Render del valor seleccionado del Select.\n * - single: texto (label) o lo que devuelva `renderChipLabel`.\n * - multiple: chips con delete. Trunca después de `maxChipsToShow` mostrando \"+N más\".\n * - empty: placeholder en color disabled.\n */\nexport function SelectValue<TValue extends SelectOption['value']>(\n props: SelectValueProps<TValue>,\n) {\n const {\n selected,\n options,\n multiple,\n placeholder,\n maxChipsToShow,\n chipVariant,\n renderChipLabel,\n onDeleteChip,\n currentValues,\n } = props;\n\n const isEmpty =\n !selected || (Array.isArray(selected) && selected.length === 0);\n\n if (isEmpty) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>{placeholder || ''}</Typography>\n );\n }\n\n if (!multiple) {\n const item = options.find((opt) => opt.value === selected);\n if (renderChipLabel && item) return <>{renderChipLabel(item)}</>;\n return <>{item?.label ?? String(selected)}</>;\n }\n\n const selectedValuesArray = selected as TValue[];\n const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);\n const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;\n\n const handleDelete = (chipValue: TValue) => {\n if (!onDeleteChip || !currentValues) return;\n onDeleteChip(currentValues.filter((v) => v !== chipValue));\n };\n\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {displayedChips.map((val) => {\n const item = options.find((o) => o.value === val);\n if (!item) return null;\n\n return (\n <Chip\n variant={chipVariant}\n color=\"primary\"\n size=\"small\"\n key={String(val)}\n label={renderChipLabel ? renderChipLabel(item) : item.label}\n avatar={item.img ? <Avatar src={item.img} /> : undefined}\n onDelete={() => handleDelete(val)}\n deleteIcon={<ClearIcon fontSize=\"small\" />}\n />\n );\n })}\n {hiddenChipsCount > 0 && (\n <Chip size=\"small\" variant={chipVariant} label={`+${hiddenChipsCount} más`} />\n )}\n </Box>\n );\n}\n\nexport default SelectValue;\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n TextField,\n InputAdornment,\n Box,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport SearchIcon from '@mui/icons-material/Search';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\nimport { SelectValue } from './_parts/SelectValue';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n/** Variante visual de los chips en modo `multiple`. */\nexport type ChipVariant = 'filled' | 'outlined';\n/** Render custom del label de cada chip/valor seleccionado. */\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n /** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */\n filterable?: boolean;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n multiple?: false;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple?: false;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\nexport interface MultipleSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple: true;\n value: TValue[];\n onChange: (val: TValue[]) => void;\n /** Máximo de chips visibles antes de truncar con \"+N más\". Default: 3. */\n maxChipsToShow?: number;\n /** Variante visual de los chips. Default: 'filled'. */\n chipVariant?: ChipVariant;\n /** Render custom del label de cada chip. */\n renderChipLabel?: RenderChipLabel;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> =\n | RHFSelectProps<TValue>\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n multiple = false,\n maxChipsToShow = 3,\n chipVariant = 'filled',\n renderChipLabel,\n filterable = false,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n multiple?: boolean;\n maxChipsToShow?: number;\n chipVariant?: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n filterable?: boolean;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // Texto del buscador (modo `filterable`).\n const [searchText, setSearchText] = useState('');\n\n const filteredOptions = useMemo(() => {\n if (!filterable || !searchText.trim()) return options;\n const q = searchText.trim().toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(q));\n }, [options, filterable, searchText]);\n\n const groupedOptions = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Items del menú (grupos + opciones). El buscador se inyecta aparte.\n const buildMenuItems = (currentValue: TValue | TValue[] | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = Array.isArray(currentValue)\n ? currentValue.includes(opt.value as TValue)\n : currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | TValue[] | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue | TValue[]>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n onValuesChange?: (next: TValue[]) => void,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = multiple\n ? ((selectValue as TValue[] | null | undefined) ?? [])\n : normalizeSelectValue(selectValue as TValue | null | undefined);\n const isEmpty = multiple\n ? (normalizedValue as TValue[]).length === 0\n : isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue | TValue[]>\n multiple={multiple}\n value={normalizedValue as TValue | TValue[]}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => {\n setIsOpen(false);\n if (filterable) setSearchText('');\n }}\n renderValue={(selected) => (\n <SelectValue<TValue>\n selected={selected as TValue | TValue[]}\n options={options}\n multiple={multiple}\n placeholder={placeholder}\n maxChipsToShow={maxChipsToShow}\n chipVariant={chipVariant}\n renderChipLabel={renderChipLabel}\n currentValues={multiple ? (selected as TValue[]) : undefined}\n onDeleteChip={onValuesChange}\n />\n )}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {filterable && (\n <Box\n sx={{ px: 1.5, py: 1, position: 'sticky', top: 0, zIndex: 1, bgcolor: 'background.paper' }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <TextField\n size=\"small\"\n fullWidth\n autoFocus\n placeholder=\"Buscar...\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n </Box>\n )}\n {buildMenuItems(normalizedValue as TValue | TValue[] | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n (nextVals) => {\n field.onChange(nextVals);\n onValueChange?.(nextVals as unknown as TValue);\n },\n )\n }\n />\n );\n }\n\n // ── Controlled mode (single o multiple) ───────────────────────────────\n const { value, onChange } = props as\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n const handleChange = onChange as (val: TValue | TValue[]) => void;\n return renderSelect(\n value as TValue | TValue[],\n (e) => handleChange(e.target.value as TValue | TValue[]),\n undefined,\n undefined,\n undefined,\n undefined,\n (next) => (onChange as (val: TValue[]) => void)(next),\n );\n}\n\nexport default Select;\n"],"names":["_a","MuiSelect"],"mappings":"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"}
|
|
@@ -33,11 +33,13 @@ var __objRest = (source, exclude) => {
|
|
|
33
33
|
const jsxRuntime = require("react/jsx-runtime");
|
|
34
34
|
const React = require("react");
|
|
35
35
|
const material = require("@mui/material");
|
|
36
|
+
const SearchIcon = require("@mui/icons-material/Search");
|
|
36
37
|
const styles = require("@mui/material/styles");
|
|
37
38
|
const reactHookForm = require("react-hook-form");
|
|
38
39
|
const formField_sx = require("./formField.sx-BAX7KwMR.cjs");
|
|
39
40
|
const resolvePreset = require("./resolvePreset-CxTI6_Ln.cjs");
|
|
40
41
|
const CheckIcon = require("@mui/icons-material/Check");
|
|
42
|
+
const ClearIcon = require("@mui/icons-material/Clear");
|
|
41
43
|
const buildSelectSx = (borderRadius, labelPosition) => formField_sx.buildFormFieldSx({ borderRadius, labelPosition });
|
|
42
44
|
const groupOptions = (options) => {
|
|
43
45
|
const groups = {};
|
|
@@ -67,6 +69,56 @@ const renderSelectMenuItem = ({
|
|
|
67
69
|
},
|
|
68
70
|
String(option.value)
|
|
69
71
|
);
|
|
72
|
+
function SelectValue(props) {
|
|
73
|
+
var _a;
|
|
74
|
+
const {
|
|
75
|
+
selected,
|
|
76
|
+
options,
|
|
77
|
+
multiple,
|
|
78
|
+
placeholder,
|
|
79
|
+
maxChipsToShow,
|
|
80
|
+
chipVariant,
|
|
81
|
+
renderChipLabel,
|
|
82
|
+
onDeleteChip,
|
|
83
|
+
currentValues
|
|
84
|
+
} = props;
|
|
85
|
+
const isEmpty = !selected || Array.isArray(selected) && selected.length === 0;
|
|
86
|
+
if (isEmpty) {
|
|
87
|
+
return /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { sx: { color: "text.disabled" }, children: placeholder || "" });
|
|
88
|
+
}
|
|
89
|
+
if (!multiple) {
|
|
90
|
+
const item = options.find((opt) => opt.value === selected);
|
|
91
|
+
if (renderChipLabel && item) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderChipLabel(item) });
|
|
92
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (_a = item == null ? void 0 : item.label) != null ? _a : String(selected) });
|
|
93
|
+
}
|
|
94
|
+
const selectedValuesArray = selected;
|
|
95
|
+
const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);
|
|
96
|
+
const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;
|
|
97
|
+
const handleDelete = (chipValue) => {
|
|
98
|
+
if (!onDeleteChip || !currentValues) return;
|
|
99
|
+
onDeleteChip(currentValues.filter((v) => v !== chipValue));
|
|
100
|
+
};
|
|
101
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { display: "flex", flexWrap: "wrap", gap: 0.5 }, children: [
|
|
102
|
+
displayedChips.map((val) => {
|
|
103
|
+
const item = options.find((o) => o.value === val);
|
|
104
|
+
if (!item) return null;
|
|
105
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
106
|
+
material.Chip,
|
|
107
|
+
{
|
|
108
|
+
variant: chipVariant,
|
|
109
|
+
color: "primary",
|
|
110
|
+
size: "small",
|
|
111
|
+
label: renderChipLabel ? renderChipLabel(item) : item.label,
|
|
112
|
+
avatar: item.img ? /* @__PURE__ */ jsxRuntime.jsx(material.Avatar, { src: item.img }) : void 0,
|
|
113
|
+
onDelete: () => handleDelete(val),
|
|
114
|
+
deleteIcon: /* @__PURE__ */ jsxRuntime.jsx(ClearIcon, { fontSize: "small" })
|
|
115
|
+
},
|
|
116
|
+
String(val)
|
|
117
|
+
);
|
|
118
|
+
}),
|
|
119
|
+
hiddenChipsCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(material.Chip, { size: "small", variant: chipVariant, label: `+${hiddenChipsCount} más` })
|
|
120
|
+
] });
|
|
121
|
+
}
|
|
70
122
|
function Option(_props) {
|
|
71
123
|
return null;
|
|
72
124
|
}
|
|
@@ -90,6 +142,11 @@ function Select(props) {
|
|
|
90
142
|
variant = "outlined",
|
|
91
143
|
sx,
|
|
92
144
|
className,
|
|
145
|
+
multiple = false,
|
|
146
|
+
maxChipsToShow = 3,
|
|
147
|
+
chipVariant = "filled",
|
|
148
|
+
renderChipLabel,
|
|
149
|
+
filterable = false,
|
|
93
150
|
name: _nameIgnored,
|
|
94
151
|
control: _controlIgnored,
|
|
95
152
|
validation: _validationIgnored,
|
|
@@ -113,6 +170,11 @@ function Select(props) {
|
|
|
113
170
|
"variant",
|
|
114
171
|
"sx",
|
|
115
172
|
"className",
|
|
173
|
+
"multiple",
|
|
174
|
+
"maxChipsToShow",
|
|
175
|
+
"chipVariant",
|
|
176
|
+
"renderChipLabel",
|
|
177
|
+
"filterable",
|
|
116
178
|
// Separamos estos aunque no se usen directamente acá — evita que lleguen
|
|
117
179
|
// al DOM del MuiSelect via `{...rest}` y generen warnings de React.
|
|
118
180
|
"name",
|
|
@@ -136,7 +198,16 @@ function Select(props) {
|
|
|
136
198
|
}, [children]);
|
|
137
199
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
138
200
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
139
|
-
const
|
|
201
|
+
const [searchText, setSearchText] = React.useState("");
|
|
202
|
+
const filteredOptions = React.useMemo(() => {
|
|
203
|
+
if (!filterable || !searchText.trim()) return options;
|
|
204
|
+
const q = searchText.trim().toLowerCase();
|
|
205
|
+
return options.filter((opt) => opt.label.toLowerCase().includes(q));
|
|
206
|
+
}, [options, filterable, searchText]);
|
|
207
|
+
const groupedOptions = React.useMemo(
|
|
208
|
+
() => groupOptions(filteredOptions),
|
|
209
|
+
[filteredOptions]
|
|
210
|
+
);
|
|
140
211
|
const buildMenuItems = (currentValue) => {
|
|
141
212
|
const items = [];
|
|
142
213
|
Object.entries(groupedOptions).forEach(([group, opts]) => {
|
|
@@ -146,7 +217,7 @@ function Select(props) {
|
|
|
146
217
|
);
|
|
147
218
|
}
|
|
148
219
|
opts.forEach((opt) => {
|
|
149
|
-
const selected = currentValue === opt.value;
|
|
220
|
+
const selected = Array.isArray(currentValue) ? currentValue.includes(opt.value) : currentValue === opt.value;
|
|
150
221
|
items.push(
|
|
151
222
|
renderSelectMenuItem({
|
|
152
223
|
option: opt,
|
|
@@ -162,12 +233,12 @@ function Select(props) {
|
|
|
162
233
|
...presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)],
|
|
163
234
|
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
164
235
|
];
|
|
165
|
-
const renderSelect = (selectValue, selectOnChange, onBlur, inputRef, rhfError, rhfHelperText) => {
|
|
236
|
+
const renderSelect = (selectValue, selectOnChange, onBlur, inputRef, rhfError, rhfHelperText, onValuesChange) => {
|
|
166
237
|
const finalError = !!rhfError || !!error;
|
|
167
238
|
const finalHelperText = rhfHelperText != null ? rhfHelperText : helperText;
|
|
168
239
|
const inputElement = variant === "filled" ? /* @__PURE__ */ jsxRuntime.jsx(material.FilledInput, {}) : labelPosition === "floating" ? /* @__PURE__ */ jsxRuntime.jsx(material.OutlinedInput, { label }) : /* @__PURE__ */ jsxRuntime.jsx(material.OutlinedInput, {});
|
|
169
|
-
const normalizedValue = normalizeSelectValue(selectValue);
|
|
170
|
-
const isEmpty = isSelectValueEmpty(normalizedValue);
|
|
240
|
+
const normalizedValue = multiple ? selectValue != null ? selectValue : [] : normalizeSelectValue(selectValue);
|
|
241
|
+
const isEmpty = multiple ? normalizedValue.length === 0 : isSelectValueEmpty(normalizedValue);
|
|
171
242
|
const shouldShrink = !isEmpty || isFocused || isOpen;
|
|
172
243
|
const shouldDisplayPlaceholder = isEmpty && (isFocused || isOpen) && !!placeholder;
|
|
173
244
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -182,9 +253,10 @@ function Select(props) {
|
|
|
182
253
|
sx: mergedSx,
|
|
183
254
|
children: [
|
|
184
255
|
label && /* @__PURE__ */ jsxRuntime.jsx(material.InputLabel, { shrink: shouldShrink, children: label }),
|
|
185
|
-
/* @__PURE__ */ jsxRuntime.
|
|
256
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
186
257
|
material.Select,
|
|
187
258
|
__spreadProps(__spreadValues({
|
|
259
|
+
multiple,
|
|
188
260
|
value: normalizedValue,
|
|
189
261
|
onChange: selectOnChange,
|
|
190
262
|
onBlur: (e) => {
|
|
@@ -193,15 +265,24 @@ function Select(props) {
|
|
|
193
265
|
},
|
|
194
266
|
onFocus: () => setIsFocused(true),
|
|
195
267
|
onOpen: () => setIsOpen(true),
|
|
196
|
-
onClose: () =>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (isSelectValueEmpty(selected)) {
|
|
200
|
-
return /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { sx: { color: "text.disabled" }, children: placeholder != null ? placeholder : "" });
|
|
201
|
-
}
|
|
202
|
-
const item = options.find((opt) => opt.value === selected);
|
|
203
|
-
return (_a2 = item == null ? void 0 : item.label) != null ? _a2 : String(selected);
|
|
268
|
+
onClose: () => {
|
|
269
|
+
setIsOpen(false);
|
|
270
|
+
if (filterable) setSearchText("");
|
|
204
271
|
},
|
|
272
|
+
renderValue: (selected) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
273
|
+
SelectValue,
|
|
274
|
+
{
|
|
275
|
+
selected,
|
|
276
|
+
options,
|
|
277
|
+
multiple,
|
|
278
|
+
placeholder,
|
|
279
|
+
maxChipsToShow,
|
|
280
|
+
chipVariant,
|
|
281
|
+
renderChipLabel,
|
|
282
|
+
currentValues: multiple ? selected : void 0,
|
|
283
|
+
onDeleteChip: onValuesChange
|
|
284
|
+
}
|
|
285
|
+
),
|
|
205
286
|
displayEmpty: shouldDisplayPlaceholder,
|
|
206
287
|
input: inputElement,
|
|
207
288
|
disabled,
|
|
@@ -212,7 +293,33 @@ function Select(props) {
|
|
|
212
293
|
},
|
|
213
294
|
inputRef
|
|
214
295
|
}, rest), {
|
|
215
|
-
children:
|
|
296
|
+
children: [
|
|
297
|
+
filterable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
298
|
+
material.Box,
|
|
299
|
+
{
|
|
300
|
+
sx: { px: 1.5, py: 1, position: "sticky", top: 0, zIndex: 1, bgcolor: "background.paper" },
|
|
301
|
+
onClick: (e) => e.stopPropagation(),
|
|
302
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
303
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
304
|
+
material.TextField,
|
|
305
|
+
{
|
|
306
|
+
size: "small",
|
|
307
|
+
fullWidth: true,
|
|
308
|
+
autoFocus: true,
|
|
309
|
+
placeholder: "Buscar...",
|
|
310
|
+
value: searchText,
|
|
311
|
+
onChange: (e) => setSearchText(e.target.value),
|
|
312
|
+
slotProps: {
|
|
313
|
+
input: {
|
|
314
|
+
startAdornment: /* @__PURE__ */ jsxRuntime.jsx(material.InputAdornment, { position: "start", children: /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { fontSize: "small" }) })
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
),
|
|
321
|
+
buildMenuItems(normalizedValue)
|
|
322
|
+
]
|
|
216
323
|
})
|
|
217
324
|
),
|
|
218
325
|
finalHelperText && /* @__PURE__ */ jsxRuntime.jsx(material.FormHelperText, { children: finalHelperText })
|
|
@@ -241,15 +348,28 @@ function Select(props) {
|
|
|
241
348
|
field.onBlur,
|
|
242
349
|
field.ref,
|
|
243
350
|
!!fieldError,
|
|
244
|
-
fieldError == null ? void 0 : fieldError.message
|
|
351
|
+
fieldError == null ? void 0 : fieldError.message,
|
|
352
|
+
(nextVals) => {
|
|
353
|
+
field.onChange(nextVals);
|
|
354
|
+
onValueChange == null ? void 0 : onValueChange(nextVals);
|
|
355
|
+
}
|
|
245
356
|
);
|
|
246
357
|
}
|
|
247
358
|
}
|
|
248
359
|
);
|
|
249
360
|
}
|
|
250
361
|
const { value, onChange } = props;
|
|
251
|
-
|
|
362
|
+
const handleChange = onChange;
|
|
363
|
+
return renderSelect(
|
|
364
|
+
value,
|
|
365
|
+
(e) => handleChange(e.target.value),
|
|
366
|
+
void 0,
|
|
367
|
+
void 0,
|
|
368
|
+
void 0,
|
|
369
|
+
void 0,
|
|
370
|
+
(next) => onChange(next)
|
|
371
|
+
);
|
|
252
372
|
}
|
|
253
373
|
exports.Option = Option;
|
|
254
374
|
exports.Select = Select;
|
|
255
|
-
//# sourceMappingURL=Select-
|
|
375
|
+
//# sourceMappingURL=Select-CURrHSyl.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select-CURrHSyl.cjs","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/_parts/SelectValue.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import { Avatar, Box, Chip, Typography } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n ChipVariant,\n} from '../Select';\n\ninterface SelectValueProps<TValue extends SelectOption['value']> {\n selected: TValue | TValue[] | null | undefined;\n options: SelectOption[];\n multiple: boolean;\n placeholder?: string;\n maxChipsToShow: number;\n chipVariant: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n /** Solo relevante en modo multiple. Recibe el nuevo array de valores. */\n onDeleteChip?: (nextValues: TValue[]) => void;\n /** Array de valores actuales (para componer el nuevo array al borrar chips). */\n currentValues?: TValue[];\n}\n\n/**\n * Render del valor seleccionado del Select.\n * - single: texto (label) o lo que devuelva `renderChipLabel`.\n * - multiple: chips con delete. Trunca después de `maxChipsToShow` mostrando \"+N más\".\n * - empty: placeholder en color disabled.\n */\nexport function SelectValue<TValue extends SelectOption['value']>(\n props: SelectValueProps<TValue>,\n) {\n const {\n selected,\n options,\n multiple,\n placeholder,\n maxChipsToShow,\n chipVariant,\n renderChipLabel,\n onDeleteChip,\n currentValues,\n } = props;\n\n const isEmpty =\n !selected || (Array.isArray(selected) && selected.length === 0);\n\n if (isEmpty) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>{placeholder || ''}</Typography>\n );\n }\n\n if (!multiple) {\n const item = options.find((opt) => opt.value === selected);\n if (renderChipLabel && item) return <>{renderChipLabel(item)}</>;\n return <>{item?.label ?? String(selected)}</>;\n }\n\n const selectedValuesArray = selected as TValue[];\n const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);\n const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;\n\n const handleDelete = (chipValue: TValue) => {\n if (!onDeleteChip || !currentValues) return;\n onDeleteChip(currentValues.filter((v) => v !== chipValue));\n };\n\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {displayedChips.map((val) => {\n const item = options.find((o) => o.value === val);\n if (!item) return null;\n\n return (\n <Chip\n variant={chipVariant}\n color=\"primary\"\n size=\"small\"\n key={String(val)}\n label={renderChipLabel ? renderChipLabel(item) : item.label}\n avatar={item.img ? <Avatar src={item.img} /> : undefined}\n onDelete={() => handleDelete(val)}\n deleteIcon={<ClearIcon fontSize=\"small\" />}\n />\n );\n })}\n {hiddenChipsCount > 0 && (\n <Chip size=\"small\" variant={chipVariant} label={`+${hiddenChipsCount} más`} />\n )}\n </Box>\n );\n}\n\nexport default SelectValue;\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n TextField,\n InputAdornment,\n Box,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport SearchIcon from '@mui/icons-material/Search';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\nimport { SelectValue } from './_parts/SelectValue';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n/** Variante visual de los chips en modo `multiple`. */\nexport type ChipVariant = 'filled' | 'outlined';\n/** Render custom del label de cada chip/valor seleccionado. */\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n /** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */\n filterable?: boolean;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n multiple?: false;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple?: false;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\nexport interface MultipleSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple: true;\n value: TValue[];\n onChange: (val: TValue[]) => void;\n /** Máximo de chips visibles antes de truncar con \"+N más\". Default: 3. */\n maxChipsToShow?: number;\n /** Variante visual de los chips. Default: 'filled'. */\n chipVariant?: ChipVariant;\n /** Render custom del label de cada chip. */\n renderChipLabel?: RenderChipLabel;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> =\n | RHFSelectProps<TValue>\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n multiple = false,\n maxChipsToShow = 3,\n chipVariant = 'filled',\n renderChipLabel,\n filterable = false,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n multiple?: boolean;\n maxChipsToShow?: number;\n chipVariant?: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n filterable?: boolean;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // Texto del buscador (modo `filterable`).\n const [searchText, setSearchText] = useState('');\n\n const filteredOptions = useMemo(() => {\n if (!filterable || !searchText.trim()) return options;\n const q = searchText.trim().toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(q));\n }, [options, filterable, searchText]);\n\n const groupedOptions = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Items del menú (grupos + opciones). El buscador se inyecta aparte.\n const buildMenuItems = (currentValue: TValue | TValue[] | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = Array.isArray(currentValue)\n ? currentValue.includes(opt.value as TValue)\n : currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | TValue[] | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue | TValue[]>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n onValuesChange?: (next: TValue[]) => void,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = multiple\n ? ((selectValue as TValue[] | null | undefined) ?? [])\n : normalizeSelectValue(selectValue as TValue | null | undefined);\n const isEmpty = multiple\n ? (normalizedValue as TValue[]).length === 0\n : isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue | TValue[]>\n multiple={multiple}\n value={normalizedValue as TValue | TValue[]}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => {\n setIsOpen(false);\n if (filterable) setSearchText('');\n }}\n renderValue={(selected) => (\n <SelectValue<TValue>\n selected={selected as TValue | TValue[]}\n options={options}\n multiple={multiple}\n placeholder={placeholder}\n maxChipsToShow={maxChipsToShow}\n chipVariant={chipVariant}\n renderChipLabel={renderChipLabel}\n currentValues={multiple ? (selected as TValue[]) : undefined}\n onDeleteChip={onValuesChange}\n />\n )}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {filterable && (\n <Box\n sx={{ px: 1.5, py: 1, position: 'sticky', top: 0, zIndex: 1, bgcolor: 'background.paper' }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <TextField\n size=\"small\"\n fullWidth\n autoFocus\n placeholder=\"Buscar...\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n </Box>\n )}\n {buildMenuItems(normalizedValue as TValue | TValue[] | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n (nextVals) => {\n field.onChange(nextVals);\n onValueChange?.(nextVals as unknown as TValue);\n },\n )\n }\n />\n );\n }\n\n // ── Controlled mode (single o multiple) ───────────────────────────────\n const { value, onChange } = props as\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n const handleChange = onChange as (val: TValue | TValue[]) => void;\n return renderSelect(\n value as TValue | TValue[],\n (e) => handleChange(e.target.value as TValue | TValue[]),\n undefined,\n undefined,\n undefined,\n undefined,\n (next) => (onChange as (val: TValue[]) => void)(next),\n );\n}\n\nexport default Select;\n"],"names":["buildFormFieldSx","jsxs","MenuItem","jsx","ListItemIcon","Typography","Fragment","Box","Chip","Avatar","useTheme","resolvePreset","useMemo","Children","isValidElement","_a","useState","ListSubheader","FilledInput","OutlinedInput","FormControl","InputLabel","MuiSelect","TextField","InputAdornment","FormHelperText","Controller"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
-
const Select = require("../../Select-
|
|
3
|
+
const Select = require("../../Select-CURrHSyl.cjs");
|
|
4
4
|
exports.Option = Select.Option;
|
|
5
5
|
exports.Select = Select.Select;
|
|
6
6
|
exports.default = Select.Select;
|
|
@@ -12,6 +12,10 @@ export interface SelectOption {
|
|
|
12
12
|
export type LabelPosition = 'outside' | 'floating';
|
|
13
13
|
export type SelectSize = 'small' | 'medium';
|
|
14
14
|
export type RenderOptionItem = (item: SelectOption) => ReactNode;
|
|
15
|
+
/** Variante visual de los chips en modo `multiple`. */
|
|
16
|
+
export type ChipVariant = 'filled' | 'outlined';
|
|
17
|
+
/** Render custom del label de cada chip/valor seleccionado. */
|
|
18
|
+
export type RenderChipLabel = (item: SelectOption) => ReactNode;
|
|
15
19
|
export interface OptionProps {
|
|
16
20
|
children: RenderOptionItem;
|
|
17
21
|
}
|
|
@@ -26,6 +30,8 @@ export interface BaseSelectProps<TValue extends SelectOption['value'] = SelectOp
|
|
|
26
30
|
}>;
|
|
27
31
|
maxHeight?: number | string;
|
|
28
32
|
maxWidth?: number | string;
|
|
33
|
+
/** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */
|
|
34
|
+
filterable?: boolean;
|
|
29
35
|
disabled?: boolean;
|
|
30
36
|
error?: boolean;
|
|
31
37
|
helperText?: string;
|
|
@@ -58,6 +64,7 @@ export interface RHFSelectProps<TValue extends SelectOption['value'] = SelectOpt
|
|
|
58
64
|
* departamento). NO reemplaza al handler de RHF.
|
|
59
65
|
*/
|
|
60
66
|
onValueChange?: (value: TValue) => void;
|
|
67
|
+
multiple?: false;
|
|
61
68
|
value?: never;
|
|
62
69
|
onChange?: never;
|
|
63
70
|
}
|
|
@@ -65,10 +72,25 @@ export interface StandardSelectProps<TValue extends SelectOption['value'] = Sele
|
|
|
65
72
|
name?: string;
|
|
66
73
|
control?: never;
|
|
67
74
|
validation?: never;
|
|
75
|
+
multiple?: false;
|
|
68
76
|
value: TValue;
|
|
69
77
|
onChange: (val: TValue) => void;
|
|
70
78
|
}
|
|
71
|
-
export
|
|
79
|
+
export interface MultipleSelectProps<TValue extends SelectOption['value'] = SelectOption['value']> extends BaseSelectProps<TValue> {
|
|
80
|
+
name?: string;
|
|
81
|
+
control?: never;
|
|
82
|
+
validation?: never;
|
|
83
|
+
multiple: true;
|
|
84
|
+
value: TValue[];
|
|
85
|
+
onChange: (val: TValue[]) => void;
|
|
86
|
+
/** Máximo de chips visibles antes de truncar con "+N más". Default: 3. */
|
|
87
|
+
maxChipsToShow?: number;
|
|
88
|
+
/** Variante visual de los chips. Default: 'filled'. */
|
|
89
|
+
chipVariant?: ChipVariant;
|
|
90
|
+
/** Render custom del label de cada chip. */
|
|
91
|
+
renderChipLabel?: RenderChipLabel;
|
|
92
|
+
}
|
|
93
|
+
export type SelectProps<TValue extends SelectOption['value'] = SelectOption['value']> = RHFSelectProps<TValue> | StandardSelectProps<TValue> | MultipleSelectProps<TValue>;
|
|
72
94
|
export declare function Option(_props: OptionProps): null;
|
|
73
95
|
export declare namespace Option {
|
|
74
96
|
var displayName: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Select, Option, default } from './Select';
|
|
2
|
-
export type { SelectProps, SelectOption, OptionProps, BaseSelectProps, RHFSelectProps, StandardSelectProps, RenderOptionItem, LabelPosition, SelectSize, } from './Select';
|
|
2
|
+
export type { SelectProps, SelectOption, OptionProps, BaseSelectProps, RHFSelectProps, StandardSelectProps, MultipleSelectProps, RenderOptionItem, ChipVariant, RenderChipLabel, LabelPosition, SelectSize, } from './Select';
|
package/index.cjs
CHANGED
|
@@ -15,7 +15,7 @@ const Table = require("./Table-C4OM6rrC.cjs");
|
|
|
15
15
|
const StatusMessage = require("./StatusMessage-B3nXpuRl.cjs");
|
|
16
16
|
const Modal = require("./Modal-CkpuI8ns.cjs");
|
|
17
17
|
const Input = require("./Input-CScC87J5.cjs");
|
|
18
|
-
const Select = require("./Select-
|
|
18
|
+
const Select = require("./Select-CURrHSyl.cjs");
|
|
19
19
|
const Autocomplete = require("./Autocomplete-CejWztBY.cjs");
|
|
20
20
|
const Switch = require("./Switch-CQFOopYy.cjs");
|
|
21
21
|
const RadioGroup = require("./RadioGroup-Dd0rHXSX.cjs");
|
package/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { T as T2 } from "./Table-C2LbW0B1.js";
|
|
|
13
13
|
import { S as S3 } from "./StatusMessage-D0WgSBx7.js";
|
|
14
14
|
import { M, b, c, a as a3 } from "./Modal-BFpX5AFV.js";
|
|
15
15
|
import { I } from "./Input-DP_fKl38.js";
|
|
16
|
-
import { O, S as S4 } from "./Select-
|
|
16
|
+
import { O, S as S4 } from "./Select-BY5Y0qZ1.js";
|
|
17
17
|
import { A as A2, a as a4 } from "./Autocomplete-C_lW1VER.js";
|
|
18
18
|
import { S as S5 } from "./Switch-D72dpkH2.js";
|
|
19
19
|
import { R } from "./RadioGroup-bO-ahP9T.js";
|
package/package.json
CHANGED
package/Select-Dycmh9vt.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select-Dycmh9vt.js","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n Typography,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> = RHFSelectProps<TValue> | StandardSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const groupedOptions = useMemo(() => groupOptions(options), [options]);\n\n // Items del menú (grupos + opciones). Un solo memoizado — sin search/async.\n const buildMenuItems = (currentValue: TValue | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = normalizeSelectValue(selectValue);\n const isEmpty = isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue>\n value={normalizedValue as TValue}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => setIsOpen(false)}\n renderValue={(selected) => {\n if (isSelectValueEmpty(selected)) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>\n {placeholder ?? ''}\n </Typography>\n );\n }\n const item = options.find((opt) => opt.value === selected);\n return item?.label ?? String(selected);\n }}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {buildMenuItems(normalizedValue as TValue | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n )\n }\n />\n );\n }\n\n // ── Controlled mode ───────────────────────────────────────────────────\n const { value, onChange } = props as StandardSelectProps<TValue>;\n return renderSelect(value, (e) => onChange(e.target.value as TValue));\n}\n\nexport default Select;\n"],"names":["_a","MuiSelect"],"mappings":"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"}
|
package/Select-kqR48jZU.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select-kqR48jZU.cjs","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n Typography,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> = RHFSelectProps<TValue> | StandardSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const groupedOptions = useMemo(() => groupOptions(options), [options]);\n\n // Items del menú (grupos + opciones). Un solo memoizado — sin search/async.\n const buildMenuItems = (currentValue: TValue | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = normalizeSelectValue(selectValue);\n const isEmpty = isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue>\n value={normalizedValue as TValue}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => setIsOpen(false)}\n renderValue={(selected) => {\n if (isSelectValueEmpty(selected)) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>\n {placeholder ?? ''}\n </Typography>\n );\n }\n const item = options.find((opt) => opt.value === selected);\n return item?.label ?? String(selected);\n }}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {buildMenuItems(normalizedValue as TValue | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n )\n }\n />\n );\n }\n\n // ── Controlled mode ───────────────────────────────────────────────────\n const { value, onChange } = props as StandardSelectProps<TValue>;\n return renderSelect(value, (e) => onChange(e.target.value as TValue));\n}\n\nexport default Select;\n"],"names":["buildFormFieldSx","jsxs","MenuItem","jsx","ListItemIcon","useTheme","resolvePreset","useMemo","Children","isValidElement","_a","useState","ListSubheader","FilledInput","OutlinedInput","FormControl","InputLabel","MuiSelect","Typography","FormHelperText","Controller"],"mappings":"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"}
|