UNPKG

8.51 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3// @inheritedComponent IconButton
4import * as React from 'react';
5import PropTypes from 'prop-types';
6import clsx from 'clsx';
7import { refType } from '@material-ui/utils';
8import withStyles from '../styles/withStyles';
9import { alpha } from '../styles/colorManipulator';
10import capitalize from '../utils/capitalize';
11import SwitchBase from '../internal/SwitchBase';
12export const styles = theme => ({
13 /* Styles applied to the root element. */
14 root: {
15 display: 'inline-flex',
16 width: 34 + 12 * 2,
17 height: 14 + 12 * 2,
18 overflow: 'hidden',
19 padding: 12,
20 boxSizing: 'border-box',
21 position: 'relative',
22 flexShrink: 0,
23 zIndex: 0,
24 // Reset the stacking context.
25 verticalAlign: 'middle',
26 // For correct alignment with the text.
27 '@media print': {
28 colorAdjust: 'exact'
29 }
30 },
31
32 /* Styles applied to the root element if `edge="start"`. */
33 edgeStart: {
34 marginLeft: -8
35 },
36
37 /* Styles applied to the root element if `edge="end"`. */
38 edgeEnd: {
39 marginRight: -8
40 },
41
42 /* Styles applied to the internal `SwitchBase` component's `root` class. */
43 switchBase: {
44 position: 'absolute',
45 top: 0,
46 left: 0,
47 zIndex: 1,
48 // Render above the focus ripple.
49 color: theme.palette.type === 'light' ? theme.palette.grey[50] : theme.palette.grey[400],
50 transition: theme.transitions.create(['left', 'transform'], {
51 duration: theme.transitions.duration.shortest
52 }),
53 '&$checked': {
54 transform: 'translateX(20px)'
55 },
56 '&$disabled': {
57 color: theme.palette.type === 'light' ? theme.palette.grey[400] : theme.palette.grey[800]
58 },
59 '&$checked + $track': {
60 opacity: 0.5
61 },
62 '&$disabled + $track': {
63 opacity: theme.palette.type === 'light' ? 0.12 : 0.1
64 }
65 },
66
67 /* Styles applied to the internal SwitchBase component's root element if `color="primary"`. */
68 colorPrimary: {
69 '&$checked': {
70 color: theme.palette.primary.main,
71 '&:hover': {
72 backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
73 '@media (hover: none)': {
74 backgroundColor: 'transparent'
75 }
76 }
77 },
78 '&$disabled': {
79 color: theme.palette.type === 'light' ? theme.palette.grey[400] : theme.palette.grey[800]
80 },
81 '&$checked + $track': {
82 backgroundColor: theme.palette.primary.main
83 },
84 '&$disabled + $track': {
85 backgroundColor: theme.palette.type === 'light' ? theme.palette.common.black : theme.palette.common.white
86 }
87 },
88
89 /* Styles applied to the internal SwitchBase component's root element if `color="secondary"`. */
90 colorSecondary: {
91 '&$checked': {
92 color: theme.palette.secondary.main,
93 '&:hover': {
94 backgroundColor: alpha(theme.palette.secondary.main, theme.palette.action.hoverOpacity),
95 '@media (hover: none)': {
96 backgroundColor: 'transparent'
97 }
98 }
99 },
100 '&$disabled': {
101 color: theme.palette.type === 'light' ? theme.palette.grey[400] : theme.palette.grey[800]
102 },
103 '&$checked + $track': {
104 backgroundColor: theme.palette.secondary.main
105 },
106 '&$disabled + $track': {
107 backgroundColor: theme.palette.type === 'light' ? theme.palette.common.black : theme.palette.common.white
108 }
109 },
110
111 /* Styles applied to the root element if `size="small"`. */
112 sizeSmall: {
113 width: 40,
114 height: 24,
115 padding: 7,
116 '& $thumb': {
117 width: 16,
118 height: 16
119 },
120 '& $switchBase': {
121 padding: 4,
122 '&$checked': {
123 transform: 'translateX(16px)'
124 }
125 }
126 },
127
128 /* Pseudo-class applied to the internal `SwitchBase` component's `checked` class. */
129 checked: {},
130
131 /* Pseudo-class applied to the internal SwitchBase component's disabled class. */
132 disabled: {},
133
134 /* Styles applied to the internal SwitchBase component's input element. */
135 input: {
136 left: '-100%',
137 width: '300%'
138 },
139
140 /* Styles used to create the thumb passed to the internal `SwitchBase` component `icon` prop. */
141 thumb: {
142 boxShadow: theme.shadows[1],
143 backgroundColor: 'currentColor',
144 width: 20,
145 height: 20,
146 borderRadius: '50%'
147 },
148
149 /* Styles applied to the track element. */
150 track: {
151 height: '100%',
152 width: '100%',
153 borderRadius: 14 / 2,
154 zIndex: -1,
155 transition: theme.transitions.create(['opacity', 'background-color'], {
156 duration: theme.transitions.duration.shortest
157 }),
158 backgroundColor: theme.palette.type === 'light' ? theme.palette.common.black : theme.palette.common.white,
159 opacity: theme.palette.type === 'light' ? 0.38 : 0.3
160 }
161});
162const Switch = /*#__PURE__*/React.forwardRef(function Switch(props, ref) {
163 const {
164 classes,
165 className,
166 color = 'secondary',
167 edge = false,
168 size = 'medium'
169 } = props,
170 other = _objectWithoutPropertiesLoose(props, ["classes", "className", "color", "edge", "size"]);
171
172 const icon = /*#__PURE__*/React.createElement("span", {
173 className: classes.thumb
174 });
175 return /*#__PURE__*/React.createElement("span", {
176 className: clsx(classes.root, className, {
177 'start': classes.edgeStart,
178 'end': classes.edgeEnd
179 }[edge], size === "small" && classes[`size${capitalize(size)}`])
180 }, /*#__PURE__*/React.createElement(SwitchBase, _extends({
181 type: "checkbox",
182 icon: icon,
183 checkedIcon: icon,
184 classes: {
185 root: clsx(classes.switchBase, classes[`color${capitalize(color)}`]),
186 input: classes.input,
187 checked: classes.checked,
188 disabled: classes.disabled
189 },
190 ref: ref
191 }, other)), /*#__PURE__*/React.createElement("span", {
192 className: classes.track
193 }));
194});
195process.env.NODE_ENV !== "production" ? Switch.propTypes = {
196 // ----------------------------- Warning --------------------------------
197 // | These PropTypes are generated from the TypeScript type definitions |
198 // | To update them edit the d.ts file and run "yarn proptypes" |
199 // ----------------------------------------------------------------------
200
201 /**
202 * If `true`, the component is checked.
203 */
204 checked: PropTypes.bool,
205
206 /**
207 * The icon to display when the component is checked.
208 */
209 checkedIcon: PropTypes.node,
210
211 /**
212 * Override or extend the styles applied to the component.
213 * See [CSS API](#css) below for more details.
214 */
215 classes: PropTypes.object,
216
217 /**
218 * @ignore
219 */
220 className: PropTypes.string,
221
222 /**
223 * The color of the component. It supports those theme colors that make sense for this component.
224 */
225 color: PropTypes.oneOf(['default', 'primary', 'secondary']),
226
227 /**
228 * @ignore
229 */
230 defaultChecked: PropTypes.bool,
231
232 /**
233 * If `true`, the switch will be disabled.
234 */
235 disabled: PropTypes.bool,
236
237 /**
238 * If `true`, the ripple effect will be disabled.
239 */
240 disableRipple: PropTypes.bool,
241
242 /**
243 * If given, uses a negative margin to counteract the padding on one
244 * side (this is often helpful for aligning the left or right
245 * side of the icon with content above or below, without ruining the border
246 * size and shape).
247 */
248 edge: PropTypes.oneOf(['end', 'start', false]),
249
250 /**
251 * The icon to display when the component is unchecked.
252 */
253 icon: PropTypes.node,
254
255 /**
256 * The id of the `input` element.
257 */
258 id: PropTypes.string,
259
260 /**
261 * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
262 */
263 inputProps: PropTypes.object,
264
265 /**
266 * Pass a ref to the `input` element.
267 */
268 inputRef: refType,
269
270 /**
271 * Callback fired when the state is changed.
272 *
273 * @param {object} event The event source of the callback.
274 * You can pull out the new value by accessing `event.target.value` (string).
275 * You can pull out the new checked state by accessing `event.target.checked` (boolean).
276 */
277 onChange: PropTypes.func,
278
279 /**
280 * If `true`, the `input` element will be required.
281 */
282 required: PropTypes.bool,
283
284 /**
285 * The size of the switch.
286 * `small` is equivalent to the dense switch styling.
287 */
288 size: PropTypes.oneOf(['medium', 'small']),
289
290 /**
291 * The value of the component. The DOM API casts this to a string.
292 * The browser uses "on" as the default value.
293 */
294 value: PropTypes.any
295} : void 0;
296export default withStyles(styles, {
297 name: 'MuiSwitch'
298})(Switch);
\No newline at end of file