UNPKG

14.4 kBJavaScriptView Raw
1import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2import _extends from "@babel/runtime/helpers/esm/extends";
3const _excluded = ["children", "color", "component", "className", "disabled", "disableElevation", "disableFocusRipple", "endIcon", "focusVisibleClassName", "fullWidth", "size", "startIcon", "type", "variant"],
4 _excluded2 = ["root"];
5import * as React from 'react';
6import PropTypes from 'prop-types';
7import clsx from 'clsx';
8import { internal_resolveProps as resolveProps } from '@mui/utils';
9import { unstable_composeClasses as composeClasses } from '@mui/base';
10import { alpha } from '@mui/system';
11import styled, { rootShouldForwardProp } from '../styles/styled';
12import useThemeProps from '../styles/useThemeProps';
13import ButtonBase from '../ButtonBase';
14import capitalize from '../utils/capitalize';
15import buttonClasses, { getButtonUtilityClass } from './buttonClasses';
16import ButtonGroupContext from '../ButtonGroup/ButtonGroupContext';
17import { jsx as _jsx } from "react/jsx-runtime";
18import { jsxs as _jsxs } from "react/jsx-runtime";
19
20const useUtilityClasses = ownerState => {
21 const {
22 color,
23 disableElevation,
24 fullWidth,
25 size,
26 variant,
27 classes
28 } = ownerState;
29 const slots = {
30 root: ['root', variant, `${variant}${capitalize(color)}`, `size${capitalize(size)}`, `${variant}Size${capitalize(size)}`, color === 'inherit' && 'colorInherit', disableElevation && 'disableElevation', fullWidth && 'fullWidth'],
31 label: ['label'],
32 startIcon: ['startIcon', `iconSize${capitalize(size)}`],
33 endIcon: ['endIcon', `iconSize${capitalize(size)}`]
34 };
35 const composedClasses = composeClasses(slots, getButtonUtilityClass, classes);
36 return _extends({}, classes, composedClasses);
37};
38
39const commonIconStyles = ownerState => _extends({}, ownerState.size === 'small' && {
40 '& > *:nth-of-type(1)': {
41 fontSize: 18
42 }
43}, ownerState.size === 'medium' && {
44 '& > *:nth-of-type(1)': {
45 fontSize: 20
46 }
47}, ownerState.size === 'large' && {
48 '& > *:nth-of-type(1)': {
49 fontSize: 22
50 }
51});
52
53const ButtonRoot = styled(ButtonBase, {
54 shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
55 name: 'MuiButton',
56 slot: 'Root',
57 overridesResolver: (props, styles) => {
58 const {
59 ownerState
60 } = props;
61 return [styles.root, styles[ownerState.variant], styles[`${ownerState.variant}${capitalize(ownerState.color)}`], styles[`size${capitalize(ownerState.size)}`], styles[`${ownerState.variant}Size${capitalize(ownerState.size)}`], ownerState.color === 'inherit' && styles.colorInherit, ownerState.disableElevation && styles.disableElevation, ownerState.fullWidth && styles.fullWidth];
62 }
63})(({
64 theme,
65 ownerState
66}) => _extends({}, theme.typography.button, {
67 minWidth: 64,
68 padding: '6px 16px',
69 borderRadius: (theme.vars || theme).shape.borderRadius,
70 transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
71 duration: theme.transitions.duration.short
72 }),
73 '&:hover': _extends({
74 textDecoration: 'none',
75 backgroundColor: theme.vars ? `rgba(${theme.vars.palette.text.primaryChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity),
76 // Reset on touch devices, it doesn't add specificity
77 '@media (hover: none)': {
78 backgroundColor: 'transparent'
79 }
80 }, ownerState.variant === 'text' && ownerState.color !== 'inherit' && {
81 backgroundColor: theme.vars ? `rgba(${theme.vars.palette[ownerState.color].mainChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette[ownerState.color].main, theme.palette.action.hoverOpacity),
82 // Reset on touch devices, it doesn't add specificity
83 '@media (hover: none)': {
84 backgroundColor: 'transparent'
85 }
86 }, ownerState.variant === 'outlined' && ownerState.color !== 'inherit' && {
87 border: `1px solid ${(theme.vars || theme).palette[ownerState.color].main}`,
88 backgroundColor: theme.vars ? `rgba(${theme.vars.palette[ownerState.color].mainChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette[ownerState.color].main, theme.palette.action.hoverOpacity),
89 // Reset on touch devices, it doesn't add specificity
90 '@media (hover: none)': {
91 backgroundColor: 'transparent'
92 }
93 }, ownerState.variant === 'contained' && {
94 backgroundColor: (theme.vars || theme).palette.grey.A100,
95 boxShadow: (theme.vars || theme).shadows[4],
96 // Reset on touch devices, it doesn't add specificity
97 '@media (hover: none)': {
98 boxShadow: (theme.vars || theme).shadows[2],
99 backgroundColor: (theme.vars || theme).palette.grey[300]
100 }
101 }, ownerState.variant === 'contained' && ownerState.color !== 'inherit' && {
102 backgroundColor: (theme.vars || theme).palette[ownerState.color].dark,
103 // Reset on touch devices, it doesn't add specificity
104 '@media (hover: none)': {
105 backgroundColor: (theme.vars || theme).palette[ownerState.color].main
106 }
107 }),
108 '&:active': _extends({}, ownerState.variant === 'contained' && {
109 boxShadow: (theme.vars || theme).shadows[8]
110 }),
111 [`&.${buttonClasses.focusVisible}`]: _extends({}, ownerState.variant === 'contained' && {
112 boxShadow: (theme.vars || theme).shadows[6]
113 }),
114 [`&.${buttonClasses.disabled}`]: _extends({
115 color: (theme.vars || theme).palette.action.disabled
116 }, ownerState.variant === 'outlined' && {
117 border: `1px solid ${(theme.vars || theme).palette.action.disabledBackground}`
118 }, ownerState.variant === 'outlined' && ownerState.color === 'secondary' && {
119 border: `1px solid ${(theme.vars || theme).palette.action.disabled}`
120 }, ownerState.variant === 'contained' && {
121 color: (theme.vars || theme).palette.action.disabled,
122 boxShadow: (theme.vars || theme).shadows[0],
123 backgroundColor: (theme.vars || theme).palette.action.disabledBackground
124 })
125}, ownerState.variant === 'text' && {
126 padding: '6px 8px'
127}, ownerState.variant === 'text' && ownerState.color !== 'inherit' && {
128 color: (theme.vars || theme).palette[ownerState.color].main
129}, ownerState.variant === 'outlined' && {
130 padding: '5px 15px',
131 border: '1px solid currentColor'
132}, ownerState.variant === 'outlined' && ownerState.color !== 'inherit' && {
133 color: (theme.vars || theme).palette[ownerState.color].main,
134 border: theme.vars ? `1px solid rgba(${theme.vars.palette[ownerState.color].mainChannel} / 0.5)` : `1px solid ${alpha(theme.palette[ownerState.color].main, 0.5)}`
135}, ownerState.variant === 'contained' && {
136 color: theme.vars ? // this is safe because grey does not change between default light/dark mode
137 theme.vars.palette.text.primary : theme.palette.getContrastText?.(theme.palette.grey[300]),
138 backgroundColor: (theme.vars || theme).palette.grey[300],
139 boxShadow: (theme.vars || theme).shadows[2]
140}, ownerState.variant === 'contained' && ownerState.color !== 'inherit' && {
141 color: (theme.vars || theme).palette[ownerState.color].contrastText,
142 backgroundColor: (theme.vars || theme).palette[ownerState.color].main
143}, ownerState.color === 'inherit' && {
144 color: 'inherit',
145 borderColor: 'currentColor'
146}, ownerState.size === 'small' && ownerState.variant === 'text' && {
147 padding: '4px 5px',
148 fontSize: theme.typography.pxToRem(13)
149}, ownerState.size === 'large' && ownerState.variant === 'text' && {
150 padding: '8px 11px',
151 fontSize: theme.typography.pxToRem(15)
152}, ownerState.size === 'small' && ownerState.variant === 'outlined' && {
153 padding: '3px 9px',
154 fontSize: theme.typography.pxToRem(13)
155}, ownerState.size === 'large' && ownerState.variant === 'outlined' && {
156 padding: '7px 21px',
157 fontSize: theme.typography.pxToRem(15)
158}, ownerState.size === 'small' && ownerState.variant === 'contained' && {
159 padding: '4px 10px',
160 fontSize: theme.typography.pxToRem(13)
161}, ownerState.size === 'large' && ownerState.variant === 'contained' && {
162 padding: '8px 22px',
163 fontSize: theme.typography.pxToRem(15)
164}, ownerState.fullWidth && {
165 width: '100%'
166}), ({
167 ownerState
168}) => ownerState.disableElevation && {
169 boxShadow: 'none',
170 '&:hover': {
171 boxShadow: 'none'
172 },
173 [`&.${buttonClasses.focusVisible}`]: {
174 boxShadow: 'none'
175 },
176 '&:active': {
177 boxShadow: 'none'
178 },
179 [`&.${buttonClasses.disabled}`]: {
180 boxShadow: 'none'
181 }
182});
183const ButtonStartIcon = styled('span', {
184 name: 'MuiButton',
185 slot: 'StartIcon',
186 overridesResolver: (props, styles) => {
187 const {
188 ownerState
189 } = props;
190 return [styles.startIcon, styles[`iconSize${capitalize(ownerState.size)}`]];
191 }
192})(({
193 ownerState
194}) => _extends({
195 display: 'inherit',
196 marginRight: 8,
197 marginLeft: -4
198}, ownerState.size === 'small' && {
199 marginLeft: -2
200}, commonIconStyles(ownerState)));
201const ButtonEndIcon = styled('span', {
202 name: 'MuiButton',
203 slot: 'EndIcon',
204 overridesResolver: (props, styles) => {
205 const {
206 ownerState
207 } = props;
208 return [styles.endIcon, styles[`iconSize${capitalize(ownerState.size)}`]];
209 }
210})(({
211 ownerState
212}) => _extends({
213 display: 'inherit',
214 marginRight: -4,
215 marginLeft: 8
216}, ownerState.size === 'small' && {
217 marginRight: -2
218}, commonIconStyles(ownerState)));
219const Button = /*#__PURE__*/React.forwardRef(function Button(inProps, ref) {
220 // props priority: `inProps` > `contextProps` > `themeDefaultProps`
221 const contextProps = React.useContext(ButtonGroupContext);
222 const resolvedProps = resolveProps(contextProps, inProps);
223 const props = useThemeProps({
224 props: resolvedProps,
225 name: 'MuiButton'
226 });
227
228 const {
229 children,
230 color = 'primary',
231 component = 'button',
232 className,
233 disabled = false,
234 disableElevation = false,
235 disableFocusRipple = false,
236 endIcon: endIconProp,
237 focusVisibleClassName,
238 fullWidth = false,
239 size = 'medium',
240 startIcon: startIconProp,
241 type,
242 variant = 'text'
243 } = props,
244 other = _objectWithoutPropertiesLoose(props, _excluded);
245
246 const ownerState = _extends({}, props, {
247 color,
248 component,
249 disabled,
250 disableElevation,
251 disableFocusRipple,
252 fullWidth,
253 size,
254 type,
255 variant
256 });
257
258 const _useUtilityClasses = useUtilityClasses(ownerState),
259 {
260 root: classesRoot
261 } = _useUtilityClasses,
262 classes = _objectWithoutPropertiesLoose(_useUtilityClasses, _excluded2);
263
264 const startIcon = startIconProp && /*#__PURE__*/_jsx(ButtonStartIcon, {
265 className: classes.startIcon,
266 ownerState: ownerState,
267 children: startIconProp
268 });
269
270 const endIcon = endIconProp && /*#__PURE__*/_jsx(ButtonEndIcon, {
271 className: classes.endIcon,
272 ownerState: ownerState,
273 children: endIconProp
274 });
275
276 return /*#__PURE__*/_jsxs(ButtonRoot, _extends({
277 ownerState: ownerState,
278 className: clsx(contextProps.className, classesRoot, className),
279 component: component,
280 disabled: disabled,
281 focusRipple: !disableFocusRipple,
282 focusVisibleClassName: clsx(classes.focusVisible, focusVisibleClassName),
283 ref: ref,
284 type: type
285 }, other, {
286 classes: classes,
287 children: [startIcon, children, endIcon]
288 }));
289});
290process.env.NODE_ENV !== "production" ? Button.propTypes
291/* remove-proptypes */
292= {
293 // ----------------------------- Warning --------------------------------
294 // | These PropTypes are generated from the TypeScript type definitions |
295 // | To update them edit the d.ts file and run "yarn proptypes" |
296 // ----------------------------------------------------------------------
297
298 /**
299 * The content of the component.
300 */
301 children: PropTypes.node,
302
303 /**
304 * Override or extend the styles applied to the component.
305 */
306 classes: PropTypes.object,
307
308 /**
309 * @ignore
310 */
311 className: PropTypes.string,
312
313 /**
314 * The color of the component.
315 * It supports both default and custom theme colors, which can be added as shown in the
316 * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors).
317 * @default 'primary'
318 */
319 color: PropTypes
320 /* @typescript-to-proptypes-ignore */
321 .oneOfType([PropTypes.oneOf(['inherit', 'primary', 'secondary', 'success', 'error', 'info', 'warning']), PropTypes.string]),
322
323 /**
324 * The component used for the root node.
325 * Either a string to use a HTML element or a component.
326 */
327 component: PropTypes.elementType,
328
329 /**
330 * If `true`, the component is disabled.
331 * @default false
332 */
333 disabled: PropTypes.bool,
334
335 /**
336 * If `true`, no elevation is used.
337 * @default false
338 */
339 disableElevation: PropTypes.bool,
340
341 /**
342 * If `true`, the keyboard focus ripple is disabled.
343 * @default false
344 */
345 disableFocusRipple: PropTypes.bool,
346
347 /**
348 * If `true`, the ripple effect is disabled.
349 *
350 * ⚠️ Without a ripple there is no styling for :focus-visible by default. Be sure
351 * to highlight the element by applying separate styles with the `.Mui-focusVisible` class.
352 * @default false
353 */
354 disableRipple: PropTypes.bool,
355
356 /**
357 * Element placed after the children.
358 */
359 endIcon: PropTypes.node,
360
361 /**
362 * @ignore
363 */
364 focusVisibleClassName: PropTypes.string,
365
366 /**
367 * If `true`, the button will take up the full width of its container.
368 * @default false
369 */
370 fullWidth: PropTypes.bool,
371
372 /**
373 * The URL to link to when the button is clicked.
374 * If defined, an `a` element will be used as the root node.
375 */
376 href: PropTypes.string,
377
378 /**
379 * The size of the component.
380 * `small` is equivalent to the dense button styling.
381 * @default 'medium'
382 */
383 size: PropTypes
384 /* @typescript-to-proptypes-ignore */
385 .oneOfType([PropTypes.oneOf(['small', 'medium', 'large']), PropTypes.string]),
386
387 /**
388 * Element placed before the children.
389 */
390 startIcon: PropTypes.node,
391
392 /**
393 * The system prop that allows defining system overrides as well as additional CSS styles.
394 */
395 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
396
397 /**
398 * @ignore
399 */
400 type: PropTypes.oneOfType([PropTypes.oneOf(['button', 'reset', 'submit']), PropTypes.string]),
401
402 /**
403 * The variant to use.
404 * @default 'text'
405 */
406 variant: PropTypes
407 /* @typescript-to-proptypes-ignore */
408 .oneOfType([PropTypes.oneOf(['contained', 'outlined', 'text']), PropTypes.string])
409} : void 0;
410export default Button;
\No newline at end of file