UNPKG

7.31 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4import * as React from 'react';
5import PropTypes from 'prop-types';
6import { unstable_useControlled as useControlled } from '@mui/utils';
7import FormControlContext from './FormControlContext';
8import { getFormControlUtilityClass } from './formControlClasses';
9import { useSlotProps } from '../utils';
10import composeClasses from '../composeClasses';
11import { useClassNamesOverride } from '../utils/ClassNameConfigurator';
12import { jsx as _jsx } from "react/jsx-runtime";
13function hasValue(value) {
14 return value != null && !(Array.isArray(value) && value.length === 0) && value !== '';
15}
16function useUtilityClasses(ownerState) {
17 var disabled = ownerState.disabled,
18 error = ownerState.error,
19 filled = ownerState.filled,
20 focused = ownerState.focused,
21 required = ownerState.required;
22 var slots = {
23 root: ['root', disabled && 'disabled', focused && 'focused', error && 'error', filled && 'filled', required && 'required']
24 };
25 return composeClasses(slots, useClassNamesOverride(getFormControlUtilityClass));
26}
27
28/**
29 * Provides context such as filled/focused/error/required for form inputs.
30 * Relying on the context provides high flexibility and ensures that the state always stays
31 * consistent across the children of the `FormControl`.
32 * This context is used by the following components:
33 *
34 * * FormLabel
35 * * FormHelperText
36 * * Input
37 * * InputLabel
38 *
39 * You can find one composition example below and more going to [the demos](https://mui.com/material-ui/react-text-field/#components).
40 *
41 * ```jsx
42 * <FormControl>
43 * <InputLabel htmlFor="my-input">Email address</InputLabel>
44 * <Input id="my-input" aria-describedby="my-helper-text" />
45 * <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
46 * </FormControl>
47 * ```
48 *
49 * ⚠️ Only one `Input` can be used within a FormControl because it create visual inconsistencies.
50 * For instance, only one input can be focused at the same time, the state shouldn't be shared.
51 *
52 * Demos:
53 *
54 * - [Form Control](https://mui.com/base/react-form-control/)
55 * - [Input](https://mui.com/joy-ui/react-input/)
56 * - [Checkbox](https://mui.com/material-ui/react-checkbox/)
57 * - [Radio Group](https://mui.com/material-ui/react-radio-button/)
58 * - [Switch](https://mui.com/material-ui/react-switch/)
59 * - [Text Field](https://mui.com/material-ui/react-text-field/)
60 *
61 * API:
62 *
63 * - [FormControl API](https://mui.com/base/react-form-control/components-api/#form-control)
64 */
65var FormControl = /*#__PURE__*/React.forwardRef(function FormControl(props, forwardedRef) {
66 var _slots$root;
67 var defaultValue = props.defaultValue,
68 children = props.children,
69 _props$disabled = props.disabled,
70 disabled = _props$disabled === void 0 ? false : _props$disabled,
71 _props$error = props.error,
72 error = _props$error === void 0 ? false : _props$error,
73 _onChange = props.onChange,
74 _props$required = props.required,
75 required = _props$required === void 0 ? false : _props$required,
76 _props$slotProps = props.slotProps,
77 slotProps = _props$slotProps === void 0 ? {} : _props$slotProps,
78 _props$slots = props.slots,
79 slots = _props$slots === void 0 ? {} : _props$slots,
80 incomingValue = props.value,
81 other = _objectWithoutProperties(props, ["defaultValue", "children", "disabled", "error", "onChange", "required", "slotProps", "slots", "value"]);
82 var _useControlled = useControlled({
83 controlled: incomingValue,
84 default: defaultValue,
85 name: 'FormControl',
86 state: 'value'
87 }),
88 _useControlled2 = _slicedToArray(_useControlled, 2),
89 value = _useControlled2[0],
90 setValue = _useControlled2[1];
91 var filled = hasValue(value);
92 var _React$useState = React.useState(false),
93 focusedState = _React$useState[0],
94 setFocused = _React$useState[1];
95 var focused = focusedState && !disabled;
96 React.useEffect(function () {
97 return setFocused(function (isFocused) {
98 return disabled ? false : isFocused;
99 });
100 }, [disabled]);
101 var ownerState = _extends({}, props, {
102 disabled: disabled,
103 error: error,
104 filled: filled,
105 focused: focused,
106 required: required
107 });
108 var childContext = React.useMemo(function () {
109 return {
110 disabled: disabled,
111 error: error,
112 filled: filled,
113 focused: focused,
114 onBlur: function onBlur() {
115 setFocused(false);
116 },
117 onChange: function onChange(event) {
118 setValue(event.target.value);
119 _onChange == null ? void 0 : _onChange(event);
120 },
121 onFocus: function onFocus() {
122 setFocused(true);
123 },
124 required: required,
125 value: value != null ? value : ''
126 };
127 }, [disabled, error, filled, focused, _onChange, required, setValue, value]);
128 var classes = useUtilityClasses(ownerState);
129 var renderChildren = function renderChildren() {
130 if (typeof children === 'function') {
131 return children(childContext);
132 }
133 return children;
134 };
135 var Root = (_slots$root = slots.root) != null ? _slots$root : 'div';
136 var rootProps = useSlotProps({
137 elementType: Root,
138 externalSlotProps: slotProps.root,
139 externalForwardedProps: other,
140 additionalProps: {
141 ref: forwardedRef,
142 children: renderChildren()
143 },
144 ownerState: ownerState,
145 className: classes.root
146 });
147 return /*#__PURE__*/_jsx(FormControlContext.Provider, {
148 value: childContext,
149 children: /*#__PURE__*/_jsx(Root, _extends({}, rootProps))
150 });
151});
152process.env.NODE_ENV !== "production" ? FormControl.propTypes /* remove-proptypes */ = {
153 // ----------------------------- Warning --------------------------------
154 // | These PropTypes are generated from the TypeScript type definitions |
155 // | To update them edit TypeScript types and run "yarn proptypes" |
156 // ----------------------------------------------------------------------
157 /**
158 * The content of the component.
159 */
160 children: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.node, PropTypes.func]),
161 /**
162 * @ignore
163 */
164 defaultValue: PropTypes.any,
165 /**
166 * If `true`, the label, input and helper text should be displayed in a disabled state.
167 * @default false
168 */
169 disabled: PropTypes.bool,
170 /**
171 * If `true`, the label is displayed in an error state.
172 * @default false
173 */
174 error: PropTypes.bool,
175 /**
176 * Callback fired when the form element's value is modified.
177 */
178 onChange: PropTypes.func,
179 /**
180 * If `true`, the label will indicate that the `input` is required.
181 * @default false
182 */
183 required: PropTypes.bool,
184 /**
185 * The props used for each slot inside the FormControl.
186 * @default {}
187 */
188 slotProps: PropTypes.shape({
189 root: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
190 }),
191 /**
192 * The components used for each slot inside the FormControl.
193 * Either a string to use a HTML element or a component.
194 * @default {}
195 */
196 slots: PropTypes.shape({
197 root: PropTypes.elementType
198 }),
199 /**
200 * The value of the form element.
201 */
202 value: PropTypes.any
203} : void 0;
204export default FormControl;
\No newline at end of file