UNPKG

@material-ui/core

Version:

React components that implement Google's Material Design.

293 lines (255 loc) 7.01 kB
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; import _extends from "@babel/runtime/helpers/extends"; // @inheritedComponent ButtonBase import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import withStyles from '../styles/withStyles'; import ButtonBase from '../ButtonBase'; import { capitalize } from '../utils/helpers'; import unsupportedProp from '../utils/unsupportedProp'; export const styles = theme => ({ /* Styles applied to the root element. */ root: _extends({}, theme.typography.button, { maxWidth: 264, minWidth: 72, position: 'relative', boxSizing: 'border-box', padding: 0, minHeight: 48, flexShrink: 0, overflow: 'hidden', whiteSpace: 'normal', textAlign: 'center', [theme.breakpoints.up('md')]: { fontSize: theme.typography.pxToRem(13), minWidth: 160 } }), /* Styles applied to the root element if both `icon` and `label` are provided. */ labelIcon: { minHeight: 72, // paddingTop supposed to be 12px // - 3px from the paddingBottom paddingTop: 9 // paddingBottom supposed to be 12px // -3px for line-height of the label // -6px for label padding // = 3px }, /* Styles applied to the root element if `textColor="inherit"`. */ textColorInherit: { color: 'inherit', opacity: 0.7, '&$selected': { opacity: 1 }, '&$disabled': { opacity: 0.4 } }, /* Styles applied to the root element if `textColor="primary"`. */ textColorPrimary: { color: theme.palette.text.secondary, '&$selected': { color: theme.palette.primary.main }, '&$disabled': { color: theme.palette.text.disabled } }, /* Styles applied to the root element if `textColor="secondary"`. */ textColorSecondary: { color: theme.palette.text.secondary, '&$selected': { color: theme.palette.secondary.main }, '&$disabled': { color: theme.palette.text.disabled } }, /* Styles applied to the root element if `selected={true}` (controlled by the Tabs component). */ selected: {}, /* Styles applied to the root element if `disabled={true}` (controlled by the Tabs component). */ disabled: {}, /* Styles applied to the root element if `fullWidth={true}` (controlled by the Tabs component). */ fullWidth: { flexShrink: 1, flexGrow: 1, maxWidth: 'none' }, /* Styles applied to the `icon` and `label`'s wrapper element. */ wrapper: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '100%', flexDirection: 'column' }, /* Styles applied to the label container element if `label` is provided. */ labelContainer: { width: '100%', // Fix an IE 11 issue boxSizing: 'border-box', padding: '6px 12px', [theme.breakpoints.up('md')]: { padding: '6px 24px' } }, /* Styles applied to the label wrapper element if `label` is provided. */ label: {}, /* Deprecated, the styles will be removed in v4. */ labelWrapped: {} }); class Tab extends React.Component { constructor(...args) { super(...args); this.state = { labelWrapped: false }; this.handleChange = event => { const { onChange, value, onClick } = this.props; if (onChange) { onChange(event, value); } if (onClick) { onClick(event); } }; this.checkTextWrap = () => { if (this.labelRef) { const labelWrapped = this.labelRef.getClientRects().length > 1; if (this.state.labelWrapped !== labelWrapped) { this.setState({ labelWrapped }); } } }; } componentDidMount() { this.checkTextWrap(); } componentDidUpdate(prevProps, prevState) { if (this.state.labelWrapped === prevState.labelWrapped) { /** * At certain text and tab lengths, a larger font size may wrap to two lines while the smaller * font size still only requires one line. This check will prevent an infinite render loop * fron occurring in that scenario. */ this.checkTextWrap(); } } render() { const _this$props = this.props, { classes, className, disabled, fullWidth, icon, indicator, label: labelProp, selected, textColor } = _this$props, other = _objectWithoutPropertiesLoose(_this$props, ["classes", "className", "disabled", "fullWidth", "icon", "indicator", "label", "onChange", "selected", "textColor", "value"]); let label; if (labelProp !== undefined) { label = React.createElement("span", { className: classes.labelContainer }, React.createElement("span", { className: classNames(classes.label, { [classes.labelWrapped]: this.state.labelWrapped }), ref: ref => { this.labelRef = ref; } }, labelProp)); } return React.createElement(ButtonBase, _extends({ focusRipple: true, className: classNames(classes.root, classes[`textColor${capitalize(textColor)}`], { [classes.disabled]: disabled, [classes.selected]: selected, [classes.labelIcon]: icon && label, [classes.fullWidth]: fullWidth }, className), role: "tab", "aria-selected": selected, disabled: disabled }, other, { onClick: this.handleChange }), React.createElement("span", { className: classes.wrapper }, icon, label), indicator); } } process.env.NODE_ENV !== "production" ? Tab.propTypes = { /** * This property isn't supported. * Use the `component` property if you need to change the children structure. */ children: unsupportedProp, /** * Override or extend the styles applied to the component. * See [CSS API](#css-api) below for more details. */ classes: PropTypes.object.isRequired, /** * @ignore */ className: PropTypes.string, /** * If `true`, the tab will be disabled. */ disabled: PropTypes.bool, /** * @ignore */ fullWidth: PropTypes.bool, /** * The icon element. */ icon: PropTypes.node, /** * @ignore * For server-side rendering consideration, we let the selected tab * render the indicator. */ indicator: PropTypes.node, /** * The label element. */ label: PropTypes.node, /** * @ignore */ onChange: PropTypes.func, /** * @ignore */ onClick: PropTypes.func, /** * @ignore */ selected: PropTypes.bool, /** * @ignore */ textColor: PropTypes.oneOf(['secondary', 'primary', 'inherit']), /** * You can provide your own value. Otherwise, we fallback to the child position index. */ value: PropTypes.any } : void 0; Tab.defaultProps = { disabled: false, textColor: 'inherit' }; export default withStyles(styles, { name: 'MuiTab' })(Tab);