UNPKG

7.3 kBJavaScriptView Raw
1'use client';
2
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import clsx from 'clsx';
6import refType from '@mui/utils/refType';
7import composeClasses from '@mui/utils/composeClasses';
8import capitalize from "../utils/capitalize.js";
9import rootShouldForwardProp from "../styles/rootShouldForwardProp.js";
10import { styled } from "../zero-styled/index.js";
11import useControlled from "../utils/useControlled.js";
12import useFormControl from "../FormControl/useFormControl.js";
13import ButtonBase from "../ButtonBase/index.js";
14import { getSwitchBaseUtilityClass } from "./switchBaseClasses.js";
15import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16const useUtilityClasses = ownerState => {
17 const {
18 classes,
19 checked,
20 disabled,
21 edge
22 } = ownerState;
23 const slots = {
24 root: ['root', checked && 'checked', disabled && 'disabled', edge && `edge${capitalize(edge)}`],
25 input: ['input']
26 };
27 return composeClasses(slots, getSwitchBaseUtilityClass, classes);
28};
29const SwitchBaseRoot = styled(ButtonBase)({
30 padding: 9,
31 borderRadius: '50%',
32 variants: [{
33 props: {
34 edge: 'start',
35 size: 'small'
36 },
37 style: {
38 marginLeft: -3
39 }
40 }, {
41 props: ({
42 edge,
43 ownerState
44 }) => edge === 'start' && ownerState.size !== 'small',
45 style: {
46 marginLeft: -12
47 }
48 }, {
49 props: {
50 edge: 'end',
51 size: 'small'
52 },
53 style: {
54 marginRight: -3
55 }
56 }, {
57 props: ({
58 edge,
59 ownerState
60 }) => edge === 'end' && ownerState.size !== 'small',
61 style: {
62 marginRight: -12
63 }
64 }]
65});
66const SwitchBaseInput = styled('input', {
67 shouldForwardProp: rootShouldForwardProp
68})({
69 cursor: 'inherit',
70 position: 'absolute',
71 opacity: 0,
72 width: '100%',
73 height: '100%',
74 top: 0,
75 left: 0,
76 margin: 0,
77 padding: 0,
78 zIndex: 1
79});
80
81/**
82 * @ignore - internal component.
83 */
84const SwitchBase = /*#__PURE__*/React.forwardRef(function SwitchBase(props, ref) {
85 const {
86 autoFocus,
87 checked: checkedProp,
88 checkedIcon,
89 className,
90 defaultChecked,
91 disabled: disabledProp,
92 disableFocusRipple = false,
93 edge = false,
94 icon,
95 id,
96 inputProps,
97 inputRef,
98 name,
99 onBlur,
100 onChange,
101 onFocus,
102 readOnly,
103 required = false,
104 tabIndex,
105 type,
106 value,
107 ...other
108 } = props;
109 const [checked, setCheckedState] = useControlled({
110 controlled: checkedProp,
111 default: Boolean(defaultChecked),
112 name: 'SwitchBase',
113 state: 'checked'
114 });
115 const muiFormControl = useFormControl();
116 const handleFocus = event => {
117 if (onFocus) {
118 onFocus(event);
119 }
120 if (muiFormControl && muiFormControl.onFocus) {
121 muiFormControl.onFocus(event);
122 }
123 };
124 const handleBlur = event => {
125 if (onBlur) {
126 onBlur(event);
127 }
128 if (muiFormControl && muiFormControl.onBlur) {
129 muiFormControl.onBlur(event);
130 }
131 };
132 const handleInputChange = event => {
133 // Workaround for https://github.com/facebook/react/issues/9023
134 if (event.nativeEvent.defaultPrevented) {
135 return;
136 }
137 const newChecked = event.target.checked;
138 setCheckedState(newChecked);
139 if (onChange) {
140 // TODO v6: remove the second argument.
141 onChange(event, newChecked);
142 }
143 };
144 let disabled = disabledProp;
145 if (muiFormControl) {
146 if (typeof disabled === 'undefined') {
147 disabled = muiFormControl.disabled;
148 }
149 }
150 const hasLabelFor = type === 'checkbox' || type === 'radio';
151 const ownerState = {
152 ...props,
153 checked,
154 disabled,
155 disableFocusRipple,
156 edge
157 };
158 const classes = useUtilityClasses(ownerState);
159 return /*#__PURE__*/_jsxs(SwitchBaseRoot, {
160 component: "span",
161 className: clsx(classes.root, className),
162 centerRipple: true,
163 focusRipple: !disableFocusRipple,
164 disabled: disabled,
165 tabIndex: null,
166 role: undefined,
167 onFocus: handleFocus,
168 onBlur: handleBlur,
169 ownerState: ownerState,
170 ref: ref,
171 ...other,
172 children: [/*#__PURE__*/_jsx(SwitchBaseInput, {
173 autoFocus: autoFocus,
174 checked: checkedProp,
175 defaultChecked: defaultChecked,
176 className: classes.input,
177 disabled: disabled,
178 id: hasLabelFor ? id : undefined,
179 name: name,
180 onChange: handleInputChange,
181 readOnly: readOnly,
182 ref: inputRef,
183 required: required,
184 ownerState: ownerState,
185 tabIndex: tabIndex,
186 type: type,
187 ...(type === 'checkbox' && value === undefined ? {} : {
188 value
189 }),
190 ...inputProps
191 }), checked ? checkedIcon : icon]
192 });
193});
194
195// NB: If changed, please update Checkbox, Switch and Radio
196// so that the API documentation is updated.
197process.env.NODE_ENV !== "production" ? SwitchBase.propTypes = {
198 /**
199 * If `true`, the `input` element is focused during the first mount.
200 */
201 autoFocus: PropTypes.bool,
202 /**
203 * If `true`, the component is checked.
204 */
205 checked: PropTypes.bool,
206 /**
207 * The icon to display when the component is checked.
208 */
209 checkedIcon: PropTypes.node.isRequired,
210 /**
211 * Override or extend the styles applied to the component.
212 */
213 classes: PropTypes.object,
214 /**
215 * @ignore
216 */
217 className: PropTypes.string,
218 /**
219 * @ignore
220 */
221 defaultChecked: PropTypes.bool,
222 /**
223 * If `true`, the component is disabled.
224 */
225 disabled: PropTypes.bool,
226 /**
227 * If `true`, the keyboard focus ripple is disabled.
228 * @default false
229 */
230 disableFocusRipple: PropTypes.bool,
231 /**
232 * If given, uses a negative margin to counteract the padding on one
233 * side (this is often helpful for aligning the left or right
234 * side of the icon with content above or below, without ruining the border
235 * size and shape).
236 * @default false
237 */
238 edge: PropTypes.oneOf(['end', 'start', false]),
239 /**
240 * The icon to display when the component is unchecked.
241 */
242 icon: PropTypes.node.isRequired,
243 /**
244 * The id of the `input` element.
245 */
246 id: PropTypes.string,
247 /**
248 * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
249 */
250 inputProps: PropTypes.object,
251 /**
252 * Pass a ref to the `input` element.
253 */
254 inputRef: refType,
255 /*
256 * @ignore
257 */
258 name: PropTypes.string,
259 /**
260 * @ignore
261 */
262 onBlur: PropTypes.func,
263 /**
264 * Callback fired when the state is changed.
265 *
266 * @param {object} event The event source of the callback.
267 * You can pull out the new checked state by accessing `event.target.checked` (boolean).
268 */
269 onChange: PropTypes.func,
270 /**
271 * @ignore
272 */
273 onFocus: PropTypes.func,
274 /**
275 * It prevents the user from changing the value of the field
276 * (not from interacting with the field).
277 */
278 readOnly: PropTypes.bool,
279 /**
280 * If `true`, the `input` element is required.
281 */
282 required: PropTypes.bool,
283 /**
284 * The system prop that allows defining system overrides as well as additional CSS styles.
285 */
286 sx: PropTypes.object,
287 /**
288 * @ignore
289 */
290 tabIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
291 /**
292 * The input component prop `type`.
293 */
294 type: PropTypes.string.isRequired,
295 /**
296 * The value of the component.
297 */
298 value: PropTypes.any
299} : void 0;
300export default SwitchBase;
\No newline at end of file