@soyfri/shared-library 4.0.2 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{Autocomplete-Bd3bN4Cw.cjs → Autocomplete-Baqwboth.cjs} +59 -38
- package/Autocomplete-Baqwboth.cjs.map +1 -0
- package/{Autocomplete-E5aSUGVK.js → Autocomplete-Cvf16lFk.js} +59 -38
- package/Autocomplete-Cvf16lFk.js.map +1 -0
- package/{DatePicker-D__RSgs-.js → DatePicker-D5BH4v1p.js} +3 -2
- package/{DatePicker-D__RSgs-.js.map → DatePicker-D5BH4v1p.js.map} +1 -1
- package/{DatePicker-CMcQddi1.cjs → DatePicker-mz7CYtVw.cjs} +3 -2
- package/{DatePicker-CMcQddi1.cjs.map → DatePicker-mz7CYtVw.cjs.map} +1 -1
- package/{DateTimePicker-LeaE716a.js → DateTimePicker-ZCf0Wh4r.js} +6 -2
- package/DateTimePicker-ZCf0Wh4r.js.map +1 -0
- package/{DateTimePicker-BVJGq1A0.cjs → DateTimePicker-ejQDpjgX.cjs} +6 -2
- package/DateTimePicker-ejQDpjgX.cjs.map +1 -0
- package/{Input-BibHlnGN.js → Input-CmvuMwXZ.js} +3 -2
- package/{Input-BibHlnGN.js.map → Input-CmvuMwXZ.js.map} +1 -1
- package/{Input-Bpjw7qwq.cjs → Input-hnQ7g6b7.cjs} +3 -2
- package/{Input-Bpjw7qwq.cjs.map → Input-hnQ7g6b7.cjs.map} +1 -1
- package/{Select-BIUq3ZPy.js → Select-CZ0BiKVN.js} +3 -2
- package/{Select-BIUq3ZPy.js.map → Select-CZ0BiKVN.js.map} +1 -1
- package/{Select-C06gHRqZ.cjs → Select-ZhFf4SBp.cjs} +3 -2
- package/{Select-C06gHRqZ.cjs.map → Select-ZhFf4SBp.cjs.map} +1 -1
- package/{StatusMessage-B3nXpuRl.cjs → StatusMessageContext-BMsbLKRq.cjs} +19 -1
- package/StatusMessageContext-BMsbLKRq.cjs.map +1 -0
- package/{StatusMessage-D0WgSBx7.js → StatusMessageContext-DgYiObYE.js} +21 -3
- package/StatusMessageContext-DgYiObYE.js.map +1 -0
- package/components/Autocomplete/Autocomplete.cjs +1 -1
- package/components/Autocomplete/Autocomplete.d.ts +30 -13
- package/components/Autocomplete/Autocomplete.helpers.d.ts +4 -4
- package/components/Autocomplete/Autocomplete.js +1 -1
- package/components/Autocomplete/_parts/AutocompleteChips.d.ts +7 -6
- package/components/Autocomplete/_parts/AutocompleteOption.d.ts +5 -5
- package/components/Autocomplete/index.d.ts +1 -1
- package/components/DatePicker/DatePicker.cjs +1 -1
- package/components/DatePicker/DatePicker.js +1 -1
- package/components/DateTimePicker/DateTimePicker.cjs +1 -1
- package/components/DateTimePicker/DateTimePicker.d.ts +9 -0
- package/components/DateTimePicker/DateTimePicker.js +1 -1
- package/components/Input/Input.cjs +1 -1
- package/components/Input/Input.js +1 -1
- package/components/Select/Select.cjs +1 -1
- package/components/Select/Select.js +1 -1
- package/components/StatusMessage/StatusMessage.cjs +5 -3
- package/components/StatusMessage/StatusMessage.cjs.map +1 -1
- package/components/StatusMessage/StatusMessage.js +4 -2
- package/components/StatusMessage/index.d.ts +2 -0
- package/components/_shared/resolvePreset.d.ts +9 -5
- package/index.cjs +25 -9
- package/index.cjs.map +1 -1
- package/index.d.ts +4 -4
- package/index.js +13 -9
- package/mui.d.ts +1 -1
- package/package.json +2 -3
- package/resolvePreset-CxTI6_Ln.cjs.map +1 -1
- package/resolvePreset-K6_BfWHD.js.map +1 -1
- package/Autocomplete-Bd3bN4Cw.cjs.map +0 -1
- package/Autocomplete-E5aSUGVK.js.map +0 -1
- package/DateTimePicker-BVJGq1A0.cjs.map +0 -1
- package/DateTimePicker-LeaE716a.js.map +0 -1
- package/README.md +0 -251
- package/StatusMessage-B3nXpuRl.cjs.map +0 -1
- package/StatusMessage-D0WgSBx7.js.map +0 -1
- package/local/affiliations/affiliations.dev.soyfri.com-key.pem +0 -28
- package/local/affiliations/affiliations.dev.soyfri.com.pem +0 -27
- package/local/aficiliaciones/afiliaciones.dev.soyfri.com-key.pem +0 -28
- package/local/aficiliaciones/afiliaciones.dev.soyfri.com.pem +0 -27
- package/local/afiliaciones/afiliaciones.dev.soyfri.com-key.pem +0 -28
- package/local/afiliaciones/afiliaciones.dev.soyfri.com.pem +0 -27
- package/local/root/rootCA-key.pem +0 -40
- package/local/root/rootCA.pem +0 -30
- package/local/soporte/supportweb.dev.soyfri.com-key.pem +0 -28
- package/local/soporte/supportweb.dev.soyfri.com.pem +0 -27
- package/local/support/supportweb.dev.soyfri.com-key.pem +0 -28
- package/local/support/supportweb.dev.soyfri.com.pem +0 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select-BIUq3ZPy.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 { FIELD_BORDER_RADIUS } from '../../theme/tokens';\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 = FIELD_BORDER_RADIUS,\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 // Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en\n // `rest` hasta el DOM del MuiSelect: \"Unknown event handler property\n // `onValueChange`. It will be ignored.\" en cada render del select en cascada.\n onValueChange: _onValueChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n onValueChange?: (value: TValue) => void;\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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"}
|
|
1
|
+
{"version":3,"file":"Select-CZ0BiKVN.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 { FIELD_BORDER_RADIUS } from '../../theme/tokens';\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 = FIELD_BORDER_RADIUS,\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 // Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en\n // `rest` hasta el DOM del MuiSelect: \"Unknown event handler property\n // `onValueChange`. It will be ignored.\" en cada render del select en cascada.\n onValueChange: _onValueChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n onValueChange?: (value: TValue) => void;\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 // Built-in primero, preset encima (ver Input).\n const mergedSx = [\n buildSelectSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,MAAM,gBAAgB,CAC3B,cACA,kBAEA,iBAAiB,EAAE,cAAc,eAAe;ACN3C,MAAM,eAAe,CAC1B,YACmC;AACnC,QAAM,SAAyC,CAAA;AAC/C,UAAQ,QAAQ,CAAC,QAAQ;AACvB,UAAM,QAAQ,IAAI,SAAS;AAC3B,QAAI,CAAC,OAAO,KAAK,EAAG,QAAO,KAAK,IAAI,CAAA;AACpC,WAAO,KAAK,EAAE,KAAK,GAAG;AAAA,EACxB,CAAC;AACD,SAAO;AACT;AAMO,MAAM,uBAAuB,CAAI,UACrC,wBAAS;AAGL,MAAM,qBAAqB,CAAC,oBACjC,oBAAoB,MACpB,oBAAoB,QACpB,oBAAoB;ACPf,MAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IAEC,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB;AAAA,IAEA,UAAA;AAAA,MAAA,oBAAC,cAAA,EAAa,IAAI,EAAE,UAAU,GAAA,GAC3B,UAAA,YAAY,oBAAC,WAAA,EAAU,OAAM,WAAU,UAAS,SAAQ,GAC3D;AAAA,MACC,eAAe,aAAa,MAAM,IAAI,OAAO;AAAA,IAAA;AAAA,EAAA;AAAA,EARzC,OAAO,OAAO,KAAK;AAS1B;ACTK,SAAS,YACd,OACA;;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAEJ,QAAM,UACJ,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW;AAE/D,MAAI,SAAS;AACX,WACE,oBAAC,cAAW,IAAI,EAAE,OAAO,gBAAA,GAAoB,yBAAe,IAAG;AAAA,EAEnE;AAEA,MAAI,CAAC,UAAU;AACb,UAAM,OAAO,QAAQ,KAAK,CAAC,QAAQ,IAAI,UAAU,QAAQ;AACzD,QAAI,mBAAmB,KAAM,QAAO,oBAAA,UAAA,EAAG,UAAA,gBAAgB,IAAI,GAAE;AAC7D,WAAO,oBAAA,UAAA,EAAG,WAAA,kCAAM,UAAN,YAAe,OAAO,QAAQ,GAAE;AAAA,EAC5C;AAEA,QAAM,sBAAsB;AAC5B,QAAM,iBAAiB,oBAAoB,MAAM,GAAG,cAAc;AAClE,QAAM,mBAAmB,oBAAoB,SAAS;AAEtD,QAAM,eAAe,CAAC,cAAsB;AAC1C,QAAI,CAAC,gBAAgB,CAAC,cAAe;AACrC,iBAAa,cAAc,OAAO,CAAC,MAAM,MAAM,SAAS,CAAC;AAAA,EAC3D;AAEA,SACE,qBAAC,KAAA,EAAI,IAAI,EAAE,SAAS,QAAQ,UAAU,QAAQ,KAAK,IAAA,GAChD,UAAA;AAAA,IAAA,eAAe,IAAI,CAAC,QAAQ;AAC3B,YAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG;AAChD,UAAI,CAAC,KAAM,QAAO;AAElB,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS;AAAA,UACT,OAAM;AAAA,UACN,MAAK;AAAA,UAEL,OAAO,kBAAkB,gBAAgB,IAAI,IAAI,KAAK;AAAA,UACtD,QAAQ,KAAK,MAAM,oBAAC,UAAO,KAAK,KAAK,KAAK,IAAK;AAAA,UAC/C,UAAU,MAAM,aAAa,GAAG;AAAA,UAChC,YAAY,oBAAC,WAAA,EAAU,UAAS,QAAA,CAAQ;AAAA,QAAA;AAAA,QAJnC,OAAO,GAAG;AAAA,MAAA;AAAA,IAOrB,CAAC;AAAA,IACA,mBAAmB,KAClB,oBAAC,MAAA,EAAK,MAAK,SAAQ,SAAS,aAAa,OAAO,IAAI,gBAAgB,OAAA,CAAQ;AAAA,EAAA,GAEhF;AAEJ;ACsEO,SAAS,OAAO,QAAqB;AAC1C,SAAO;AACT;AACA,OAAO,cAAc;AAGd,SAAS,OAEd,OAA4B;AAC5B,QAmCI,YAlCF;AAAA;AAAA,IACA,UAAU,CAAA;AAAA,IACV;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA,WAAW;AAAA,IACX,QAAQ;AAAA,IACR;AAAA,IACA,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd;AAAA,IACA,aAAa;AAAA,IAGb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,UAAU;AAAA,IAIV,eAAe;AAAA,MAEb,IADC,iBACD,IADC;AAAA,IAjCH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAcF,QAAM,QAAQ,SAAA;AACd,QAAM,WAAW,cAAc,UAAU,QAAQ,KAAK;AAEtD,QAAM,YAAY,aAAa,SAAU,MAAiC,YAAY;AAGtF,QAAM,eAAwC,QAAQ,MAAM;;AAC1D,QAAI,SAAS,MAAM,QAAQ,MAAM,GAAG;AAClC,YAAM,QAAQ,SAAS,KAAK,QAAQ;AACpC,UAAI,eAAe,KAAK,OAAMA,MAAA,MAAM,SAAN,gBAAAA,IAAoB,iBAAgB,UAAU;AAC1E,eAAQ,MAAM,MAAsB;AAAA,MACtC;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,EAAE;AAE/C,QAAM,kBAAkB,QAAQ,MAAM;AACpC,QAAI,CAAC,cAAc,CAAC,WAAW,KAAA,EAAQ,QAAO;AAC9C,UAAM,IAAI,WAAW,KAAA,EAAO,YAAA;AAC5B,WAAO,QAAQ,OAAO,CAAC,QAAQ,IAAI,MAAM,YAAA,EAAc,SAAS,CAAC,CAAC;AAAA,EACpE,GAAG,CAAC,SAAS,YAAY,UAAU,CAAC;AAEpC,QAAM,iBAAiB;AAAA,IACrB,MAAM,aAAa,eAAe;AAAA,IAClC,CAAC,eAAe;AAAA,EAAA;AAIlB,QAAM,iBAAiB,CAAC,iBAAyC;AAC/D,UAAM,QAAqB,CAAA;AAC3B,WAAO,QAAQ,cAAc,EAAE,QAAQ,CAAC,CAAC,OAAO,IAAI,MAAM;AACxD,UAAI,UAAU,aAAa;AACzB,cAAM;AAAA,UACJ,oBAAC,eAAA,EAA0B,eAAa,MACrC,mBADiB,KAEpB;AAAA,QAAA;AAAA,MAEJ;AACA,WAAK,QAAQ,CAAC,QAAQ;AACpB,cAAM,WAAW,MAAM,QAAQ,YAAY,IACvC,aAAa,SAAS,IAAI,KAAe,IACzC,iBAAiB,IAAI;AACzB,cAAM;AAAA,UACJ,qBAAqB;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UAAA,CACD;AAAA,QAAA;AAAA,MAEL,CAAC;AAAA,IACH,CAAC;AACD,WAAO;AAAA,EACT;AAGA,QAAM,WAAW;AAAA,IACf,cAAc,cAAc,aAAa;AAAA,IACzC,GAAI,WAAW,CAAC,QAAQ,IAAI,CAAA;AAAA,IAC5B,GAAI,MAAM,QAAQ,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,IAAI,CAAA;AAAA,EAAC;AAI5C,QAAM,eAAe,CACnB,aACA,gBACA,QACA,UACA,UACA,eACA,mBACG;AACH,UAAM,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC;AACnC,UAAM,kBAAkB,wCAAiB;AAEzC,UAAM,eACJ,YAAY,WACR,oBAAC,aAAA,CAAA,CAAY,IACb,kBAAkB,aAChB,oBAAC,eAAA,EAAc,MAAA,CAAc,wBAC5B,eAAA,EAAc;AAEvB,UAAM,kBAAkB,WAClB,oCAA+C,CAAA,IACjD,qBAAqB,WAAwC;AACjE,UAAM,UAAU,WACX,gBAA6B,WAAW,IACzC,mBAAmB,eAAe;AAGtC,UAAM,eAAe,CAAC,WAAW,aAAa;AAE9C,UAAM,2BACJ,YAAY,aAAa,WAAW,CAAC,CAAC;AAExC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,IAAI;AAAA,QAEH,UAAA;AAAA,UAAA,SAAS,oBAAC,YAAA,EAAW,QAAQ,cAAe,UAAA,OAAM;AAAA,UACnD;AAAA,YAACC;AAAAA,YAAA;AAAA,cACC;AAAA,cACA,OAAO;AAAA,cACP,UAAU;AAAA,cACV,QAAQ,CAAC,MAAM;AACb,6BAAa,KAAK;AAClB,iDAAS;AAAA,cACX;AAAA,cACA,SAAS,MAAM,aAAa,IAAI;AAAA,cAChC,QAAQ,MAAM,UAAU,IAAI;AAAA,cAC5B,SAAS,MAAM;AACb,0BAAU,KAAK;AACf,oBAAI,0BAA0B,EAAE;AAAA,cAClC;AAAA,cACA,aAAa,CAAC,aACZ;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,eAAe,WAAY,WAAwB;AAAA,kBACnD,cAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGlB,cAAc;AAAA,cACd,OAAO;AAAA,cACP;AAAA,cACA,WAAW;AAAA,gBACT,YAAY;AAAA,kBACV,OAAO,EAAE,WAAW,SAAA;AAAA,gBAAS;AAAA,cAC/B;AAAA,cAEF;AAAA,eACK,OApCN;AAAA,cAsCE,UAAA;AAAA,gBAAA,cACC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,UAAU,UAAU,KAAK,GAAG,QAAQ,GAAG,SAAS,mBAAA;AAAA,oBACtE,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,oBAClB,WAAW,CAAC,MAAM,EAAE,gBAAA;AAAA,oBAEpB,UAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAS;AAAA,wBACT,WAAS;AAAA,wBACT,aAAY;AAAA,wBACZ,OAAO;AAAA,wBACP,UAAU,CAAC,MAAM,cAAc,EAAE,OAAO,KAAK;AAAA,wBAC7C,WAAW;AAAA,0BACT,OAAO;AAAA,4BACL,oCACG,gBAAA,EAAe,UAAS,SACvB,UAAA,oBAAC,YAAA,EAAW,UAAS,QAAA,CAAQ,EAAA,CAC/B;AAAA,0BAAA;AAAA,wBAEJ;AAAA,sBACF;AAAA,oBAAA;AAAA,kBACF;AAAA,gBAAA;AAAA,gBAGH,eAAe,eAAyC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAE1D,mBAAmB,oBAAC,gBAAA,EAAgB,UAAA,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3D;AAGA,MAAI,WAAW;AACb,UAAM,EAAE,MAAM,SAAS,YAAY,kBAAkB;AACrD,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,OAAO,WAAA,EAAW;;AAChD;AAAA,aACED,MAAA,MAAM,UAAN,OAAAA,MAAe;AAAA,YACf,CAAC,MAAM;AACL,oBAAM,OAAO,EAAE,OAAO;AACtB,oBAAM,SAAS,IAAI;AACnB,6DAAgB;AAAA,YAClB;AAAA,YACA,MAAM;AAAA,YACN,MAAM;AAAA,YACN,CAAC,CAAC;AAAA,YACF,yCAAY;AAAA,YACZ,CAAC,aAAa;AACZ,oBAAM,SAAS,QAAQ;AACvB,6DAAgB;AAAA,YAClB;AAAA,UAAA;AAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAIR;AAGA,QAAM,EAAE,OAAO,SAAA,IAAa;AAG5B,QAAM,eAAe;AACrB,SAAO;AAAA,IACL;AAAA,IACA,CAAC,MAAM,aAAa,EAAE,OAAO,KAA0B;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC,SAAU,SAAqC,IAAI;AAAA,EAAA;AAExD;"}
|
|
@@ -236,7 +236,8 @@ function Select(props) {
|
|
|
236
236
|
return items;
|
|
237
237
|
};
|
|
238
238
|
const mergedSx = [
|
|
239
|
-
|
|
239
|
+
buildSelectSx(borderRadius, labelPosition),
|
|
240
|
+
...presetSx ? [presetSx] : [],
|
|
240
241
|
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
241
242
|
];
|
|
242
243
|
const renderSelect = (selectValue, selectOnChange, onBlur, inputRef, rhfError, rhfHelperText, onValuesChange) => {
|
|
@@ -378,4 +379,4 @@ function Select(props) {
|
|
|
378
379
|
}
|
|
379
380
|
exports.Option = Option;
|
|
380
381
|
exports.Select = Select;
|
|
381
|
-
//# sourceMappingURL=Select-
|
|
382
|
+
//# sourceMappingURL=Select-ZhFf4SBp.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select-C06gHRqZ.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 { FIELD_BORDER_RADIUS } from '../../theme/tokens';\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 = FIELD_BORDER_RADIUS,\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 // Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en\n // `rest` hasta el DOM del MuiSelect: \"Unknown event handler property\n // `onValueChange`. It will be ignored.\" en cada render del select en cascada.\n onValueChange: _onValueChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n onValueChange?: (value: TValue) => void;\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","FIELD_BORDER_RADIUS","useTheme","resolvePreset","useMemo","Children","isValidElement","_a","useState","ListSubheader","FilledInput","OutlinedInput","FormControl","InputLabel","MuiSelect","TextField","InputAdornment","FormHelperText","Controller"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select-ZhFf4SBp.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 { FIELD_BORDER_RADIUS } from '../../theme/tokens';\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 = FIELD_BORDER_RADIUS,\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 // Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en\n // `rest` hasta el DOM del MuiSelect: \"Unknown event handler property\n // `onValueChange`. It will be ignored.\" en cada render del select en cascada.\n onValueChange: _onValueChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n onValueChange?: (value: TValue) => void;\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 // Built-in primero, preset encima (ver Input).\n const mergedSx = [\n buildSelectSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\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","FIELD_BORDER_RADIUS","useTheme","resolvePreset","useMemo","Children","isValidElement","_a","useState","ListSubheader","FilledInput","OutlinedInput","FormControl","InputLabel","MuiSelect","TextField","InputAdornment","FormHelperText","Controller"],"mappings":"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"}
|
|
@@ -84,5 +84,23 @@ const StatusMessage = ({
|
|
|
84
84
|
}
|
|
85
85
|
);
|
|
86
86
|
};
|
|
87
|
+
const initialValues = {
|
|
88
|
+
state: void 0,
|
|
89
|
+
setMessage: () => {
|
|
90
|
+
},
|
|
91
|
+
cleanMessage: () => {
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const StatusMessageContext = React.createContext(initialValues);
|
|
95
|
+
const useStatusMessageContext = () => React.useContext(StatusMessageContext);
|
|
96
|
+
const StatusMessageProvider = ({ children }) => {
|
|
97
|
+
const [stateMessage, setMessage] = React.useState(void 0);
|
|
98
|
+
const cleanMessage = () => {
|
|
99
|
+
setMessage(void 0);
|
|
100
|
+
};
|
|
101
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatusMessageContext.Provider, { value: { setMessage, cleanMessage, state: stateMessage }, children });
|
|
102
|
+
};
|
|
87
103
|
exports.StatusMessage = StatusMessage;
|
|
88
|
-
|
|
104
|
+
exports.StatusMessageProvider = StatusMessageProvider;
|
|
105
|
+
exports.useStatusMessageContext = useStatusMessageContext;
|
|
106
|
+
//# sourceMappingURL=StatusMessageContext-BMsbLKRq.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusMessageContext-BMsbLKRq.cjs","sources":["../src/components/StatusMessage/StatusMessage.tsx","../src/components/StatusMessage/StatusMessageContext.tsx"],"sourcesContent":["import { useId, useState, type FC } from 'react';\nimport {\n Alert,\n Box,\n Typography,\n Dialog,\n DialogContent,\n DialogActions,\n Button,\n} from '@mui/material';\nimport {\n ErrorOutline as ErrorOutlineIcon,\n CheckCircleOutline as CheckCircleOutlineIcon,\n WarningAmber as WarningAmberIcon,\n} from '@mui/icons-material';\n\nexport interface StatusMessageProps {\n /** Título del mensaje. */\n title?: string;\n /** Descripción/contenido detallado. Requerido para que el componente renderice. */\n description?: string;\n /** Tipo de mensaje (controla color + icono). `danger` mapea a `error` de MUI. */\n messageType?: 'success' | 'danger' | 'warning';\n /** Forma de presentación: alerta inline o modal. Default: `'alert'`. */\n displayType?: 'alert' | 'modal';\n /** Callback al cerrar. Si se omite, no se muestra botón de cerrar. */\n close?: () => void;\n /**\n * Controla visibilidad. Si se omite, el componente maneja su propio\n * state (se oculta solo al llamar `close`). Si se pasa, queda controlled\n * y el consumer es responsable de actualizarlo.\n */\n open?: boolean;\n}\n\n/**\n * Mensaje de éxito / error / advertencia en forma de alerta inline o modal.\n *\n * - **Uncontrolled**: sin pasar `open`, el componente maneja su propia\n * visibilidad. Al llamar `close`, se oculta automáticamente.\n * - **Controlled**: pasando `open`, el consumer decide cuándo mostrar/ocultar.\n */\nexport const StatusMessage: FC<StatusMessageProps> = ({\n title,\n description,\n messageType = 'success',\n displayType = 'alert',\n close,\n open: controlledOpen,\n}) => {\n const [internalOpen, setInternalOpen] = useState(true);\n const titleId = useId();\n const descId = useId();\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleClose = () => {\n if (!isControlled) setInternalOpen(false);\n close?.();\n };\n\n const alertVariant = messageType === 'danger' ? 'error' : messageType;\n\n const icon =\n messageType === 'success' ? (\n <CheckCircleOutlineIcon sx={{ fontSize: 64, color: 'success.main' }} />\n ) : messageType === 'danger' ? (\n <ErrorOutlineIcon sx={{ fontSize: 64, color: 'error.main' }} />\n ) : (\n <WarningAmberIcon sx={{ fontSize: 64, color: 'warning.main' }} />\n );\n\n if (!description) return null;\n if (!isOpen) return null;\n\n if (displayType === 'modal') {\n return (\n <Dialog\n open={isOpen}\n onClose={handleClose}\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={descId}\n maxWidth=\"md\"\n slotProps={{\n paper: {\n sx: { borderRadius: '16px', p: 2 },\n },\n }}\n >\n <DialogContent\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n p: 4,\n gap: 2,\n }}\n >\n <Box sx={{ mb: 2 }}>{icon}</Box>\n {title && (\n <Typography\n id={titleId}\n variant=\"h4\"\n component=\"h2\"\n sx={{ fontWeight: 'bold' }}\n >\n {title}\n </Typography>\n )}\n <Typography id={descId} variant=\"body1\" color=\"text.secondary\">\n {description}\n </Typography>\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'center', p: 2 }}>\n <Button onClick={handleClose} variant=\"contained\" color={alertVariant}>\n Aceptar\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n\n return (\n <Alert\n severity={alertVariant}\n sx={{ mb: 2, mt: 2 }}\n onClose={close !== undefined ? handleClose : undefined}\n >\n {title && (\n <Typography variant=\"h6\" sx={{ fontWeight: 'bold' }}>\n {title}\n </Typography>\n )}\n <Typography variant=\"body2\" sx={{ mt: 1 }}>\n {description}\n </Typography>\n </Alert>\n );\n};\n\nexport default StatusMessage;\n","import {\n createContext,\n useState,\n useContext,\n type Dispatch,\n type SetStateAction,\n type ReactNode,\n} from 'react';\nimport type { StatusMessageProps } from './StatusMessage';\n\nexport type StatusMessageState = {\n [K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;\n} & Pick<StatusMessageProps, 'displayType'>;\n\ninterface StatusMessageContextValue {\n state: StatusMessageState | undefined;\n setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;\n cleanMessage: () => void;\n}\n\nconst initialValues: StatusMessageContextValue = {\n state: undefined,\n setMessage: () => {},\n cleanMessage: () => {},\n};\n\nconst StatusMessageContext = createContext<StatusMessageContextValue>(initialValues);\n\nexport const useStatusMessageContext = () => useContext(StatusMessageContext);\n\ninterface StatusMessageProviderProps {\n children: ReactNode;\n}\n\nexport const StatusMessageProvider = ({ children }: StatusMessageProviderProps) => {\n const [stateMessage, setMessage] = useState<StatusMessageState | undefined>(undefined);\n const cleanMessage = () => {\n setMessage(undefined);\n };\n\n return (\n <StatusMessageContext.Provider value={{ setMessage, cleanMessage, state: stateMessage }}>\n {children}\n </StatusMessageContext.Provider>\n );\n};\n"],"names":["useState","useId","jsx","CheckCircleOutlineIcon","ErrorOutlineIcon","WarningAmberIcon","jsxs","Dialog","DialogContent","Box","Typography","DialogActions","Button","Alert","createContext","useContext"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useId } from "react";
|
|
2
|
+
import { useState, useId, createContext, useContext } from "react";
|
|
3
3
|
import { Dialog, DialogContent, Box, Typography, DialogActions, Button, Alert } from "@mui/material";
|
|
4
4
|
import { CheckCircleOutline, ErrorOutline, WarningAmber } from "@mui/icons-material";
|
|
5
5
|
const StatusMessage = ({
|
|
@@ -83,7 +83,25 @@ const StatusMessage = ({
|
|
|
83
83
|
}
|
|
84
84
|
);
|
|
85
85
|
};
|
|
86
|
+
const initialValues = {
|
|
87
|
+
state: void 0,
|
|
88
|
+
setMessage: () => {
|
|
89
|
+
},
|
|
90
|
+
cleanMessage: () => {
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const StatusMessageContext = createContext(initialValues);
|
|
94
|
+
const useStatusMessageContext = () => useContext(StatusMessageContext);
|
|
95
|
+
const StatusMessageProvider = ({ children }) => {
|
|
96
|
+
const [stateMessage, setMessage] = useState(void 0);
|
|
97
|
+
const cleanMessage = () => {
|
|
98
|
+
setMessage(void 0);
|
|
99
|
+
};
|
|
100
|
+
return /* @__PURE__ */ jsx(StatusMessageContext.Provider, { value: { setMessage, cleanMessage, state: stateMessage }, children });
|
|
101
|
+
};
|
|
86
102
|
export {
|
|
87
|
-
StatusMessage as S
|
|
103
|
+
StatusMessage as S,
|
|
104
|
+
StatusMessageProvider as a,
|
|
105
|
+
useStatusMessageContext as u
|
|
88
106
|
};
|
|
89
|
-
//# sourceMappingURL=
|
|
107
|
+
//# sourceMappingURL=StatusMessageContext-DgYiObYE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusMessageContext-DgYiObYE.js","sources":["../src/components/StatusMessage/StatusMessage.tsx","../src/components/StatusMessage/StatusMessageContext.tsx"],"sourcesContent":["import { useId, useState, type FC } from 'react';\nimport {\n Alert,\n Box,\n Typography,\n Dialog,\n DialogContent,\n DialogActions,\n Button,\n} from '@mui/material';\nimport {\n ErrorOutline as ErrorOutlineIcon,\n CheckCircleOutline as CheckCircleOutlineIcon,\n WarningAmber as WarningAmberIcon,\n} from '@mui/icons-material';\n\nexport interface StatusMessageProps {\n /** Título del mensaje. */\n title?: string;\n /** Descripción/contenido detallado. Requerido para que el componente renderice. */\n description?: string;\n /** Tipo de mensaje (controla color + icono). `danger` mapea a `error` de MUI. */\n messageType?: 'success' | 'danger' | 'warning';\n /** Forma de presentación: alerta inline o modal. Default: `'alert'`. */\n displayType?: 'alert' | 'modal';\n /** Callback al cerrar. Si se omite, no se muestra botón de cerrar. */\n close?: () => void;\n /**\n * Controla visibilidad. Si se omite, el componente maneja su propio\n * state (se oculta solo al llamar `close`). Si se pasa, queda controlled\n * y el consumer es responsable de actualizarlo.\n */\n open?: boolean;\n}\n\n/**\n * Mensaje de éxito / error / advertencia en forma de alerta inline o modal.\n *\n * - **Uncontrolled**: sin pasar `open`, el componente maneja su propia\n * visibilidad. Al llamar `close`, se oculta automáticamente.\n * - **Controlled**: pasando `open`, el consumer decide cuándo mostrar/ocultar.\n */\nexport const StatusMessage: FC<StatusMessageProps> = ({\n title,\n description,\n messageType = 'success',\n displayType = 'alert',\n close,\n open: controlledOpen,\n}) => {\n const [internalOpen, setInternalOpen] = useState(true);\n const titleId = useId();\n const descId = useId();\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleClose = () => {\n if (!isControlled) setInternalOpen(false);\n close?.();\n };\n\n const alertVariant = messageType === 'danger' ? 'error' : messageType;\n\n const icon =\n messageType === 'success' ? (\n <CheckCircleOutlineIcon sx={{ fontSize: 64, color: 'success.main' }} />\n ) : messageType === 'danger' ? (\n <ErrorOutlineIcon sx={{ fontSize: 64, color: 'error.main' }} />\n ) : (\n <WarningAmberIcon sx={{ fontSize: 64, color: 'warning.main' }} />\n );\n\n if (!description) return null;\n if (!isOpen) return null;\n\n if (displayType === 'modal') {\n return (\n <Dialog\n open={isOpen}\n onClose={handleClose}\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={descId}\n maxWidth=\"md\"\n slotProps={{\n paper: {\n sx: { borderRadius: '16px', p: 2 },\n },\n }}\n >\n <DialogContent\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n p: 4,\n gap: 2,\n }}\n >\n <Box sx={{ mb: 2 }}>{icon}</Box>\n {title && (\n <Typography\n id={titleId}\n variant=\"h4\"\n component=\"h2\"\n sx={{ fontWeight: 'bold' }}\n >\n {title}\n </Typography>\n )}\n <Typography id={descId} variant=\"body1\" color=\"text.secondary\">\n {description}\n </Typography>\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'center', p: 2 }}>\n <Button onClick={handleClose} variant=\"contained\" color={alertVariant}>\n Aceptar\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n\n return (\n <Alert\n severity={alertVariant}\n sx={{ mb: 2, mt: 2 }}\n onClose={close !== undefined ? handleClose : undefined}\n >\n {title && (\n <Typography variant=\"h6\" sx={{ fontWeight: 'bold' }}>\n {title}\n </Typography>\n )}\n <Typography variant=\"body2\" sx={{ mt: 1 }}>\n {description}\n </Typography>\n </Alert>\n );\n};\n\nexport default StatusMessage;\n","import {\n createContext,\n useState,\n useContext,\n type Dispatch,\n type SetStateAction,\n type ReactNode,\n} from 'react';\nimport type { StatusMessageProps } from './StatusMessage';\n\nexport type StatusMessageState = {\n [K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;\n} & Pick<StatusMessageProps, 'displayType'>;\n\ninterface StatusMessageContextValue {\n state: StatusMessageState | undefined;\n setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;\n cleanMessage: () => void;\n}\n\nconst initialValues: StatusMessageContextValue = {\n state: undefined,\n setMessage: () => {},\n cleanMessage: () => {},\n};\n\nconst StatusMessageContext = createContext<StatusMessageContextValue>(initialValues);\n\nexport const useStatusMessageContext = () => useContext(StatusMessageContext);\n\ninterface StatusMessageProviderProps {\n children: ReactNode;\n}\n\nexport const StatusMessageProvider = ({ children }: StatusMessageProviderProps) => {\n const [stateMessage, setMessage] = useState<StatusMessageState | undefined>(undefined);\n const cleanMessage = () => {\n setMessage(undefined);\n };\n\n return (\n <StatusMessageContext.Provider value={{ setMessage, cleanMessage, state: stateMessage }}>\n {children}\n </StatusMessageContext.Provider>\n );\n};\n"],"names":["CheckCircleOutlineIcon","ErrorOutlineIcon","WarningAmberIcon"],"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 Autocomplete = require("../../Autocomplete-
|
|
3
|
+
const Autocomplete = require("../../Autocomplete-Baqwboth.cjs");
|
|
4
4
|
exports.Autocomplete = Autocomplete.Autocomplete;
|
|
5
5
|
exports.AutocompleteSelect = Autocomplete.AutocompleteSelect;
|
|
6
6
|
exports.default = Autocomplete.Autocomplete;
|
|
@@ -2,8 +2,10 @@ import { ReactNode, SyntheticEvent } from 'react';
|
|
|
2
2
|
import { TextFieldProps } from '@mui/material';
|
|
3
3
|
import { SxProps, Theme } from '@mui/material/styles';
|
|
4
4
|
import { RegisterOptions } from 'react-hook-form';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** Key estable usada para comparar values, indexar caches y como React key. */
|
|
6
|
+
export type AutocompleteValueKey = string | number;
|
|
7
|
+
export interface SelectOption<TValue = AutocompleteValueKey> {
|
|
8
|
+
value: TValue;
|
|
7
9
|
label: string;
|
|
8
10
|
img?: string;
|
|
9
11
|
disabled?: boolean;
|
|
@@ -12,11 +14,12 @@ export interface SelectOption {
|
|
|
12
14
|
}
|
|
13
15
|
export type LabelPosition = 'outside' | 'floating';
|
|
14
16
|
export type AutocompleteSize = 'small' | 'medium';
|
|
15
|
-
export type RenderOptionItem = (item: SelectOption) => ReactNode;
|
|
16
|
-
export type RenderChipLabel = (item: SelectOption) => ReactNode;
|
|
17
|
-
export type
|
|
17
|
+
export type RenderOptionItem<TValue = AutocompleteValueKey> = (item: SelectOption<TValue>) => ReactNode;
|
|
18
|
+
export type RenderChipLabel<TValue = AutocompleteValueKey> = (item: SelectOption<TValue>) => ReactNode;
|
|
19
|
+
export type RenderSingleValue<TValue = AutocompleteValueKey> = (item: SelectOption<TValue>) => ReactNode;
|
|
20
|
+
export type BaseAutocompleteProps<TValue = AutocompleteValueKey> = {
|
|
18
21
|
label?: string;
|
|
19
|
-
options: SelectOption[];
|
|
22
|
+
options: SelectOption<TValue>[];
|
|
20
23
|
placeholder?: string;
|
|
21
24
|
multiple?: boolean;
|
|
22
25
|
disabled?: boolean;
|
|
@@ -25,8 +28,22 @@ export type BaseAutocompleteProps<_TValue extends SelectOption['value'] = Select
|
|
|
25
28
|
error?: boolean;
|
|
26
29
|
helperText?: string;
|
|
27
30
|
maxChipsToShow?: number;
|
|
28
|
-
renderOptionItem?: RenderOptionItem
|
|
29
|
-
renderChipLabel?: RenderChipLabel
|
|
31
|
+
renderOptionItem?: RenderOptionItem<TValue>;
|
|
32
|
+
renderChipLabel?: RenderChipLabel<TValue>;
|
|
33
|
+
/**
|
|
34
|
+
* Renderiza JSX custom como `startAdornment` del input en single mode.
|
|
35
|
+
* Recibe la `SelectOption` seleccionada. Útil para mostrar avatars, iconos,
|
|
36
|
+
* etc. junto al texto del label. En `multiple` no aplica (se usa `renderChipLabel`).
|
|
37
|
+
*/
|
|
38
|
+
renderSingleValue?: RenderSingleValue<TValue>;
|
|
39
|
+
/**
|
|
40
|
+
* Extrae una key estable (string | number) desde el `value`. Obligatorio
|
|
41
|
+
* cuando `TValue` es un objeto: se usa para comparar values (`isOptionEqualToValue`,
|
|
42
|
+
* resolución desde el value del form), indexar el cache interno de opciones
|
|
43
|
+
* vistas y como React key en chips/options del dropdown. Para primitivos se
|
|
44
|
+
* puede omitir (default: identidad, o sea `===`).
|
|
45
|
+
*/
|
|
46
|
+
getOptionKey?: (value: TValue) => AutocompleteValueKey;
|
|
30
47
|
/** Border radius del input. Default: 10. */
|
|
31
48
|
borderRadius?: number | string;
|
|
32
49
|
/** "outside" (default) = label arriba del input; "floating" = comportamiento nativo MUI. */
|
|
@@ -52,21 +69,21 @@ export type BaseAutocompleteProps<_TValue extends SelectOption['value'] = Select
|
|
|
52
69
|
/** Valor controlado del texto de búsqueda. */
|
|
53
70
|
inputValue?: string;
|
|
54
71
|
/** Filtro custom. Para búsqueda remota pasar `(x) => x` y confiar sólo en el servicio. */
|
|
55
|
-
filterOptions?: (options: SelectOption[], state: any) => SelectOption[];
|
|
72
|
+
filterOptions?: (options: SelectOption<TValue>[], state: any) => SelectOption<TValue>[];
|
|
56
73
|
/** Permite valores arbitrarios (no solo de la lista). */
|
|
57
74
|
freeSolo?: boolean;
|
|
58
75
|
open?: boolean;
|
|
59
76
|
onOpen?: (event: SyntheticEvent) => void;
|
|
60
77
|
onClose?: (event: SyntheticEvent, reason: string) => void;
|
|
61
78
|
};
|
|
62
|
-
export interface ControlledAutocompleteProps<TValue
|
|
79
|
+
export interface ControlledAutocompleteProps<TValue = AutocompleteValueKey> extends BaseAutocompleteProps<TValue> {
|
|
63
80
|
value: TValue | TValue[] | null;
|
|
64
81
|
onChange: (val: TValue | TValue[] | null) => void;
|
|
65
82
|
name?: string;
|
|
66
83
|
control?: never;
|
|
67
84
|
validation?: never;
|
|
68
85
|
}
|
|
69
|
-
export interface RHFAutocompleteProps<TValue
|
|
86
|
+
export interface RHFAutocompleteProps<TValue = AutocompleteValueKey> extends BaseAutocompleteProps<TValue> {
|
|
70
87
|
name: string;
|
|
71
88
|
control: any;
|
|
72
89
|
validation?: RegisterOptions;
|
|
@@ -78,8 +95,8 @@ export interface RHFAutocompleteProps<TValue extends SelectOption['value'] = Sel
|
|
|
78
95
|
value?: never;
|
|
79
96
|
onChange?: never;
|
|
80
97
|
}
|
|
81
|
-
export type AutocompleteProps<TValue
|
|
82
|
-
export declare function Autocomplete<TValue
|
|
98
|
+
export type AutocompleteProps<TValue = AutocompleteValueKey> = ControlledAutocompleteProps<TValue> | RHFAutocompleteProps<TValue>;
|
|
99
|
+
export declare function Autocomplete<TValue = AutocompleteValueKey>(props: AutocompleteProps<TValue>): import("react/jsx-runtime").JSX.Element;
|
|
83
100
|
/** Alias de `Autocomplete`. Ambos nombres son equivalentes. */
|
|
84
101
|
export declare const AutocompleteSelect: typeof Autocomplete;
|
|
85
102
|
export default Autocomplete;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { SxProps, Theme } from '@mui/material/styles';
|
|
2
|
-
import { SelectOption } from './Autocomplete';
|
|
2
|
+
import { AutocompleteValueKey, SelectOption } from './Autocomplete';
|
|
3
3
|
/** Resuelve un value único a su SelectOption dentro del pool. */
|
|
4
|
-
export declare const resolveSingleValue: (options: SelectOption[], value:
|
|
4
|
+
export declare const resolveSingleValue: <TValue>(options: SelectOption<TValue>[], value: TValue | null | undefined, getKey: (v: TValue) => AutocompleteValueKey) => SelectOption<TValue> | null;
|
|
5
5
|
/** Resuelve un array de values a sus SelectOption dentro del pool. */
|
|
6
|
-
export declare const resolveMultipleValue: (options: SelectOption[], value:
|
|
6
|
+
export declare const resolveMultipleValue: <TValue>(options: SelectOption<TValue>[], value: TValue[] | null | undefined, getKey: (v: TValue) => AutocompleteValueKey) => SelectOption<TValue>[];
|
|
7
7
|
/** Merge de sx base + extra del consumer, respetando el contrato de MUI. */
|
|
8
8
|
export declare const mergeSx: (base: SxProps<Theme>, extra?: SxProps<Theme>) => SxProps<Theme>;
|
|
9
9
|
/**
|
|
@@ -17,6 +17,6 @@ export declare const mergeSx: (base: SxProps<Theme>, extra?: SxProps<Theme>) =>
|
|
|
17
17
|
* refresh de metadata (label/img/etc.) invalide la referencia estabilizada
|
|
18
18
|
* y la UI muestre los datos actualizados.
|
|
19
19
|
*/
|
|
20
|
-
export declare const areResolvedValuesEqual: (prev: SelectOption | SelectOption[] | null, next: SelectOption | SelectOption[] | null, multiple: boolean) => boolean;
|
|
20
|
+
export declare const areResolvedValuesEqual: <TValue>(prev: SelectOption<TValue> | SelectOption<TValue>[] | null, next: SelectOption<TValue> | SelectOption<TValue>[] | null, multiple: boolean, getKey: (v: TValue) => AutocompleteValueKey) => boolean;
|
|
21
21
|
/** Determina si un valor resuelto está vacío (para placeholder/shrink). */
|
|
22
22
|
export declare const isResolvedValueEmpty: (resolvedValue: unknown, multiple: boolean) => boolean;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
value: SelectOption[];
|
|
1
|
+
import { AutocompleteValueKey, SelectOption, RenderChipLabel, AutocompleteSize } from '../Autocomplete';
|
|
2
|
+
interface AutocompleteChipsProps<TValue = AutocompleteValueKey> {
|
|
3
|
+
value: SelectOption<TValue>[];
|
|
5
4
|
getTagProps: (args: {
|
|
6
5
|
index: number;
|
|
7
6
|
}) => Record<string, any>;
|
|
8
7
|
size: AutocompleteSize;
|
|
9
8
|
maxChipsToShow: number;
|
|
10
|
-
renderChipLabel?: RenderChipLabel
|
|
9
|
+
renderChipLabel?: RenderChipLabel<TValue>;
|
|
10
|
+
/** Key estable del value: React key del chip. Ver `getOptionKey`. */
|
|
11
|
+
getKey: (value: TValue) => AutocompleteValueKey;
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
14
|
* Render de los chips del Autocomplete en modo multiple.
|
|
@@ -15,5 +16,5 @@ interface AutocompleteChipsProps {
|
|
|
15
16
|
* El `getTagProps({ index })` viene de MUI y contiene el handler de delete,
|
|
16
17
|
* la key, etc. — se spreadea tal cual al Chip.
|
|
17
18
|
*/
|
|
18
|
-
export declare const AutocompleteChips:
|
|
19
|
+
export declare const AutocompleteChips: <TValue>({ value, getTagProps, size, maxChipsToShow, renderChipLabel, getKey, }: AutocompleteChipsProps<TValue>) => import("react/jsx-runtime").JSX.Element;
|
|
19
20
|
export default AutocompleteChips;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import { SelectOption, RenderOptionItem } from '../Autocomplete';
|
|
3
|
-
interface AutocompleteOptionProps {
|
|
2
|
+
import { AutocompleteValueKey, SelectOption, RenderOptionItem } from '../Autocomplete';
|
|
3
|
+
interface AutocompleteOptionProps<TValue = AutocompleteValueKey> {
|
|
4
4
|
liProps: React.HTMLAttributes<HTMLLIElement>;
|
|
5
|
-
option: SelectOption
|
|
6
|
-
customRender?: RenderOptionItem
|
|
5
|
+
option: SelectOption<TValue>;
|
|
6
|
+
customRender?: RenderOptionItem<TValue>;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Render por defecto de un `<li>` del dropdown del Autocomplete.
|
|
@@ -12,5 +12,5 @@ interface AutocompleteOptionProps {
|
|
|
12
12
|
* La `key` la maneja el padre (`renderOption` en Autocomplete.tsx). Este
|
|
13
13
|
* componente solo recibe los props restantes del `<li>` para spread.
|
|
14
14
|
*/
|
|
15
|
-
export declare const AutocompleteOption:
|
|
15
|
+
export declare const AutocompleteOption: <TValue>({ liProps, option, customRender, }: AutocompleteOptionProps<TValue>) => import("react/jsx-runtime").JSX.Element;
|
|
16
16
|
export default AutocompleteOption;
|