UNPKG

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