@m4l/components 9.3.27 → 9.3.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEnvironment, useModuleSkeleton, useModuleDictionary } from "@m4l/core";
|
|
3
3
|
import { useTheme } from "@mui/material";
|
|
4
|
+
import { useForkRef } from "@mui/material/utils";
|
|
4
5
|
import clsx from "clsx";
|
|
5
|
-
import { forwardRef, useMemo, useState, useCallback } from "react";
|
|
6
|
+
import { forwardRef, useMemo, useState, useRef, useCallback, useEffect } from "react";
|
|
6
7
|
import { A as ArrowDownStyled, a as AdormentStyled, S as SelectRootStyled, b as SkeletonSelectStyled, M as MenuItemListStyled, c as MenuItemNoOptionStyled, L as LabelPlaceholerStyled, R as RenderValueContainerStyled, d as RenderValueTypography } from "./slots/SelectSlots.js";
|
|
7
8
|
import { I as ICON_ARROW_DOWN, S as SELECT_CLASSES, a as SELECT_KEY_COMPONENT } from "./constants.js";
|
|
8
9
|
import { S as SELECT_DICTIONARY } from "./dictionary.js";
|
|
@@ -23,6 +24,7 @@ const Select = forwardRef(
|
|
|
23
24
|
placeholder,
|
|
24
25
|
className,
|
|
25
26
|
dataTestId,
|
|
27
|
+
readOnly = false,
|
|
26
28
|
...otherProps
|
|
27
29
|
}, ref) {
|
|
28
30
|
const { currentSize } = useComponentSize(size);
|
|
@@ -33,22 +35,27 @@ const Select = forwardRef(
|
|
|
33
35
|
const arrowDropDownIcon = `${host_static_assets}/${environment_assets}/${ICON_ARROW_DOWN}`;
|
|
34
36
|
const selectedValue = useMemo(() => value, [value]);
|
|
35
37
|
const [openLocal, setOpenLocal] = useState(false);
|
|
38
|
+
const selectRef = useRef(null);
|
|
36
39
|
const theme = useTheme();
|
|
37
40
|
const ownerState = useMemo(() => ({
|
|
38
41
|
size: adjustedSize,
|
|
39
42
|
disabled,
|
|
40
43
|
error,
|
|
41
44
|
variant,
|
|
42
|
-
multiple
|
|
43
|
-
|
|
45
|
+
multiple,
|
|
46
|
+
readOnly
|
|
47
|
+
}), [adjustedSize, disabled, error, variant, multiple, readOnly]);
|
|
44
48
|
const handleLocalChange = useCallback((event) => {
|
|
49
|
+
if (readOnly || disabled) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
45
52
|
const newValue = event.target.value;
|
|
46
53
|
if (!onChange) {
|
|
47
54
|
return;
|
|
48
55
|
}
|
|
49
56
|
if (multiple) {
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
if (Array.isArray(newValue)) {
|
|
58
|
+
const selectedOptions = options.filter((option) => newValue.includes(option.id));
|
|
52
59
|
onChange(selectedOptions);
|
|
53
60
|
}
|
|
54
61
|
} else {
|
|
@@ -57,28 +64,41 @@ const Select = forwardRef(
|
|
|
57
64
|
onChange(selectedOption);
|
|
58
65
|
}
|
|
59
66
|
}
|
|
60
|
-
}, [multiple, onChange, options]);
|
|
67
|
+
}, [multiple, onChange, options, readOnly, disabled]);
|
|
61
68
|
const handleDelete = useCallback((optionToDelete) => {
|
|
69
|
+
if (readOnly || disabled) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
62
72
|
if (multiple && Array.isArray(selectedValue)) {
|
|
63
73
|
const newSelectedOptions = options.filter((option) => option.id !== optionToDelete.id && selectedValue.includes(option.id));
|
|
64
74
|
onChange?.(newSelectedOptions);
|
|
65
75
|
}
|
|
66
|
-
}, [multiple, selectedValue, onChange, options]);
|
|
76
|
+
}, [multiple, selectedValue, onChange, options, readOnly, disabled]);
|
|
77
|
+
const handleToggleClick = useCallback(() => {
|
|
78
|
+
if (disabled || readOnly) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (multiple) {
|
|
82
|
+
if (!openLocal) {
|
|
83
|
+
setOpenLocal(true);
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setOpenLocal(!openLocal);
|
|
88
|
+
}, [disabled, readOnly, multiple, openLocal]);
|
|
67
89
|
const ArrowIcon = useMemo(() => {
|
|
68
90
|
return () => /* @__PURE__ */ jsx(
|
|
69
91
|
ArrowDownStyled,
|
|
70
92
|
{
|
|
71
93
|
ownerState: { ...ownerState },
|
|
72
94
|
icon: arrowDropDownIcon,
|
|
73
|
-
disabled,
|
|
95
|
+
disabled: disabled || readOnly,
|
|
74
96
|
size: adjustedSize,
|
|
75
|
-
onClick:
|
|
76
|
-
!disabled && setOpenLocal(!openLocal);
|
|
77
|
-
},
|
|
97
|
+
onClick: handleToggleClick,
|
|
78
98
|
rotationAngle: openLocal ? 180 : 0
|
|
79
99
|
}
|
|
80
100
|
);
|
|
81
|
-
}, [ownerState, arrowDropDownIcon, disabled, adjustedSize, openLocal]);
|
|
101
|
+
}, [ownerState, arrowDropDownIcon, disabled, readOnly, adjustedSize, openLocal, handleToggleClick]);
|
|
82
102
|
const RenderIcon = useCallback((icon) => {
|
|
83
103
|
if (!icon) {
|
|
84
104
|
return null;
|
|
@@ -104,8 +124,8 @@ const Select = forwardRef(
|
|
|
104
124
|
e.stopPropagation();
|
|
105
125
|
}, []);
|
|
106
126
|
const renderValue = () => {
|
|
107
|
-
if (
|
|
108
|
-
return /* @__PURE__ */ jsx(LabelPlaceholerStyled, { variant: "body", color: "text.disabled", children: placeholder });
|
|
127
|
+
if (selectedValue === null || selectedValue === void 0 || multiple && Array.isArray(selectedValue) && selectedValue.length === 0) {
|
|
128
|
+
return /* @__PURE__ */ jsx(LabelPlaceholerStyled, { ownerState: { disabled, readOnly }, variant: "body", color: "text.disabled", children: placeholder });
|
|
109
129
|
}
|
|
110
130
|
if (multiple) {
|
|
111
131
|
if (!Array.isArray(selectedValue)) {
|
|
@@ -124,7 +144,7 @@ const Select = forwardRef(
|
|
|
124
144
|
label: option.label,
|
|
125
145
|
startIcon: option.startAdornment,
|
|
126
146
|
opacity: true,
|
|
127
|
-
onDeleted: () => handleDelete(option),
|
|
147
|
+
onDeleted: readOnly || disabled ? void 0 : () => handleDelete(option),
|
|
128
148
|
iconButtonProps: { onMouseDown: onMouseDownIconButtonChip, onKeyDown: onKeyDownIconButtonChip }
|
|
129
149
|
},
|
|
130
150
|
option.id
|
|
@@ -135,17 +155,26 @@ const Select = forwardRef(
|
|
|
135
155
|
const selectedOption = options.find((option) => String(option.id) === String(selectedValue));
|
|
136
156
|
return selectedOption ? /* @__PURE__ */ jsxs(RenderValueContainerStyled, { ownerState: { ...ownerState }, className: SELECT_CLASSES.renderValueContainer, children: [
|
|
137
157
|
selectedOption.startAdornment && RenderIcon(selectedOption.startAdornment),
|
|
138
|
-
/* @__PURE__ */ jsx(RenderValueTypography, { variant: "body", color: "text.primary", size: adjustedSize, className: SELECT_CLASSES.renderValueTypography, children: selectedOption.label })
|
|
158
|
+
/* @__PURE__ */ jsx(RenderValueTypography, { ownerState: { disabled, readOnly }, variant: "body", color: "text.primary", size: adjustedSize, className: SELECT_CLASSES.renderValueTypography, children: selectedOption.label })
|
|
139
159
|
] }) : "";
|
|
140
160
|
}
|
|
141
161
|
};
|
|
142
162
|
const onOpen = useCallback(() => {
|
|
163
|
+
if (disabled || readOnly) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
143
166
|
setOpenLocal(true);
|
|
144
|
-
}, []);
|
|
167
|
+
}, [disabled, readOnly]);
|
|
145
168
|
const onClose = useCallback(() => {
|
|
146
169
|
setOpenLocal(false);
|
|
147
170
|
}, []);
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
if (readOnly && openLocal) {
|
|
173
|
+
setOpenLocal(false);
|
|
174
|
+
}
|
|
175
|
+
}, [readOnly, openLocal]);
|
|
148
176
|
const StyledSelect = useMemo(() => SelectRootStyled(), []);
|
|
177
|
+
const handleRef = useForkRef(selectRef, ref);
|
|
149
178
|
if (isSkeleton) {
|
|
150
179
|
return /* @__PURE__ */ jsx(SkeletonSelectStyled, { ownerState: { ...ownerState }, className: SELECT_CLASSES.skeletonSelect });
|
|
151
180
|
}
|
|
@@ -154,7 +183,7 @@ const Select = forwardRef(
|
|
|
154
183
|
{
|
|
155
184
|
...otherProps,
|
|
156
185
|
...getPropDataTestId(SELECT_KEY_COMPONENT, SelectSlots.root, dataTestId),
|
|
157
|
-
ref,
|
|
186
|
+
ref: handleRef,
|
|
158
187
|
className: clsx(SELECT_CLASSES.root, SELECT_CLASSES[variant], className),
|
|
159
188
|
ownerState: { ...ownerState },
|
|
160
189
|
IconComponent: ArrowIcon,
|
|
@@ -165,29 +194,42 @@ const Select = forwardRef(
|
|
|
165
194
|
disabled,
|
|
166
195
|
error,
|
|
167
196
|
renderValue,
|
|
168
|
-
open: openLocal,
|
|
197
|
+
open: readOnly ? false : openLocal,
|
|
169
198
|
native: false,
|
|
170
199
|
onOpen,
|
|
171
200
|
onClose,
|
|
201
|
+
onClick: handleToggleClick,
|
|
172
202
|
displayEmpty: true,
|
|
203
|
+
inputProps: {
|
|
204
|
+
...otherProps.inputProps,
|
|
205
|
+
readOnly
|
|
206
|
+
},
|
|
173
207
|
MenuProps: {
|
|
174
208
|
disableScrollLock: true,
|
|
209
|
+
anchorOrigin: {
|
|
210
|
+
vertical: "bottom",
|
|
211
|
+
horizontal: "left"
|
|
212
|
+
},
|
|
213
|
+
transformOrigin: {
|
|
214
|
+
vertical: "top",
|
|
215
|
+
horizontal: "left"
|
|
216
|
+
},
|
|
175
217
|
sx: {
|
|
176
218
|
"& .MuiPaper-root": {
|
|
177
|
-
|
|
178
|
-
paddingBottom: theme.vars.size.baseSpacings.sp3,
|
|
179
|
-
paddingLeft: 0,
|
|
180
|
-
paddingRight: 0,
|
|
219
|
+
padding: theme.vars.size.baseSpacings.sp1,
|
|
181
220
|
maxHeight: "200px",
|
|
182
221
|
overflow: "auto",
|
|
222
|
+
minWidth: `${(selectRef?.current?.offsetWidth ?? 0) + 1}px!important`,
|
|
223
|
+
// +1 para incluir el border del contenedor root.
|
|
183
224
|
"& .MuiList-root": {
|
|
184
225
|
padding: 0,
|
|
185
|
-
display: "
|
|
186
|
-
|
|
226
|
+
display: "grid",
|
|
227
|
+
gridTemplateColumns: "auto",
|
|
187
228
|
gap: theme.vars.size.baseSpacings.sp1,
|
|
188
|
-
width: "fit-content",
|
|
229
|
+
width: "fit-content!important",
|
|
230
|
+
minWidth: "100%",
|
|
189
231
|
"& .MuiMenuItem-root": {
|
|
190
|
-
width: "
|
|
232
|
+
width: "100%"
|
|
191
233
|
}
|
|
192
234
|
}
|
|
193
235
|
}
|
|
@@ -13,6 +13,18 @@ const selectStyles = {
|
|
|
13
13
|
border: theme.vars.size.borderStroke.actionInput,
|
|
14
14
|
borderColor: ownerState?.error ? theme.vars.palette[color].enabled : theme.vars.palette.border.default,
|
|
15
15
|
padding: 0,
|
|
16
|
+
cursor: ownerState?.readOnly || ownerState?.disabled ? "default" : "pointer",
|
|
17
|
+
...ownerState?.readOnly && {
|
|
18
|
+
"& .M4LSelect-renderValueTypography": {
|
|
19
|
+
userSelect: "text",
|
|
20
|
+
cursor: "text"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"& .MuiSelect-nativeInput": {
|
|
24
|
+
inset: 0,
|
|
25
|
+
border: "unset",
|
|
26
|
+
outline: "unset"
|
|
27
|
+
},
|
|
16
28
|
"& .MuiOutlinedInput-notchedOutline": {
|
|
17
29
|
all: "unset",
|
|
18
30
|
display: "none"
|
|
@@ -41,7 +53,10 @@ const selectStyles = {
|
|
|
41
53
|
boxSizing: "border-box",
|
|
42
54
|
display: "flex",
|
|
43
55
|
flexDirection: "column",
|
|
44
|
-
flexWrap: "unset"
|
|
56
|
+
flexWrap: "unset",
|
|
57
|
+
...ownerState?.readOnly && {
|
|
58
|
+
cursor: "default"
|
|
59
|
+
}
|
|
45
60
|
},
|
|
46
61
|
// Estilos para la variante text
|
|
47
62
|
[`&&&.${SELECT_CLASSES.text}`]: {
|
|
@@ -106,8 +121,12 @@ const selectStyles = {
|
|
|
106
121
|
}
|
|
107
122
|
}),
|
|
108
123
|
arrowDown: {},
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Styles for the render value typography
|
|
126
|
+
*/
|
|
127
|
+
renderValueTypography: ({ ownerState }) => ({
|
|
128
|
+
lineHeight: "inherit!important",
|
|
129
|
+
cursor: ownerState?.readOnly || ownerState?.disabled ? "default" : "pointer"
|
|
111
130
|
}),
|
|
112
131
|
// chip: () => ({
|
|
113
132
|
// }),
|
|
@@ -122,16 +141,32 @@ const selectStyles = {
|
|
|
122
141
|
* Styles for the label placeholder
|
|
123
142
|
* @returns {object} The styles for the label placeholder
|
|
124
143
|
*/
|
|
125
|
-
labelPlaceholer: ({ theme }) => ({
|
|
144
|
+
labelPlaceholer: ({ theme, ownerState }) => ({
|
|
126
145
|
paddingLeft: theme.vars.size.baseSpacings.sp1,
|
|
127
|
-
paddingRight: theme.vars.size.baseSpacings.sp3
|
|
146
|
+
paddingRight: theme.vars.size.baseSpacings.sp3,
|
|
147
|
+
cursor: ownerState?.readOnly || ownerState?.disabled ? "default" : "pointer"
|
|
128
148
|
}),
|
|
129
149
|
/**
|
|
130
150
|
* Styles for the menu item select
|
|
131
151
|
* @param {object} theme - The theme object
|
|
132
152
|
* @returns {object} The styles for the menu item select
|
|
133
153
|
*/
|
|
134
|
-
menuItem: {
|
|
154
|
+
menuItem: {
|
|
155
|
+
"& .M4LMenuItem-menuItemContainer": {
|
|
156
|
+
width: "fit-content",
|
|
157
|
+
overflow: "unset",
|
|
158
|
+
"& .M4LImage-root": {
|
|
159
|
+
flexGrow: 1,
|
|
160
|
+
overflow: "auto",
|
|
161
|
+
flexShrink: 0
|
|
162
|
+
},
|
|
163
|
+
"& .M4LTypography-root": {
|
|
164
|
+
textOverflow: "unset",
|
|
165
|
+
overflow: "unset",
|
|
166
|
+
whiteSpace: "unset"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
},
|
|
135
170
|
/**
|
|
136
171
|
* Estilos del menuItem que no tiene opciones
|
|
137
172
|
* @param {object} theme - The theme object
|
|
@@ -45,6 +45,10 @@ export interface BaseSelectProps {
|
|
|
45
45
|
* Identificador único del componente, para pruebas automatizadas.
|
|
46
46
|
*/
|
|
47
47
|
dataTestId?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Define si el Select está en modo solo lectura.
|
|
50
|
+
*/
|
|
51
|
+
readOnly?: boolean;
|
|
48
52
|
}
|
|
49
53
|
export type SelectOptionValue<T extends string | number, Multiple> = Multiple extends true ? Array<SelectOption<T>> : SelectOption<T> | null;
|
|
50
54
|
/**
|
|
@@ -72,8 +76,9 @@ export interface SelectProps<T extends string | number, Multiple extends boolean
|
|
|
72
76
|
* Propiedades internas que definen el estado del componente `Select`.
|
|
73
77
|
* paletteColor - Color de la paleta aplicado al Select.
|
|
74
78
|
*/
|
|
75
|
-
export interface SelectOwnerState<T extends string | number, Multiple extends boolean | undefined = false> extends Pick<SelectProps<T, Multiple>, 'classes' | 'size' | 'error' | 'variant' | 'disabled' | 'multiple'> {
|
|
79
|
+
export interface SelectOwnerState<T extends string | number, Multiple extends boolean | undefined = false> extends Pick<SelectProps<T, Multiple>, 'classes' | 'size' | 'error' | 'variant' | 'disabled' | 'multiple' | 'readOnly'> {
|
|
76
80
|
disabled?: boolean;
|
|
81
|
+
readOnly?: boolean;
|
|
77
82
|
}
|
|
78
83
|
/**
|
|
79
84
|
* Define los tipos de slots disponibles en el Select.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m4l/components",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.28",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"description": "M4L Components",
|
|
6
6
|
"lint-staged": {
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
"attr-accept": "2.2.2",
|
|
65
65
|
"@vitejs/plugin-react": "4.3.4",
|
|
66
66
|
"storybook": "8.3.4",
|
|
67
|
-
"@storybook/react": "8.3.4"
|
|
67
|
+
"@storybook/react": "8.3.4",
|
|
68
|
+
"rollup": "4.52.5"
|
|
68
69
|
},
|
|
69
70
|
"overrides": {
|
|
70
71
|
"glob": "^10.4.5",
|
|
@@ -73,7 +74,8 @@
|
|
|
73
74
|
"@types/react": "18.3.23",
|
|
74
75
|
"@types/react-dom": "18.3.7",
|
|
75
76
|
"react-dom": "18.3.1",
|
|
76
|
-
"attr-accept": "2.2.2"
|
|
77
|
+
"attr-accept": "2.2.2",
|
|
78
|
+
"rollup": "4.52.5"
|
|
77
79
|
},
|
|
78
80
|
"files": [
|
|
79
81
|
"*"
|