UNPKG

10.7 kBJavaScriptView Raw
1'use client';
2
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import clsx from 'clsx';
6import deepmerge from '@mui/utils/deepmerge';
7import composeClasses from '@mui/utils/composeClasses';
8import getReactElementRef from '@mui/utils/getReactElementRef';
9import SelectInput from "./SelectInput.js";
10import formControlState from "../FormControl/formControlState.js";
11import useFormControl from "../FormControl/useFormControl.js";
12import ArrowDropDownIcon from "../internal/svg-icons/ArrowDropDown.js";
13import Input from "../Input/index.js";
14import NativeSelectInput from "../NativeSelect/NativeSelectInput.js";
15import FilledInput from "../FilledInput/index.js";
16import OutlinedInput from "../OutlinedInput/index.js";
17import { useDefaultProps } from "../DefaultPropsProvider/index.js";
18import useForkRef from "../utils/useForkRef.js";
19import { styled } from "../zero-styled/index.js";
20import rootShouldForwardProp from "../styles/rootShouldForwardProp.js";
21import { getSelectUtilityClasses } from "./selectClasses.js";
22import { jsx as _jsx } from "react/jsx-runtime";
23const useUtilityClasses = ownerState => {
24 const {
25 classes
26 } = ownerState;
27 const slots = {
28 root: ['root']
29 };
30 const composedClasses = composeClasses(slots, getSelectUtilityClasses, classes);
31 return {
32 ...classes,
33 ...composedClasses
34 };
35};
36const styledRootConfig = {
37 name: 'MuiSelect',
38 overridesResolver: (props, styles) => styles.root,
39 shouldForwardProp: prop => rootShouldForwardProp(prop) && prop !== 'variant',
40 slot: 'Root'
41};
42const StyledInput = styled(Input, styledRootConfig)('');
43const StyledOutlinedInput = styled(OutlinedInput, styledRootConfig)('');
44const StyledFilledInput = styled(FilledInput, styledRootConfig)('');
45const Select = /*#__PURE__*/React.forwardRef(function Select(inProps, ref) {
46 const props = useDefaultProps({
47 name: 'MuiSelect',
48 props: inProps
49 });
50 const {
51 autoWidth = false,
52 children,
53 classes: classesProp = {},
54 className,
55 defaultOpen = false,
56 displayEmpty = false,
57 IconComponent = ArrowDropDownIcon,
58 id,
59 input,
60 inputProps,
61 label,
62 labelId,
63 MenuProps,
64 multiple = false,
65 native = false,
66 onClose,
67 onOpen,
68 open,
69 renderValue,
70 SelectDisplayProps,
71 variant: variantProp = 'outlined',
72 ...other
73 } = props;
74 const inputComponent = native ? NativeSelectInput : SelectInput;
75 const muiFormControl = useFormControl();
76 const fcs = formControlState({
77 props,
78 muiFormControl,
79 states: ['variant', 'error']
80 });
81 const variant = fcs.variant || variantProp;
82 const ownerState = {
83 ...props,
84 variant,
85 classes: classesProp
86 };
87 const classes = useUtilityClasses(ownerState);
88 const {
89 root,
90 ...restOfClasses
91 } = classes;
92 const InputComponent = input || {
93 standard: /*#__PURE__*/_jsx(StyledInput, {
94 ownerState: ownerState
95 }),
96 outlined: /*#__PURE__*/_jsx(StyledOutlinedInput, {
97 label: label,
98 ownerState: ownerState
99 }),
100 filled: /*#__PURE__*/_jsx(StyledFilledInput, {
101 ownerState: ownerState
102 })
103 }[variant];
104 const inputComponentRef = useForkRef(ref, getReactElementRef(InputComponent));
105 return /*#__PURE__*/_jsx(React.Fragment, {
106 children: /*#__PURE__*/React.cloneElement(InputComponent, {
107 // Most of the logic is implemented in `SelectInput`.
108 // The `Select` component is a simple API wrapper to expose something better to play with.
109 inputComponent,
110 inputProps: {
111 children,
112 error: fcs.error,
113 IconComponent,
114 variant,
115 type: undefined,
116 // We render a select. We can ignore the type provided by the `Input`.
117 multiple,
118 ...(native ? {
119 id
120 } : {
121 autoWidth,
122 defaultOpen,
123 displayEmpty,
124 labelId,
125 MenuProps,
126 onClose,
127 onOpen,
128 open,
129 renderValue,
130 SelectDisplayProps: {
131 id,
132 ...SelectDisplayProps
133 }
134 }),
135 ...inputProps,
136 classes: inputProps ? deepmerge(restOfClasses, inputProps.classes) : restOfClasses,
137 ...(input ? input.props.inputProps : {})
138 },
139 ...((multiple && native || displayEmpty) && variant === 'outlined' ? {
140 notched: true
141 } : {}),
142 ref: inputComponentRef,
143 className: clsx(InputComponent.props.className, className, classes.root),
144 // If a custom input is provided via 'input' prop, do not allow 'variant' to be propagated to it's root element. See https://github.com/mui/material-ui/issues/33894.
145 ...(!input && {
146 variant
147 }),
148 ...other
149 })
150 });
151});
152process.env.NODE_ENV !== "production" ? Select.propTypes /* remove-proptypes */ = {
153 // ┌────────────────────────────── Warning ──────────────────────────────┐
154 // │ These PropTypes are generated from the TypeScript type definitions. │
155 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
156 // └─────────────────────────────────────────────────────────────────────┘
157 /**
158 * If `true`, the width of the popover will automatically be set according to the items inside the
159 * menu, otherwise it will be at least the width of the select input.
160 * @default false
161 */
162 autoWidth: PropTypes.bool,
163 /**
164 * The option elements to populate the select with.
165 * Can be some `MenuItem` when `native` is false and `option` when `native` is true.
166 *
167 * ⚠️The `MenuItem` elements **must** be direct descendants when `native` is false.
168 */
169 children: PropTypes.node,
170 /**
171 * Override or extend the styles applied to the component.
172 * @default {}
173 */
174 classes: PropTypes.object,
175 /**
176 * @ignore
177 */
178 className: PropTypes.string,
179 /**
180 * If `true`, the component is initially open. Use when the component open state is not controlled (i.e. the `open` prop is not defined).
181 * You can only use it when the `native` prop is `false` (default).
182 * @default false
183 */
184 defaultOpen: PropTypes.bool,
185 /**
186 * The default value. Use when the component is not controlled.
187 */
188 defaultValue: PropTypes.any,
189 /**
190 * If `true`, a value is displayed even if no items are selected.
191 *
192 * In order to display a meaningful value, a function can be passed to the `renderValue` prop which
193 * returns the value to be displayed when no items are selected.
194 *
195 * ⚠️ When using this prop, make sure the label doesn't overlap with the empty displayed value.
196 * The label should either be hidden or forced to a shrunk state.
197 * @default false
198 */
199 displayEmpty: PropTypes.bool,
200 /**
201 * The icon that displays the arrow.
202 * @default ArrowDropDownIcon
203 */
204 IconComponent: PropTypes.elementType,
205 /**
206 * The `id` of the wrapper element or the `select` element when `native`.
207 */
208 id: PropTypes.string,
209 /**
210 * An `Input` element; does not have to be a material-ui specific `Input`.
211 */
212 input: PropTypes.element,
213 /**
214 * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
215 * When `native` is `true`, the attributes are applied on the `select` element.
216 */
217 inputProps: PropTypes.object,
218 /**
219 * See [OutlinedInput#label](https://mui.com/material-ui/api/outlined-input/#props)
220 */
221 label: PropTypes.node,
222 /**
223 * The ID of an element that acts as an additional label. The Select will
224 * be labelled by the additional label and the selected value.
225 */
226 labelId: PropTypes.string,
227 /**
228 * Props applied to the [`Menu`](https://mui.com/material-ui/api/menu/) element.
229 */
230 MenuProps: PropTypes.object,
231 /**
232 * If `true`, `value` must be an array and the menu will support multiple selections.
233 * @default false
234 */
235 multiple: PropTypes.bool,
236 /**
237 * If `true`, the component uses a native `select` element.
238 * @default false
239 */
240 native: PropTypes.bool,
241 /**
242 * Callback fired when a menu item is selected.
243 *
244 * @param {SelectChangeEvent<Value>} event The event source of the callback.
245 * You can pull out the new value by accessing `event.target.value` (any).
246 * **Warning**: This is a generic event, not a change event, unless the change event is caused by browser autofill.
247 * @param {object} [child] The react element that was selected when `native` is `false` (default).
248 */
249 onChange: PropTypes.func,
250 /**
251 * Callback fired when the component requests to be closed.
252 * Use it in either controlled (see the `open` prop), or uncontrolled mode (to detect when the Select collapses).
253 *
254 * @param {object} event The event source of the callback.
255 */
256 onClose: PropTypes.func,
257 /**
258 * Callback fired when the component requests to be opened.
259 * Use it in either controlled (see the `open` prop), or uncontrolled mode (to detect when the Select expands).
260 *
261 * @param {object} event The event source of the callback.
262 */
263 onOpen: PropTypes.func,
264 /**
265 * If `true`, the component is shown.
266 * You can only use it when the `native` prop is `false` (default).
267 */
268 open: PropTypes.bool,
269 /**
270 * Render the selected value.
271 * You can only use it when the `native` prop is `false` (default).
272 *
273 * @param {any} value The `value` provided to the component.
274 * @returns {ReactNode}
275 */
276 renderValue: PropTypes.func,
277 /**
278 * Props applied to the clickable div element.
279 */
280 SelectDisplayProps: PropTypes.object,
281 /**
282 * The system prop that allows defining system overrides as well as additional CSS styles.
283 */
284 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
285 /**
286 * The `input` value. Providing an empty string will select no options.
287 * Set to an empty string `''` if you don't want any of the available options to be selected.
288 *
289 * If the value is an object it must have reference equality with the option in order to be selected.
290 * If the value is not an object, the string representation must match with the string representation of the option in order to be selected.
291 */
292 value: PropTypes.oneOfType([PropTypes.oneOf(['']), PropTypes.any]),
293 /**
294 * The variant to use.
295 * @default 'outlined'
296 */
297 variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
298} : void 0;
299Select.muiName = 'Select';
300export default Select;
\No newline at end of file